we now flush the backend (e.g. GL) after the color pass, this a
good time because a lot of GPU work has been queued by that point, this
allows the GPU to start while we queue the post-processing commands.
This reduces latency by about 2.5ms on pixel4.
gltfio-lite now has its own template file rather than re-using the
ubershader one, which allows us to optimize the materials by removing
support for various glTF extensions like texture matrices,
specular-glossiness, and clear coat.
in OpenGL we need to check the status of queries on the gl thread,
so we did this in when beginFrame was called -- however, this is
too late, because beginFrame is asynchronous, so we were always
behind by 1 frame.
we fix this by running the callbacks more often.
The user can now choose amongst 3 specular AO methods:
- None, specAO is off
- Simple, specAO is inferred from roughness and diffuse AO
- Bent normals, specAO is computed accurately from cone intersections
The last method is more expensive but produces the best results.
This change also fixes a few issues:
- Rename materialRefraction() and materialRefractionType() for
consistency
- Fixes user time in shaders
On drivers that don't implement timer queries properly, we use
fences instead, however we can't use a fence to determine the start
time of the GPU work (only the end time). To workaround this we
use the last call to glFlush() as a proxy.
At least on Pixel it works very well.
We also remove all mid-frame calls to flush(), we did this to kick
cpu work early, but it's not as efficient as overlapping the work
with the previous frame, it increases latency a bit though.
A sync object for us is like a fence that cannot be waited on. It can
only be queried.
This is useful for filament to know if (not when) some previous
commands have finished executing.
In OpenGL this is different from "fences" which only exist in EGL and
can be waited on from any thread.
"sync" objects correspond to GLsync object in OpenGL and are widely
supported, as opposed to EGL fences.
So we use the term "fence" to refer to synchronization object that are
external to OpenGL and the term "sync" for the native gl synchronization
objects. This distinction may or may not exist in other APIs.
rewrite the FrameSkipper to use this, which enables it on MacOS.
Stores font texture as RGBA instead of R. This is because the ui material will not be compatible for RGBA textures, as it is expecting an R texture. I was unable get a texture with ALPHA format to function as I wanted.
This also removes material instance caching by scissor rect. Instead it just assigns the scissor rect to each new primitive, as well as an optional texture.
- now the DynamicResolutionOptions don't specify the target frame rate,
they only specify how to scale this given view
- there is a new FrameRateOptions setting on Renderer, which is used
to specify the desired target frame rate for the whole Renderer
- the frame rate is now specified as a "frame interval" in units of
the display frame period.
- the display frame period is (indirectly) set via DisplayInfo.
In other words, the use must set (and update) DisplayInfo properly
(the default are reasonable, but assume 60 Hz). They must also set the
desired interval (default is 1, which is probably what you want).
Finally they must enable dynamic scaling per View, the defaults are
also reasonable.
Currently Renderer doesn't attempt (yet) to actually target the
requested frame rate, so it's up to the caller to push frames at the
desired speed. however, dynamic resolution, like before, will attempt
to shrink work to fit the target.
Renderer can now be given a DisplayInfo that contains some
important information about the current display. This will be used
for frame-pacing and dynamic-resolution.
This is most relevant on Android, where we can accurately query these
parameters. Added support for that in our samples.
This also sets the minSDK to 19 (including gltf viewer's), since this is
the version we support. We were cheating before by under-reporting our
minSdk.
Until now, only the memory of Hw handes was allocated synchronously,
handles were constructed later asynchronously. This was error prone
with the few (but growing) synchronous calls we have.
Now we have an init<> call that allocates and constructs handles synchronously,
the asynchronous construction if needed, is still performed with construct<>,
which is now implemented as "destroy+construct", this is okay because
most of our handles have trivial dtors.
This fixes a race with TimerQuery and Fence. Fences are still not fully
working though, but at least won't access uninitialized memory.
Currently backend fences MUST be used trough FFence.
On metals (made only of specular light), specular AO can
create large black spots. This change simply kills specular
AO to avoid this artifact. In practice we should take into
account multiple bounces but this is rasterization...
This adds a simple query API to the backend.
There are 2 methods to create/destroy queries, which are
essentially futures. And 3 methods to mesure elapsed time:
beginTimerQuery/endTimerQuery and getTimerQueryValue.
The begin/end pair is not nestable.
On the GL backend side, there are 2 implementations of this, one uses
arb_timer_query or disjoint_timer_query, the other uses fences.
We need both implementations because on some GPUs, including
qualcomm's elapsed-time timer query is useless, as it measures
cpu time.
Metal/Vulkan implementations will be part of subsequent PRs. Vulkan
will be able to implement this with vkWriteTimestamp which is
reported to be accurate.
An immediate benefit is that we can now get frame times on MacOS, which
should allow it to use dynamic-resolution.