Even when hex modifier is used, 'char' should be printed as characters,
this is particularly relevant with 0.
e.g. out << (char)0, should write a nul terminator, not "0".
Instead of passing SamplerInterfaceBlocks and a SamplerBindingMap to
Program, we now set a 'sampler group' per binding point:
Program::addSamplerGroup(...)
A sampler group here consists of a list of N 'Sampler' and a 'Sampler'
is just a unique name (unifrom name in the shader) and binding point in
the shader.
That's all the driver layer needs.
With this change we get rid of the code that re-created the uniform
names in the driver -- this should never have been done there. And we
also remove the hash-map lookups in vulkan and metal drivers.
Program::shader() was taking a string before which didn't make sense
for spirv. Now it's just a blob, in the case of GL/Metal, the blob
must be a null terminated c-string, and the size must include the
terminating null character.
This fixes an out-of-bound access in ShaderBuilder::getShader() (which
doesn't exist anymore), because it was creating a CString passing
a size that included the null terminating char, which is not was CString
expects. CString can now assert() in that case.
driver::Program now uses a std::vector<> for storage, which we should
fix at some point (b/c it's a public header). CString was not suited to
store binary blobs.
This reverts a JobSystem optimization that attempted to avoid signaling
a condition when there was no waiters. Unfortunately, there was a
race that caused the the signaling thread to miss that the waiter flag
was set, thus not signaling.
Fixes a header usage problem for MSVC, which complains about StaticString not having a constexpr constructor thus making the "make" method not constexpr.
- only signal waitAndRelease() when the corresponding job finishes and
only if there is waitAndRelease() active -- instead of signaling
every time a job ends.
- don't surrender time slice when attempting to steal a job and it fails
as long as some queue has jobs.
- check that we have to wait, because taking the lock
- add a benchmark
This change more than doubles the amount of jobs we can handle per
second (~965,000 jobs/s on Pixel3)
JobSystem::waitAndRelease used to spin to wait for the job to finish,
usually this wasn't a problem because the spinning thread was
able to handle other jobs. However, in cases where no job was
available it would actually spin in burn cpu cycles.
we now use a (separate) condition variable to handle that case.
In a lot of case the StaticString hash can be computed a compile time,
so we now take advantage of that.
Removed StaticString(const char*) ctor, and replaced it with a
StaticString::make() method.
Fixed a couple wrong uses of the old StaticString(const char*) ctor.
We simply don't emit unwind tables, which are not needed anyways since
we're compiling without exceptions. the combined saving for all four
targets we support is about 120K.
This seems to improve .aar's compression, for a total gain of 152 KiB.
We also disable stack-protector in the jni code, since it wasn't
enabled in libfilament.a anyways. However, we now compile all debug
builds with -fstack-protector
- make Profiler::readCounters() not inline as it didn't need to be,
it's not performance critical and it's sufficiently large.
- don't inline hasExtensions(), same reason.
We used to only wake up a job-queue if there was already some jobs
running, the idea was that the current thread would handle the new job
as soon as calling wait(). However, there is no guarantee that wait()
will be called anytime soon.
cv.signal() is not very expensive on Android/Linux, as we're using
a custom implementation.
An assert checking invariants would sometime trigger, the problem
was a logic error that would be exposed by a race when running out
of space in the list.
The root of the problem is that in one place we were not remapping the
-1 offset to nullptr, storing a pointer violating our invariants.
Also added more asserts!!!
We're using timed condition variable in one place, but the STL version
pulls in a lot of code because it does clock calculations in
"long double" (!!!!). Since we already had an implementation
of condition_variable, we just add the timed version.
This saves several KiB of code.
Also don't use unique_lock() lock/unlock because it can throw exceptions.