Texture handles were resolved to pointers when updating a SamplerGroup,
as that point the handle was checked for use-after-free. However, the
texture could be destroyed later while still active in the SamplerGroup,
this would result in using the pointer which now contains garbage.
We now keep the handle and resolve the texture when binding samplers
to the program; which will also perform the use-after-free check.
If a user is using `setFrameScheduledCallback()`, managing the provided PresentCallable during engine shutdown is tricky -- we'll likely get a final frame scheduled when we flush the engine's work queue, but the PresentCallable will schedule the final CAMetalDrawable to be released on main thread afterwards, even if we call `present(false)` to skip it. If the swap chain is destroyed before that main queue block gets executed, the mutex presenting that drawable will no longer exist, causing a crash.
To make things easier, store the std::mutex in a shared_ptr, so that a PresentCallable can safely outlive the FSwapChain instance that created it and clean itself up afterwards.
Alternatives considered, all of which seem unfortunate:
* Require users to clear out the callback before shutting down the engine, so that any final drawables are immediately discarded instead of using PresentCallable
* Require users to split up the engine teardown across two main queue blocks, ensuring that the PresentCallable cleanup executes before swapchains are destroyed
* Drop the PresentCallable on the ground and leak the memory
When a user drags and drops a gltf file to the gltf_viewer window, it
loads the new asset.
While this happens, the function `checkAsset` tries parsing the gltf
file, but it doesn't free it. Fix this.
The number of SH bands used for the indirect light irradiance
computations can be set to 1, 2 or 3 (default) in Material::Builder.
For e.g. in lower-end devices w/ non HDR content, it might be
beneficial to set this value to 2.
BUGS=[341971013]
Abstracts the synchronization of the vulkan swapchain so that it is easier to override during the acquisition and presentation of images. A new structure (ImageSyncData) is created to hold swapchain synchronization data.
FIXES=[338303279]
PresentDrawable was moved to main thread by default in google#7535 and stopped
most crashes when a drawable is released. But there still appears to be crashes
if a drawable is released on main thread at the same time that -nextDrawable is
called from the Filament render thread. (It's likely that the drawable pool in
CAMetalLayer is completely non-thread-safe.)
So, add a mutex to the swapchain and always acquire it before creating or
releasing a CAMetalDrawable.
Users can opt out of this behavior by passing
-DFILAMENT_LOCK_METAL_DRAWABLE_POOL=0.
Currently, if this fails we log the error message to stderr (which
doesn't get captured by most crash reporting systems) and then crash in
a postcondition assert. By including the error message in an exception
reason and throwing an ObjC exception, we get better discoverability of
error causes.
(Building a render pipeline state from shaders is usually when a shader
actually gets JITted from LLVM IR to GPU-specific code, so if we
accidentally used a feature that's not available on the local GPU, we'll
find out about it here.)
going forward, instead of using the printf style syntax for panics
we use the c++ stream syntax
The new macros that replace ASSERT_*CONDITON are
FILAMENT_CHECK_PRECONDITON
FILAMENT_CHECK_POSTCONDITION
FILAMENT_CHECK_ARITIHMETIC
Example usage:
FILAMENT_CHECK_PRECONDITON(condition) << "Message";
It's also now possible to define FILAMENT_PANIC_USES_ABSL=1 to redirect
all these calls to Abseil's CHECK() macro.
Set combine_multiview_images to false by default as it's the desirable
setting for most Android devices.
Set the flag to true for GUI by default.
Put the `Combine Multiview Images` checkbox under the `Stereo mode` box
for an easier access.
The current API allowed to have a buffer for each primitive in a
renderable. We instead restrict the API so that there is a single
MorphTargetBuffer for the whole renderable, shared by all primitives.
The buffer can be shared thanks to the "offset" parameter on
setMorphTargetBufferAt().
Also
- fix FMorphTargetBuffer::updateDataAt()
- add support for the "offset" parameter of setMorphTargetBufferAt()
- Add option to build.sh to build for paritcular stereo
techniques (default to NONE). Only applies to samples.
- Consoldiate viewer checkbox for debugging stereo rendering
- Add DriverConfig flag for stereoscopic type so that it can
be used to determine availability of the feature and
(to be completed) enable corresponding GPU features.
Co-authored-by: Mathias Agopian <mathias@google.com>
we use a different hook for the draw() call when on an ES2 context,
this eliminates completely the overhead of supporting ES2 for the draw
call. draw calls are expected to be the most common calls.
- Use custom ICD path to enable Swiftshader instead of
specifying direct path to the lib.
- Remove unused `swiftshader` directory in `build`
- Remove swiftshader options in `build.sh` and cmakefiles
- Change BUILD.md
- Correctly handle XCB-only swapchain surface in VulkanPlatform
for swiftshader.
- Refactor `VulkanPlatform::ExtensionSet` so that `utils::CString`
is used instead of string_view, so that we don't get into
tricky lifetime issues with `const char*`
- a field was added, which broke the layout of the structure. We fix it
by adding constructors which will handle the old and new way of
initializing this structure.
- one of the test needed a hash update
- OpenGLContext wrongly asserted when trying to unbind texture 0
If a .metallib was compiled with a target iOS version that's newer than
the current device, loading the .metallib may succeed, but finding main0
(or any other function in it) will fail. Currently, this causes a crash
due to an assert. Logging the error and returning
MetalFunctionBundle::error() makes the crash slightly easier to
diagnose.
(Note that in practice, this will probably be a useless "Compiler
encountered an internal error" message -- the GPU backend is crashing,
and the Metal stub library sees XPC_ERROR_CONNECTION_INTERRUPTED. It
retries up to 3 times (crashing each time) and then gives up.)
* Add an Engine debug setting to force GLES 2.0
This setting is only meaningful on GLES backends, it's otherwise
ignored. When set to true, the backend will try to force a ES2 context
if supported. If not supported by the platform,
the backend will pretend it's a ES2 context.
This setting is currently only taken into account by the EGL platform.
* Update filament/backend/include/backend/Platform.h
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
- make sure we can build with ES2 headers only
- make sure to not use ES3 features when in ES2 mode
(post processing was accidentally creating an R8 texture,
which is not supported)
I was unfortunately naive about the way that Filament handled external textures
on non-GLES platforms. This fix restricts the changes to Android (which is the
only place this change is required in the first place). Long story short, the
change broke WebGL. Desktop seems to be unaffected.
- At the end of a renderpass we use a more fine-grained barrier
for each of the attachments in the render target
- Make sure that buffer update are barrier'd from previous reads
- Remove previous Mali workaround barriers. Seems to be fine
without them on pixels + Mali.
This change will enable proper flat-shading and MikkTSpace.
Caveats:
- Only for disk-local glTF resources
- iOS, Web, Android do not work as of now
Fixes#6358, #7444
- use namespace for ImageUtility
- use FILAMENT_BACKEND_DEBUG_FLAG
- remove unused usage flag type
- add const list of VKFormat for iteration
- fix sampler name debug
The main goal of this change is to avoid having to select the
"per renderable" UBO at execution time. Instead we want the
PrimitiveInfo structure to already know which UBO will be used.
Concretely, this means that this determination must be done when
the RenderPass is created.
When automatic instancing is used, the RenderPass creates a temporary
UBO to store the instance info. This UBO's life-time is dictated by both
the life-time of the RenderPass and the Executors that where created
from it. For this reason we introduce SharedHandle<> to correctly
account for the owner's lifetime. This fixes a potential bugs where
that handle could have been destroyed and used later; in practice this
bug didn't happen however.
A couple other changes:
- RenderPass has a bunch of fields that were actually temporary, so we
removed those.
- The canonical "per-renderable" UBO was owned by View but accessed
through Scene. This was confusing, it's now accessed through View.
It's been a while that generateCommands() can only generate either
the depth or color pass but not both at once; we can simplify/de-dup
the code by leveraging that.
To allow easy enabling/disabling of debug options like vulkan
validation, android systrace, debug printing, and others, we
introduce an option to add a preprocessor flag so that a
backend can (optionally) use it to manage debug options.
* vk: Fix unsupported depth blitting
On certain hardware (pixel 4 for example), blitting of depth texture
is not supported as an "optimalTilingFeature". In these cases, we'd
would need to do a shader-based blit. We
- Add the shader blit in PostProcessingManager
- Add a driver API to check for support for blitting depthStencil
attachments.
- Fix some debugging ifdefs in vk backend.
The validation fixed is:
`[ VUID-vkCmdBlitImage-dstImage-02000 ] Object 0: handle = 0xb400007c300701d0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0xf2039b0000000771, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x86bc2a78 | In vkCmdBlitImage, VkFormatFeatureFlags (0x1c601) does not support required feature VK_FORMAT_FEATURE_2_BLIT_DST_BIT for format 126 used by VkImage 0xf2039b0000000771[] with tiling VK_IMAGE_TILING_OPTIMAL. The Vulkan spec states: The format features of dstImage must contain VK_FORMAT_FEATURE_BLIT_DST_BIT`
This largely undoes a change I did recently where PrimitiveInfo has
a FRenderPrimitive* to save some space and keep a command at 64 bytes.
This wasn't a good idea because the inner rendering loop shouldn't
to any dereference in the common case.
This change reorganises PrimitiveInfo such that it stores all the data
necessary to render a primitive in the common case. The less common
cases are when hybrid instancing, morphing or skinning are used; in
those cases, a dereference into the renderable SOA is needed.
PrimitiveInfo currently has 16 bytes free, which we keep for futur use.
In opengl it's possible to bind several textures to the same texture
unit as long as they're a different target. Until now we were tracking
that state. In practice it's not very useful to bind several textures
to the same unit (it is a little bit when updating texture data, but
not when rendering). With the coming change to a descriptor set API, it
is better to have a 1-to-1 mapping between bound textures and texture
units.
So with this change, only a single texture can be bound to a texture
unit. If another texture in bound to the same unit with a different
target, we first unbind the texture from the current target.
There is less state to track, and it allows us to
"unbind a texture unit" (whereas before we'd have to iterate through
all the possible targets for that unit and unbind all of them).
* don't rely on FMaterialInstance having a default ctor
FMaterialInstance needed a default ctor because it is a field of
FMaterial but cannot be initialized before FMaterial itself is
initialized. So we had a defautl ctor and we'd finish the initialization
later. Conceptually the default material instance should have been
new'ed and a pointer to it stored instead.
That's basically what we do now, but to avoid the extra allocation,
we in-place new and delete the default material instance into an
aligned_storage inside FMaterial.
* Update filament/src/details/Material.h
Co-authored-by: Ben Doherty <bendoherty@google.com>
---------
Co-authored-by: Ben Doherty <bendoherty@google.com>
the gl backend did some of its cleanup in the its destructor,
including calling into OpenGL, however, the destructor is called from
the main thread, not the GL thread, so these calls would be no-ops at
best, and crashes in the worst case.
* don't crash if we don't have a Camera set on View
- also add a method to query if a camera was set
* Update android/filament-android/src/main/java/com/google/android/filament/View.java
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
using thread affinity naively on big.little architectures is very flaky,
for now it's better to simplify and not use it at all, let the kernel
figure things out.
BUGS=[333582569]
* gltfio: add Asset/Resource extended implementations
- Add gltfio/src/extended to implement an alternate loader for
primitives. This is largely based on the implementation in
AssetLoader/ResourceLoader
- Able to correctly produce flat shading from gltf that only have
vertex positions and indices.
- This is not hooked into current code and should have no
practical effect on gltfio.
Originally we did this because we wanted to run on a big core on
android. However setting the thread affinity in this way is fragile,
we are not guaranteed to be on a big core, and we don't even know
if some thread is pinned to that core already; which was the case
with some GL drivers. This can also cause scheduling problems with
other threads.
We just remove this logic entirely for now, and we'll figure out
something better later to run on a big core.
Fixes#7748
BUGS=[333949404]
This change introduces a new chunk type to material files for precompiled Metal libraries. Previously, SPIR-V was the only binary type, so there's also a couple of refactor commits present here. Nothing is changed in Filament or matc yet.
BUGS=[333547148]
- Use new descriptor set and layout caching
- Remove descriptor set related code in VulkanPipelineCache
- fix leaks for descriptor sets/layouts
FIXES=248594812,325157400
A MaterialParser could be leaked if several edits happened before they
were latched -- this was because the MaterialParser was stored as
a raw pointer instead of a unique_ptr<>, this was done as an attempt
to avoid to use a lock around accessing mPendingEdits.
Added
- Cache for layouts
- Pools for descriptor sets
- Cache for descriptor set updates
- Cache for pipeline layouts
Does not have effect on implementation.
- Move VulkanDescriptorSet to VulkanHandles.h
- Add VulkanDescriptorSetLayout to VulkanHandles.h
- Add "input" descriptor set types to VulkanUtility.h. These are
structs that will be defined in the backend API (shared across
all backends) and eventually passed from the front-end to the
vk backend.
- Logic to parse descriptor set layout from the spirv-v shaders.
- Move UsageFlags type to VulkanUtility.h
- Just prep work. No effect to current implementations.
We were calculating the shadow visibility of spot/point lights. The
visibility was calculated during the "execute" phase of the FrameGraph
but it was used/needed during the setup phase. The result was that
the visibility was always delayed by one frame (really it was stale
data from the previous calculation).
We are now computing the shadow visibility earlier, during the
setup phase. This is also better because we can now skip culling
of these shadow maps entirely if we know they're not visible.
Fixes#7715
going forward we want to be able to throw exceptions from the backend
at the very least, we need to be consistant, currently we are
potentially throwing exceptions from `noexcept` places.
this changes makes it possible to throw exceptions from the backend,
during handle construction and conversion to pointers, which wasn't
allowed before.
We still can't throw from dtors because it's generally a bad idea,
better abort in that case.
Replace the num_views for OpenGL multiviwe only when
- The engine is initialized with multiview stereo
- The variant for the material contains STE flag
- The program is for surface
- It's vertex shader (this is already in)
For OpenGL multiview, it honors the qualifier `layout(num_views = X)`
specified in shader files to determine the number of views for
multiview.
We cannot recompile materials everytime the value changes. So replace
the value of num_views with the engine's eye count when shaders compile.
This PR adds a new `pause()` option to the `Engine` `Builder` and a new function
`setPaused()` to the `Engine`. While paused, the rendering thread will pause
indefinitely for commands as if none are available. As soon as the rendering
thread is unpaused, the commands are immediately executed.
in case the swapchain creation fails, it will now return a swapchain
with an EGL_NO_SURFACE handle. this will avoid having to nullptr check
the pointer in various places and will revert to the previous behavior
on failure.
FIXES=[329659681]
We verify that the buffer given to setImage() is at least as large
as needed for the given region to transfer; at least based on the
size given.
This might help catch b/330407429.
BUGS=330407429
This is due to color attachments being set to store=discard when
they are multi-sampled. It's unclear why that condition exists. For
now, removing it will fix the rendering issues with transparent
object + MSAA. We'll keep it as such until an issue surfaces.
Fixes#7674
- dynamic (default) no restriction apply
- static bounds: bounds and world transform can't be changed
- static: additionaly morphing/skinning and vertex/index buffers are
immutable.
This will allow some optimizations in the future. Currently, we just
store the type but don't do anything with it.
Plumb through multiview configurations to the pipeline so that the
engine draws scenes using multiview extension. Users need to prepare
shaders compiled with the `multiview` param and set the
`stereoscopicType` flag to MULTIVIEW in the Engine::Config to enable
multiview feature.
In this change, postprocessings for multiview are not yet supported. So
we all disable them until they're supported.
The debug option `combineMultiviewImages` combines layers as one image,
which allows us to check the final result.
- TangentsJobExtended extracts data from cgltf accessor and
runs geometry::TangentSpaceMesh on the attributes and computes
the tangent space.
- The /extended folder is meant for running this process. Note that
this API might remesh the input and will require corresponding
changes that might break previous assumptions.
- The general flow of the code is modeled after src/TangentsJob.h
- This is not hooked into current code and should have no
practical effect on gltfio.
This new parameter indicates whether the render target will be created
for multiview.
If the value is greater than 1, it tells the render target should be
created for multiview. Otherwise, 1 or 0, it creates a single layer
render target.
Instead of holding pointers to class instances in VulkanDriver,
we standardize by making the relevant classes have proper
constructors and initialize in VulkanDriver's constructor
initializer list.
- `isSwapChainProtected()` is now virtual
- `createDefaultRenderTarget()` is renamed to `getDefaultFramebufferObject()`
- new `getCurrentContextType()` returns the current context type
- `makeCurrent` now takes an additional `ContextType`
- `PlatformEGL::getContextForType()` to retrieve the `EGLContext` for
a given type.
- `PlatformEGL::makeCurrent` non-virtual utilities to set only the
context or swapchains.
For reasons unknown, after upgrading to XCode 15.3, dlopen can
no longer find libvulkan.1.dylib. We fix it by explicitly adding
/usr/local/lib to rpath for macos.
PipelineState now holds a handle to a HwVertexBufferInfo.
DriverAPI::draw() is now technically deprecated and replaced by the
more efficient draw2(), which only takes an index offset, index count
and instance count. The Pipeline to use is now specified with a new
API bindPipeline() and the primitive to use with bindRenderPrimitive().
This allows clients to reuse RenderPrimitives and ultimately Pipelines.
This change reduces CPU usage significantly on Metal and Vulkan, by
reducing the need to lookup for a pipeline at every draw call.
The application, however, must be a "good citizen" by reusing
MaterialInstance and RenderPrimitive as much as possible. We do have
RenderPrimitive cache however, so reusing the same VertexBuffer and
associated parameters also works.
Some default materials such as defaultMaterial and skybox have discrete
material file for feature level 0.
Combine these materials as one utilizing the `-P` option of matc.
This adds a new material property (float postLightingMixFactor) which
is used to mix the original color with the post-lighting blended color.
The default value is 1.0, which keeps the current behavior.
FIXES=[328498606]
cmgen mirrors environment maps by default so that the reflection map
appears un-mirrored. IBLPrefilter didn't do that.
EquirectangularToCubemap now takes a Config parameter that allows to
specify the mirroring, which is enabled by default.
FIXES=[320856413]
Protected contexts are now supported by the OpenGLPlatform interface
and implemented in EGLPlatform.
Protected contexts can read from regular and protected resources but
can only write to protected resources (e.g. protected swap chains or
textures backed by protected memory. These can be created on Android
via AHardwareBuffer and EGLImage for instance).
The underlaying EGL implementation must support protected contexts.
Switching to a protected context is achieved by using a
protected-content SwapChain in Renderer::beginFrame().
A protected-content SwapChain can be created using the new
CONFIG_PROTECTED_CONTENT flag at creation time.
The OpenGL backend implementation will then use a protected context for
rendering until an unprotected SwapChain is used again.
The crux of this implementation is to use different VAOs in
the different contexts, because those can't be shared between contexts.
We also need to synchronize the state with our state cache and ensure
VAOs objects are destructed properly in the right context.
* Add new parameter -P for matc
This new matc parameter `-P` or `--material-parameter` allows users to
set material properties to the specified value.
Values passed through this matc parameters have the highest priorities.
I.e., they overwrite material properties specified in the material file.
Previously the cache would try to keep its size below a user-settable
value. This was not effective because when that value was too small,
it would cause a lot of churn every frame without actually keeping
the memory usage below the specified value.
We now evict buffer aggressively after they've not been used
(for two frames by default), but we don't cap the size of the cache.
The cache will naturally settle at the size it needs. When dynamic
resolution is used, it might be needed to increase resources
maximum age, which is a user-settable value still.
This improves performance on mobile on many scenes because the 64MB
default value was too low, causing the crash to thrash.
The validation error triggers on hellotriangle using AMD (desktop), QCOM (mobile) and Mali (mobile) GPU.
Before this MR, only a single semaphore object was used to synchronize all the calls to vkAcquireNextImage (signal) and vkQueueSubmit (wait).
The issue is that by the time vkQueueSubmit returns, the semaphore is not necessarily reset.
When multiple frames are in flight, the next call to vkAcquireNextImage might try to reuse the semaphore while it is still in the wait status.
The semaphore is reset at a driver/hardware-dependent timing that's likely to be linked to the GPU queue execution.
The solution proposed by this MR is to use a pool of semaphores big enough to cover all possible queue submissions.
Previous commit [1] changed the semantic of the index to
mBufferObjects. Here we just make sure that if a buffer has been
allocated, we don't allocate another (otherwise, we'd leak).
Also cleaned up `updateBoneIndicesAndWeights` indexing
[1]: a3131a64b6
- Add cache for ds layouts and ds
- Abstract descriptors API into VulkanDescriptorSetManager
- Note that this is just a draft and not hooked into the current
implementation.
- better naming
- TimerQueryFactory doesn't depend on OpenGLDriver anymore,
only a OpenGLContext.
- timer query factory is now owned by and accessed through OpenGLDriver
- we can't temporarily store a negative number
in the query shared state, because it now indicates an error.
This is supported only by the PlatformEGL currently. There is not much
that can be done with it either at this point. A protected swapchain is
one that can only be written by a protected context, however, there
is currently no way to create such context.
This is currently only implemented in the GLES backend and simply
exposes GL_EXT_protected_textures. There is not much that can be done
with this yet. Protected textures can't be read nor written at the
moment.
* Add a new material param, stereoscopicType
This new parameter allows us to specify which implementation of
stereoscopic rendering Filament uses for the material.
This change just includes material parameter addition and shader code
changes, so it doesn't affect the current rendering behavior.
These changes will follow as separate commits.
- render pipeline changes
- material parameter override via matc parameter
- material document update
We're going to add a new implementation of stereoscopic rendering using
multiview. Thus we want to remove the word `Instanced` from all methods
and properties.
This shader takes an array texture and a layer index to draw to the
current render target.
This will be used for debugging purpose to combine an array texture
rendered from the multiview feature that is going to be implemented
later, so that we can verify the feature properly performed.
When shader compilation happens in threadpool mode, shader source code
isn't stored correctly in the token. This leads to empty error messages
if a shader has problems later on.
- added many precondition checks and asserts to VertexBuffer creation
- simplified code in VertexBuffer as well
- enforce BONE_INDICES to integer when specified by user since that's
what shaders expect.
- better comments about *always* setting BONE_INDICES to integer
- some code simplification in RenderPass + some comments about skinning
- in the GL backend we no longer set the vertex buffer objects at
renderprimitive creation time, because they might not be available
yet. Instead, we let the natural age mechanism update them next
time it's needed. This allows us to add some asserts about the
declared buffer being present
We do this to better match Gl, Vulkan and Metal, which don't need
to specify the scissor in the pipeline. In practice, this will also
allow us to set the scissor less often, saving a bit of CPU.
These are missing parts from the commit
111ad96134.
NDK 26.1.10909125 is used by default
Minimum API level on Android is now API 21 instead of API 19. This allows the use of OpenGL ES 3.1
Throw an NSException when a program fails to compile and then is used for drawing; this helps aid debugging compiler errors in production, where stdout logs are not available.
The OOB would happen is the scene never had any renderables, in that
case the scene's SoA would stay unallocated, but the summedAreaTable
code relies on it have at least a capacity of 1.
It was incorrect to skip the RenderPass entirely because it might have
had some custom commands that needed to be executed (e.g. for applying
post-processing in subpass mode).
This new backend object holds the information needed to create the
pipeline on vulkan/metal relative to draw calls.
It is used to create HwVertexBuffer.
* Add OpenGL extension for multiview
This extension is going to be used for multiview implementation in
OpenGL.
Now the API isStereoSupported takes a stereo type as a parameter.
HwRenderPrimitive doesn't need to know about the index offset and
index count, these parameters are only needed when drawing. draw()
is updated consequently.
This is a first step towards being able to lower the overhead of
draw similar draw calls.
A side effect of this is that the HwRenderPrimitiveFactory now will
cache buffers regardless of their index count & offset.
This reduces resource utilisation for Views that never need shadows.
It saves a UBO, two Entities and about 10KB memory. We also lazily
allocate the debugging DataSource, which saves about 10K per View
in debug builds.
Overall this change makes "simple" Views less than 4KB heavy down from
about 24KB (debug, 14KB release).
The main changes:
- ShadowMapManager is now allocated lazily
- the ShadowMap cache object is also allocated lazily
- debug DataSource is allocated lazily
- ShadowMaps are prepared/initialized with a Builder, which makes it
clearer that some APIs are only for preparing the ShadowMap cache.
- each handle now has a 4-bits "age", meaning that handles are recycled
only after 16 alloc/free cycles.
This is used to detect double-free and use-after free.
This should also allow us to compare handles, because freeing and
reallocating an object, won't produce the same Handle (at least
for 16 rounds).
- removed "type safety" checks because it's almost impossible to
get it wrong thanks to our compile time type safety checks. This
didn't provide a useful value added.
- This feature is built on top of being able to set/get a 8 bits tag
associated with the memory block returned by the pool allocator. We
use the "extra" parameter of the allocator to allocate a "hidden"
structure containing the age of that memory block.
- Also we don't allow to compare Handle<> of different types
- update the pools sizes for metal and vulkan, which were very outdated.
- add debug code on all backends to print the size of each handle
(with a compile time switch)
The most important change is that now the 3 pools of HandleAllocator
are sized so that each can accommodate about the same amount of handles.
This makes it easier to reason about. The total amount of handles is
three times that, since there are 3 pools.
We also try to allocate the buckets so that handles are evenly
distributed, however, that's very hand wavy.
With the current setup the number of handles per pool is as follows:
- GL : 3240 / pool / MiB
- VK : 1820 / pool / MiB
- MTL: 1310 / pool / MiB
* Automatically flush CommandStream
When generating commands, we now automatically flush the CommandStream,
so that we're guaranteed to not overrun the circular buffer.
* clenaup CircularBuffer implementation and API
Also fix a bug in DEBUG mode that could corrupt the CircularBuffer, it
was due to a wrong debugging code attempting to clear the unused
area of the buffer (this was wrong because in "ashmem" mode, there are
no guaranteed unused areas).
* Fix a couple threading vs. allocations
- prepareVisibleLights was run on a dedicated thread (via JobSystem),
but was using its own local ArenaScope. This is wrong because it
could reset the root arena at any later point. This is fixed by
just not using a local ArenaScope.
- related to the above, the root Arena (LinearAllocatorArena) didn't
use a locked policy, which cause also cause problems since some
allocations are done off the main thread. We now pre-allocate the one
buffer we need.
This PR also renames some variable and types to improve readability.
* Rework RenderPass to improve allocations and API
RenderPass now is a fully immutable object that gets constructed with a
RenderPassBuilder. RenderPassBuilder can be passed around and doesn't
do any (major) allocations.
All RenderPass allocations and heavy lifting is done in
RenderPassBuilder::Build().
Additionally, RenderPass cannot be copied anymore.
Where allocations happen is now much clearer.
* new LinearAllocatorWithFallback
LinearAllocatorWithFallback is a linear allocator that can fall back
to the heap allocator. We use it for the high level command buffer to
avoid crashing when running out of memory.
FIXES=[277115740]
* Update filament/src/RenderPass.h
Co-authored-by: Powei Feng <powei@google.com>
* Update libs/utils/include/utils/Allocator.h
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
- Add methods for adding attributes to the input mesh
- Add method in TangentSpaceMesh for when user provides the
tangents
- Separate client-side Algorithm enum from implementation algorithm
(AlgorithmImpl)
- Fix CMake config for combining static libs
32 sample may be more suited to 2x upsampling, it gives 8 samples per
high-res pixel (instead of 4). This is also what FSR 2.0 is using,
which is useful for comparing.
This has caused issues and over time we have reduced the use of
spinlocks, it was only used in few places and we still have evidence
that it's causing ANRs.
We use utils::Mutex instead which is a low overhead mutex implementation
on Linux systems.
FIXES=[321101014]
it was incorrectly mapping the equirect image to a cubemap due to a
typo in our overload of atan2 which was swapping its parameters.
atan2 is now removed, and we use atan(y,x) instead. Also modified the
code slightly so it matches almost exactly cmgen's.
FIXES=[320856413]
When parsing a lexeme, we use one less byte than it's intended to be for
comparing the current string.
This results in a success in cases like:
- true and truX
- false and falsX
- null and nulX
where X means an arbitrary character.
Fix this by the full intended length.
* Bokeh aspect ratio
new DoF option to set the bokeh aspect ratio, this can be used to
simulate anamorphic lenses
* Update android/filament-android/src/main/java/com/google/android/filament/View.java
Co-authored-by: Powei Feng <powei@google.com>
* Update web/filament-js/filament.d.ts
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
See #7415 for a more detailed description of why this change is necessary.
The remaining variants which are filtered from FL0 materials are all related to
lighting, so further hacks like this won't be necessary.
Future work involves properly supporting differing sets of variants based on
shader language.
both vk and metal don't support depth resolves, and are currently
implemented in the backend. vk is buggy and they don't resolve the
same way that gl does.
* TAA improvements
- fix variance + AABB history clipping (we were computing the union
of both AABB instead of the intersection).
- added a setting for the variance parameter
- added a setting for the jitter pattern
- improved some default values
- fixed a few comments
- smaller code tweaks to facilitate future improvements
This is what the NDK does, it's needed to keep debug infos for the
STL symbols (because the STL is provided by the platform and doesn't
have debug infos).
In practice none of the extensions we would use eglGetProcAddress for
are supported. And we had a case where an extension was reported
supported but eglGetProcAddress didn't return the corresponding
entry point.
update web demos remote ui.
FIXES=[315033914]
We shouldn't remove the listener callbacks when a surface is destroyed
by the system (e.g. screen off/on) because then we won't know when
it comes back.
But we still need to do this when the user calls UiHelper.detach() or
when we are attaching to a new surface.
Fixes#7424
getUserWorldFromWorldMatrix() was always set to identity during the
shadow pass. It needs to be set the the same value as the main
camera.
FIXES=[315504607]
The per-light shadow caster flag wasn't updated when a light was
toggled from casting to non-casting. This resulted in an out of date or
incorrect shadowmap to be used.
FIXES=[315859790]
we make PostProcessMaterial, getPostProcessMaterial() as well as
render(), commitAndRender() public (as in public to filament internals).
These methods have no reason to be private to PostProcessManager.
Imported targets always use the imported flags, not the flags that
where specified when the target was created. The clear flags
should be cleared after they've been used once in case that rendertarget
is reused by multiple passes.
For e.g. if the clear flag is set, the target will be cleared the first
time it is used, but if it's used again, we don't want to clear again,
in that case we'll use the "local" flags used when the target was
created (as opposed to the imported flags).
Material constants (a.k.a: specialization constants) can only be set
during Material creation through Material::Builder.
This change somewhat relaxes that limitation by allowing constants to
be set at runtime on Material directly.
Currently this new API is still private and only supported on FMaterial.
This feature works by invalidating the HwProgram cache of the concerned
Material, causing a shader recompile per variant; so this API is costly
and should be used only for debugging or during app/game configuration.
The TAA material is modified to use constants instead of #defines for
various settings and those are exposed in TaaOptions as well is in
ViewerGui. So with this change all aspects of the TAA material can
be changed at runtime.
This allows to turn off the OpenGL backend (using -DFILAMENT_SUPPORTS_OPENGL=OFF).
Previously, disabling the OpenGL backend was leading to a compilation error related to missing level 0 materials.
Swiftshader runs spirv validation before compilation. However,
the validation does not like having Nop (no-op) in the input.
So we skip instructions instead of writing no-op for the
output of `workaroundSpecConstant`.
Also, fix issue to keep the value in the original shader if a
specialization wasn't provided.
Even if skinning is not fully implemented on FL0, we have clients which depend
on materials with skinning variants that otherwise could easily be converted to
FL0 materials. There are two proper ways to deal with this:
1. Support skinning/morphing in Feature Level 0.
2. Allow ESSL 1.0 code and ESSL 3.0 code to support different sets of variants.
However, the simplest solution is to just include skinning/morphing variants,
but disable codegen for ESSL 1.0 code, making them identical to the base
variants. This shouldn't increase the file size much due to the dictionary
deflation. Of course, skinning will not work correctly on FL0, but this has
always been the case. Future work here would be to properly implement one of the
two solutions described above.
- deprecate blit(), renamed to blitDEPRECATED. It's only used in one
place in copyFrame() now. We can't void it because we don't have
access to the texture from the RenderTarget.
- add a new blit() api that works with textures instead of render
targets.
- add a new resolve() api that works with textures instead of render
targets. doesn't support scaling.
- always use a shader when scaling in the framegraph
(there was only one place where we used blit)
- use the new blit() for:
- for mipmap generation on vk (fixme)
- copying the depth buffer to avoid ssao feedback loop
- use the new resolve() for:
- manually resolving MSAA color/depth
- Simplify the resolve APIs on the filament side
- implement generateMipmaps for the vulkan backend
simplify MetalBlitter
- remove metal blit workarounds
- don't issue a blit from a renderpass, this only affect Renderer::copyFrame
- We only handle a single texture now (instead of color+depth), so we
can simplify the code a lot.
Didn't touch the "slowpath" much, but it now assumes it blits color or
depth, not both.
* on ANGLE we now use a thread pool for parallel shader compilation
in general we now prefer using a thread pool instead of the KHR
extension, because we have less control over how the queue is
managed by the driver.
ANGLE supports many threads very well, so we use cpu_threads/2 for the
pool size, at background priority.
* Update filament/backend/src/opengl/ShaderCompilerService.h
Co-authored-by: Ben Doherty <bendoherty@google.com>
* Update filament/backend/src/opengl/ShaderCompilerService.h
Co-authored-by: Ben Doherty <bendoherty@google.com>
---------
Co-authored-by: Ben Doherty <bendoherty@google.com>
* Add spirv-headers as a separate third_party repo
Previously, we pulled in spirv-headers as part of spirv-tools. We
still keep this behavior but move the content of the repo to
third_party.
We introduce a script for updating spirv-tools, and update the patch
file. The same script will also pull in a dependent spirv-headers.
* better handle invalid programs in release builds
Until now invalid program would basically be undefined behavior,
which in practice was a crash via a null pointer dereference.
With this change, invalid programs cause drawing ops to become no-ops.
Additionally fixed an unsynchronized access of a the variable containing
the program id. I don't think it would have caused issues though.
FIXES=[311775564]
Co-authored-by: Powei Feng <powei@google.com>
We were not unregistering the TextureView or SurfaceHolder callbacks on
detach, so they could fire and access an null'ed RenderSurface
FIXES=[308443790]
The CL introducing the ESSL 1.0 chunk in materials inadvertently disabled
optimizations for said code. This commit reintroduces those optimizations and
fixes associated bugs which manifested. In particular, spirv-cross was
generating uints for bools; this has been fixed with a hack. Additionally,
spirv-cross is now compiled with exceptions enabled so that matc can gracefully
fail and show the code which failed to compile rather than abruptly aborting.
With these fixes failing tests are:
OpenGL:
BackendTest.FeedbackLoops
Metal:
BackendTest.ColorResolve
BackendTest.BufferObjectUpdateWithOffset
BasicStencilBufferTest.StencilBufferMSAA
Vulkan:
Many failures still
Since #7358 is blocked by an upstream spirv-cross issue, we can at least do a
bit of preprocessor optimization for ESSL 1.0 code in the meantime and introduce
the FILAMENT_EFFECTIVE_VERSION preprocessor definitions.
This change in glslang removes the include of "intermediate.h" from
GlslangToSpv.h:
https://github.com/KhronosGroup/glslang/commit/62de186c3383feef067feb6ea578f79977910722
As a result, the definition of "class TIntermediate" is removed, and
will fail compilation of MaterialCompiler.cpp when glslang is updated to
a version including the aforementioned change. We fix this by adding an
explicit include to this header in MaterialCompiler.cpp.
Co-authored-by: Powei Feng <powei@google.com>
- gltfio: Enable -Wall -Werror for gltfio_core
- gltfio: Fix various errors that were missed warnings
- matdbg: switch from std::atomic_uint64_t to
std::atomic<uint64_t> for older clang
* Add Material.compile() Java binding.
* Add Engine.flush() java binding
* Add Scene.forEach java binding
update the Android gltf-viewer sample to precompile all variants of all
materials in the scene, similarly to the desktop sample.
- we were not using the correct field in ShadowMapManager
- we were not computing the transform correctly, it should applied
after the local transform, not before.
FIXES=[299310624]
we recently added calls to Material::compile in gltfio to precompile
materials are they are discovered. that wasn't a good call, because
this should be the responsibility of the app, not of gltfio, at least
not without an option.
This is now done in gltf_viewer. We need something similar for
Android.
Bugs #7318, #7336
Moving setFrontFaceWindingInverted to MaterialInstance will enable
finer control over face inversion and aligns better with Vulkan's
pipeline definition (see VkGraphicsPipelineCreateInfo).
There's no functional change. Remove an unused local variable
`outgoingEdges` to save CPU resource. Tidy up an usage of local variable
to slightly improve readability.
We removed the no-op queue submit for headless in PR #7264. This
means that a semaphore will not be waited on and caused a
validation error. Here, we simply don't acquire that semaphore
for present.
Also reorganzied the pSempaphores array code for better
readability.
Fixes#7334
Drag and dropping a gltf folder was broken:
- the handle didn't find the gltf file on drag&drop
- the ResourceLoader cached the asset path
- don't exit(1) when drag&dropping an invalid file
- Make sure matinfo works by selecting a default backend in the
absence of activeShaders.
- Add options to select backend in matinfo mode.
- Workaround cursor misplacement for monaco
- Refactor menu sections into a common element.
First, this commit introduces some very simple bugfixes regarding ES2
compatibility related to postprocessing.
Second, this commit adds support for creating textures specified as R8, SRGB8,
and SRGB8_A8 in ES2. R8 is trivial: just use GL_LUMINANCE instead. The sRGB
formats, however, are maybe a bit more controversial. As implemented, they
instead just use the equivalent non-sRGB formats. This is of course technically
incorrect. There are a few approaches to how to add sRGB compatibility for ES2
that I can think of.
1. Do a bunch of complex shader nonsense in matc. Maybe even traversing the AST
and ensuring any texture lookup of a texture flagged as sRGB uses some
compatibility function. This would require static analysis to track if samplers
are reassigned to another variable, for example. This of course also breaks down
if you don't know at compile time if the shader will receive an RGB or an sRGB
sampler, or if the shader should be able to support both RGB or sRGB samplers.
Really only worth mentioning here for the sake of completion.
2. You could also generate simple compatibility functions to look up each
sampler, which would only apply to FL0 materials.
First, we would have to extend the material format to be able to explicitly
"color" a sampler as sRGB or not, like:
```
parameters : [
{
type : sampler2d,
name : albedo,
precision : medium,
colorSpace : srgb,
},
{
type : sampler2d,
name : normal,
precision : medium,
colorSpace : linear,
}
],
```
Then, the following GLSL code would be generated.
```glsl
\#if __VERSION__ == 100
vec4 texture_albedo(vec2 position) {
return sRGBtoLinear(texture2D(materialParams_albedo, position));
}
vec4 texture_normal(vec2 position) {
return texture2D(materialParams_albedo, position);
}
\#else
vec4 texture_albedo(vec2 position) {
return texture(materialParams_albedo, position);
}
vec4 texture_normal(vec2 normal) {
return texture(materialParams_normal, position);
}
\#endif
```
Finally, at runtime, if a sampler is "colored" one way or the other, we would
verify that only the appropriate kinds of samplers are bound.
I'm actually very partial to this solution. Since sRGB compatibility is only a
concern on ES2, we can generate this code only for FL0 shaders, which already
require GLSL shader authors to care about ESSL 1.0 compatibility by calling the
appropriate `textureXX` functions. Additionally, it provides a layer of
high-level validation that texture lookups are correct, even if a real ES2
context is not available on the device being tested.
3. Leave it entirely up to the client. (What this commit does.) This leaves
client code ripe for making mistakes, but luckily, we can go back and do
solution 2 whenever. If specifying a color space for a sampler remains optional,
then if this feature is retrofitted in the future, client code will continue to
compile.
Enable a limited subset of materials in PostProcessManager for FL0.
Create new function Material::getFeatureLevel() in C++ and Java.
Create missing Material::getReflectionMode() method in Java.
This change hard-codes writing the post process output at index 0 (i.e. color)
to gl_FragColor when generating ESSL 1.0 shaders. Any other outputs (besides
depth) are discarded with a warning, but as far as I can tell, no such cases yet
exist in Filament.
Fix edge case where an empty struct could be generated in an ESSL 1.0 shader.
Include _maskThreshold and _doubleSided in ESSL 1.0 shaders.
Add GL_OES_standard_derivatives extension to ESSL 1.0 shaders. According to
gpuinfo.org, this has 96% device coverage and supports both Mali-400 and Adreno
(TM) 304.
Remove 3D sampler support from ESSL 1.0 shaders. This extension is only
supported by 62% of devices.
Change filagui material to a FL0 material.
don't use FixedCapacityVector to store pointers to active shadowmaps,
that's just not needed. They're all stored un a static array already
and directional and spot shadows are partitioned.
This saves a couple heap allocations as well a an pointer dereference.
compile_commands.json was being generated, but hidden away inside of the cmake
build directories. This change makes build.sh link it to the main project dir
and adds some associated .gitignore entries. Now compile_commands.json is
properly read when starting clangd from Emacs, for example, and probably many
other editors.
When we enable SSR the first time, the SSR buffer is not initialized,
this can result in the color pass fragment shader aborting, which in
turn prevents the SSR history buffer from being initialized (since
it's made from the result of the color pass), repeating the cycle.
In some other case, the system somehow recovers but we still see a
flicker when enabling SSR.
The solution here is to disable SSR in the shader until the history
buffer is ready (i.e. a frame later).
The reason is that some implementations of WGL require all contexts to
be created on the same thread, which we're not necessarily doing here.
fixes#7078
- only check/log in debug builds
- use epsilon = 2e-7 * double(tempPairCount)
- compute boneWeightsSum in double
- don't modify the weights if they're within the threshold
FIXES=[306565054]
We've seen hangs/ANR that are not well understood on that spinlock, so
for now we're going back to mutexes, which, on android, are very
efficient under low contention (no syscall).
FIXES=[308029108]
This change does three main things. First, it adds an option to the Engine
Builder to pick the feature level at which to instantiate Filament. The only
real practical purpose of allowing this is to be able to instantiate at feature
level 0. Secondly, it allows feature level 0 to properly work on non-ES2
devices. Thirdly, it changes both Android and desktop hellotriangle samples to
explicitly opt-in to feature level 0.
Unfortunately, feature levels are used in two different, somewhat contradictory
ways presently in Filament, which can make reasoning about this change a bit
confusing. From a client perspective, feature levels refer to buckets of
capabilities which are guaranteed to be supported. Internally, there is a
separate "feature level" stored internally at the Driver subclass level which
generally corresponds to the maximum supported feature level, but is also
referenced when activating workarounds for limited devices. For example, Uniform
Buffer Objects are not supported in ES2, however, Filament supports emulating
them such that the client does not need to care at all; a supported feature is a
supported feature. But internally, Filament uses this "Driver" feature level to
determine whether or not a given workaround is needed. There were several cases
where the "active feature level" was being examined in order to activate these
workarounds rather than the "driver feature level", which was incorrect.
Why should non-ES2-only devices want to activate feature level 0? Allowing this
behavior 1. makes feature level 0 more consistent with the behavior of other
feature levels and 2. allows clients a layer of validation that their software
will work on all devices supported by Filament if they explicitly opt into it.
Consistency: Filament guarantees that any given device which supports a given
feature level will also support running on every feature level below, except for
feature level 0. This change removes that exception.
Validation: It's not perfect, and there will likely be bugs and unexpected
differences in behavior between ES2 and non-ES2 devices that crop up in the
future between two devices running on the same feature level. However, it's at
least a basic high level layer of validation that enables more rapid testing
workflows directly via desktop versions of Filament rather than having to fiddle
with something like ANGLE to get perfect GLES 2.0 compliance. Additionally, it
expands options for automated testing (with the same caveats).
This change has been tested on both the desktop and Android versions of
hellotriangle.
* prevent public classes from being created on the stack
- we used to to this by deleting operator delete, but this prevented
the internal "F" classes from being virtual; which can be useful
when using EntityManger::Listener.
now we just make the destructor protected in each class.
- EntityManger::Listener now has a virtual destructor so that
objects could be correctly destroyed from Listener*
* improve EntityManger and Component managers
- all component managers now have the same "base" API
- getComponentCount()
- empty()
- getEntity()
- getEntities()
- Scene now has getEntityCount()
- EntityManager now has getEntityCount()
- all component manager implement gc() the same way, by calling destroy()
- SingleInstanceComponentManager::gc() that calls removeComponent() has
been removed because it's dangerous. removeComponent() is often
not enough, some additional cleanup might be needed.
CameraManager creates a Transform component for each Camera component
is not already present. However, it didn't destroy the transform
component when it's itself destroyed. the leaked transform component
would eventually be garbage collected, but caused significant
slow down and memory pressure. This is because camera components are
created every frame for the shadow maps.
FIXES=[303914944]
- the insert and retrieve handlers can now be set/unset independently.
this could be useful for debugging.
- program caching is disabled if the GL implementation doesn't support it.
- removed unused code
FIXES=[307549547]
- Ensure that waiting on lock times out so that we don't lock
up a thread when the client is gone.
- Add an experimental folder to matdbg/web/ for the new
UI work.
The transient property `mRootNotes` in FAssetLoader is built when a new
root asset is created and referenced whenever a new instance is created.
So it incurs an undefined behavior when a previously created asset tries
creating a new instance after a newly created asset has already created
via the same asset loader.
Move this transient property to each asset so that they can reference it
when a new instance is created.
This partially fixes#7269
There's no functional change in this commit.
Make some parameter names more legible by renaming them and put output
parameters to the right of their function.
The temporary variable has been used to store the current instance of
FFilamentAsset being loaded for easy access from internal methods. This
causes a crash as to a complex scenario as follows.
val asset1 = assetLoader.createAsset(assetBuffer1)
val instance1 = assetLoader.createInstance(asset1)
val asset2 = assetLoader.createAsset(assetBuffer2)
val instance2 = assetLoader.createInstance(asset1)
As the first step of fixing this issue, remove the transient property
`mAsset` from FAssetLoader. This commit alone doesn't resolve the issue,
and more commits are following.
Consolidate the low level version of createInstance, which takes a
pointer to cgltf_data type, into the high level version as the latter
one uses a parameter for FFilamentAsset instead of referencing mAsset.
Update all other relevant methods to take a FFilamentAsset pointer
instead of cgltf_data.
This partially fixes#7269
* debugging PCF mode
This mode always uses a hard PCF and takes a
slightly slower code path.
* dynamic shadowmap visualization
The directional shadowmap visualizer is implemented behind a
specialization constant. Add the DebugRegistry infrastructure to be
able to update the spec-constant at runtime and have a subset of
all materials invalidated.
This allows to toggle the visualization at runtime using a debug
property.
This is also a proof of concept that we can update spec-constants
at runtime; we could probably leverage this work for engine-wide
shader configurations.
* Update main.fs
* Update filament/src/details/Material.cpp
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
- Remove queue submit call when using headless swapchain. It was meant
to emulate a real swapchain, but queue submits are expensive.
- Add option to remove flush and wait when window resizes. If a
headless platform uses this signal to refresh the swapchain, we
don't necessarily need it to also flush and wait before the refresh.
- Refactor VulkanPlatform customizations
- shadows are now stable (in stable mode) when an IBL rotation is
used.
- fix the shadow transform option which didn't work when an IBL rotation
was used
- also use the x-axis as a reference for the "up" direction when
computing the light space matrix so that we don't fall into the
degenerate case when the light points straight down, which is a
common case
FIXES=[299310624]
- Use a hanging-GET approach to reduce dependency on websockets.
- Also add mutex to protect access to MaterialRecords, which is
written to/read from from multiple threads.
The websocket code for parsing the EDIT command is pretty verbose.
Proposing that we move to a HTTP POST request instead.
Also moved the API handler code out of DebugServer.h for clarity.
- reverse the link and original relationship between
docs/viewer/filament-viewer.js and
web/filament-js/filament-viewer.js
- symlink in github pages does not seem to link to outside of the
/doc directory (it does not get pulled in during deploy).
- setProjection and setLensProjection are now less special, they can
now be entirely implemented by the user thanks to two new helper
functions. Everything can now be done with setCustomProjection.
- fix some out-dated comments
- remove dead code
- reorder methods in Camera.h
- Pin lit to version 2.8.0 (to fix a breakage caused by new
release).
- Update viewer filament version to latest
- Use symbolic link instead of having two copies of the same
file. (Could we consider removing `filament-viewer.js` in
`web/filament-js/` ?)
- Update `web/filament-js/README.md`
When we update the Far plane in the projection matrix, we assumed the
shape of the matrix. This fell appart when the projection matrix was
(for instance) a blend between an ortho and perspective projection.
We now do this more generally, that is, with less assumptions on the
projection matrix shape.
- Return the correct SubresourceRange for depth attachments
- Fix transition for when one layout within mulitple mip-levels
is different
- Use implicit layout transition for renderpasses
- Fix access mask for sampler in vertex shaders
- Use unordered_map for VkSubresourceRange in VulkanTexture
This reverts most of commit 9a6b8bf24e. The hello
triangle sample remains unreverted.
The original commit inadvertently broke screen space reflections, and perhaps
other features when the default material was used. The source of the issue is
that MaterialBuilder.cpp (correctly) filters out variants that aren't supported
in feature level 0 materials, including screen space reflections.
Unfortunately, while the "feature level 0 compatibility" feature itself was
intended to make creating duplicate materials like this redundant in client
code, unfortunately, it seems the best solution for resolving this issue is to
simply keep these redundant materials in the core.
To elaborate: clients should expect that feature level 0 materials that they
create work on /all/ feature levels /exactly/ or /close to exactly/ identically.
This includes restricting more advanced features that theoretically could be
available on a higher feature level, like SSR. It's already true that if a user
would like to optionally opt-in to a more advanced material which takes
advantage of more advanced features, they would have to maintain two separate
versions of that material: one for feature level 3 and one for feature level 1.
It should be no different in this case.
However, the materials built into the engine core are an exception to this
expectation. Given that feature level 0 was tacked on after the fact with fewer
features, there must /by necessity/ have been a new material introduced for both
the default material and the default skybox specifically for feature level 0
with fewer features than extant client apps expected to be included by default.
I imagine if filament were to be rebuilt from the ground up, this exception
wouldn't exist. However, the end result is this somewhat messy redundancy.
Instead of a hard cutoff, we fade shadows out at
the shadowFar distance if active, fading occurs
over about 10% of the shadowFar distance.
- this works only for the directional shadow
(other lights don't use shadowFar).
these materials would not generate proper structure or shadow buffer,
because they used a special variant that in most case removed the
user code.
now when the user code writes the depth or calls discard, the user
shader is kept.
- fix IDE warnings
- rename ASTUtils to ASTHelpers to match filename
- break dependency of ASTHelper on GLSLTools
- break dependency of GLSLTools on MaterialInfo
Previously, when a material was expilicitly built for feature level 0, it was
necessary to write ESSL 1.0 code which was incompatible with the OpenGL feature
level 1 implementation in Filament. Rather than adjust the Filament
implementation so that feature level 1 uses the same workarounds as feature
level 0 to emulate GLES 3.0+ features, it's more runtime-efficient to have matc
embed ESSL 1.0 and 3.0 shaders as separate chunks and load the corresponding
one based on the active feature level.
Feature level 0 material shaders must still be written in what is effectively
ESSL 1.0. To assist with this, a small set of compatibility definitions are
introduced when building the ESSL 3.0 variant. These are virtually all
textureXXX() functions, and end up either optimized out or inlined by glslang.
One final effect of this change is that external and 3D samplers are now
properly supported in feature level 0 materials.
This informs a broad variety of text editors of some of the formatting
conventions of the filament project. It may be possible to replicate some of the
more specific formatting conventions like brace placement in a future commit.
all textures declared in a shader must be bound, in the case of the
new skinning API, if less than 4 bone weights are used the texture is
not needed, but it must still be bound.
* Add skinning and morphing samples to check functionality
* Implement skinning for more than four bones pair vertex
The API allows defining an unlimited number of bone indices and weights of primitives. Data is defined in building process of the renderable manager. Backward compatibility with the original solution.
Skinning of vertices is calculated on GPU, data is transferred to the vertex shader in the texture.
To reduce CPU on draw(), we move the VertexBuffer related metadata
out of draw into a cache. We store the cache info outside of the
actual VulkanVertexBuffer class since VulkanVertexBuffer subclass
HwVertexBuffer, which is a Handle meant to be minimal.
This means that we need to cache on the heap, but it should be ok
since the caching is only for scene set-up and not per-frame.
The latest macOS toolchain triggers warnings for duplicate libraries at
link time. This is caused by our dependency chains.
Also remove an inlining warning in Kotlin and unnecessary warnings in
build.sh when doing a clean or generating web docs.
Functionally this shouldn't be too different, but we have some
improvements:
- better detection of "no shadows" cases
- more computations done in light-space, which should result in
better light frustum.
- spit the code into several static functions
This features didn't work well, had a lot of artifacts and generally
wasn't very useful. This kind of effect should be accomplished
differently.
This is an API break because BloomOptions::anamorphism has been removed.
- add a quality option
- remove the ping-pong code, we'll disable for GPU that don't work
instead.
- improve quality by doing a better first downscale
(using a 5x5 gaussian).
- improve performance by using a 9 tap filter instead of 13 for
in most cases
- fix usages of setMinMaxLevels as it resets the base level to "min"
We allocate all the fences beforehand to reduce calls to
vkCreateFence.
Also remove blocking code in `getFenceStatus` since there is
not a usecase that would require that.
We were calling vkFreeCommandBuffers directly, but resetting
the buffers implicitly (when vkBeginCommandBuffer is called)
seems to be a lot more performant.
Also, cleaned up destructor for VkBuffer to no longer require
a separate terminate() method.
This is admittedly a very nitpicky change.
For most of the changes, I went through the various Markdown files and added
language names to the source blocks for better syntax highlighting on GitHub. It
also makes it easier to copy and paste commands without copying the leading `$`.
I avoided changing anything in `third_party`.
Additionally, I added some instructions for compiling the Android samples on the
command line and fixed some typos.
- use the geometric normal to apply the shadow bias. This affects
cascades > 0 and spot/point lights.
- use the scene's origin as a reference point for stabilizing the
shadowmap, this is more robust.
- clamp directional shadowmap correctly to the 1-texel border, which
needs to be reachable, as it is a valid value.
- don't snap the shadowmap to texel boundaries if stable mode is not
active (before we only didn't do it based on lispsm). Stable mode can
make the shadow unstable when both the camera and the scene move
together, so it's better to have a more predictable API where
"stable" mode means that the snapping occurs and doesn't otherwise.
- add "far origin" distance slider to the debug ui
FIXES=[299310624]
in stable mode the scale was ever so slightly varying with the
camera position, because it was calculated from the camera frustum in
world-space, this variation was amplified when the camera is far from
the origin, which eventually caused the modulo needed for snapping the
shadowmap projection to widely vary, leading to the instability.
We now calculate the camera frustum sphere in view space, which is
guaranteed to be constant. If "shadow caster mode" is chosen, we
quantize the scale a little bit so it stays constant.
The snapping code itself has been cleaned.
We wrote a bool directly into 4 bytes (as the first byte). This has two issues:
- the other 3 bytes are not initialized
- should be writing VK_TRUE/FALSE instead
* Don't force masked blending for transmission/volume materials
glTF lets you choose your own alpha mode when using the transmission
and volume material extensions. We were forcing the masked mode which
was incorrect, except to pass the standard tests.
* Update release notes
* Properly apply emissive to masked materials
The emissive property should not be multiplied by the color alpha
in masked materials. The alpha is treated as a coverage value in
that case, not an opacity value.
* Update release notes
This reverts commit 58f96be2c4.
This caused material files to increase in size significantly. It turns
out that glslang has to generate a copy for each parameter that is
passed to a function as a non-const parameter.
This revert will break IMG devices again, but that should be the case
only on debug builds. Release builds lose the const qualifier by
virtue of going through spirv. We'll try to address this some other
way later.
- separate out the settings for bloom, ssao and ssr
- update webgl binaries
- change default bloom resolution to 384 from 360 to have up to 7
mipmap levels vertically
- don't rely on it being 32-bits
- update the jni code to store SamplerParams in a long (64 bits)
instead of a int. This gives us some future-proofing of the java side.
* rework how we initialize the gl context
- early initialization is now implemented with static methods so that
it's very clear which state they need.
- the version number is no longer used outside of initialization,
instead we use the feature level.
- ES3.0 Adreno devices are downgraded to feature level 0
* Update filament/backend/src/opengl/OpenGLContext.cpp
Co-authored-by: Powei Feng <powei@google.com>
---------
Co-authored-by: Powei Feng <powei@google.com>
CompilerThreadPool:
- it now supports a thread cleanup function
- some initialization is moved to the setup function
OpenGLPlatform:
- now cleans-up the thread pool threads upon exit
readPixels requests staging memory to be host-visible/coherent/cached.
But "cached" is not supported on Mali (Pixel 6pro). We make it a
preferrable but optional bit.
turns out that KHR_surfaceless_context is implied for ES3.0 when
KHR_create_context is present. However, Adreno 306 fails even if
it advertises it. So, we now reset the value of KHR_surfaceless_context
based on actually calling eglMakeCurrent(EGL_NO_SURFACE).
- remove support for non-shared contextes parallel compilation.
this wasn't used. we can always revive it later if we need to.
- rework how callbacks work so that we don't have to use a work list
executed at each tick() in the shared context case (common case).
this improves performance significantly on low-end devices, by
not having to go through the list to check if all programs are
compiled, multiple times per frame.
The new CallbackManager handles scheduling the callbacks after all
previous programs are compiled.
The only use of this API was with a timeout 0 to check the fence
status. Timeouts other than zero could be very dangerous and since we're
not using that feature for now, we just get rid of it.
wait() is replaced with getFenceStatus(). It is currently only used by
the FrameSkipper.
This is not a public API.
This is more appropriate (and simple) than runEveryNowAndThen because
the later doesn't manage a fence, and therefore is more of a superset.
This will allow us to use a shared context implementation in the future.
This is technically forbidden by the GLES 3.x specification but many
GPU support it, which saves us a depth buffer copy.
Note that this is supported in GL desktop.
Destroying the FBO target of a blit operation causes a stall similar
to calling glFnish().
We workaround this by delaying all FBO destructions to after the
GPU is finished with the current frame.
In some situation, functions with const parameter cause the shader
compilation to fail without an error message.
We remove all the `const` qualifiers on functions, assuming this
shouldn't impact code generation a lot.
instead of moving the "urgent" compilation to the head of the queue,
we simply remove it from the queue and process it immediately. This
has the benefit that on drivers that truly support parallel compilation,
the latency will be reduced as we don't need to wait for the current
compile to finish.
* add a GLES compiler unit test
* Update filament/test/compiler_test.cpp
Co-authored-by: Ben Doherty <bendoherty@google.com>
---------
Co-authored-by: Ben Doherty <bendoherty@google.com>
Previously, we have a VulkanSync with a default constructor that
allows us to have sync objects that returns error when
actual fences are not yet present. We need to replicate that
with VulkanFence since sync objects have been removed from the
API.
Fixes#7034
We were breaking the promise of pending shader compilation jobs by
destroying the corresponding std::promise embedded in the job queue.
In practice there was no danger of a deadlock by construction, but
std::promise throws an exception in that case. On builds without
exception enabled, this we be turned into an abort().
We fix this by using our own mechanism for signaling instead of
std::promise. This ends up be more lightweight anyways.
Fix: #6933
We don't need to convert the object id to float,
instead we can just "reinterpret_cast" it.
With the current possible values of Entities, there was a risk of
overflow once the age gets to 128 (very rare).
The crashes are triggered by spirv-opt's MergeReturnPass, so we
just disable it. This pass also caused issues with AMD drivers on macOS.
fixes b/291140208
We get rid of the backend's HwSync object because on all platforms
but GL it was implemented just like a HwFence. We now use HwFence
instead.
On GL platforms though, HwFence doesn't exist natively it is instead
provided by the Platform. In that case, we emulate it as with GLSync
objects -- the emulation incurs some latency that can cause frames
to be skipped.
On Android and platforms that provide the Fence functionality, there is
no such issue.
This change improves significantly frame pacing on Android.
The frame latency specified was off-by-one, i.e. a value of 1 meant a
latency of 2. The default was 2, which meant 3. Also it wasn't possible
to specify the max latency of 4, which would OOB.
When the engine is shut down, it's possible for some parallel
compilation jobs (and callbacks) to be queued. We need to make sure
to clear the queues and call the callbacks before destroying the
parallel compilation service.
Fixes b/290388359
We were waiting for programs from both queues to be compiled before
calling the callback associated with one queue. In practice this caused
the callback associated with high priority programs to be called only
after low priority programs were ready.
Also cleanup-up "token" so that it doesn't store the priority.
Update the documentation and sample to better reflect what the
implementation does.
This PR sets up the ability for shaders to use `gl_ClipDistance`, which will be needed in the future. Desktop GL supports this natively. OpenGL ES requires the EXT_clip_cull_distance extension.
Unfortunately glslang does not support this extension, so we have to employ a workaround for mobile when going through glslang. We instead write to `filament_gl_ClipDistance`, and then modify the SPIR-V to decorate this as `gl_ClipDistance`. See the comment in SpirvFixup.h.
Note this PR does not actually use `gl_ClipDistance` yet, so there should be no change to shaders.
- Carry out readPixels without blocking and wait for the read to
complete own a separate thread.
- Add mContext.commands->wait() in finish()
- Wait for readPixels to complete in finish()
- Remove unused commandBuffer in Context
- Before, we supposed that the maximum number of input attachment
should match the maximum number of color attachments. But in
reality, we've only used one input attachment for the second
subpass.
- The problem with the above supposition is that the descriptor
set layout for the input attachment descriptor set must have the
exact number of input attachment specified in the shader. If the
*layout* has more input attachment slots than specified in the
shader, then we'd run into a validation error.
- In this patch, we fix the number of max input attachment in
the descriptor set layout to 1, since we ever only make use of
one.
Fixes#6513
The work queue is sorted by priority but when we insert a notification
job we didn't have a priority to use for insertion, in addition the
priority was taken from the token, but for the notification job we don't
have a token.
The fix consists in passing the priority around so we have it when needed.
The scene graph was using the wrong boolean to decide whether to fallback
to low quality upscaling when the render target is translucent. It was
instead only looking at the view's blending mode. We need to check both,
as color grading does in the same function.
- Use of getter method instead of property access syntax (for getInstance)
- 'rangeTo' or the '..' call should be replaced with 'until' (in for)
Co-authored-by: jeongth9446 <taehuniy@gmail.com>
when using the thread pool we were destroying the shaders immediately,
we need to defer this until we query the program link status, so that
in case of failure we can query each shader compile status.
we make the shader handles part of the promise/future so they can be
transferred to the main thread, just like the program id is.
vkCmdEndDebugUtilsLabelEXT expects that a label was "pushed" onto
the command queue (as described in the spec). It is possible to push
labels across command buffers, but the pushed label must still be in
the queue (unexecuted) when End is called. This implies that we need
to make sure the labels are in a good state (all popped) when
vkQueueSubmit is called.
- We add a stack to carry the labels across vkQueueSubmit.
- Also add CPU time durations between push and pop to provide rough
CPU execution times (in debug).
- Add systrace markers for Android systrace
- Validation failing due to incorrect layout wrt Blitter
render pass.
- Clear colors are also not needed for blitter renderpass.
- SAMPLEABLE + DEPTH_ATTACHMENT needs to have the correct layout.
- Timer query stashed a pointer to VulkanCommandBuffer, but this
points to an object that can be reused.
- We use the shared_ptr'd fence object instead to track whether
the query request has been completed.
It supports KHR_parallel_shader_compile as well as a
thread pool of GL contexts.
- we have a new 2-priorities queue for shader compilation
- use this feature in gltfio in the ubershader case
There was two related issues:
- we need to "latch" the new TextureView size when its resized. That
can only be done by recreating the EGLSurface (i.e. recreating the
SwapChain). UiHelper now calls onNativeWindowChanged in the case of
the TextureView resize, so clients can recreate their SwapChain.
- we also needed to make sure that all current filament frames have
finished to render (i.e. the last eglSwapBuffers has been called) so
that they don't pick-up a new size (this happens after
eglSwapBuffers) that doesn't match the viewport.
Fixes b/282220665
this is needed on armv7 because we use alignas to get strcture-alignment,
but that also implies (to the compiler) that the structure itself
is aligned properly.
the math needs to be maintained in highp, including during the blur
pass.
we add the ability to specify a "precision" qualifier to the "output"
of a post-process material.
we also remove the mediump clamping we used to do on mobile, it shouldn't
be done automatically behind the scenes, it's up to the shaders to do
it if it makes sense.
- flush() and wait() before destroying a swapchain
- Make sure the debug marker extension is enabled under correct
circumstances.
- Change shared_ptrs to unique_ptrs and raw pointers.
- Rename most teardown methods to terminate()
- Introduce new custom swapchain API for VulkanPlatform.h
- Implement the API for the base VulkanPlatform by refactoring
the existing swapchain code.
- VulkanSwapChain is now a wrapper for VulkanPlatform's
swap chain API.
- Actual implementation is in
vulkan/platform/VulkanPlatformSwapChainImpl.{h,cpp}
this is implemented by here by using the skybox texture and blurring it
with the irradiance filter + mipmapping. This only creates a subtle
anisotropic phase-function effect.
- we must sort commmands *after* we have added all commands!
- custom commands could change the UBO/Sampler bindings so we need
to make sure to invalidate them after executing the command.
When sampling the fog color from the IBL we need to take into account
the IBL transform. This broke recently when the for calculation was
moved in user world coordinates.
* froxelizer doesn't use textures anymore
All data is stored in UBOs.
Additionally, the buffer size is no longer hardcoded at compile time.
This CL cuts in half the numbers of froxels to accommodate devices
limited to 16KiB,
* Use a specialization constant to adjust the size of froxel UBO
This really only affects OpenGL in practice because metal supports 256MB
minimum and only 3% of android devices support less than 32K, which is
what we need.
- Passing filename.bin to --sh-output generates a file containing the SH
as binary floats in native endianness (LE on x86 and arm64)
- Fix --sh-output so it works properly with -x
- Cleanup variable names to avoid shadowing
We need to keep the context handles as part of the platform
class so that we can implement the new swapchain API based
on them.
- Move creation of "context" handles from Context to Platform
- VulkanContext contains immutable data
- Change constructor of classes that depended on VulkanContext
- Move timer query logic from VulkanDriver to VulkanTimerQuery
and VulkanTimestamps
Fog can now be opted-out on a per renderable basis. When fog is disabled
on a renderable it removes the requirement that this renderable's
materials have the FOG variant.
This works by making the fog an entity which can be used to create
a TransformManager component an participate to the transform hierarchy.
This feature can be used as more advanced way to set the fog's floor,
which now can have an orientation (essentially be a plane).
This is useful for coordinate systems that are not y-up.
Material::compile() can be used to asynchronously ask the backend to
compile a subset of the variants of a Material and be notified when
done. This can be used during initialization to avoid hiccups later.
This will also force caching of those material programs if the
Platform provides the blob cache API.
This doesn't add or remove functionality, but merely changes the API
to create an Engine, to be more consistant with how we construct other
objects in filament.
You can now use Engine::Builder to construct an Engine.
By default ancillary buffers are discarded on commit (eg. depth buffer),
but in certain situations the platform may want to preserve them. this
new virtual allows a concrete implementation to specify which buffers
need to be preserved.
Note that in ES2 mode, the depth value returned by the picking API
only has 8-bits precision and incurs a bigger performance penalty,
because glReadPixels is synchronous.
This is only the first step where we:
- clean-up some code to prepare for 2nd step
- add support for the linear->srgb in the shaders
The linear->srgb conversion is protected by a
specification constant and will be enabled only
if the corresponding EGL extension in not present.
Then, if enabled, the actual conversion is
controlled by a uniform so that it can be
selectively enabled on swapchains that have it
turned on.
In this change, the emulation logic that sets
these gates is not implemented (that's step 2).
This CL contains two parts:
- changes to matc/filamat
- changes to filament itself
Filamat can now generate ES2 compatible shaders. Only the unlit variant
is supported. Fog and picking are supported as well.
post-processing, skinning, instancing, all lighting and shadowing are not supported.
Filament is updated to not issue commands that are not supported in ES2.
Addtionnally, the hello-triangle sample is updated to work on an ES2 device.
From the backend's point of view, UBOs are emulated with uniforms.
The backend will maintain a data structure that maps an offset into
the UBO to a uniform and will do the appropriate glUniform* calls
at the right time and if needed (e.g. only if the UBO content has
changed).
The mapping from an UBO content to uniforms is passed to Program
upon creation.
This first round is mostly about making the backend compile with the
ES2 header only and use the ES2 code path when running on an ES2
context. We also add feature level 0, which corresponds to ES2
devices.
We introduce the macro FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2, which is
exclusively used to compile-out code that cannot compile with ES2
headers. This macro is active when ES2 headers are used.
There is also a new `OpenGLContext::isES2()` method that is returns
whether we're running an ES2 context, either statically (desktop, ios)
or dynamically (mobile).
This PR should add or remove any functionality.
A material global is a variable seen by all materials. There are 4 such
variable which are all vec4 and they can be set on a per-view basis.
All materials used during Renderer::render() will see the same value.
These variable can be accessed in the materials by using
getMaterialGloabal{0|1|2|3}.
* vulkan: Fix Adreno issue with optimized material
Turning off the simplification pass seems to remove all of the
artifacts associated with Adreno GPUs.
- `-g` option was missing from `build.sh`
- `-Pcom.google.android.filament.matnopt` should be passed to
the sample apps as well.
- Add logic to respect `-Pcom.google.android.filament.matnopt`
in `FilamentPlugin.groovy`
They're not hardcoded in a database inside MaterialBuilder and are
generated. This will be needed later for ES2 support.
We could actually imagine something more dynamic in the future too.
- Moved most of the layout transition logic into VulkanImageUtil
so that we'd have a single place to consider if failure arises
- Add an abstraction on top of vk's layouts so that reasoning
about our use cases (and corresponding layout is easier).
- Removed the redundant VulkanDepthLayout
- Refactor VulkanTexture::transitionLayout so that most of the
transition paths can be done through this entry point. It also
enables us to handle tracking the current layout.
- Add a special case to transition the depth attachment/texture
if it is both a sampler and an attachment.
- Add a few debug printing markers across the classe - guarded
under the existing FILAMENT_VULKAN_VERBOSE define.
- refactor the code so that all defines are generated in the same place
- generate common_type after all defines are generated
- protect (with defines) structures and UBOs that are not needed, based
on the variant
* Support the external image on macOS
Implement CocoaExternalImage.
* Fix to take an onwership of the external image
* Correct incorrect comments
* Rename a function explicitly
Make a function name to know copying RECTANGLE to TEXTURE2D.
* Do lazy initialization
Create CocoaExternalImage::SharedGl when it's needed.
* Fix a crash when engine is terminated
Destroy the external image shared gl before gl context is destroyed.
* Remove an useless variable
* Improve size optimizations when compiling material
This changes the behavior of the size optimizer in matc (-S), but
only for GLSL and MSL. With this change we gain a ~65% size reduction
on a lit material compiled for OpenGL. To get those gains we generate
extra SPIRV debug information to preserve variable names and better
utilize the line dictionary. Unfortunately this break the SPIRV
optimizer so we skip it and instead rely on a simple DCE pass provided
by glslang. We also enhance the whitespace removal pass of the GLSL
minifier to move lone { and } to the previous line, which avoids
generating an extra index in each shader variant. Each index being
at least as big as the character itself, this is quite wasteful.
When generating SPIRV for Vulkan, we rely on spirv-opt for size
optimizations as before.
Some shaders can be shared across all materials (e.g. the depth
shaders). We use the filament default material as the "source" of
the cache, but until now we relied on an a priori knowledge of which
variants were present in the default material.
With this change, we now query once the list of variants (of interest)
in the default material and reuse that list for caching these variants
later.
This is better because the cached variants are now entirely driven by
the default material (which they depend on anyways). This is also faster
because we don't need to query which variant we need each time we create
a material.
- Depth attachment layout has generated a lot of error due to
it being read-only. But the store-ops for the attachment during
the renderpass are all write ops. We set the depth attachment
layout as VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
- Enable extra blitting step for SSAO because of the above layout
conundrum.
- Index buffers did not have a pipeline barriers after loading
them.
- Remove `assert_invariant(utils::popcount(sampleCount) == 1);`
from `reduceSampleCount`. This assert fails when enabling the
duplicate pass for SSAO.
The VSM variant is never needed for unlit materials, it was filtered
out correctly for color shaders but not for the depth shaders.
This removes 4 variants from all unlit materials.
Also improve matinfo variants output.
* Suppress numerous libz warnings
zlib will fix this issue later (see https://github.com/madler/zlib/issues/633).
For now we will just turn off the warning.
* Fix Windows build
The feature-level option sets the maximum feature level allowed for
the material. matc will fail if the specified material has a higher
feature level than the value set with the feature-level option. The
default is 3 (max).
This can be used to ensure that materials don't use features above
a specified level.
... which is needed to avoid compilation error with recent LLVM libc++ (after https://reviews.llvm.org/D146097). Previously, symbols like std::terminate() were available through other headers (e.g. <functional>, <vector>, etc.).
- FogOption::color is now correctly multiplied by the exposure and
environment intensity.
- New option to exclude the skybox from the fog
- better documentation and naming
In device vertex domain it is easy to specify infinite world-space
coordinated (e.g. with the skybox), this results in complications
everywhere. We were mitigating this by essentially moving these
coordinates to around 16000 (give or take depending on the near plane),
but that was way too small.
Now we move them around 1e19, which seems to work. It's important with
applications rendering very large scenes to not use too small of a value.
This happened because the code iterated over the keys of a hashmap,
which obviously were not guaranteed to be in the same order as those
entries where added to the hashmap.
We fix this by adding a "visitor" to the materialchunk, so we can
iterate through it in order and retried the info we need.
When we call TextureProvider::cancelDecoding, we should make sure
that textures that have been decoded, but not yet used (popped)
should be released (i.e. memory freed and the meta data marked
appropriately.)
The PixelBufferDescriptor was not being deallocated properly, which
resulted in the leak. This patch explicitly deletes the
PixelBufferDescriptor at the end of the callback to prevent the leak
.This is necessary as the move constructor does not automatically
deallocate the existing PixelBufferDescriptor.
An attachment would be wrongly discarded if used as read-only: because
it didn't have a dependency to it, the discard flag was set.
This is fixed by setting the discard flag only if a resource is written
and has dependencies to it.
Should fix: #5005
- Add a TaskHandler class for process events on the backend
thread
- Check fence status when handler runs and copy bits to the client
when the fence is reached.
* Add way to retrieve the user world-space in materials
added `getUserWorldFromWorldMatrix()` and `getUserWorldPosition()` to
retrieve the API-level (user) world position in materials.
Deprecated `getWorldOffset()`
`getWorldOffset` didn't work when an IBL rotation was applied.
* fix large scenes with an ibl rotation
Rotate the IBL around the camera instead of the world so that the camera
is always at the origin regardless of the rotation.
* Add new alphaToCoverage material property
The alphaToCoverage property lets you enable or disable alpha to coverage
in a material. More importantly it lets you overrides the behavior of
blending: masked which automatically enables alphaToCoverage.
* Update release notes
The fog calculation could fail when the falloff was strong and the
camera z position was far from the fog height. The problem was
that the computation was spread between the cpu and gpu by splitting
an exp(), but with certain parameters the two exp() would independently
blow-up. We fix this by doing the exp() only on the gpu side.
try to be more explicit about which configurations are supported,
and use the same pattern everywhere for checking the gl version at
either compile and runtime.
This didn't happen in practice, but we would call (null) if the
clip_control extension was available and we were not on GL 4.1.
We "fix" this by not supporting the clip_control extension on desktop.
It doesn't matter because clip_control is core as of 4.5 and is
present in only 8% of non 4.5 GL implementation, and this doesn't
include any macOS versions.
This small abstraction is (will be) needed because GLES 2.0 doesn't
have sync object, however synchronization is sometimes available
externally, in particular with EGL.
This PR doesn't provide other implementations.
- make sure to initialize all extension booleans, we treat them
as feature flags.
- be more explicit about #define'ing gl tokens, so we can more easily
catch errors later.
- don't blindly use extension tokens that might not be available
(e.g.: GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_CUBE_MAP_ARRAY). It
would probably cause a spurious gl error.
- iOS is treated the same way than Android now. The only difference
is that iOS only provides prototypes and no typedef, whereas
Android only provides typedefs and no prototypes.
- Timer queries is core in GL and an extension on all versions of
GLES. On iOS it's not available at the header level. An additional
subtlety is that glGetObjectuiv is core in GLES 3.0, so it conflicts
with the extension.
So, now we do things correctly:
- on desktop we use the core methods
- on ios we ifdef out everything related to timer queries
- on gles 2.0 and up we use only the extension entry-points
We were not testing for that case properly. This case is taken when
either:
- depth & stencil textures are the same and not null
- or, only depth is specified but both attachments are requested
Also cleanup the dimension checks in debug builds.
- some of the convenience are not available in ES2
- it's less efficient
- we can save some PBO space when reading back
a partial framebuffer.
We also avoid using GL_PACK_ROW_LENGTH which technically is not
a convenience, but in our case we are doing an extra copy anyways, so
we can account for the row-length at that point.
- We now call visitScene only once for the directional shadowmap instead of
1 + cascade_count times.
- Don't use visitScene for spot shadows
it was only used to compute the near/far planes, but instead we can
use the radius of the light. This could degrade the quality of the
spot shadows, but this can be corrected by setting a correct radius.
caveat: currently the near is hardcoded to 0.01 units. this should be
user-settable.
- Improve performance of visitScene calls
instead of transforming 8 points of an AABB and finding the min/max,
we transform the AABB and use its minz and maxz. This works for affine
transforms.
This change also cleans-up AABB and Box transform APIs, which also
are now inline.
- StructureOfArray: don't initialize trivial ctors
We mimic the behavior of std::vector<> here, where a resize() won't
initialize the array if the type is trivially_default_constructible.
This can reveal existing bugs, where we depended on the initialization
to 0.
- StructureOfArray: add push_back(std::tuple<>)
This basically allows us to push_back() a struct of the SoA.
- Make PerRenderableData trivially constructible
this improves performance when we have tons of objects in the scene
because PerRenderableData is used in arrays.
We use isnan() to detect that the estimation of directional light
parameters from the IBL has failed, however isnan() always returns
false with -ffast-math, which we're using in release builds.
This works around that. The affected code is non essential, performance
is not a concern here.
When loading a glTF file on platforms without a filesystem, a client
calls `addResourceData` to populate `ResourceLoader`'s cache with data.
For example, a web client might make HTTP fetch requests to fill in
buffer data. This internal cache of data is stored in
`ResourceLoader::Impl::mUriDataCache`.
This works well, except the cache must persist until after it has been
uploaded to the GPU.
There was already a mechanism (see `uploadUserdata`) in place to ensure
that glTF data persisted until after it had been uploaded to the GPU.
However, this mechanism did not extend to client-provided data. Thus, a
race occured between Filament's driver consuming the buffer and it
getting freed.
Instead of storing the arrays into an array of void*, we use a
tuple<> instead. This improves debugging because now the tuple<>
has pointer with the correct types.
It also improves most of the code except `push_back` which now
relies on a hack -- this is the only place where I'm not able to
resolve the array strictly at compile time, even if in practice it is.
UbershaderProvider.getNativeObject() is accessed from AssetLoader.cpp,
so it must be annotated with @UsedByNative("AssetLoader.cpp") to
avoid runtime crashes when minification is applied.
Fixes#5944
`-d` now enables matdbg and adds debugging data, but doesn't affect
material optimization
`-g` disables material optimizations
A similar change is done with gradle options. The new proprety
`com.google.android.filament.matnopt` is used to disable material
optimizations.
These options mimic `matc` options.
- -m option now works with "directory_*.png" or just "*.png"
- "color" replaced by "albedo" to mach other places in the source tree
- fixed warnings
- clear the background when IBL is not used
* Calculate view vector without using camera eye position
* Fix compilation error (during parsing the material when a height map is passed in)
* Add SUN light to the scene
This change adds a 'SRGB' config flag when creating a SwapChain that
enables linear to sRGB conversion on write.
When using this flag, the linear->srgb conversion in the color grading
post processing should be disabled (or, the whole post-processing
stage should be disabled).
There is also a new query to determine if this flag is supported by
the underlaying platform.
On Metal, this happens automatically when the underlaying layer is sRGB.
This reverts commit 3799e219fc.
This change adds a 'SRGB' config flag when creating a SwapChain that
enables linear to sRGB conversion on write.
When using this flag, the linear->srgb conversion in the color grading
post processing should be disabled (or, the whole post-processing
stage should be disabled).
There is also a new query to determine if this flag is supported by
the underlaying platform.
On Metal, this happens automatically when the underlaying layer is sRGB.
We now structure the code to assume we have EGL_KHR_no_config_context,
which is the common case. This allows use to decouple context creation
from swapchain creation.
We still handle the case where the extension is not present by always
selecting a transparent config.
There can be up to 4 channels drawing commands can be associated to.
Channels work like "priorities" except it's the strongest command ordering
key, in particular it takes precedence over the object's blending mode.
We were using a specialization constant to size an array inside an
UBO interface block, which caused the crash in the Vulkan driver.
However, this specialization constant was only used to workaround a
Chrome bug on WebGL. Additionally, specialized array size inside blocks
are not fully supported in spirv.
This workaround simply replaces the specialization constant by a
constant on Vulkan.
Fix#6444
- Remove DefaultPlatform from public headers
DefaultPlatform is now PlatormFactory and is just an implementation
detail.
- VulkanPlatform is now public
- Improvements to the OpenGLPlatform interface
- Cleanup PlatformEGL and PlatformEGLAndroid
Also:
- reworked how external image worked so that all the implementation
is contained in the Platform and no dependency to the backend is
needed.
- MetalPlatform is now entirely private and final
This is because MetalPlatform wasn't an interface. We probably need one
so it could be customized in the future. But as it stands now it's
better to be private.
* Refactor VulkanContext/Driver initialization
Move the initialization of VulkanContext fields to the class
itself. This will clean up how the various extension support
flags are deteremined.
Also disable debugUtils extension for Mesa driver (#6192).
* Re-land #1 "[vulkan] Refactor vkEnumerate methods (#6423)"
This reverts commit 6f7d203adb.
The above commit (6f7d20) is the revert of #6423. Commit
6f7d20 is PR #6425.
"[vulkan] Refactor vkEnumerate methods (#6423)" failed [here] due to
a missing function attribute (VKAPI_ATTR in bluevk) for ARM64
compilers.
[here]: https://github.com/google/filament/actions/runs/3841550984
At least some adreno compilers don't like returning an element of a
UBO array that is a structure in the vertex shader.
To work this around we have to copy the each of the structure fields.
Fixes#6355
Vulkan and Metal should be handled exactly the same within filament,
when it comes to texture-space and clip-space because filament
always transforms vulkan's clip-space to gl's/metal's).
Our shadow code took different paths, both equivalent though, but it's
confusing.
The race coud lead to user after free and crashes.
We now keep a list of acquired streams with pending images on the
main thread, and use that to update the streams synchronously in
beginFrame. We can then enqueue a command for the driver thread that
will look for that stream in the active list of textures with stream
attached. Race avoided.
The previous code used the later list from both threads.
When more than one view was used, only the first view was cleared with
the ClearOption. This was actually intended when the views are rendering
into the swapchain (e.g. post process disabled), but that's incorrect
when the views render into intermediate buffers.
The clear flags are now associated with the actual rendertarget.
* Add new outputColorSpace() API to ColorGrading
This allows the application to select the desired output color space.
The default is set to Rec709-sRGB-D65 ("sRGB") but can be changed to
Rec709-Linear-D65.
Currently only the transfer function is taken into account and must
be either sRGB or Linear. Future updates will add support for
different gamuts and white points.
* Update release notes
WebGL complained about:
Precisions of uniform block 'ShadowUniforms' member
'ShadowUniforms.shadows.texelSizeAtOneMeter' differ between VERTEX and
FRAGMENT shaders.
this field didn't have a precision qualifier, this might be specific to
WebGL or a Chrome bug, unsure. Either we fix it by specifying all
qualifiers.
Since cmake 3.25 LINUX is automatically set based on CMAKE_SYSTEM_NAME,
which the android cmake files are setting to "Linux". This created an
inconsistant state in our build system.
Use a much more precise way to calculate the directional shadow frustum.
With very large scenes, we were losing the precision on the direction
of the light, and in some case even producing NaN in the matrix.
This partially addresses #6293
All shadow maps need a 1-px border for different reasons.
The directional shadow needs a "not in shadow" border because it uses
the intersection of receivers and casters in light-space.
Other shadow types need a border because of bilinear access at the
edges. Until now, the spot/point shadow border was handled with the
sampler's CLAMP.
Instead, now, we always generate a border and in one case we fill it
with "not in shadow" (by not rendering into it), in the other cases we
render the 2px larger shadowmap so we get completely correct bilinear
filter.
Additionally, for PCF, DPCF and PCSS we use a large filter kernel which
accesses data outside the texture, until now this was handled with CLAMP,
but that failed (2 of the edges were not handled in the same way) when
the shadowmap was smaller than the texture.
We fix this by clamping manually the texture coordinates.
The real motivation for these changes is to allow the use of a
shadow Atlas later.
When width/height is converted to GLSizei, which is signed, it can
become negative, which happened with a "full" viewport.
On some GL implementation, this resulted in a failure.
The viewport is now entirely handled by ShadowMap, that is, we're no
longer setting a viewport in the renderpass, instead the ShadowMap
uses a post projection transform to achieve the same effect.
This will become useful when store shadow maps in an Atlas.
point light shadows are not sampled just like spotlight shadows, the
only difference is that we're calculating the face first to access the
corresponding shadowmap data (including the light transform).
- the layer is now stored in the shadow ubo
- we now have one shadow ubo per face
- ShadowMap holds UBO index even for cascades
- move some shadow "view" uniforms into the shadow UBO
breakage was due to an uninitialized variable at the beginning of the
frame, caused by a recent change.
shadows would disappear when cascades were used with 'stable' shadows.
ShadowMap had recently inflated due to its internal use of
PerViewUniforms, which keeps a shadow copy of the uniform data. This
copy is not needed for ShadowMaps.
In addition to the new getters, this change fixes the duplication of
a MaterialInstance, which didn't carry along the following states:
- alpha mask threshold
- specular AA threshold
- specular AA variance
- double sidedness
TODO: stencil state, polygon offset and scissor are stil not queryable
* Recompute bounding boxes with morph targets
* Reduce the number of heap allocation while recomputing bounding boxes
Co-authored-by: Romain Guy <romainguy@curious-creature.com>
Instead of constantly reusing the View's UBO, each shadowmap now
manages it own. All UBOs for all shadow maps are updated together,
then later during rendering, we're simply binding the correct UBO.
This change will be needed later so that we can update several
shadow maps in a single texture.
There are two main changes to achieve this:
1. ShadowMap now has PerViewUniforms object
2. For point lights, each face now has a ShadowMap object
One consequence is that ShadowMap is now very large (over 2KB). This
will be addressed later.
This 2D allocator only supports power-of-two, square allocations. It
uses a quadtree to store the allocated regions.
The quadtree implementation currently has a fixed depth (templated).
The allocator does a best-fit match, but currently doesn't implement a
free method.
- RenderPass::Executor now only executes the commands, it doesn't
create a backend render pass anymore. This is still done in the
RenderPass::execute() helper.
- scissor and poloyon offset overrides are now set on Executor because
they are not needed to generate the commands.
glDispatchCompute requires Android API level 21, however bumping our
required minimum from 19 to 21 caused some clients' builds to fail.
Commenting-out that line for now to proceed with the 1.28.0 upgrade.
- remove mEngine from ShadowMap
- remove storage of ShadowMapInfo in ShadowMap
- ShadowMap::render should be on ShadowMapManager
- remove more attributes from ShadowMap
ShadowMap is now reduced to 32 bytes.
Spotlight shadow maps are now limited only by h/w limits (UBO size and
2d array maximum layers), which works out to about 146 shadows.
In practice we hardcode the limite to 64, but this can be changed at
compile time. A higher maximum increases memory usage.
There used to be a bitfield per renderable with a bit for each shadow
map indicating if the renderable was "visible" from this light. The
limit to 14 came from that bitfield. All shadow maps used to be culled
first, setting the bitfield appropriately.
Instead, we are now processing spotlight shadows one at a time,
performing culling as we go. For this reason we don't need a bit per
shadow map.
No need to generate a sentinel command in the main loop when a
command is canceled, this is now done automatically at a higher level.
The main benefit is that we can reject renderables that are not visible
a bit faster.
The VulkanProgram constructor was bailing out early and emitting a
warning because it saw that one of the stages wasn't fulfilled.
However it's okay for a pipeline to be missing a compute program.
Fixes regression that started with fabba73b1.
this case was causing uninitialized variables to be used creating a
false positive "shadows on" in the first cascade.
The main change here is to bail out as soon as we know there is no shadowing.
we attempted to select a shader which processed the required number of
component, but were always selecting the 4-components version.
this should improve blur performance for VSM.
This basically adds two settings:
- highPrecision at the View level, which controls the bit depth
of the vsm shadow texture used. This affects all shadowmaps.
- elvsm per shadowmap, which enables Exponential Layered VSM.
the main change in the shaders is that we now always output the
"negative" EVSM, even when it's not enabled. If no shadowmap uses
ELVSM, then the texture is stil an RG texture and the calculation is
lost (with some luck culled by the shader compiler), either way it's
not a lot of math and it's done only once per shadow texel.
During the color pass, on the other hand, we compute the "negative"
EVSM only if enabled.
We were always adjusting the near/far of the view volume based on the
scene content for shadowing, which defeated the "stable" shadows.
Also changed the default cascade splits from a linear split to a
log2 split, because due to the perspective projection, the log2 split
actually looks linear. Also intuitively, it makes more sense to give
more resolution to the shadows close to the camera.
* Fix a crash by setting not exist material parameters on ubershader
* gltfio: add getFeatureMap, remove logic for dummy textures
Co-authored-by: Philip Rideout <philiprideout@gmail.com>
to emulate the bindless API in the gl backend we always used the highest
texture unit available. However at feature level 3, we support up to 62
textures, so the that max was bumped to 62 -- however, where we're not
on a feature level 2 device, that texture unit doesn't exist.
Instead we now always use binding 31, which is guaranteed to exist by
EGL's minspec.
* minimal backend support for compute
- added api to dispatch a compute shader
- added api to create and bind a ssbo
- added api to read back a buffer
Only implemented in the gl backend
* Add a backend compute test suite
* basic support for compute shaders in matc
this is still very much work-in-progress.
We're not supporting images nor ssbo for now.
* rename UniformInterfaceBlock to BufferInterfaceBlock
* augment BufferInterfaceBlock to support ssbo features
- add support for std430
- add support for ssbo
- add support for variable-size array
- add support for memory qualifiers
* reformat MaterialBuilder
* material format: move subpasses outside of parameters
subpasses now are their own json property instead of being a
"parameter".
* refactor parameter() methods to match Buffer/SamplerInterfaceBlock
We're just shuffling the arguments.
* add support for buffers in .mat files
* filamat now generates buffer blocks (ssbo)
* take feature level into consideration when optimizing shaders
* don't store the 'uniform binding' chunk for level 2 materials
this includes some refactoring/cleanups of MaterialParser
* matinfo: fixes for compute
- separate subpasses from parameters
- don't attempt to print material properties
it is not true that the whole box is inside the frustum if we have
8 vertices and some frustum vertices are in the box -- that's even
non-sensical.
We now test for this case by checking that we have all (8) vertices of
the box inside the frustum.
This caused some shadows to be missing.
This is because most android devices only support 16 texture in the
shaders (94.4%), so we can't realistically have feature level 2 demand
that.
Instead feature level 2 enables compute/ES3.1 features.
This is a feature request from Google. It allows users to "preload" an
asset, ie you can now create all VertexBuffer objects, Texture objects,
etc, without actually creating any entities or renderable components.
In the past we used TransformManager to help out with computing the big
asset-level bounding box, but now we use `gltf_node_transform_world()`
because entities might not yet exist.
One minor side effect is that `FilamentAsset::getBoundingBox()` now
returns the AABB that was determined at load time, and does not account
for instances. As a result, our `gltf_instances` sample app looks
slightly different but this is expected.
In VulkanPipelineCache, `getShaderStageFlags()` and `getUsageFlags()`
are used to track which samplers are used in the VERTEX stage and which
are used in the FRAGMENT stage. The recent change I made was incorrect
because it did not account for samplers that are used in BOTH stages.
This fixes the recent regression where we see validation errors when
running `gltf_viewer` in ubershader mode.
Some (poorly authored) glTF assets have several `image` elements
that all refer to the same URL or buffer view. When this occurs,
we create only 1 Filament Texture.
These assets regressed after PR 6051, which consolidated the texture
related fields in `FilamentAsset`, but did not include an ownership flag
in the new `TextureInfo` struct.
- fix View::setVisibleLayers to match code. By default only layer 0
is active, despite the documentation stating otherwise.
- add a helper to enable/disable layers more easily
- don't use layer 0,1,2 for the overdraw function as they were used by
FilamentApp in "multi view" mode.
- improve scissor documentation, specify coordinate system and
clipping behavior
- scissor now takes the guard bands into account
- on the backend side the scissor is no longer clipped to the viewport
- clipping to the viewport is now done on the filament side
- don't set scissor when material instance doesn't specify one
(common case)
AssetLoader now loads assets in two passes:
- Pass 1 creates VertexBuffer objects, MorphTargetBuffer objects, etc.
- Pass 2 creates entities, renderables, etc (only if numInstances > 0)
This feature will help us integrate gltfio with an internal library at
Google.
The asset previously had three confusing fields related to textures:
mTextures, mTextureSlots, and mTextureBindings.
These are now consolidated into a single field, which simply has one top
level array item per `cgltf_texture`.
The memory footprint is smaller because we no longer bother to store
`TextureSampler` objects, instead we simply defer their construction
until calling setParameter.
Last but not least, we now assert in debug builds if the usages of a
particular texture have inconsistent sRGB flags. In the past,
inconsistent sRGB would be silently ignored.
In other words, we will now assert if you try to use the same texture
for `baseColor` and `normalMap`, whereas in the past we would simply
exhibit non-deterministic behavior in this situation (with respect to
sRGB semantics).
gltfio can now ask the material provider plugin which `Material` would
be used for a given set of requirements. Prior to this change, gltfio
could only create a new `MaterialInstance`.
This method is necessary to support an upcoming gltfio feature.
This broke asyncGetLoadProgress() and caused WebGL to crash reliably
because ResourceLoader got destroyed too soon.
Bug was introduced with de7dfc2ea6.
I intend to cherry pick this to rc/1.27.0, which is where it was
introduced, so there's no need to update the release notes.
* check that user materials don't exceed their allowed features
* backend sampler limits now take feature level into account
- in the backend, the constants are now in an array indexed by the
feature level
- samplerBindingMap now asserts only what it can.
- matc (filamat) now logs the user samplers when an error is detected.
* Add JNI for TransformManager.getChildCount(), TransformManager.getChildren() and scene.hasEntity()
* Update RELEASE_NOTES.md
* Fixes
* Change getChildren to take a nullable array
* Remove no params TransformManager.getChildren()
* Update RELEASE_NOTES.md
Co-authored-by: Ben Doherty <benjdoherty15@gmail.com>
Co-authored-by: Ben Doherty <bendoherty@google.com>
One of the bloom texture ended-up dangling in the material's
SamplerGroup. That sampler group was never used to draw with, but was
made active which caused problem with the backends.
Also make sure the public API can unset a texture in a MaterialInstance
by passing nullptr for the texture.
For each "cgltf_material", we now create one "MaterialInstance", even
if a given asset has multiple instances. In the future, we might make
this behavior configurable to make better use of Filament's
auto-instancing feature.
This change is a feature request from Google, but also this behavior is
more consistent with the code comments.
Also some related cleanup:
(1) Use FixedCapacityVector instead of robin_map.
(2) Move the cache to move out of the asset and into the loader,
because it is only used at load time.
in a few places filamat loses the value of targetApi and targetLanguage
and attempt to guess it from other values, this lead to inconsistencies.
we now keep both targetApi and targetLanguage and use them appropriately.
in particular we don't use the optimization level to "guess" what
targetLangage we're on.
In the end this resolve a prior unit test failure and allows us to not
have to use "spirv" rules when generating only GLSL.
We use TargetLanguage::SPIRV instead of GLSL which affects how the
source GLSL is generated, in particular which version is used.
This change is not a problem for these unit tests, but is probably
exposing another problem -- we will address that separately.
We were keeping the list if uniform names in Material and passing
pointers to the backend. Unfortunately, HwProgram can outlive
Material because it is legal to destroy a Material once it's not
needed on the client side. e.g. just after rendering something.
This was happening with the IBLPrefilter code, but probably elsewhere
too.
We now just store CStrings in HwProgram.
The immutable inverse bind matrices can be shared among instances, so
they are now stored in Asset, not in Instance.
Also, there are now two "load" phases for skinning data:
(1) storing the inverse bind matrices
(2) building the Entity mappings (for animation efficiency)
Phase 1 is done in `ResourceLoader` because inverse bind matrices can
live in an external bin file.
Phase 2 is done during Instance creation, because that's when entities
are created.
Prior to this change, `recomputeBoundingBoxes` was an opt-in config
parameter in ResourceLoader. It is now a method on FilamentInstance.
The old API did not work for dynamically created instances. Since this
is a relatively obscure feature, we considered removing it completely,
especially since the computation requires the presence of CPU-side
vertex data combined with the transform hierarchy.
Instead of removing the feature, we decided to move it to a better
place. This paves the way for some upcoming improvements, which include
reducing the memory footprint for assets. It also improves overall code
organization and separation of concerns.
* Fix warning C4146: unary minus operator applied to unsigned type, result still unsigned
* Fix warning C4068: unknown pragma 'nounroll'
* Fix warning C4068: unknown pragma 'unroll'
* Fix warning C4068: unknown pragma 'clang'
* Fix warning C4305: 'initializing': truncation from 'double' to 'float'
* Fix warning C4267: 'argument': conversion from 'size_t' to 'utils::FixedCapacityVector<filament::uberz::WritableArchive::Material,std::allocator<T>,true>::size_type', possible loss of data
* Fix warning C4267: 'argument': conversion from 'size_t' to 'uint32_t', possible loss of data
* Fix warning C4244: 'initializing': conversion from 'A' to 'T', possible loss of data
* Fix warning C4334: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
* Fix warning C4293: '>>': shift count negative or too big, undefined behavior
* Fix diagnostic warning C4189: 'channels': local variable is initialized but not referenced
* Use [[maybe_unused]] where possible and revert aa79bd6fa8.
* Revert unary minus for non-MSVC compilers
* Add macro for enabling warnings temporarily
* Get rid of UTILS_HAS_CXX17
* Revisit warning related macros
Co-authored-by: Levente Koncz <levente.koncz@shapr3d.com>
this case could cause an assert in debug builds. There was a few bugs:
- when computing the intersection between a box and a frustum, a special
case test had a typo which would cause extra work in some case. Also,
we were not detecting correctly when there was no intersection at all.
This could result in some intersection point being found.
- Finally, we reject the intersection volume when it has only 3 vertices
because that's not a volume.
Fixes#5933
The main goal of this change is to have "ugly" code only in filamat.
In particular, the sampler binding information is now recorded
into the material file and used on the filament side to inform the
backend.
This means that on the filament side we only have generic code with
all the "uglyness" in filamat. In particular SamplerBindingMap and
SibGenerator now only exist in filamat.
Files of greater interest:
Material.cpp, MaterialBuilder.cpp
This is a workaround for the following Chrome issues:
https://crbug.com/1348017 Compiling GLSL is very slow with struct arrays
https://crbug.com/1348363 Lighting looks wrong with D3D11 but not OpenGL
This requires a rebuild of materials for WebGL users.
Fixes#5859.
partially revert a recent change where Program needs a DriverApi in its
ctor. This was a misguided change. Backend API never take a DriverApi
as parameter.
Checking the feature level, for instance, should happen as a
precondition, or in the backend as postcondition.
GLES3.0 (and GL4.1) need informations about the uniform block bindings
because they don't allow to do that setup in the shaders. So we store
that information in the material blob and retrieve it on the filament
side in Material. This information is passed to Program so it can
create the bindings.
Prior to this change, this information was set by Material itself, but
this ment we had two places where these bindings were hardcoded.
The bulk of the change is to add a new material chunk which stores an
array of {name, binding}, retrieve it on the Material side and pass it
to Program.
- remove unused SamplerBindingMap parameter
In fact, the SamplerBindingMap is used, but it is passed inside the
MaterialInfo structure, so it doesn't need to be passed as parameter.
- Don't create unneeded SamplerBindingMap temporaries
This change was motivated by some internal work at Google and has the
benefit of simplifying the gltfio API and implementation. There are 2
major API changes:
(1) Consolidate separate loader entry points for GLB and GLTF.
The distinction between GLB and GLTF can be made from the file content
alone, because GLB has a 4-byte magic string in its header. There is no
need for separate entry points. Clients do not (and should not) need
to check the file name extension.
(2) Remove the distinction between "instanced" and "non-instanced"
glTF assets.
In the new scheme, all assets have at least 1 instance.
Broadly speaking, in gltfio an "asset" is a collection of Filament
objects like textures and vertex buffers, while an "instance" is a
collection of entities and components (e.g. the transform hierarchy).
This API change makes life easier for clients because they no longer
need to decide a priori if they will ever need to add instances.
This change also moves some public-facing methods from FilamentAsset to
FilamentInstance:
- getSkinCount, getSkinNameAt
- getJointCountAt, getJointsAt
- attachSkin, detachSkin
* Begin Sorting SubProjects into Folders
* Add more subprojects to folders
* Add even more subprojects to folders
* Add further subprojects to folders
* Move the last two projects
* Move Resources to a Resources subfolder
* Remove spaces to be stylistically coherent
* Revert Improper CMake Modifications
* Revert erroneous line removals
* Only specify sdl2's folder on WIN32
* Add the shader subprojects to a Generated folder
* Move shaders to Filament/Shaders
* new feature level API for backends
backend can now return a "feature level", each level corresponds to a
"bundle" of features.
Level1: ES3.0 capabilities
Level2: ES3.1 capabilities + 31 textures + cubemap arrays
Currently metal always returns level 1, GL and Vulkan return level 2
if 31 textures or more are supported.
* Add public APIs for feature levels
* Add infrastructure to check feature levels in materials
* validate material feature level on use
The validation is done when creating a renderable. If the engine doesn't
support the material's feature level, an exception is thrown (or assert
if exceptions are not enabled).
* material documentation
* activate ESSL 3.10 for feature level 2
also generate #defines to identify available feature levels
* support for cubemap arrays in the public API
if feature level 2 is supported, cubemap arrays can be used from the
public API.
* add release notes
With VERTEX_DOMAIN_DEVICE the vertex shader doesn't apply the
projection (since the vertices are already in clip space), however,
both TAA and guard bands need to jitter/offset the clip space, and
it is done at the projection level.
We now store the clip space offset separately so that it can be applied
to VERTEX_DOMAIN_DEVICE vertices.
We also introduce a new material parameter, vertexDomainDeviceJittered,
a boolean that controls whether clip space offset (above) is applied.
This is because a VERTEX_DOMAIN_DEVICE material that uses the built-in
projection matrices generally ends-up with the jitter already applied,
this is the case with the Skybox for instance.
Fixes#5917
Fixed a comment that said "We store 64 bytes per bone.". The actual
number is 32.
Developers who know their users have powerful devices may wish to exceed
ES3.0 minspec constraints to allow more bones and / or morph targets.
Fixes#5785.
The custom release callback that I provided was in the wrong place; it
was only being used for a path string, not the actual buffer content.
The cgltf API is a bit awkward in this area.
No need to update RELEASE_NOTES because this will be cherry picked to
the RC branch, which is where the bug introduced.
Fixes#5918.
Filament does not yet fully support threads with WASM, but this is a
baby step in that direction.
To enable experimental pthreads support, enable the WEBGL_PTHREADS CMake
option. This will enable pthreads support in `gltfio` and `utils`, which
is known to work, but not when served with GitHub Pages.
The web server must emit COOP, COEP and CORP headers, so our build
instructions now recommend the use of `emrun` for local testing.
This also changes our demos so that they do not use unpkg, which
does not work when using `emrun`, due to cross-origin restrictions.
This feature can improve load time when textures are downloaded from the
web on non-filesystem platforms like Android.
More specifically, this allows downloaded texture assets to arrive after
the user calls asyncBeginLoad(), which means that decoding and
downloading can occur concurrently.
Prior to this PR, we already used JobSystem for decoding, but we did not
kick off any jobs until after all assets were downloaded.
Still TBD: add this feature for external vertex data.
Partial fix for #5909.
Earlier versions of cgltf did not support file reader customization.
This was fixed back in Dec 2019 but at the time I did not notice, so
we never bothered cleaning up our usage.
In the future we would like WebGL + Android builds to permit texture
downloads to occur concurrently with the texture decoder jobs. This PR
is basically a preparatory refactoring, but with the nice side effect of
removing a memcpy.
it was a duplicate state from the true gl state which could easily cause
problems. It only existed to optimize state updates when nothing changed
but we already have fine-grained tests for this.
It was culled by the frame-graph because it didn't have "read" from
any of its resource, only writes. However, it does set uniforms, so need
to be called.
fix#5874
StructureOfArray always aligned each array to the same alignment as
malloc (usually 8 bytes), but that was not enough if one of its type
has stricter alignment requirements.
StructureOfArray now always honors at least the alignment requirement
of each array.
Also removed dependency on EntityInstance.h
Fixes#5727
We used to have a mix of fatal and non-fatal assertions for precondtions
errors. From now on, we always throw if exceptions are enabled or
crash with a log otherwise.
In most places this is simply replaced by `std::string_view`.
We also change a few internal/private headers so they accept
`std::string_view` instead of `utils::CString`.
Internally we use std::string_view and the public API is augmented
with APIs that take a length for strings, which makes them useable
with string_view parameters.
Also fix exception specification for all setParameter methods, which
can throw if exceptions are enabled (or exit the program otherwise).
When FTransformManager computes accurate world transforms, it adds downcasted leftover to translation part to restore precision.
However, both transltation and leftover are given as float3 - simply adding them resut float3, so addling leftover become meaningless.
one or both should be upcasted first.
I have disabled building SDL with headless EGL, because
SDL_config_minimal.h doesn't work with EGL, and I don't know how to
implement a an SDL config that would work with EGL.
I have verified that this works in a separate project, and that it
compiles in this project.
```
$ ./build.sh -e release
$ find ./out/ -name "*EGL*"
./out/cmake-release/filament/backend/CMakeFiles/backend.dir/src/opengl/platforms/PlatformEGL.cpp.o
./out/cmake-release/filament/backend/CMakeFiles/backend.dir/src/opengl/platforms/PlatformEGLHeadless.cpp.o
./out/cmake-release/libs/bluegl/CMakeFiles/bluegl.dir/src/BlueGLLinuxEGL.cpp.o
```
GL_ES_30 becomes MOBILE
GL_CORE_41 becomes DESKTOP
ShaderModel controls which flavor of GLSL (GL or ES) is used both when
reading and outputting materials.
It's also used to set default quality settings and the default precision
of all fragment shaders.
Technically, Vulkan and Metal don't need this distinction, but the GL
backend does.
this is more in line with other APIs of the backend. This change is
complete for the GL backend, but for the metal/vulkan backend we still
use a SamplerGroup as the internal data structure, which is just
temporary.
Eventually, SamplerGroup should becomes a "filament" only API (not
a backend API).
SamplerGroup itself is now a more "traditional" class where copy and
move ctor do what you'd expect. This actually removes a few copy of
the internal data in some cases and uses less memory, at the cost of
doing some heap allocations, but they should be rare and outside of
the main loop.
we mow do most of the work of validating the sampler parameters and
resolving to an actual GL sampler, when updating a SamplerGroup,
instead of doing this each time a program is made active.
A lot of cpu work is saved when the same samplergroup is reused with
multiple programs.
this is the start at making HwSamplerGroup more "real". It shouldn't
keep a reference to the filament::SamplerGroup, which is just an object
to pass the data.
for now, we move the SamplerGroup reference into the concrete classes to
keep the same implementation. But now it becomes an "implementation
detail" of the respective backends.
- remove the 2 argument version of setSampler
- use a bool instead of bitfield for the dirty state
- try to avoid setting dirty bit if setting same sampler
Starting with 3.1.14, embind started to support for `noexcept`
which caused multiple definition errors since we have a workaround
in place that alreadys supplies template instantiations for `noexcept`.
This change should not affect G3 since our JS bindings are not used
in G3.
The upstream fix is here:
https://github.com/emscripten-core/emscripten/pull/17140Fixes#5789.
This is not intended to be used yet because we're not currently
checking that cubemap array are actually supported, however, if they
are, they should work.
the depth of the texture wasn't taken into account. In practice this
would restrict the number of mip levels of a 3d texture that would have
a larger dimension in depth.
The main goal is to allow more flexibility, allow cubemap arrays in
the future and better match vk and metal apis.
Main changes:
- remove updateCubeImage
- remove update2DImage
- update3DImage is now the only texture upload backend API
cubemaps are now treated just like a 2D array of 6 layers.
For this reason, Texture::setImage(..., FaceOFfsets) is deprecated.
Additionally, the 2D versions of Texture::setImage() become inline
helpers.
A side effect of this change is that it is now possible to update only
a single face of a cubemap, but also a region of a face (or faces).
This PR changes how Metal handles buffer updates. Previously, Metal allocated a full new buffer each time an `updateBufferObject` command was issued; however, it did not copy the previous contents of the buffer over to the new buffer, so partial updates did not work correctly.
Now, Metal allocates a single, private GPU buffer and employs temporary staging buffers whose contents get blitted to the private buffer at each update.
There's still some room for optimizations, and I need to give more thought to how I want to implement `updateBufferObjectUnsynchronized`.
- move all froxel configuration constants out of Engine.h, unlike
the previous todo/comment, these shouldn't be part of Engine::Config.
- same for irradiance map
For some android gpu drivers, some uniform arrays should be initialized to be used in the shader, even if not used.
Co-authored-by: Mathias Agopian <mathias@google.com>
This code adds a config object, "ConfigParams," to Engine creation parameters for setting memory buffer sizes for command buffers and driver handle arena sizes. It will use #define values (FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, etc.) as defaults (and as minimum acceptable values) if the user does not provide values. It attempts to validate the values given to prevent the user from creating a unusable state.
BlobDictionary and LineDictionary were storing blobs as map keys to
achieve simple compression, but they also stored duplicates of
in a vector for index-based lookup.
Now, the vector is storage and the map has keys that are string_view.
- getNear() and getCullingFar() now return doubles
- updated documentation
- all setProjection() calls can now throw (when enabled) and will
do so if preconditions are not met (instead of setting a default
projection).
- Frustum can now be logged on debug builds
This patch enables user scissor in Metal backend; There was no implementation for it.
While the absence of the feature in Metal does not incur serious problem, many rendering glitches were found in apps using ImGui due to it.
Co-authored-by: Benjamin Doherty <bendoherty@google.com>
auto-instancing can have some overhead, so when it is known that the
scene doesn't have identical primitives, it is better to disable it.
(disabled by default).
Also add some missing bindings for `enableAccurateTranslations`.
Reflects a change from Betty and should be cherry picked to v1.23.3
Users could customize the ImGuiHelper camera, but they had no control
over the scissor coordinates. This allows them to use vertically flipped
coordinates, which, unfortunately, is required for MediaPipe
integration.
This was too tricky, it highlights that we definitely need refactor this
to share code with the flattener / unflattener pipeline. I'll look at
that next.
* BlueVKDarwin: Simplify the build and loading process.
Some of our CMake logic was not necessary because we do not staticly
link against anything for Vulkan. All entry points are dynamically
loaded.
Some of the load-time code was also needlessly complicated. In fact the
ICD environment variable that we were setting is now deprecated.
I tested this PR with:
- macOS + June LunarG SDK
- Android on a Pixel 6
* Fix up, further simplification.
This lets us avoid the following validation error.
Attempting to create a VkDevice from a VkPhysicalDevice which is
from a portability driver without the
VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the
VkInstanceCreateInfo flags being set...
This will allow us to fix the validation error related to
VK_KHR_portability_enumeration.
Also, macOS comes with Python 3 nowadays so we're upgrading the script
from Python 2.
Unsynchronized update just means that the buffer is updated regardless
if what the gpu is doing, the synchronization is the responsibility of
the caller.
Also added resetBufferObject(), which essentially destroys and reallocate
a buffer for the same handle.
- rename PerRenderableUibBones to PerRenderableBonesUib to be more
consistant with other interface block naming.
- make sure the C++ struct and the UBO definition match.
PerRenderableBonesUib is a UBO with one bones[256] field, but the
C++ struct has a single bone and treated the UBO as an array.
This makes things less confusing.
We can now use sizeof(PerRenderableBonesUib) in many places which
better expresse what we are doing.
- Fix an off-by-one assert when setting a skinning buffer to a renderable
- Asserts that no more than 256 bones are associated to a renderable
- improve documentation and fix some typos
We no longer use the hardcoded objectUniform UBO name, instead, we
access the object uniforms through the new getObjectUniforms().
Because it's not possible to return a "Uniform Block" from a function
in GLSL, a large part of this change, is to replace the interface block
by a structure.
Note: getObjectUniforms() is not public, but it is used by gltfio to
access the userData field, which is also not public at the moment.
DEPTH commands are now sorted just like COLOR commands, that is,
they use a 10 bits z-bucket and the material id in the sorting key.
This allows instance-able primitives to be sorted next to each other.
We still use resgen for convience, but the archive is now passed in
from the client application.
This will allow us to shrink the gltfio Android library (stay tuned).
This boolean parameter is used with materials that need to access
`getInstanceIndex()` (filament's equivalent to `gl_InstanceIndex`).
It is false by default, and getInstanceIndex() is not accessible.
This is intended to be used in concert with
`RenderableManager::Builder::instances()`.
a 64 bytes pool seems to work with both clang and msvc, unfortunately,
c++ doesn't let us know the allocator object size at compile time
for map containers, so we have to guess.
An ubershader archive is a bundle of filamat packages with some metadata
that conveys which glTF features each material supports.
This PR does three things:
1. Adds a new command line tool called `uberz` that consumes a list
of filamat files and metadata text files and produces a single
ubershader archive.
2. Adds a new library (also called `uberz`) that is used by `gltfio`
to read ubershader archives, and used by the above command line
tool to write ubershader archives.
3. Enhances `UbershaderLoader` so that it no longers uses a hardcoded
set of materials, and instead takes an ubershader archive.
Ubershader archives have a simple binary layout that can be memcpy'd
directly into a C struct. The metadata is specified using a text file
with key-value pairs. These two file formats have formal desriptions in
the README in `libs/uberz`.
In a subsequent PR, we will remove the `gltfio_resources` target and
change the signature of `createUbershaderLoader` so that it takes
an archive.
We were re-building various C++ files in three different targets
(basis_encoder, basis_transcoder, basisu executable), it's probably
better just to set up proper dependencies between the libraries. Note
that I'm not sure if this actually improves build times.
More importantly, this creates a CMake target for the zstd library
because we want to use zstd in other places.
blendOrder was used to control the draw order of blended render
primitive within a Renderable. We now have an option to make the
blend order global, in this case those primitives with a global blend
order are always sorted solely using the blend order value (i.e. the
distance from the camera is not take into account).
This change includes a fix for an issue we filed against spirv-tools:
https://github.com/KhronosGroup/SPIRV-Tools/issues/4371
So, it should reduce the number of extraneous matrix copies in finalized
GLSL code.
I did quick size total of all filamat files (*) before and after this
update, it went from 11.3 MB to 11.1 MB.
(*) All backends are enabled, includes built-in Filament shaders and
gltfio ubershaders.
* Add JS bindings for Texture class methods
This change introduces bindings for the following methods:
- getWidth
- getHeight
- getDepth
- getLevels
Closes 4492
* Mark level arguments as optional
* Revert docs defs
* Revert docs/webgl/filament.js
if we have more than 16K of UBO data, we now use a "out of band" buffer
on the heap instead of the command stream, which has limited space.
to minimize the heap allocation we use a simple pool allocator that
recycles a few heap buffers (per Scene).
This optimizes and cleans up some code from a 3P contributor.
When computing a bounding box, there was no need for an inner loop
through the entire skins array.
Tested using the torus model in #4973 and the `-r` flag in gltf_viewer.
I think the most important thing here is that we now let users know that
"offset" is not a byte count. This also fixes some small typos, e.g.
"weights" was used in the docstring instead of "positions".
To avoid making API changes, this does not fix a few weird things I
noticed in the Java API. For example, there is a redundant "count"
argument in methods that take an array. Also some methods do not
provide an "offset" argument, which is not consistent with C++.
Our `morphNormal` GLSL function treats each normal target as a
displacement from the base normal (similar to the glTF spec) but the
normal that is extracted from the tangent frame is actually an absolute
normal.
In other words, if b is the base normal, we were doing:
b = b + w0 * n0 + w1 * n1 + ...
This is obviously wrong, since the base normal has an overpowering
influence.
The fixed math looks like this:
b = b + w0 * (n0 - b) + w1 * (n1 - b) + ...
Fixes#5584.
By design we shouldn't access the scene SOA when executing the
high level commands.
This change increases the size of a command to 64 bytes and
PrimitiveInfo to 48 bytes (both with some small padding left).
This removes usage of regexps from the parsing phase and splits the
program into three sub-packages: parser, database, and emitters.
The parser now generates an AST according to the formal grammar
described in the README:
https://github.com/google/filament/blob/pr/beamsplitter_rewrite2/tools/beamsplitter/README.md#grammar
This allows for nice readable error messages. More importantly, it
permits the C++ syntax to be less restrictive and paves the way for
possible expansion of the tool beyond `Options.h`.
I looked at the C++ AST generated by clang but it is huge and unwieldy.
For our purposes this simplified AST is much easier to work with.
The new lexer is inspired by the following Rob Pike talk.
- https://www.youtube.com/watch?v=HxaD_trXwRE
Beamsplitter does not use the state machine described in the above
prezo, but it does use a Go channel for separating the parser from the
lexer. In our case, the lexer is actually a recursive descent parser
with simple lookahead functionality. This made it easy for the "real"
parser to create an ergonomic coarse-grained AST.
This is a big change but it is a no-op in terms of the generated code.
* gltfio: Clear texture caches before loading resources
* iOS gltf-viewer: add double-tap to reload model for debugging
* iOS samples: add instructions on ASan / UBSan debugging
- Ensure C++17 is used to compile sample projects
- Upgrade to the latest Xcodegen and re-generate projects
- Add a bundle ID disambiguator so users don't need create unique bundle Ids when opening sample projects
- Add a simple generate-samples.sh script
The API is the same but there are some minor differences, which include:
- Ordering of fields in AmbientOcclusionOptions
- More @NonNull annotations that we forgot
- Javadoc formatting is different
There were two places where we were doing unaligned reads: one when
computing the hash for the material identifier, and one when parsing
the chunk in ShaderReplacer.
We also had a potential overflow since civetweb does not add a trailing
null to incoming WebSockets messages.
This moves parser into a subpackage to shield it from the various
emitters (this folder structure is similar to what Rob Pike used for his
text templating library). This also adds a WIP Java code generator,
currently disabled.
We now have 3 public APIS:
- opaqueBlit() which is used for basic blitting and scaling and
supports sub-resources.
- blit() which is used for blitting + composition
- can optionally perform basic scaling
- doesn't support sub-resources
- upscale() which is used for high quality upscaling
- can do composition (blending)
- doesn't support sub-resources
This is a temporary workaround for a memory corruption issue observed on
some devices from a specific vendor. We will try to make this workaround
more targeted in a subequent change.
Partial revert for b2cdf9f2b4.
The most important change here is that we no longer apply the
backend (e.g. Metal/Vulkan) UV transformation before calling the
user's vertex shader. This is an API change for post-process materials
(but they're not public).
Now the user is responsible for using uvToRenderTargetUV() in their
shaders (either in the fragment or vertex as appropriate).
This makes it easier to handle offsets/transforms with all APIs.
Conceptually, the only thing that is needed is to call
uvToRenderTargetUV() just before making a texture call.
This fixes a couple of issues:
- some image shifting in metal/vk
- flare in metal/vk was upside down
We also simplify the DoF code quite a bit now that we can rely on the
rendertargets begin multiple of 16.
We also "fix" SSAO that was working by accident on metal/vk. The UV
correction was applied 3 times 2 of which were canceling each other.
This adds a code generator, implemented in Go.
This PR also prepares `Options.h` (the ground truth) by simplifying its
syntax just a bit. The ground truth file must have very simple C++
syntax, which is described in the README:
https://github.com/google/filament/blob/pr/codegen2/tools/codegen-options/README.md
This process revealed a small bug: `Filter.MEDIAN` was bound to the
incorrect value in Java.
The generated code is not yet used, stay tuned.
* Add multi-scene support to gltf_viewer.
To test this, I generated a multi-scene asset as follows.
```
gltf-transform merge Avocado/glTF/Avocado.gltf \
BarramundiFish/glTF/BarramundiFish.gltf \
~/Desktop/Merged.gltf
```
* Specify c++17 in pbxproj files.
When the guard band is enabled, the effective rendering area is
increased by a certain amount (currently 16 pixels on each side) so
that screen-space effects (e.g. SSAO, SSR, DoF) behave better around
the edges of the screen. Of course, this comes at a performance and
memory cost.
Currently the guard band is not configurable other than being optional.
Added c++, java and js bindings.
This also removes clipping of the blit rectangle that occurred in the VK
backend that is no longer necessary. There's also no need to assert
since validation will catch out-of-bounds blitting.
Reverts the clipping in acdb8addfd.
Also deprecate some fields of DisplayInfo this shouldn't be a problem
because they were not actually used.
This change should allow an external-to-filament code to manage
frame pacing (e.g. something like swappy).
- For completion, FilamentAsset now has getRenderableEntities(). This is
similar to sister methods getLightEntities() and getCameraEntities()
except there is no need to store a separate array.
- The web helmet demo does not need to enable shadows, they are already
enabled.
- The ViewerGui populateAsset() method was doing two things that are
now decoupled for clarity: setAsset() and populateAsset().
- The updateRootTransform() method is now called only when the autoscale
checkbox is toggled, instead of every frame.
- The getFooEntities() methods in Java now skip doing work for empty
lists. Actually these should not return arrays at all, but let's fix
that later, since it will break backwards compatibility.
We can't call prepareProgram() from any thread, since it is calling
into the backend. When we had more than a certain number of commands,
we would use the jobsystem to generate them and so prepareProgram()
could end up being called from a jobsystem thread.
This is fixed by looping through all the commands once they're generated
and calling prepareProgram() then.
The main changes are:
- ColorPass() and RefractionPass() are now static and moved into a
new RendererUtils file. These methods don't need FRenderer and are
more like a big "script".
- Cleaned-up includes
- Reformatted/reordered methods
The SimpleViewer C++ class was not viewer component like `ModelViewer`
and `<filament-viewer>`. It was actually just the UI builder used
in the `gltf_viewer` desktop app and the remote Android interface.
This adds a new implementation of the TextureProvider interface called
Ktx2Provider.
Tested using the KTX2 variant of the StainedGlassLamp model in the
Khronos samples repo.
Tested on WebGL 2.0 (Chrome v100), Android (Pixel 6 Pro), and Desktop
(Metal, OpenGL, and Vulkan via MoltenVK).
A "safe" mip-level is one that has exactly half the dimensions of
the current level. In other words, we guarantee that we can halve the
dimensions 4 times without loss (i.e. odd dimension).
This is achieved by effectively padding the viewport (i.e. making the
viewport's dimensions multiple of 16). The post-processing passes
eventually take care of cropping the extra padding so the final
image is unchanged.
This is a more generic solution to dynamic resolution padding, helps
with memory allocations and helps all the algorithms that depend on
mipmaping (e.g. DoF, SSAO, Bloom).
One important improvement brought by this change is that all "final"
post-processing effects are now able to handle a sub-region of the
source, including: color-gradding, fxaa and upscaling.
It was assumed that ETC2 is supported on all ES3 devices, but WebGL on
desktop machines does not support ETC2.
Note that WebGL has its own special extension strings for compressed
textures.
Some uniforms are needed during shadow map generation, other
during shadow sampling (color pass). We didn't have a clear separation
between them and ended up setting the UBOs that were needed only for
sampling multiple times during generation.
- rename common_math and common_shadowing from .fs to .glsl
because they were both included in both vertex and fragment
shaders
- add getFragCoord() which always returns coordinates in the
glsl convention. This is useful when used with RNGs to get
consistant results accross backends.
this is because this uniform is not well defined -- it's unclear if
it is set to the viewport or the buffer size.
also, it's not needed, and removes a couple multiplies from the shader.
- add getUserViewMatrix() on CameraInfo, the "user" view matrix is the
view matrix before we apply the world origin transform, it is needed in
a few places, so we make it a method so that in the future we could
precompute it if we wanted to.
- remove worldOffset which is just the last column of worldOrigin
it made it actually more confusing to have two version of the uv
(normalized and not). Also the unnormalized version was computed from
frameUniforms which is not great in the case of post-processing
(it just happened to work).
This allows clients to provide their own asynchronous texture decoders
for various mime-typed images. This is a plug-in component for gltfio,
in some ways similar to MaterialProvider.
There are two motivations for this: to decouple gltfio from STB and
to make it easier to integrate support for BasisU textures.
This also has the side effect of simplifying ResourceLoader, since the
texture decoding jobs have been moved out.
As part of this work, I made the "stb" CMake target into a traditional
static library. Previously we had several files called `Image.cpp`
whose sole purpose was to enable STB_IMAGE_IMPLEMENTATION.
If there is an error during the driver initialization, Engine::create()
returns nullptr, but the FEngine was allocated and would then never
be destroyed.
mTerminated was useless because by construction it would always have
the expected value.
This version is used only on qualcomm devices. It's now forbidden to
create a program inside a renderpass. Unfortunately there was still
one codepath doing so.
this state only exists during Renderer::render(), having it outside
of view is more flexible as it give us an opportunity to adjust
camera parameter globally before drawing.
Also greatly reduced the size of RenderPass (which is a Value object).
mipgen can now emit basis-encoded KTX2 files. Both the desktop and
web "suzanne" samples use this as a test for compressed textures.
This PR does not add KTX2 support to glTF, but it's on the way.
`BasisEncoder` has a builder style API that calls the basis encoder to
create KTX2 files. This hides some low-level BasisU features that we are
not using, like file I/O and mipmap generation.
`Ktx2Reader` is an easy-to-use API for creating Filament textures from
KTX2 files. Its API primarily consists of these two methods:
bool requestFormat(Texture::InternalFormat format);
Filament::Texture* load(const uint8_t* data, size_t size);
The first method is used to build an ordered list of formats that are
supported by your hardware. The second method consumes the contents of a
basis-encoded KTX2 file and attempts to produce a Filament texture with
a preferred format.
IMPORTANT: Our tools still let you use KTX1 for non-compressed images
because it is useful for HDR, but you can no longer use KTX1 for
block-compressed data.
Partial fix for #4771.
This is only a good place for a flush *if* we're going to draw another
view (so the GPU can start working). Otherwise, it can be costly
on some drivers and unnecessary since swapbuffers will do the same.
The original article we used for our bloom (siggraph'14) called for
a radius parameter for the upsample stage. We're always using 1.0 right
now, but it is useful to keep this possibility for experimentations.
a bug was introduced in 8/2020 where the downsampling filter was wrong,
due to a mistake using textureLodOffset, which obviously uses offsets
in source texel -- we were assuming destination.
Path resolution was broken with #5285, which only worked when the glTF
happened to be at root level. This new fix has been tested against:
- My Sponza zip file that hass all files in a "sponza" folder.
- My Bistro zip file, which has resources in a child folder relative to
the gltf file
- A self-created flat zip using IridescentDishWithOlives, with
everything at root level.
Side note: Bistro still fails on a Pixel 6 Pro Mali but for an unrelated
reason: (null deref in backend::TimerQueryNative::queryResultAvailable)
- don't use __PRETTY_FUNCTION__ and try to parse it, __func__ is
standardized and in most case returns what we want (the function name).
- add native support for string_view in our ostream.
- uninline string support from ostream
When creating a KTX file (e.g. with mipgen), you can of course choose
whether or not you want to use an sRGB format.
At load time, your app has an expectation about whether a particular
texture has an sRGB format. e.g. the glTF convention is that albedo
textures should be sRGB, while roughness textures are linear.
Before this commit, our KTX loader would look at the app's expectation,
then silently re-interpret the bits in the glTF texture in order to
match this expectation. This seems very wrong.
Instead, if the expectated format does not match the format in the KTX
file, we now print a warning.
Fixes#2422, which will also be obsoleted by our upcoming KTX2 support.
The `g_linearized` variable was being used for two purposes: to denote
the linearity of the source format AND the linearity of the destination
format. This was confusing and is now split is `sourceIsLinear` and
`destIsLinear`.
This change has no effect on the the look of the suzanne demo.
We do not support these formats and they add bloat to the basis tables.
In a release x86 build, this reduces the transcoder size from 774 KiB to
475 KiB.
Allocation and destruction of handles generates a fair amount of code
because they are synchronized and the spinlock is inlined.
So we fix this by generating the 3 (de)allocation methods we really
need, we only need 3 because we're using 3 pools. These are now
out-of-line, which reduces size and reduces pressure on the i-cache.
Performance is not affected much because in the end it's just a
static branch (and in most case the return is elided).
The main change here is that instead of allocating a Dispatcher on the
heap and storing a pointer to it in the CommandStream, we now have
a Dispatcher directly inside the CommandStream.
This avoids a heap allocation and a dereference when executing a command.
Changes:
- Remove the strange header-only variant of libs/image
- Rename KtxBundle => Ktx1Bundle
- Move image/KtxUtility => ktxreader/Ktx1Reader
- Add unit test for Ktx1Reader and test stub for KTX2.
Notes:
- Ktx1Bundle does not depend on Filament and is used by cmgen
and mipgen to generate KTX files.
- Ktx1Reader has a dependency on Filament and should therefore live in
a separate library, which it now does.
The `demo_*` web samples were using unpkg to refer to the Filament build
rather than using the local copy, which was inconsistent with the other
web samples.
We now use the local copy of Filament for everything except the
drag-and-drop viewer, which always uses the latest version of Filament.
With this change we are now generating refraction and reflections
buffer into their own layer of a 2D array -- so they can coexist.
This change doesn't actually enable both at the same time yet.
There are downsides to this approach:
- a 2d array of 2 layers is created even if only one of reflection or
refraction is active. This could be fixed at the cost of more
complexity.
- if reflections are active then refraction must use a RGBA16F texture
instead of RGB_11_11_10, because they share the texture
unlike for refraction, the reflection buffer is distinct from "the"
color buffer, this allows an optimization (compared to ssr) when we
generate the mipmap chain -- we can allocate the mipmaped texture
and render the SSR pass directly into its level 0. This achieved
use the framegraph's forward resource feature.
With this change, shaders are compiled at program creation, programs
are linked at the start of the next render pass and queries are
deferred until first use.
This should improve overall performance on some drivers.
This reduces the size of OpenGLProgram from 64 to 32 bytes and
improves the code that sets new samplers.
The main simplification is that we're not trying to "pack" the
texture units used in the program. For e.g. we could be using
units 0,3,4, where before it would be 0,1,2.
This allows us to do less tracking.
Another optimization is that we're discarding entirely a SamplerGroup
if the program doesn't use any of its samplers. This helps remove
a test in updateSampler which in turn remove somem tracking data.
Instead of recomputing the Frustum from its 8 vertices, we compute it
from the projection matrix directly. This ensures this works with any
projection matrix. Building a Frustum object from 8 vertices required
these vertices to be given in a certain order which wasn't correct if
the projection was flipped for instance.
Removed the API to construct a Frustum from vertices.
fixes b/225975881
move its content to DriverEnums.h, we do this because it is used
in libfilabridge, which has an unspoken rule that it only includes
DriverEnums.h.
filabridge also only has a header dependency, so it can't call any
method, not even operator<<.
Also cleanups and simplifications.
The main simplification is that we don't need an actual map to retrieve
the global offset of a sampler, it can be easily calculated as:
global_offset = offset_of_the_block + local_offset
Instead of passing the level and layer explicitly to gaussianBlurPass,
we rely on the information already contained in the handle. i.e. we
honor the "subresource" part of the handle (if it has one).
In other words, it's now possible to pass a subresource (e.g. a layer)
to generateGaussianMipmap or gaussianBlurPass and things should work as
expected.
The problem here would happen when forwarding a subresource (i.e.
replacing an existing resource by a subresource) and the existing
resource had been written to. In this situation, the subresource's
parent needs to depend on the subresource (i.e. as if it was written to
by it). This would normally happen during write() but in this situation,
the write had already happened.
the dependency graph would be incorrectly severed in the situation where
a subresource was written to and later its parent was read from.
In this situation, the parent node is in fact a new version of the
original parent node, so we need a "read" dependency of the orginal to
the copy (otherwise the orginal node is not a dependent of anyone
and gets culled).
Some clients need to link against both Filament and OpenGL. This can lead to symbol clashes under certain circumstances. As a fix, prefix all of our `bluegl` symbols with `bluegl_`. Previously we made this naming change for Windows, but now we'll do it on all platforms for simplicity.
The existing behavior was surprising for users who draw opaque objects
into a semitransparent views, and this was especially evident with
the labels in `TextureLinearInterpolationTest`.
We now disable blending for MASKED, which is what our existing materials
documentation already says. We also now set the fragment alpha to 1 when
the fragment is not discarded, which prevents the "punch through"
effect. This is consistent with ThreeJS.
Fixes#4576.
We were decrementing activeJobCount after removing the job from the
queue, which could cause other threads in the pool to preempt us before
the decrement, causing them to spin forever trying to get a non-existant
job, until the decrement actually happened.
Now we always decrement first and fix-up the count if we couldn't get
a job from the queues. The race is inverted, and doesn't cause threads
to spin a long time.
fixes b/201100123
This removes some special handling of the default render target lifetime
that is no longer needed, and renames "surface" to "swapChain" where it
is appropriate to do so.
This is a gltfio API change (!)
Jave clients now need to call destroy on MaterialProvider.
Previously, the Java AssetLoader took over ownership of a native
material provider upon construction, but this was neither documented
nor consistent with the C++ layer. (This is historical; in the past we
did not expose MaterialProvider to Java.)
One motivation for this (aside from API consistency) is that users may
wish to preserve the material cache from one run to another.
Fixes#5132.
We now have a single varyings.glsl containing our varyings for both
the vertex and fragment shader. This file is included with the right
definition of VARYING as `in` or `out`.
inputs.vs is now renamed attributes.vs
This changes the WebGL and desktop glTF viewers so that they always
call `updateBoneMatrices`, even when there are 0 animations. Note
that our Android sample was already doing this correctly.
When combined with #5301, this fixes#5299, although users would need to
use the `recomputeBoundingBoxes` feature in gltfio (`-r` in the desktop
viewer) for this model to be scaled to fill the viewport, since its
embedded bounds are quite large.
In the past there was an API gotcha because users had to "get" the
animator before releasing the glTF source data. This could have been
surprising because it was a getter method, not a factory method.
This was due to overeager optimization on my part, I wanted to avoid
animator overhead for non-animated models, when in fact it has very
little overhead.
Moreover, the animator is conceivably useful even when there are no
pre-supplied animations (e.g. for applying skins), so let's just create
it unconditionally.
Motivated by #5299.
Two changes:
1) Khronos has moved from "master" to "main".
2) BlueVK was attempting to generate reasonable "operator<<" support for
bit flags but this was buggy due to type aliases. Since we weren't using
it anyway, I simply removed this functionality from BlueVK.
Instead of having 2 fields we're following the vulkan convention of
having only the layer field.
The layer/face convention is still maintained in the public APIs.
fixes#5273
Dragging a zip file into the Remote Viewer page would fail if it
contained a glTF with `./` prefixes in the `images` section. The best
fix is to use Java's proper URI object rather than trying to parse the
string.
The JSON response to /api/active became malformed after #4465 because
raw hex strings need to be enclosed by quotes.
This commit changes the variant format in the /api/materials response
to be consistent with one used for /api/active. By using integers
instead of strings, we're avoiding the need to parse integers at run
time.
The JSON error did not appear in the Chrome console because it was being
silenced as a hack to appease "matinfo --web-server". I fix this by
removing the hack and simply emitting a valid response when there's
no live backend.
Also fixed the display of materials, which were always being marked
as active even when they had no active variants.
We held a reference to a cache item after potentially clearing it due to
pool growth. I was able to trigger an error only after enabling ASAN and
loading a large model. Many thanks to @jeanlemotan for catching this.
When we added per-layout arenas for each of the 3 descriptor types, we
did not account for them when determining how much of the Vk Pool is in
use. Therefore the "growth" (really a re-creation) of the Vk Pool wasn't
always occurring when necessary, causing descriptor set allocation to
fail with large models.
In the current version of the library, it looks like the DYNAMIC config
macro has been replaced with a STATIC config macro.
Also disabled the "unused-private-field" warning since this is a 3rd
party library and its not our fault.
The main change here is from ResourceList which ended-up generating
a lot of code due to inlining. This class is only used for tracking
user resources and is not in the performance path.
This saves another ~5K or so of code.
This caused a unit test failure because a StaticString constructed
from "make" had a different hash than one constructed from a literal,
even though the two strings were lexigraphically equivalent.
Having MorphTargetBuffer in FRenderPrimitive is a concept of glTF. Filament doesn't have to follow this concept. Actually the responsibility of FRenderPrimitive is to define vertex input stream because FRenderPrimitive maps to HwRenderPrimitive in Filament. If we store MorphTargetBuffer into FRenderPrimitive then it exceeds the responsibility of FRenderPrimitive. Because MorphTargetBuffer doesn't have any information on how to set up vertex input stream. So handling morphing like skinning will be better.
We were not unrolling the == loop because the generated code with
unrolling was very branchy; but that's not a good call either because
the loop has the same number of unpredicted branches.
Theoretically the compiler should be able to emit a branchless == but
it doesn't. At least we give it a chance.
When we introduced texture-based morphing, our custom depth resolver
needed to be updated to set up samplers correctly. This fixes a
validation error about shader stage access.
Every sidecar texture should have the same dimensions as its parent
texture.
Prior to this change, the sidecar texture would have the dimensions of
the RenderTarget wrapper rather than the parent texture. This was wrong
because the RenderTarget might be slightly smaller than the texture.
This caused an issue when the same texture was attached to two render
targets with different sizes, because there's only 1 cached sidecar per
texture.
We were passing the wrong texture object to VulkanDisposer::acquire().
MSAA depth sidecar textures are not managed by VulkanDisposer, but their
parent textures are.
Fixes#5217.
When we overhauled image layout transitions, we moved as many
transitions as possible into the render pass. However the transition
that we perform for "depth read only" layout needs to be applied to
multiple miplevels, so we cannot use the render pass for that.
We now handle "too many bone weights" in the same way that we handle
"too many UV sets". i.e. emit an error message and do not panic.
This change allows us to render the model in #5234 quite reasonably.
Fixes#5234.
This fixes the emscripten binding errors that we've been seeing
with the <filament-viewer> test page, which prevented us from
including web in the last few Filament releases.
The binding errors were caused by double-initializing the emscripten
module.
I fixed this by allowing clients (e.g. FilamentViewer) to call
Filament.init() more than once. We now accumulate a list of "on ready"
callbacks that get triggered after the emscripten module becomes ready.
As far as I can tell, multiple canvases were actually always broken, and
the viewer test page worked in the past only because we got lucky.
Previously, the Vulkan backend made an educated guess about the depth
write state during the start of the render pass. The logic for this
did not make any sense, so now we're replacing it with an explicit
hint that PostProcessManager sets up. In a sense this gives backends
a sneak peek into the raster state.
The existing unit test had an incorrect expectation in what happens
after splicing an existing range. Fixing the unit test revealed an
actual bug in the RangeMap implementation. It should never modify the
lower bound of an existing interval, because that invalidates the
iterator. It should also never retain a pointer or reference to a range
when the range is potentially removed by subsequent codelines.
We can now specify an "instance count" per renderable during creation.
This instance count applies to all render primitives in the
Renderable.
This will simply draw the renderable "instance count" times. A new
method available to vertex shaders, getInstanceIndex(), allows the
material to discriminate the instances and adjust the position/transform
accordingly.
Typically this is used for particle systems.
Two big changes to simplify and fix layout transitions:
(1) The RenderPassKey struct has been reduced from 88 bytes to 56 bytes
by using custom enum types and bitmasks. It also now has separate fields
for "final" and "initial" image layouts.
(2) VulkanSwapChain now leverages VulkanTexture, which enables it to
share tracking functionality, avoid duplicated state, and have less code
overall.
In a future PR we will clean up the ReadPixels and Blit paths, and also
remove some hacks that appease Vulkan when SSAO is enabled.
The main change here is that for screen-space reflections, the lod
calculation takes the camera distance into account.
We also now correctly take into account that we blur each lod
successively which increases the standard deviation by 10%. This applies
to both refraction and reflection.
This works by first generating a reflection buffer which gets blurred,
then the color pass samples from this buffer according to the roughness
of the surface being rendered.
A lot of the changes here involve utilizing "reserved" variants for
the new "SSR" pass and all the fallout from that.
Variants are no longer just a bit mask, but rather a combination of
some bits, depending on the variant. Because of that the variant filer
must be updated.
Basically we now make a distinction between the "variants" as a public
material API and the actual `Variant` data type.
This change does the impedance match between the two.
The previous code would convert each element of the source data
into 8 bit-per-element, but we wnat to preserve the original format
that the user provides.
The new solution is to use `slice()` which is a robust way to clone
all the data in a typed array.
This fixes the new regression with Triangle that Ben caught.
If emscripten grows the heap inside one of our BufferDescriptor binding
functions, then the old heap becomes "detached" and an error can
occur.
This fixes the issue seen with the Parquet demo that Ben caught.
filament/src/Renderer.cpp
- make code mode readable, hopefully
- SSR mipmap generation is now more or less standalone
- when possible, resolve color buffer directly into
mimpmapped texture's base level.
All three types of caches (descriptor sets, pipelines, and pipeline
layouts) are now managed in exactly the same way. They all use an LRU
eviction scheme that is based on a count of command buffer flush
events.
Vulkan objects can only be destroyed if there are no in-flight command
buffers that reference them, so an easy way to know when it is safe to
evict a given entry is to wait for "N" flushes after its last use, where
"N" is the number of command buffers in the command buffer ring.
Another big simplification is that there are no more dirty flags,
instead we store two sets of state vectors for each type of cache: the
"currently bound" state, and the "current requirements" state.
- Rename projectToPixelMatrix to uvFromViewMatrix, this match our
existing style better.
- slightly more efficient direction transform
- limit roughness to 0.1 instead of 0.01, because in a lot of cases,
the roughness increases with the LOD, for instance if it comes from
a texture (to combat aliasing).
The current Variant is need to calculate BindingIndexMap correctly.
But we can't use the current Variant when calculate BindingIndexMap
because SamplerBindingMap uses only the dummy Variant. Both are
should be same.
The morphing sampler group can be added if skinning or morphing is
enabled. However SamplerBindingMap can't know skinning or morphing
is enabled because only dummy Variant is used. It causes generating
the different sampler bindings between SamplerBindingMap and
program's sampler groups.
Fixes#5139
- Make sure to disabled SSR when it's... disabled.
- Fade the reflection when the ray direction is towards de camera,
where it will likely hit a back face
- Simplify the fading code, for near identical results.
Fixes#5142 by replacing unsafe pointers with map keys.
One of the differences between robin_map and unordered_map is the
following:
pointers to keys or values in the map are invalidated in the same
way as iterators to these keys-values
Therefore it is unsafe to track the pointer to a value that is stored
in a robin_map.
This is mostly just code cleanup. One actual bug was the fact that the
dummy sampler was re-created every time a new pipeline layout was
created.
It also felt strange to use `auto&` to refer to a C-style array. I
changed this into a `std::array` which is more consistent with other
fixed size arrays in this class.
This fixes the gltf_viewer automated testing mode, invoked via
`--batch=default --headless`.
ReadPixels was being issued with an out-of-bounds size on high DPI
platforms, which caused weird backend errors.
Since we create an invisible SDL window while in headless mode, the
presence of the SDL window does *not* indicate headless vs non-headless.
Partial fix for #5111
Because the morphing buffer is actually a texture, it's possible that
the last line is not a full width when updating the buffer.
Because texture are updated via a rectangle, it was possible to read
past the malloc'ed buffer during the update.
Moreover, because the count can be specified, we can't just blindly send
more "dummy" data.
Finally, added an offset to match the skinning API, and in that case,
the first line can also be incomplete.
We fix this by issuing up to 3 texture update calls if needed.
The java/js API update will come later.
Support legacy morphing (morphing with targets supplied via VertexAttributes) for older clients. This gives clients more time to transition over to the new MorphTargetBuffer API.
Instead of building the Variant based on flags in RenderPass, we just
pass the Variant itself to RenderPass. The caller has more knowledge
of what it wants to do.
This allows the `Horse.glb` model to work with Vulkan without any
validation errors. As a reminder, the glTF spec says:
```
When normals are not specified, client implementations MUST calculate
flat normals
```
Fixes#5115.
* Get the morph target count from the renderable
* Set the morph target count by Builder
* Update morph target weights partially
* Remove noexcept at functions could throw exceptions
* Update Java bindings at RenderableManager
* Add missing comments
* Update morph target weights from offset
Co-authored-by: Mathias Agopian <mathias@google.com>
This allows `MorphStressTest` to work on Vulkan.
However, `Horse` is still broken because it provides positions but not
tangents. Separate fix for that is coming.
Partial fix for #5109.
This fixes validation errors and makes a first pass at simplification.
VulkanTexture now tracks image layout using RangeMap, which paves the
way for further simplification.
There is no need to go through all primitive and call updateSamplerGroup,
because the SamplerGroup never changes -- it just hold the texture that
holds the data.
This is because we're using the same program variant for skinning
and morphing, in the skinning-only case, the buffer won't be accessed
in the shader, but it must be present.
fixes#5085
This will allow the Vulkan backend to efficiently track the subresource
image layouts for each texture.
This is a sparse container for a series of ordered non-overlapping
integer intervals, where each interval maps to a concrete value.
This fixes a double-initialization problem for one of the function
pointers, and also updates the BlueVK generator to fix issues with the
latest Khronos XML file.
The corollary C++ changes will be made in a subsequent PR since they
will be difficult to review.
See #5026.
2D array textures are initialized with .depth = 1 and layerCount = depth (see line 58 in VulkanTexture.cpp). By setting layerCount = 1 only the first layer was copied over, leaving the other layers uninitialized.
This functionality (in the Automation section) was violating a
constraint that was landed in November.
1) Call postRender inside beginFrame / endFrame.
2) Use RGBA when issuing ReadPixels (required by some backends) and
convert to RGB when dumping out the PPM file.
screen-space reflections are integrated in the indirect light computation
(similarly to screen-space refraction), this is because it can be seen as
the specular term of screen-space GI.
However, because this effect is screen-space, the data it accesses has
the ibl luminance (and exposure) applied.
Besides some minor refactoring, this change just applies the
screen-space reflections *after* the ibl's specular term is exposed.
We can now do screen-space refraction and reflections at the same time.
This change mostly removes the checks that were preventing it from
working.
The real change in the PR is to adjust the reprojection matrix based
on whether the SSR buffer (both for refractions and reflections) comes
from this or the previous frame.
what's not allowed at this point is an object which has both screen
space refraction and reflection.
this is accomplished by just always disabling screen-space reflections
for the translucent step of the refraction pass.
The `uint8_t` here needs to be cast to an integer to be printed
correctly. Also these warnings seem to be quite common so we should
hide them in Release builds.
These warnings probably indicate an actual problem that I do not fully
understand yet.
Move the command generation of the structure pass into its execute
block, meaning that if the structure pass is culled, the command
generation is now skipped too.
The same can be achieved with VSM + blur=3 however, this is noticeably
slower. Also when using transparent shadows, VSM needs a much larger
blur to iron out the dithering pattern.
Fixes#5048, #5039
* Replace generic tonemap curve with a simpler one
This change removes the shoulder parameter which had inconsistent
behaviors. The new curve is simpler and designed to still match
by default the gray point and the contrast of ACES in a bright
surround.
* Fix build
ostream internals are now protected by a lock, which ensures the
internal state stays consistant, however, this won't prevent
multiple threads to have their output ominterfering with each other,
which is no different from the stl behavior.
This fixes#4992
The version of Texture::setBitmap() that tool an Android bitmap handled
callbacks differently and in certain case caused a "double release" of
the callback object. This didn't actually cause problems though.
We now use the same mechanism used elsewhere (i.e. JniCallback).
it was incorrect to store bone matrices as quaternions because it is
allowed for these matrices to have a skew component.
We now store the 4x4 matrix -- which is the same amount of data as
before, however we compute the cofactor matrix in the vertex shader when
transforming normals.
fixes#4887
- the hammersley sequence was completely wrong because of a missing
highp precision qualifier
- roughness 0 was also wrong because of divide-by-0
Fixes#4668
- FILAMENT_SKIP_SDL2=ON is used to skip dependencies of sdl2 and sdl2 CMake
- FILAMENT_LINUX_IS_MOBILE is used for Mobile build
Signed-off-by: Joel Winarske <joel.winarske@gmail.com>
__ANDROID__ is always set by the toolchain and less likely to cause
conflicts than ANDROID. This change also removes the -DANDROID flag
we set ourselves in our toolchain CMake files since we don't need
it anymore.
* Use locale-independent string->float conversion
strtof and friends are locale aware and won't parse decimal numbers
with a period ("12.6" for instance) in locales that use another
character for the decimal period ("," in French for instance).
This change introduces a new function called strtof_c that forces
the use of a specific locale (called "C") to make sure we always
parse floats in the desired "C" format ("12.6").
With C++17 we should be able to use std::from_chars but this API
is not implemented in clang for floats at the moment.
* Fix Linux
A recent refactor was causing the following error when the vertex domain
was set to `device`:
```
ERROR: main.vs:23: 'material' : undeclared identifier
ERROR: main.vs:23: 'materialVertex' : no matching overloaded function found
```
We're currently only using the positive layer of EVSM which works
work small blurs and anti-aliasing. This just rearranges the code to
make it easy to test the full formulation.
This is possible because, in fact, we know if we're dealing with a
spot or directional light when we invoke shadow(). So a conditional
inside it is resolved at compile time.
This will allow more flexibility in the future. Also now the shadow()
function only needs the shadow index and cascade -- which is more
future proof (e.g. if we want to handle more than one directional
shadow or spot lights with cascades).
this effectively undoes a recent change, where we had a method for
spot lights and one for the directional light. instead, we can
calculate the bias at the correct Z on the caller side -- which is
needed only for spotlights.
The faulty commit was:
commit 23dab0a013
Author: Mathias Agopian <mathias@google.com>
Date: Fri Oct 29 12:03:14 2021 -0700
Fix very narrow spotlight lighting and other minor issues
Shadow Receiver Plane Depth Bias is only needed when using large PCF
filters, which we are no longer doing. Large filter kernels are now
supported through VSM sampling.
This changes how we select the "optimized depth vertex shader", but
this shouldn't change the current behavior.
We now select the "optimized depth vertex shader" if and only if the
user code is empty. In that case, we can safely assume we can remove
all the code that's not necessary for the depth, since it is all
controlled by filament.
- remove PCF "low" quality, we only use "HARD" now, when using PCF.
Higher quality levels are achieved by using VSM.
- added a version of PCF that doesn't use a shadowSampler for future
use.
The normal bias is now computed correctly, this requires to compute
the z in lightspace in the shader.
Note that this would not work as well if we used LISPSM, but we'll
cross that bridge when we get there.
- constant bias and normal bias default values in java didn't match
C++ or the documentation
- stable shadows were enabled by default in java
- polygon offset biases were missing from the java API
- document and don't apply polygon offset to VSM
- remove unused code
We now cull the shadow casters before computing the near/far plane
for spotlights -- we can do that because we know the light's frustum.
So only these casters that contribute to the shadow are accounted for
when calculating the near/far plane.
This PR also include more cleanup and simplifications.
Near/far plane is now computed dynamically, this significantly
improves the shadowmap depth resolution.
Quite a bit of refactoring was necessary to get all the right data
in the right place, in particular SceneInfo is now passed around for
both directional and spot shadows.
The froxel code was failing when a spotlight cone was too narrow. This
is fixed here by never using a cone smaller than 0.5 degrees during
forxelization.
Additionally we now silently clamp the cone angles to 0.5 degrees at
the API level because, the falloff was also failing due to floating
point precision in the shader.
Finally, we clamp the inner cone upper value to the outer cone's
instead of the other way around. i.e. the outer cone defines the
spotlight while the inner cone just controls the falloff.
When calculating the linear depth for VSM, we were using the whole
range between 0 and the far plane, the near plane wasn't taken into
account.
This can be a problem is the light is very far, but it's near plane is
closer to the camera/scene, in this case the depth precision wasn't
used optimally.
Note that we don't hit this problem currently, because the directional
light is constructed such that its origin is at the near plane, and the
spotlights have a fixed near plane (which is a problem and will be
fixed at a later time).
The bug that prevented them to work has been worked around, but we
don't know when or how. The original bug still exists as demonstrated
by our standalone test apk.
For now, we reenable MSAA VSM on Adreno.
* Perform sanity check when combining static libraries
This is a small modification that simplifies Debian packaging when one
or more vendored dependencies are replaced by system shared libraries
and no longer need to be combined with a Filament library.
* Verify vendoring before including license texts
This is another small modification to simplify Debian packaging when one
or more vendored dependencies are removed and replaced by system
libraries, so they no longer need to be considered when compiling the
license texts.
- remove PCF MEDIUM and HIGH quality -- these were never used in
practice, and "quality" really meant "blurriness", now we have VSM
for doing that with much more control and more efficiently.
PCF_HARD is now the default. PCF_LOW is still available at compile time
for now. It shouldn't be needed though because VSM can achieve the same.
Moved the divide-by-w of light space into the shadow() method -- which
known if it should be done or not.
The codebase needs only a few additional standard #includes to compile
against libstdc++ on Linux; presumably those headers are implicitly
included with MSVC's and Clang's standard C++ library, but even if
libstdc++ compatibility is not a goal, it is advisable to have them
included directly.
in particular add a terminate() method to FrameSkipper instead of
destroying driver objects in the destructor -- this matches all other
objects.
also remove dependency on FEngine which wasn't needed.
- move the control code out of FrameInfo and into
View itself. FrameInfo now just gathers information about the
frames instead of also doing part of the control.
- the control code has been refactored into a more formal PIDController.
- a few bugs were fixed in the control loop and default parameters
tuned.
The control loop itself now outputs a relative scale factor instead
of an absolute one. The relative scale factor seems easier to
control and is less jittery, and doesn't have to rely on the "integral"
term of the PID.
It's possible that more tuning is needed, but the scaling is now
more stable.
- remove getProperties() we'll put it back if we need it some day
- use unordered_map because it generates less code than robin_map and
here performance is not critical
- defaults to 31 history points instead of 3, this gives a much better
estimate of the frame rate.
- make sure the calculations work for any definition of our internal
duration<> (it's useful to use milliseconds when dealing with
refresh periods).
- don't round to 8 pixels if the scale factor is exactly 1
- fix a few comments and warnings
* mipgen: Linearized PNG bitmaps (such as normal maps) no longer perform gamma transform on read.
* mipgen: Using "-k normals" argument now works for all file types, not just KTX
* Web: Exposed SurfaceOrientation functions getQuatsHalf4() and getQuatsFloat()
Unfortunately this bug appeared in recent drivers on some devices, it's
virtually impossible to know which device/drivers have this issue, so
the workaround is active for all Adreno GPUs.
glInvalidateFramebuffer is too aggressive and prevents loading of the
GMEM even if it's only called at the end of the render pass.
Statically link SDL2 to make our samples (glTF Viewer, etc.) completely
standalone, and include missing resources (fonts and default environment
map for the IBL).
When supported and enabled, resolve MSAA using an HDR aware filter,
which improves anti-aliasing quality.
This is only supported with backends that support multi-sampled
framebuffer-fetch. Currently, only Metal on iOS and GLES.
Update remote ui.
The DSR options were carried all the way to the final blit that is
sometimes needed to impedence-match our rendering features with the
swapchain. This blit is never a scaling blit, but we were using the
FSR option, which would sometimes trigger the FSR scaling code.
FSR assumes modern OpenGL. The functions that pose problem are in fact
never used in filament, so it doesn't matter how they're implemented.
We use the HLSL version instead.
Java callbacks are now directly dispatched to their handler, instead
of first going through filament's opportunistic dispatch, reducing
callback latency.
All APIs that take a callback as argument now also takes a
CallbackHandler* which is a new interface used to dispatch the
callback.
CallbackHandler* can always be nullptr in which case the behavior is
unchanged.
When CallbackHandler* is specified however, it is used to dispatch the
callback: its post() method is called from a service thread as soon
as possible (this will NEVER be the main thread), CallbackHandler::post
is then responsible for scheduling the callback onto the thread the
user desires. This is intended to make callbacks interoperate with
the platform/OS's own messaging system.
The main issue that gets fixed here are:
- VK_IMAGE_LAYOUT_UNDEFINED cannot be used if the image content is to
be preserved after the transition. Unfortunately, there is more than a
few places in the VK backend where we use VK_IMAGE_LAYOUT_UNDEFINED on
images that are later used as sources.
- accessing an image memory from the host is only supported if the the
layout is PREINITIALIZED or GENERAL. However, images in the staging
pool were transitioned to other layouts and put back into the pool,
later they would be mapped/memcpy'ed into. Instead we now always use
the GENERAL layout and never change it.
- images that where in the pool where transitioned using the miplevel
of the texture we were copying into, however this didn't make sense
because images from the pool don't have mip levels.
As part of these fixes, we also refactor imageLayoutTranstion(),
because there was two copies of this function, one specific to texture
and another one more generic. We now always use the more generic one,
with a new helper for textures.
Note: didn't fix "readPixels" which has at least problem (1), because
it's a tricky implementation, and it requires more toughts.
A new Engine::pumpMessageQueues() method can be used to trigger all
pending user callbacks right away. This can help reducing latency
of certain callbacks such as picking queries.
This is typically called once before calculating the next frame's
parameters (e.g. object positions or appearance that may depend on a
callback result).
Fix some comments and documentation.
This is a pixel accurate implementation of picking. Picking queries
can be created on view, and upon completion a user provided callback
is called with the Entity of the renderable at the queried coordinates
in the viewport.
Picking queries typically have 1 or 2 frame of latency and may impact
performance on some drivers.
It is mostly intended for use by editors, or when latency is not a major
concern. This api should not be used for dragging/moving objects, it is
intended for initial picking only.
Picking is implemented in the structure pass.
The depth buffer value is retrieved and the fragment coordinate is
reconstructed and passed to PickingQueryResult. This can be used in
turn to calculate the view and/or world space position.
This is just a minimal change to get the R_INTEGER format to work.
- if src/dst types are identical, just copy (this avoids a mul and a div)
- add R,RG and INTEGER types
There a just new inline helpers to more easily use lambdas, functors and
method callbacks with {Pixel}BufferDescriptor.
A BufferDescriptor can be constructed like this:
auto bd = BufferDescriptor::make(buffer, size, [](void* b, size_t s){ });
or
auto bd = BufferDescriptor::make(buffer, size, &Foo::bar, *foo);
the code generating the commands for the structure pass (called DEPTH)
in the code was different that from the color. This made sense, but
isn't great from an architectural standpoint.
Moreover, the special filtering flags DEPTH_FILTER_*_OBJECTS were
useless because part of their functionality was handled in the DEPTH
code directly.
Instead, we now generate the DEPTH commands the same way than we do for
COLOR, but we honor the DEPTH_FILTER_*_OBJECTS flags properly.
This should help Filament properly support more glTF assets with
transparency, and should make Filament behave more like other
renderers such as three.js.
The finalizer can't be used to dispose of filament resource, because
it runs on its own thread.
Added a destroy() method to all IBLPrefilter related classes that must
be called once the object is no longer needed.
note: Resources will be freed eventually anyways when the Engine itself is
destroyed.
fixes#4633
A lod bias can be applied to textures when dynamic resolution is
enabled. A proper lod bias is calculated and applied for quality levels
HIGH and ULTRA.
Lod Bias is implemented in glslang, which mean it's ignored when
glslang is not used, which currently happens with OpenGL backends with
optimization turned off (which includes filament LITE). This may be
fixed in the future.
We were decrementing activeJobCount after removing the job from the
queue, which could cause other threads in the pool to preempt us before
the decrement, causing them to spin forever trying to get a non-existant
job, until the decrement actually happened.
Now we always decrement first and fix-up the count if we couldn't get
a job from the queues. The race is inverted, and doesn't cause threads
to spin a long time.
the gc usually runs for a very short amount of time, so the jobsystem
overhead is very significant compared to the actual work.
additionally this works around a scheduling issue that happens sometimes
on some devices where a thread could be "runnable but not running" for
many milliseconds.
On some GPU such as Adreno, the shader compiler flattens the early
exit condition, which becomes useless. We work around this by using a
two pass version of the algorithm using the depth buffer for
skipping "fast" fragments that have already been rendered.
This improves performance significantly, e.g. from 5ms to 1.3ms on
Pixel4.
Currently this mode is always enabled, which hurst performance on GPUs
that don't have this problem. This will be remediated later.
Now that FSR scaling is cheap enough on mobile, we use it for quality
levels MEDIUM to ULTRA.
MEDIUM and HIGH use the mobile optimized version, which has a slightly
lower quality, ULTRA uses the original version.
Additionally the RCAS sharpening pass can always be disabled by setting
the sharpen value to 0.
We used the "float" code with the "half" texture coords, turns out FSR
uses slightly different code for both.
We're now using the "half" code (using mediump float).
filament cannot use fp16, so we make the necessary changes for the
float version. Note that we are using mediump float, which ends up
using 16 bits floats anyways.
This provides 78% reduction in execution time (i.e. 4.6x performance
improvement). We see the EASU go from 4.2ms to 0.9ms.
The quality is slightly impacted.
Non sampleable buffers (Renderbuffers) are always rounded to 32 pixels
currently and on the backend side this buffer can end up being cached
as a sidecar buffer for MSAA. When it is created, it needs to be created
with the size of the texture it represents, not the size of the FBO,
which might be smaller.
In low-light conditions, peak luminance sensitivity of the eye shifts
toward the blue end of the visible spectrum. This effect called the
Purkinje effect occurs during the transition from photopic (cone-based)
vision to scotopic (rod-based) vision. Because the rods and cones use the
same neural pathways, a color shift is introduced as the rods take over to
improve low-light perception.
This function aims to (somewhat) replicate this color shift and peak
luminance sensitivity increase to more faithfully reproduce scenes in
low-light conditions as they would be perceived by a human observer
(as opposed to an artificial observer such as a camera sensor).
The night adaptation can be controlled using a 0..1 factor for artistic
reasons: `ColorGrading::Builder::nightAdaptation()`.
* Use wide gamut color grading and gamut mapping
This change introduces a new API on ColorGrading to enable or disable gamut mapping at will. This feature is currently off by default and while useful and recommended, it isn't cheap and we need to figure out what we want our defaults to be especially on mobile targets.
Gamut mapping can be combined with luminance scaling to properly control hue skews.
* Small cleanup
* More precise Rec.2020 conversion
- don't use a separate array for "reversedWindingOrder"
it's just one bit of data and we had 7 bits left in the Visibility structure.
- use Culler::result_type instead of hardcoded value everywhere
- other minor cleanups
The main changes are:
- shadowmap command generation is now done in the framegraph pass
itself, which allows it to be culled should the pass be culled.
- CameraInfo is created only once instead of twice / shadowmap.
It's not super heavy but also not cheap, as several matrices are
computed.
- simplified code.
src/details now only has the private headers of public types/classes.
Private/implementation classes have their header next to them under src.
This makes things more consistant.
This used to reside in View and it is now its own class. The reality is
that "per view" UBO is a bit of a misnomer -- currently we indeed have
one per View, but that's not required and in fact, in the future we might
want to have a separate one for shadow maps for instance.
A better name would be "per camera". Currently it is dynamically updated
when rendering the View and shadow maps. In the future this probably need
to be separated.
There was a confusion on utils::bitset<> API, it specifies the number
of words to use, not then number of bits in the set.
VariantList was sized to store 8192 bits instead of 128.
model/view matrices on Camera now store their translation as double
double precision. This allows filament to handle a very large world
space (thousands of kilometers).
Augment the TransformManager so it can maintain the 4th column as
double precision; we accomplish this by storing an extra float3 per matrix.
It's calculated as `doubleTranslation - float3{doubleTranslation}`.
We also add methods to set and get a transform as mat4, internally only
the 4th column is kept as double precision.
Finally when we calculate the worldTransform, we take this extra data into
account, but only for calculating the new 4th column, so the extra work
is small.
The new default values match almost exactly the filmic tone mapper which
is itself a close approximation of ACES. This result in a slightly more
contrasty and pleasing image out of the box.
- Images with an alpha channel are now properly supported. Blending is implemented directly in the image material by blending against the known opaque background color.
- Non-EXR/HDR images were not applying the proper transfer function and were therefore displayed incorrectly.
* Properly address the color grading LUT
With this change we properly sample from the texel centers when we should, thus avoiding a bias toward the low values. This was particularly problematic in the darks, resulting in darker results than they should have been.
* Save 3 scalar muls
We made this wrong assumption that views with a custom rendertarget
are never blended, but it's not true -- e.g. two views can use the
same rendertarget.
Fixes#4430
May impact #2802
* Use a clip space that matches our screen space for the z axis
We now set the projection matrix so that the clip space for the z
axis follows the inverted DX convention, i.e.: z_clip between 1 (near)
and 0 (far), which matches our screen space.
Note that the actual clip space in the GPU can revert to the "inverted
GL convention", i.e.: z_clip between -1 and 1, if the clip_control
extension is not present. In that case the precision benefits are
mostly lost.
Also note that there shouldn't be any user facing changes.
The projection matrix at the API level, still follows the GL convention.
Also, currently, the VERTEX_DOMAIN_DEVICE for materials also keeps
the GL convention (this is corrected in the vertex shader).
The gist of this change is to move the "reversed DX" mapping from the
vertex shader to the projection matrix.
* Update shaders/src/getters.vs
Co-authored-by: Ben Doherty <bendoherty@google.com>
Co-authored-by: Ben Doherty <bendoherty@google.com>
Camera::getProjectionMatrix and Camera::getCullingProjectionMatrix used
to return the projection matrix modified by scaling and shift, instead
they should return the value set by the user, especially when
setCustomProjection() is used.
Bring color grading back into the Rec.709 color space to match
previous behaviors. This change also implements an exact inverse
tone map function for the "Filmic" operator.
* Fix specular AO for the sheen and clear coat layers
We used a single specular AO term for the sheen and clear coat layers,
computed for the base layer. This was creating occlusion that was way
too strong when the roughness from the top layers was very different from
the roughness of the base layer. The effect was particularly obvious
on clear coat materials (car paint for instance).
With this change we can also remove the "grazing angle fade" artistic
hack that was previously introduced to combat this effect.
* Safer code
Currently there are 8 light channels, both renderables and lights can
be associated to one or several light channel, lighting occurs when
at least one channel is active on both the light and the renderable.
Fixes#4275
When we associate a sidecar renderbuffer (for MSRTT emulation) to a
texture, the msaa count comes from the rendertarget -- if this texture
is later used with a rendertarget with a different MS count, it should
still work -- in this case we have to reallocate the sidecar buffer.
This helps prevent over-darkening but it's an artistic hack.
We need to check how we compute the bent normals as it seems we
find occlusion where there is no occlusion. The effect is
particularly visible on clear coat materials like a car's body.
When calculating the froxel z slice, a depth buffer value of exactly
1 (i.e. far plane) would map to after the last slice, this value
must be clamped.
made the code more readable, hopefully.
Fixes#4388
We now have an option for evaluating the bent normals from SSAO.
This is used to improve specular AO.
Currently these bent normals are not used for diffuse lighting because
they're "flat" (face normals), which is too distracting.
The bent normal buffer is stored in the SSAO texture, in a separate
layer. This is the first post processing effect that uses 2D array
in order to limit our sampler usage.
This CL also changes how we handle SPECULAR_AO_BENT_NORMALS when
material bent normals are not available: we're now using the "Cones"
algorithm with the regular normal, instead of Lagarde's approximation.
- depthUtils.fs and geometry.fs are actually completely generic
at this point, and could be moved out of the SSAO folder.
- saoImpl and ssctImpl are just a way to be able make several versions
of the SAO material easily (which will be needed soon)
This all started because the gl backend version of blit() didn't
handle color attachments other than COLOR0 *AND* would actually
corrupt the destination attachments other than COLOR0 if present.
This is due to how very stateful the gl API is.
Since this is a case we're not running into currently, the GL backend will
now assert in that case.
Updated the Vulkan and Metal backends to also reject blits where
color buffers other than COLOR0 are requested.
Ultimately, we need to change entirely our backend blit API so it
is less GL centric.
It looks like they are not working, at least with the current version
of the drivers and/or MoltenVK. It is not impossible that we have a
bug in how we set the subpasses as well. This will need more investigation
later.
This fixes two bugs that combined in a way that prevented a double-free
error.
The destructor of the impl class for AssetLoader was never called, which
was sort of good, because it should not destroy the material provider.
The asset loader was never meant to have ownership over the provider.
SamplerGroup was comparing texture handles to decide if a texture needed
to be updated, however, texture handles are (quickly) recycled and
therefore can't be used for that purpose. e.g. if a texture is destroyed,
its handle could be reused quickly by another texture, if that texture
is now set on the SamplerGroup, it will ignore it, thinking it's not
different.
Previously, if you accidentally had two matdbg tabs open in Chrome, the
web app would hang. This fixes two bugs that prevented multiple
simultaneous clients:
1) The websocket handler broadcasted edit events to only the most
recent connection.
2) The number of server threads was only 2, but the actual web app
requires at least 2 threads for each instance, due to the
externally linked CSS file.
This can have a dramatic effect on SSAO and needs
to be adjusted based on the scene's scale/units.
The default value used to be about 6cm, and has
been changed to 5mm.
this allows the sidecar buffer to have the same lifetime than the
texture it represents, and therefore participate to the caching of
that texture.
Fixes#4338
* WIP New tone mapper API
* Implement tone mapper constructors and destructors
* Add new genertic tone mapper
* Make the generic tone mapper available in our sample UIs
* Fix warnings and crashes
* Fix generic tone mapper and graph mappers in the UI
* Add Java APIs for ToneMapper
* Implement copy/move operators for GenericToneMapper
This lets you see highly readable GLSL when transpiling the generated
SPIRV back to GLSL, with the original variable names preserved.
For now this is only useful when using `matinfo`, but it will soon be
useful in `matdbg` too.
The API now allows to create a standalone SkinningBuffer containing
Bones for skinning. This SkinningBuffer can even be very large and
contain bone data for several renderables.
New APIs on RenderableManager allow to switch to skinning buffer mode
and to set the SkinningBuffer (and window into it) to use.
Fixes#3238
* Generalize luminance scaling in color grading
Previously the luminance scaling step was tied to a specific tone
mapping operator, called "EVILS" in the API. This was however
somewhat misleading as EVILS really is a color handling system
that's independent of what we call tone mapping.
This change splits the luminance scaling step from the tone mapping
step, allowing the use of luminance scaling (the LICH part of EVILS)
with any tone mapping operator.
As a result, the operator known as EVILS is currently mapped to the
linear operator and renamed to "RESERVED" until it is replaced by
a proper — configurable — operator.
* Update release notes
* Fix web build
Saturation and vibrance were using the wrong luminance weights,
and this change switches EVILS to HK weighted luminance weights
to give better results.
What was happening is that we were doing two blits at the end of the
frame instead of one, those blits are setup so that they only work
when the destination is the an imported target (it doesn't have to be
this way, but currently that's the only case we should have). Because
of the 2nd blit, the first one's destination would not be the
imported target and it would fail.
The real problem is that we shouldn't be doing two blits, just one
is enough. That was happening because the logic to decide if we
needed the last blit was flawed.
Fixes#4306
Previously we were zero filling the data blob used to store all Vulkan
handles. This occured in VulkanDriver::alloc_handle().
There were several places that depended on the zero fill. These
have now been fixed up so that the handle can be constructed in a
more natural way.
Also: remove the OPENGL specific constant from HandleAllocator. This
breaks in non-CMake build systems (e.g. Bazel) that do not provide the
constant at a global level.
We now have:
allocate<> which just allocates the handle's memory
construct<> which constructs the handle allocated with allocate<>
allocateAndConstruct<> which allocates AND constructs the handle
destroyAndConstruct<> which destroys and constructs a handle in place
Normally you'd use allocate/construct but with synchronous calls, it
might be necessary to have an initialized handle immediately.
Previously, Metal was never performing any texture conversions during upload. For example, `iblprefilter` loads `FLOAT` image data into the `R11F_G11_B10F` texture format. This PR fixes the issue, refactors the upload pipeline, and adds a new backend test for coverage.
Image loading errors are handled more gracefully by showing a
background color.
Added UI to set the background color.
Replaced fragment discards with solid background color.
* Add new sample app: image_viewer
This app shows how to load and visualize images. It's also useful to work
on color grading and other post-processing effects by just loading an HDR
or EXR image as a reference.
This change also adds a new exposure setting to the color grading LUT.
* Fix comments and build
* Fix Metal
* Use high precision for the UV coordinates
* Fix refactoring issue
* Add support for KHR_materials_volume
* Add ubershader support for KHR_materials_volume
* Update readmes
* User highp on anything that affects UVs
* Add missing precision qualifiers
* Fix transmission
* gltfio: fix precision in KHR_texture_transform
Fixes#4253.
* Update to the new order of parameters
Co-authored-by: Romain Guy <romainguy@curious-creature.com>
* API CHANGE: honor user-defined precision, rename SamplerPrecision.
matc now honors 'precision' on non-samplers in mat files, and
the filamat API now allows clients to specify precision for
non-samplers.
This involved flattening a union that is internal to filamat.
* MaterialBuilder: Add Java bindings for precision.
We were inserting the colorgrading subpass command between the
refracted and blended objects, instead of after all of them.
Another bad side effect of this was to trigger the refraction pass for
no reason.
We use a hashmap instead, which won't change the behavior of the
HandleAllocator (due to the increased size of the handles) between
debug and release modes.
We always may need to discard lights because we have a limited
number we can use in the shader. We now do this earlier, in particular
before we set up the shadowmaps.
Because we also have a limited (smaller) number of shadowmap, this
allows us to automatically select the ones that are closer to the
camera, which gives better results.
The most recently loaded model is now automatically re-loaded if you
re-start the sampler-gltf-viewer app.
Super useful in my case for `rgb-lights.glb` :)
* Add support for transparent shadows
This solution uses an 8x8 Bayer matrix. We could find a better
noise. We also need better filtering of the shadow maps. A PCF
is barely enough and VSM fails without blurring.
* Use a fixed Bayer matrix, fix pre-caching of depth shaders
* Use gradient noise instead of fixed bayer pattern
* Update docs
This is a trivial change since we moved the lightspace computation
in the fragment shader. The limitation to 6 is due to how we're storing
the culling result.
* Remove support for Java/desktop builds
These builds are never tested nor used on our end. We cannot
guarantee their proper support. It should also be possible
for an app to handle this itself.
* Remove Tungsten since it cannot be compiled anymore
When HandleArena is full, we now revert to a slower system-heap
based mechanism. The problem is logged once. This allows the
system to continue to run.
This means it can easily be used by our other backend.
HandleAllocator uses 3 pool (which currently can't be configured),
and is very efficient in terms of memory overhead and handle to
pointer conversion.
A Handle<> is just an offset into a large heap managed by the 3 pools.
* Add simple ReadPixels performance test.
This simply lets the gtest framework report the total test time, which
includes startup and teardown. However we perform 100 runs of the
render+readback code to reduce the run-to-run variance. For 100 runs of
a 2000x2000 buffer, I see the following results on my mac:
- Vulkan: 1881 ms
- Metal: 1625 ms
- OpenGL: 978 ms
The test can be built & invoked like this:
```
./build.sh release backend_test_mac && \
./out/cmake-release/filament/backend/backend_test_mac -a opengl --gtest_filter="*ReadPixelsPerformance"
```
See also issue #4246.
* ReadPixels test: minor refactor.
The operator!= in std::array compares SPLIT_COUNT elements, which
is potentially greater than cascadeCount, which was the number of
initialized elements in splitPercentages.
- the ShadowMap cache is now inline and doesn't use unique_ptr<>
- reduced the size of ShadowMap significantly, it used some temporary
storage as member, but now that we have many of those, we shouldn't
do that.
- removed some duplication of fields
- fixed some headers inclusion
Instead of managing a GrowingSlice<> more or less shared between
several RenderPass, RenderPass now works directly with an Arena which
owns the commands. We do this so RenderPass can be copiable, which is
useful for creating a RenderPass from a "template" RenderPass
(usually empty, but with some scene parameters set).
RenderPass is now a lot more self contained.
Execution of the commands is now done with a RenderPass::Execcutor
which can be obtained from a RenderPass.
This change led to some code clean-up as well.
We also had to improve Arena<> to be able to take a custom Area.
This adds some significant JNI glue in order to make the Java API for
gltfio materials much more consistent with C++, and create feature
parity between the two languages.
The motivation is to allow Java clients to provide their own
ubershader-based solution or filamat-based solution.
- The `MaterialProvider` Java class is now an interface.
- The `UbershaderLoader` Java class is now a concrete implementation.
- Users can now write their own provider class using Java / Kotlin.
To streamline the amount of JNI work that occurs at run time, the
MaterialProvider Java interface uses ints in a couple spots instead
of enums. This sacrafices some readability for Java clients who wish
to write their own provider, but makes the JNI much simpler.
This replaces #3975.
We have a limited number of interpolants, and 2 were used for spotlights,
but this is a fairly uncommon case, so we move the calculation to the
fragment shader. A side effect of this is that we are not limited to
two spot-light anymore from the shader's point of view.
This essentially adds a vector transform per fragment, but on the other
hand, it removes communication between the vertex and fragment shader,
as well as interpolation of the position.
This basically expresses the fact that we won't need an "auto-resolve",
indeed the temporary depth buffer is always discarded. In the GLES
backend, this is likely (if MSRTT is supported) to take a less
complicated code path.
Improve some comments.
- the clear color was broken since we switched dot EVSM
- use the scissor instead of the viewport, it makes it easier to compute
the uv-scale.
- the min/max lod level wasn't reset properly
- also clamp the minimum shadowmap size to 8, and document it.
We make better use of the framegraph, by using a pass per shadowmap,
instead of generating all shadowmaps in a single framegraph pass.
This allows us to use less temporary memory when blurring, but also
simplifies the code.
This is still somewhat work-in-progress, but good enough to be useful.
Some caveats:
- large blurs don't work well with cascades
- the implementation uses more memory than it could
This allows clients to obtain the extras strings for the asset and
for individual nodes. Note that extras for buffer views, accessors, etc
are not supported, although C++ clients can access the raw cgltf data
directly if they need to.
Filament uses a handful of known UBO, the code for creating their
interface block is not needed in filament (via filabridge), so
reorganize things so that we can move that code to filamat.
On the other hand, filament needs the C structure corresponding to
the UBO, to find the fields offset and ubo size and name.
We now have a UibStructs.h in filabridge which only defines C struct
with a static name for the interface block's.
This should slightly reduce the size of filament proper.
We also now have a new helper TypedUniformBuffer<> which simply holds
one of these structs (or an array), and allows to set the fields
directly and more naturally from C++. std140 alignment is now left to
the caller, when going through that class.
- use EVSM (exponential VSM), helps a lot with light bleeding
- don't apply shadow biases with VSM
- improve VSM user settings: added more controls, expose to java
- minor code cleanups:
- rename some structures
- remove unused parameters
- remove unused uniforms
VSM requires shadow receivers to be in the shadowmap, instead of
handling this in the shadow mapping code, we're handling it in
FScene::prepare(), which guarantees it'll ripple everywhere it needs to.
When creating a texture with a swizzle, the swizzle should be applied to
the image view only when sampling from that texture. When a swizzled
texture is used as a render target attachment, the image view should not
have any swizzle applied.
- OpenGL ES on Android
- Metal on MacOS/iOS
- Vulkan everywhere else (Linux/Windows)
The main change here is that OpenGL is no longer the default on
desktop.
Most of our samples have a `-a` option that can be use to specify the
desired backend.
1) Add a missing destroyTexture to the test, which I believe fixed
the Metal assert that I was seeing, as well as some Vulkan validation
warnings.
2) Add a flushAndWait() utility to BackendTest, which is useful for
diagnostics.
3) Fix a layout validation issue in VulkanSwapChain for empty render
passes.
This reworks how we compute the bloom buffer size. The main changes are:
- The BloomOptions.resolution is changed to height instead of minor axis.
This keeps a consistant look of the bloom regardless of the viewport.
- The anamorphism setting now dilates the bloom rather than to compress
it (in the other direction), which maintains the same amount of bloom.
However, the resolution decreases meaning that the user might need to
adjust resolution and/or levels.
- limit the resolution do 2048 which is gles minspec.
We were disabling the color pass render target clear when a skybox
was present. This optimization doesn't work when the viewport is not
full. Currently there is no way to know that, so we disable this
optimization for now. Performance loss is not expected to be significant
if present at all.
We were automatically clearing the color pass render target when
the view was translucent -- the idea was that when it gets blended at
the end it wouldn't override the content of the render target.
Unfortunately, this doesn't work when the rendertarget is imported,
because in that case, it's not actually blended, we're just rendering
into it directly. The clear would then erase the previous content.
This is fixed by moving the clearing decision in the execute closure and
piggy-backing on the computed discard flag. Discard means clear.
The discard flag will be set for newly created buffers and not for an
imported target that needs to keep its content.
An imported target shouldn't specify the discardStart flags, those
are calculated from the graph. However, it needs to specify "keep" flags,
to take into account constaints that the graph cannot see (due to the fact
that it's imported into the graph). i.e. the imported target may have
content that needs to be preserved.
An imported target can specify a clear color and clear flags that will
override the flags from the logical Descriptor -- this is a way to
delay the swapchain clear to when we're actually rendering into it
(which usually happens in the very last pass).
When the source of a blit refers to an imported render target,
we can't create a HwRenderTarget from it because the resource
is not a real texture and doesn't have a HwTexture.
However, it can be converted back to the HwRenderTarget it
represents, using the FrameGraph's declareRenderPass API.
It's a slightly strange usage of this API, but not technically
wrong.
This is the main fix for bug #4085
* Materials can now provide custom lighting/shading
When a material uses the "lit" shading model, customSurfaceShading can
be enabled to replace Filament's lighting implementation. When this
feature is enabled, the material *must* provide the following function
in the fragment shader block:
vec3 surfaceShading(
const MaterialInputs materialInputs,
const ShadingData shadingData,
const LightData lightData
) {
return vec3(1.0); // custom lighting here
}
Please refer to the docs in Materials.html for more information about
this feature and the different values provided by the data structures
passed to the function.
* Update docs
* Update docs/Materials.md.html
Co-authored-by: Philip Rideout <philiprideout@gmail.com>
Co-authored-by: Philip Rideout <philiprideout@gmail.com>
This makes the car load in 3 seconds instead of 30 seconds on Mali.
On devices that have bufferImageGranularity set to 1 in the
VkPhysicalDeviceLimits caps structure, we observe that vmaCreateBuffer
can be two orders of magnitude faster than with devices that have a
higher value for their bufferImageGranularity.
According to the Vulkan spec, the bufferImageGranularity aligment
constraint needs to be honored only when linear and non-linear resources
live next to each other in memory. Since all VkBuffer objects are
linear, we can allocate them all from the same pool and ignore the
alignment constraint.
VK debug markers do not show up in an AGI system trace, but we can sneak
them in by using debug_utils to assign labels to VkFramebuffer.
Note that the debug_utils extension is enabled only when launching your
app from AGI.
More precisely, this logs the time that the Filament backend takes
to process all the commands that were issued in the gltfio synchronous
loading phase, which mostly consists of creating and populating vertex
buffers.
This can be quite slow for vertex-heavy (CAD-style) models, and seems to
vary by several orders of magnitude from device to device on Vulkan.
This constant was previously set to 3 because of triple buffering, which
does not account for the fact that Filament may issue multiple commit()
calls during a single frame.
This new number was determined via experimentation.
On a Pixel 4, this reduces a 4.5 ms gap in "GPU Queue 0" to 420 us.
We reuse the current job for the right side instead of spawning a new
job, which has overhead. This also cuts in half the number of times we
need to copy the user functor.
The overhead of the jobsystem / job is about 50-100us, so we should
try to use jobs about an order of magnitude bigger -- which is actually
quite rare.
In particular the culling is so efficient that we'd need to process
10000 or more primitives for the jobsystem to be of any help, so for
now we never use the jobsystem for culling.
A side effect of this flag was that we had to always use notify_all
when starting a job, instead of notify_one -- in practice, we found
experimentally that more calls to notify_one is cheaper than fewer
calls to notify_all.
If your build system does not provide a definition for this macro, then
you cannot compile CommandBufferQueue.cpp.
Since Allocators.h provides a backup value, it needs to be included.
std::allocator::deallocate() expects the same value that was given
during allocate().
Interestingly, this bug did not manifest any issues (even with ASAN) on
some platforms.
This fixes an issue caught by a memory sanitizer, whereby padding in the
cache key structure was being consumed by a hashing function. In
practice this oversight was fairly harmless, but this change makes the
code more safe and predictable.
Fixes the "triangle count is zero" assertion with the big car model.
We do have nominal support for points and lines, but we should not
attempt to compute tangents for these.
As a reminder, glTF also supports loops, strips, and fans; this is the
only way in which Filament is non-conformant.
The CommandStream hold backend commands, but it has a limited size.
With some large models, we can run out of space especially during
initialization.
We can combat this by flushing the command stream regularly. With this
change, we do this every 128 renderable creation.
We also flush the CommandStream just before generating the draw
commands for the frame.
If the buffer is not sized correctly (currently at compile time), this
could cause stalls, which will be logged in DEBUG builds.
On Android, set `debug.filament.backend` to the desired backend:
0: default
1: gl/gles
2: vulkan
3: metal
4: noop
example:
`adb shell setprop debug.filament.backend 2`
This will affect all filament apps on the device.
This sets the backed as if it was set from the public API.
* fix runtime warnings about certain NSView methods being called off the main thread
* address code style issues
* fix code style and threading concerns
* Remove unneeded __strong qualifiers, put __weak after the star as recommended by Apple, convert weak to strong before testing for nil to avoid a race
* convert tabs to spaces
All (and only) git-ignored files under android/ are deleted.
This is to prevent a recurring problem where "clean" builds were not
actually clean in some cases.
This reverts commit cc6201b0db.
On Android the loggers are not always initialized when several .so are
used, leading to crashes. It's not completely clear what is exactly
happening.
This fixes most of the warnings that are emitted by the relatively new
SYNCHRONIZATION_VALIDATION feature that LunarG provides.
This commit does not fix a warning that is emitted when SSAO is enabled,
when we sample from the currently bound depth attachment. This one is
tricky to fix.
the CommandStream is limited in size and can get corrupted if
that size (default 1 MiB) is exceeded. We used to catch this
only on Debug builds, but this is too serious and unrecoverable, so
it must be caught in Release builds too.
At the point of detection the stream is corrupted, which can cause
the backend to get in an unknown state. But worse, program execution
could end up anywhere because the stream contains function pointers.
- libutil's slog, cout, cerr, cwarn and cinfo were not thread safe
at all.
- they are now thread_local
- for that reason the log buffer (which now exists per thread) is not
allocated until it's needed and is aggressively shrunk.
- removed our thread_local emulation which was incomplete.
- don't expose LogStream publicly.
This is (almost) drop-in replacement for std::vector, the main
difference is that FixedCapacityVector has a fixed (at runtime)
capacity, which makes it a lot more efficient and small for operations
like push_back();
The capacity can be set (and re-set) as usual with reserve(),
but exceeding the capacity when adding items will throw.
The capacity is also set when creating the vector with a size.
In addition a FixedCapacityVector<> instance is only 16 bytes instead
of 24 for std::vector<>.
The aim here is to reduce code bloat.
Newer versions of MoltenVK seem to behave similarly to Android,
so there's no need to separate codepaths. I tested this by not only
resizing the window, but also dragging between displays with different
pixel ratios, and rotating on Android with & without `orientation` in
`configChanges`. I also tried our headless unit tests.
The sample would crash when removing `orientation` from `configChanges`
and rotating the device, because the old RemoteServer would still be
alive when creating the second one, so the WebSocket port would be
unavailable.
This has no behavioral changes, it's mostly just moving code around,
except that VulkanDriver::createSwapChain() is simpler now, and some
of the logic in beginRenderPass() makes more sense too.
This removes the useless `VulkanSurfaceContext` structure by moving
its data directly into `VulkanSwapChain`. Also created a new cpp file
just for the swap chain wrapper, which makes `VulkanContext` much less
unwieldy.
This change allows access to the Engine's underlying Platform object. This is useful for Metal clients to access a new method on MetalPlatform, createAndEnqueueCommandBuffer.
* a way to keep the content of custom RenderTarget attachments
Until now, all attachments of RenderTarget beyond COLOR0 were discarded
after rendering.
With this change, attachment whose texture has the SAMPLEABLE usage
bit set will be kept.
Fixes#3962
This adds support for decoding HDR files, dropping them into the remote
web page, and sending them over the wire. However the decoded results
are not yet passed into IBLPrefilterContext, that will be subsequent
PR.
Rename KtxLoader to KTXLoader.
The remote UI has been tweaked a bit, so that it shows a more helpful
message when disconnected.
(1)
The C++ RenderTarget API might be used by an external Android library
such as filament-utils-android and therefore needs to be in the map
file.
(2)
Texture, Skybox, and IndirectLight each had two "nativeObject"
constructors which exist for the benefit of filament-utils-android,
but each of these classes only need one nativeObject constructor.
Vulkan does not permit the GENERAL layout when the depth buffer that is
currently being used for depth testing is also sampled from.
This (finally) fixes the last validation error that we were silencing,
which would occur only when SSAO was enabled.
deprecate Stream::stream(intptr_t).
This method was needed for ARCore back in the days, but there is now a
zero-copy way to achieve the same thing. This API shouldn't be used anymore.
The code that determined the "base slot" (i.e. the buffer object index
for the first morphed attribute) was very fragile and buggy.
MorphHelper now simply looks up the slot index in a stored mapping,
rather than trying to mimic the AssetLoader to determine the base slot.
Until now, most of the models we tested against only morphed the
position attribute, and never had a large set of target weights that
could be non-zero in a given time slice.
MATERIAL BREAKAGE: this change breaks materials
In order to use one less sampler, we now use a UBO instead of a texture
to store the "froxel records". Currently this UBO is limited to 16KiB
vs. 64KiB before with the texture.
We also handle running out of record space better, by using a predefined
record that has all the lights in the scene. This way the scene will be
rendered properly, albeit at a potentially large performance cost.
* Allow using specific NDK version, for CI don't use latest but required
* Default to highest available NDK version within same major release sequence
* Refactor NDK version selection
This fixes the "descriptor set fragmentation" error that we would see on
Mali.
The pipeline cache now maintains an arena of descriptors that can be
re-used. We call this an "arena" to avoid confusion with
VkDescriptorPool.
Descriptors are returned to the arena only when they are not in use
by any pending command buffer. This allows them to be mutated safely
without worrying about synchronization.
The API of the pipeline cache is now easier to use. Internally, it now
maintains separate pipeline and descriptor bindings for each command
buffer, since that's how Vulkan works.
If expecting a bool and receiving anything other than true or false,
this is invalid and should fail. This change triggered a unit test
failure which uncovered several actual problems.
We should take care not to call glVertexAttribPointer when there is
no bound ARRAY_BUFFER (i.e. when its binding is zero).
This fixes the black screen seen with some WebGL samples after
the recent memory leak fix related to the new BufferObject API.
It did improve the look of the blur on far way geometry in some case,
but overall it hurts a lot more.
The case that falls appart is when everything is in the background layer
but there is a large depth difference anyways.
This creates a halo around edges.
Fixes#3221
* BackendTest: add blit cubemap test.
This test is similar to manual mipmap generation for cubemaps and
can uncover issues that are provked by libiblprefilter. It simply
dumps out a PNG that can be manually inspected.
Also, this test does not do makeCurrent / commit and is therefore
similar to renderStandaloneView.
* Update filament/backend/test/test_Blit.cpp
Co-authored-by: Ben Doherty <bendoherty@google.com>
Co-authored-by: Ben Doherty <bendoherty@google.com>
This leak was introduced in the following PR on April 7.
https://github.com/google/filament/pull/3775
The guilty party has been contacted and properly admonished for his
transgression.
This was tested by adding the following code after applyAnimation in
gltf_viewer.cpp
static int nframes = 0;
if (!gpath.empty() && nframes++ > 100) {
static int count = 0;
printf("reloading %d\n", count++);
nframes = 0;
app.resourceLoader->asyncCancelLoad();
app.resourceLoader->evictResourceData();
app.viewer->removeAsset();
app.assetLoader->destroyAsset(app.asset);
loadAsset(gpath, app);
loadResources(gpath, app);
}
- remove areFeedbackLoopsSupported from backend API, since this is only
a problem on WebGL
- binary only include either the regular or webgl version of the bloom
code, never both, which should save some binary size
- bloom pass is now called outside of the colorGrading pass, which is
cleaner and makes it available for other pass, should they need it
(not the case right now).
- always pass ColorGradingConfig to all color grading related methods,
instead of individual parameters
- very minor optimization in bloom shader
- move kernel weight computation to the gpu side as a small cost, in
order to simplify the CPU side and reduce the binary size.
- skip samples with a weight of 0, which is a completely coherent
check.
- fix a typo in move ctor
We chose 8 renderbuffer because it seems to be commonly supported
on mobile gpu and is more than 6 which is needed for generating
cubemaps. 4 was the minimum guaranteed by ES3.0.
The main changes here are:
- TargetBufferFlags is now a uint32_t instead of uint8_t
- The number of render buffer supported by filament and supported by
the hardware can now be different. Applications/users now must
query this value if more than 4 is needed.
- added a backend query (used gl terminology)
This is a redo of a previous attempt. There was an issue in the GL
backend that caused MRT to fail on some devices.
This removes a lot of caveats that we had in the Vulkan backend. Many
driver API calls were unsupported due to a lack of command buffer, but
in the new scheme, a command buffer can *always* be made available,
and there's no weird separate "work and swap chain command buffers".
Here's how various driver API entry points now map into Vulkan actions:
```
makeCurrent => Acquire Swap Chain.
beginFrame => Do nothing.
endFrame => Submit command buffer and create a new one.
commit => Submit commit buffer again if necessary, Present Swap Chain.
```
This handles both copyFrame (which does not do beginFrame / endFrame)
and renderStandaloneView (which does not do makeCurrent / commit).
This makes release builds consistent with continuous builds and default
local builds. It also makes it easier to test the Vulkan backend.
Clients who need a smaller APK size can always make their own build.
This also makes filament-android-release.aar go from 1.8M to 2.3M.
Note that we are now including bluevk, vkshaders (for the blit shader),
smol-v (for SPIRV decompression) and vk_mem_alloc (for mem allocation).
Simply tweak the "spiralTurns" parameter, empirically to improve the
noise pattern produced by the gradient noise. In turn, this helps the
gaussian filter.
We used to have that before, but it was hardcoded and depended on
mobile vs. desktop.
With this change, users can set the quality on the material itself.
The default match the current settings. There are 3 quality levels:
low: enables optimization that might not be 100% correct
(e.g. abs(x) instead of sqrt(x*x))
normal: like low, but doesn't sacrifices correctness.
high: could be improved upsampling, etc...
- create a new FILAMENT_HAS_FEATURE_TEXTURE_GATHER, which can be used
in the shaders to use textureGather.
- A new TARGET_GLES_ENVIRONMENT and TARGET_GL_ENVIRONMENT in addition
to TARGET_METAL_ and TARGET_VULKAN_, for completeness.
- Rename TARGET_LANGUAGE_SPIRV to FILAMENT_VULKAN_SEMANTICS and add
FILAMENT_OPENGL_SEMANTICS for completeness.
- expose the shader model to shaders as: FILAMENT_SHADER_MODEL_ES30 and
FILAMENT_SHADER_MODEL_GL41
Use these new #define where appropriate.
The main change here is that TARGET_MOBILE is now only used for dealing
with the `mediump` default on mobile.
This change also enables textureGather on Metal.
We chose 8 renderbuffer because it seems to be commonly supported
on mobile gpu and is more than 6 which is needed for generating
cubemaps. 4 was the minimum guaranteed by ES3.0.
The main changes here are:
- TargetBufferFlags is now a uint32_t instead of uint8_t
- The number of render buffer supported by filament and supported by
the hardware can now be different. Applications/users now must
query this value if more than 4 is needed.
- added a backend query (used gl terminology)
* New experimental tone mapper
The new tone mapper proposed in this change replaces Uchimura (see
below) and is composed of two distinct algorithms:
- The first is the customizable compression curve from Timothy Lotte
(from GDC 2015). The curve's default parameters were chosen to
match the overall appearance (contrast) of the ACES curves used
as our current default tone mapper. This was done to provide a
good migration path to making this new solution the default in
a future version of Filament.
The compression curve can be customized via its contrast, shoulder,
input middle gray, output middle gray, and maximum "HDR value"
(scene referred).
It is important to note that the compression is only applied to
the luminance of the input scene referred value.
- The second is a novel approach by Troy Sobotka called Exposure
Value Invariant Luminance Scaling (or EVILS). This solution works
on the largest chromatic channel of the input value as opposed
to mapping all RGB channels as we do in our other tone mappers.
The algorithm effectively scales all channel by a ratio that
depends on both the compressed luminance from the first stage
and the luminance of input value normalized by the largest
channel.
This new solution offers important benefits as it manages to
preserve chromaticity for high input values. It is also designed
to provide a desirable rolloff to white on overexposure. This
means that even without gamut mapping, this solution avoids many
hue skews (red to orange, blue to purple, etc.). The results
provided by this solution are much more natural and make using
other color grading tools much easier.
* Use std::pow instead of pow
* Fix Web builds
- move public headers from filament/foo to filament-foo/
to avoid confusion with libfilament's headers
- add support for equirectangular to cubemap conversion
- add support for using an .hdr file directly in all our samples
Fixes issue seen with Vulkan + the quantized version of Avocado.
We already support the quantized glTF extension, which is when this
comes up. Technically this is only needed for Vulkan but gltfio does
not (and should not) know which backend is being used, so we simply
apply these transformations assuming the worst.
In practice this code usually won't be activated, and if even when it
is, it won't hurt loading time as much as other things like large
textures.
* Add Transcoder API for C++ clients.
We will add JavaScript and Java support in a later PR.
* Transcoder: use fixed inner loop in some cases.
This lets clang produce better ARM code for common cases.
* Transcoder: stronger typing in Config, etc.
* Transcoder: add UTILS_RESTRICT and noexcept.
This is the first step at trying to un-hardcode the number of drawbuffer
we support. The ultimate goal is to go from currently 4 to 8.
Until now the maximum render buffer supported was the same than the actual
number of render buffer supported. At some point in the future this will
change, it this will have to be dynamic.
This change is to allow rendering a cubemap in a single pass on h/w that
support it. Many mobile GPU support 8 draw buffers.
- the miplevel wasn't computed correctly
- the random rotation was incorrect
- the default HDR compression was too aggressive
- better validation of the input cubemap
we now store the kernel for each lod in a texture, this has several
advantages:
- the texture can be reused, so we can amortize that cost a bit
- we could generate the texture with a shader, so that we don't
have to do any texture uplaod (TBD).
Until now we were using TARGET_MOBILE in our shaders for both
quality setting and correctness.
With this PR we introduce a new define FILAMENT_QUALITY which currently
can take two value FILAMENT_QUALITY_LOW and FILAMENT_QUALITY_HIGH and
we use that instead of TARGET_MOBILE for quality settings.
Currently, FILAMENT_QUALITY_LOW is selected when TARGET_MOBILE is set.
New Api:
- Renderer::renderStandaloneView() is a new method that can be used
outside of beginFrame/endFrame on Views that have a RenderTarget
associated. This can be used as a poor man's compute API.
Improvements to Renderer:
- more aggressively skip lighting/shadowing code that won't be
needed by the current view
- Allow up to 64 KiB to be allocated from the render stream, up from
1 KiB
Even though the vertex shader comes before the fragment shader,
both bits needs to be present in the barrier, since a Vulkan
implementation might partition its uniform cache between stages.
Thanks to Chris Forbes for pointing this out.
After eyeballing this barrier I realized it was configured incorrectly,
but it did not seem to manifest as an actual error anywhere.
Basically, it needs to ensure that the UBO is fully updated before it
is read by the vertex shader associated with the next draw call.
This will allow folks to drop a GLB into the following page to get a
WebGL preview. It always uses the latest version of Filament via unpkg.
https://google.github.io/filament/viewer
After the next release we can also use the `<filament-viewer>` component
itself from unpkg and remove the local copy.
- If a resource file is missing, show toast instead of crashing.
- Allow glb files in zip files.
- Run blocking calls like createTempFile() on IO thread.
It's an error to ask for a higher MSAA sample count than supported by
the gl driver, and results in corrupted rendering.
We now always clamp the requested sample count to the maximum allowed
but the gl driver.
includes some minor refactoring.
Some drivers claim to support anisotropic filtering but don't allow
setting it via glSamplerParameter. Until now we were disabling
anisotropic filtering entirely on these drivers at compile time.
With this change, we should detect at runtime which drivers have this
issue and use a workaround -- instead of disabling anisotropic
filtering entirely.
- it was called on the main thread side, which didn't allow to,
for instance, systrace commands on the backend thread side.
- moved to a begin/end callback model
- implemented basic logging/systracing for all backends in Driver.cpp
(and removed this functionality for the metal driver).
note: refactored CommandStream class attributes only to work around
a clang bug we running into in CI.
This includes changes to OpenGL, Metal, and Vulkan backends.
At the backend level, vertex buffers are now always composed of buffer
objects. This lets us simplify the Driver API and some bookkeeping in
the backends.
This change also splits MAX_VERTEX_ATTRIBUTE_COUNT into two constants
because the maximum number of bound buffers is a separate concept from
the maximum number of attribute semantics (e.g. consider interleaving).
For now these two constants are set to the same value.
We also now store a byte count in HwBufferObject, which allows us to
remove the byte count from the Metal-specific handle, and to add some
asserts to debug builds to prevent size overflow.
- DoF: don't convert gl_FragCoord to mediump when generating noise
- SSAO: add a bunch of missing highp qualifiers
- all matrices and UV should be highp
- Also fix some typo in comments.
The focal length slider now works over a remote connection. Also, the
slider for focus distance now controls the value in `ViewerSettings`
(which gets applied to Camera) rather than the value in
`DepthOfFieldOptions` (which is deprecated).
according to the gl spec, we can't mix the EXT versions of
glRenderbufferStorageMultisample/glFramebufferMultisample with
the regular versions. Other drivers are more permissive.
When allocating a renderbuffer and the extention is supported, we always
use it.
It looks like the layout(location) is needed for output parameters of
the fragment shader in GLES. Adreno dirver didn't seem to care, but
Mali drivers do.
This fixes shaders that use multiple out buffers in debug mode.
This adds the 565 enum to a switch block (which is an actual bug),
and it fixes a JavaDoc warning about missing summary fragments (which
is just a silly warning).
Just for fun, this is an example of a web component that allows you to
embed a Filament viewer with a single HTML element. It does not have
many features, but is much easier to use than our raw JavaScript API.
* ImGuiHelper supports client-provided context
this lets impress load >1 embedded font into the font table
* ImGuiHelper supports client-provided context
this lets impress load >1 embedded font into the font table
Co-authored-by: Philip Rideout <philiprideout@gmail.com>
We now annotate the JS wrapper for Engine with a GL context handle.
This is fairly hacky because emscripten hides its internal GL object
from JavaScript, and it does not provide a mechanism to pass JS objects
into inline assembly.
This script makes it easy to update the web page at
https://google.github.io/filament/remote/ even if you do not have the
emscripten SDK. It works by downloadinug the latest continuous web
build, then placing the wasm file in the right place.
After running the script, the user must make a git commit to finish the
operation.
This is a big hackish, but is intended to help us debug scaling issues,
this adds a couple of sliders under [Debug] to control dynamic
scaling manually.
Shockingly there were no unit tests that did a simple write-then-read.
This is important because it's easy to forget details such as trailing
commas and the fact that uint8_t is a char.
NOTE: after Metal and Vulkan support lands, we can potentially simplify
the Driver API by removing some of the old VertexBuffer entry points.
This introduces a new API-level object called `BufferObject`, and a new
backend-level object called `HwBufferObject`. This encapsulates a single
VBO. It's especially useful when clients need to share data between
multiple VertexBuffer objects. (e.g. for morphing).
In the future, buffer objects could perhaps be used for non-vertex data
(e.g. for compute).
The existing `VertexBuffer` class can now be configured to use buffer
objects by calling `enableBufferObjects` on the builder. By default its
API is unchanged. If buffer objects are enabled, then clients should use
`setBufferObjectAt` (which takes a buffer object) rather than
`setBufferAt` (which takes CPU data).
OpenGL is the trickiest backend for this, due to existence of VAOs.
The implementation in this PR uses a version-tracking scheme to
figure out when to update the VAO.
We use the technique used by Jimenez for the foreground applied to the
background, where we "guess" the missing background information from
neighboring pixels. In several papers it's not deemed useful for the
background, however, it does improve the blur quality a lot very shallow
DoF, i.e. when a moderately blurred background sits over a strongly
blured one.
Before we were keeping a foreground and background version of the
low resolution source, but in practice it really doesn't make a big
difference and we save a fair amount of bandwidth this way.
The bulk of the change is to remove a texture/target which mostly
affects the downsample and mipmap passes.
Also renamed some variables to be less confusing (MaxMin to MinMax for e.g.)
and fixed a few typos.
there has been a typo in the DoF code a while, but fixing it looks
much worse. we need to understand why. so for now we at least
document the typo in the code.
The gist of it is that we can't always accumulate samples naively, and
we have to use different strategies with different tile types.
For the fast tiles it seems enough to reorder the sum, accumulating each
ring first, and then accumulating that into the output, because all
samples have the same weight.
For the foreground tiles, for some reason I couldn't find any major
issue and I'm not sure why.
For the background tiles, we need to use highp intermediates because
every sample has different magnitudes (weights)
* move the focus distance from DofOptions to Camera
The DofOption parameter is now deprecated, but will still work if the
focus distance is not set on Camera.
* A few new helper APIs on Camera
- getFocalLength() which returns the focal length used internally for
DoF computations.
- computeEffectiveFov() and computeEffectiveFocalLength() which can be
used to better simulate a real camera's FOV changes with the
focus distance.
Modified gltf_viewer so it uses the effective fov/focallendth when
DoF is active.
* simplify setLensProjection
We can call setProjection directly instead of converting to a fov
first, which ends up performing atan(tan(x)).
Also improve parameters names.
This adjustment is conservative, i.e. we limit the number of rings in
the kernel based on the kernel size in a way that it won't impact the
result. For instance, if the kernel size is 2 or lower, we don't need 4
rings.
This improves performance significantly, especially with large maximum
right counts.
As far as I can tell, there is no need for the `enabledAttributes`
argument in `setRenderPrimitiveBuffer`. This helps pave the way for
the upcoming BufferObject API.
- setImage() used the width of the texture for calculating the required
user buffer size, but this was too large when only updating a
portion of the texture. It would result in a BufferOverFlowException.
- setImage3D() had the opposite problem where it didn't take into
account the depth of the texture.
- the offset in the user buffer was called "bottom" on the C++ JNI side,
but it is called "top" on the java and filament side.
Fixes#3685
Currently the only NONE and MEDIAN are available options, at some
point we may add a "MAX" option which is cheaper.
There is no real practical uses for this option with these only two
choices, other than for debugging.
This is mostly used for debugging and having somewhat of a reference.
Change to the shader are minimal because all CoC values were always
treated as full-resolution. We just need to replace the downsampling
shader by one that just calculates the CoC. And we need to introduce
a CoC scale factor to compute the LOD to use (this was hardcoded
before).
On the C++ side, it's mostly a matter of replacing hardcoded buffer size
scales by a runtime or compile time variable.
* CString can construct from a string_view
(string_views lack a null terminator)
* Update libs/utils/src/CString.cpp
Co-authored-by: Mathias Agopian <pixelflinger@gmail.com>
We're implementing the two-layer technique described in
Jimenez DoF paper, where the foreground field is split in two layers, front
and back. In addition we compute accurately the foreground field alpha.
From a performance standpoint, most of the extra work is increased
register pressure and a bit of ALU.
Always store min CoC in the red channel and max Coc in the green
channel for both the CoC and Tiles textures.
(The tiles texture was doing the opposite).
this would happen only when a fast tile had a CoC < 2, because it
would then have an opacity, but we were ignoring it. It's color then
didn't match the color of the surrounding layer and the median filter
would spread a pixel from the surrounding layer into the fast tile.
we simply fix this by (1) generating the alpha/color for fast tiles,
which is easy to do and on the combine pass, skip the fast tile
combine when the tile has a an opacity.
before we were not doing that because it caused some aliasing
artifacts with mipmapping, however it turns out that there are artifacts
anyways, and using the proper weights actually reduces the most severe
ones.
the artifacts are due -- it seems -- to the low density of the kernel.
* Fix blanking windows not being drawn into on macOS
* Refactored to create swap chain info object; added fixes for resizing; added sample.
* CocoaGLSwapChain should inherit from Platform::SwapChain
* Link to SDL directly for multiple_windows example
* SDL apparently redefines main to SDL_main and requires C++ linkage
* Fix main to have SDL-approved signature
* gltfio: Add internal MorphHelper, enable up to 255 targets.
Previously, gltfio could not animate models with more than 4 morph
targets. Now we can handle up to 255 targets, as long as no more than
4 targets are ever used simultaneously. This allows us to handle
many more models, such as those exported by Modo, and the horse model
in #1852.
We do this by picking the highest 4 weights. The indices for these
weights are called the "primary indices", and we construct a new
VertexBuffer for each unique set of primary indices.
In the near future this will be made more efficient by adding a new
VertexBuffer API to the Filament core.
Fixes#1487.
* Code review fixups.
The hang was caused by a subtle race. When a job is completed, its
thread must signal all the threads that might be waiting on this job.
The signaling code was attempting to signal only the minimum number
of threads -- this was important especially in the case where no threads
were waiting, then the call to notify() could be avoided.
Unfortunately, for performance reasons we're not calling notify() with
the condition lock held, this meant that between the time the number of
waiting threads was latched and the time of the notify() call, more
threads could enter their condition variable wait(), and it would
then be possible for these threads to wake up, instead of the thread
we were trying to wake up (the one waiting on the job).
It would then get stuck forever.
This bug was introduced in 2df639133b
Also add some debugging code for this kind of failure (disabled)
we can't use a projection with infinite far as a custom
projection matrix, because this is not suited for culling.
recently a new version of setCustomProjection was added which allows
to specify both the rendering and culling projections.
This wasn't very useful in the first place because we're recycling
handles very quickly. Additionally there was a race condition
which cause false positives.
This reverts commit bc6acd5c5a.
This reverts commit 3a15756c78.
The vertex data for glTF morph targets are deltas rather than final
values, so we were passing incorrect data into the SurfaceOrientation
helper.
This has been a long-standing bug that affected models with morphing,
including Buster Drone. However in practice we have observed visual
issues only with AnimatedMorphCube.
Tested against AnimatedMorphCube, Buster Drone, Cesium Man, Fox, and
Littlest Tokyo.
Fixes#1609
This fixes two different logcat messages that would occur when scrubbing
a slider in the UI:
- "Discarding message, message queue overflow."
- "Downloading model..." would repeat itself needlessly
- Add a "shift" parameter to Camera. This has the effect of translating
the viewport, without changing its size.
This is an effect similar to using a shift lens.
- Camera::setScaling() now takes a double2 instead of double4, this is
because scaling the result of the projection in the Z direction
can lead to very confusing problems -- it will essentially move the
near/far planes, and we don't want to expose that as a public API.
- setCustomProjection() now allows to set a different projection for
rendering and culling (useful for e.g. for using an infinite far
rendering projection matrix).
- generously document the CoC computation
- rewrite the code so that the computation will work for any
perspective projection matrix, instead of assuming
an "infinite-far" projection.
MaterialInstance: generate versions of setParameter() methods that
are templated on the parameter sizeof(), which allows us to
coalesce implementations, e.g. vec4<float> and vec4<int> are now
the same. We make the compiler generate non-inline version of all
these methods, the typed version just call through, taking
advantage of the tail-call optimization in clang.
MaterialParser: improve code to avoid calling multiple methods that
all did more or less the same thing and were inlined.
PostProcessManager: use a loop to initialize the materials
ToneMapping: de-dup ACES implementation
And other more minor optimizations.
Fix alignment issues with setting booleans in UBOs
With multithreaded variant compilation, compiled materials differ based on which variants finish first. This change ensures that compiled materials are always bit-for-bit identical.
This is helpful when comparing two compiled materials. Hashing the material files can be used to check for equality. It's also convenient for variants to occupy the same index when using matinfo's --print-glsl flag, for example.
This adds a WebSockets server to filament-utils-android.
Unlike my first attempt (#3599), this does not use a piping server and
is therefore much faster to use over a LAN. It also has lower user
friction because there is no need to touch a button in the app or
scan a QR code.
The main goal of this rewrite was to make the code
simpler and easier to maintain.
The API is mostly unchanged, however there are some differences.
- we now have the concept of subresources, e.g. for Textures, as
subresource is a mip level or layer.
- RenderTargets are no longer resources, instead they are transiant
objects associated to a pass and are now called RenderPasses.
- RenderPasses take subresources for attachments.
- We have better validation of graph building.
We should also compute discard flags more accurately.
This adds libs/viewer to filament-utils-android and provides JNI
bindings for AutomationEngine.
This commit also changes the AutomationEngine to use PPM for screenshots
rather than PNG. The reasoning is that it is wasteful to include stb and
our two image-related libraries just to dump screenshots, especially for
a feature we might not use on Android.
Mathias noticed that the `setAcquiredImage` method was not well
documented on the C++ side. While fixing this I figured I'd try to write
up a docstring for the class itself.
assert() is now replaced by assert_invariant() which has the same
prototype and (currently) behaves the same than assert().
<assert.h> should not be used anymore, and is replaced by
<utils/debug.h>, which is where assert_invariant() is found.
The main motivation for this is to be able to set a breakpoint on the
assertion as lldb doesn't handle abort() very well, and doesn't
permit to inspect the stack trace.
A secondary motivation is to be able (at some point) to enable
assertions without necessarily doing a debug build.
Since we cannot upload a depth buffer, this test works by first drawing
a triangle into COLOR + DEPTH, copying them both to a new render target,
then drawing a slightly larger triangle just underneath the first one.
One of Filament's Linux clients at Google wishes to specify a special
path to the SwiftShader library that proffers Vulkan entry points, and
this path can only be determined at run time.
An environment variable seems like the easiest way to support this
functionality. To prevent a security hazard, the env var is checked only
if a special build-time flag is enabled.
According to the portability spec: "If this extension is supported by
the Vulkan implementation, the application must enable this extension."
On my 2019 MacBook, enabling this extension triggers errors relating to
depth comparison samplers which I believe to be bogus, so I filed a
LunarG bug. For now we silence this specific error message.
When running semantic analysis on a material, we were arbitrarily choosing the first code gen permutation to analyze. So, running matc with arguments --api metal versus --api all would run analysis on slightly different shader code. This causes bugs when flags passed to glslang differ during semantic analysis. This change updates all semantic analysis to always use the same shader code.
This fixes some OpenGL non-compliance (as per "Rendering Feedback
Loops" in the spec), as well as validation errors with Vulkan.
I'm hopeful this can be automatic in the new frame graph. :)
This prevents an "Invalid VkImageView Object" error that would occur
after disabling bloom.
This was caused by the fact that we do not bother zeroing out all the
descriptor slots that are not used by the current draw call.
This fixes `GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE` caused by the
following spec clause being violated:
```
The value of RENDERBUFFER_SAMPLES [must be] the same for all
attached renderbuffers and, if the attached images are a mix of
renderbuffers and textures, the value of RENDERBUFFER_SAMPLES
is zero.
```
Tested on Chrome with Triangle and Helmet demos (after enabling MSAA).
Also tried running the automation suite in a debug build on macOS.
Fixes#3128.
This adds setMinMaxLevels to the DriverAPI and calls it from
PostProcessManager and the new unit test. The allows us to be compliant
to the OpenGL specification. The new unit test now looks much better on
Intel GPUs. Chrome still gives an INVALID_OPERATION.
Unfortunately the actual bloom effect still has issues on my Intel GPU,
even though the test passes. So, we need to keep the ping-pong
implementation both for Chrome and for Intel.
I noticed that our slerp function sometimes produces a jolt in
animation, but only when the time delta is very small, and only when the
two operands have completely opposing signs.
For example, let's say you are slerping from <0.76, 0.39, 0.51, 0.19>
to <-0.72, -0.45, -0.49, -0.17>.
These quats are actually quite near to each other because the total
negation of the second quat is similar to the first quat.
We were already doing the short path check in the proper slerp path, but
not when falling back to lerp due to a small angle.
MaterialGenerator selects a custom blend mode for transmissive models,
therefore the AssetLoader should look at the material's blend mode when
it sets up properties, not the one requested by the glTF file.
Fixes#3444.
Previously this test was actually finding a ReadPixels failure on Intel
GPU's, rather than a failure of feedback loop behavior. This was due to
the fact that it was calling ReadPixels on a non-zero miplevel, which
seems to be unsupported on Intel GPU's.
The test now follows the downsample phase with an upsample phase, just
like the real bloom effect. This allows us to issue ReadPixels on the
base level, thus making the test more targetted to rendering feedback
loops.
* Stop using members as globals between methods
* Multi-thread shaders generation with JobSystem
* Pass JobSystem to MaterialBuilder::build()
* Fix MeshAssimp to use the new API
* Allow the Java API to pass a job system via Engine
* Update docs
* Apply suggestions from code review
Co-authored-by: Philip Rideout <philiprideout@gmail.com>
Recall that we now use shared_ptr to simplify lifetime management of
cgltf source data (#3413).
Before this commit, we were only using shared_ptr to retain the source
data during buffer uploads. After this commit, we are using it to retain
source data during texture decoding.
Fixes#3428.
Second attempt after abandoning #3451.
Feedback loops do not work with Chrome or Intel GPU's, so we now have an
optional ping-pong implementation of Bloom.
Issue #2338.
This fixes "illegal hardware instruction" seen on my MacBook, which
is the same as #1839, but triggered only in a test environment where
the main thread is the same as the driver thread, and filament is built
with HAS_THREADING enabled.
* Add swap() methods to Allocator.h
This allows StructureOfArraysBase's move constructor to compile.
Removed an apparent workaround in SingleInstanceComponentManager.
* swap can be noexcept
* Add swap() methods to Allocator.h
This allows StructureOfArraysBase's move constructor to compile.
Co-authored-by: Mathias Agopian <pixelflinger@gmail.com>
Fix a possible out-of-bound access when reading the x-planes array.
Also account for the fact that the loops filling the froxels assume
stl-like iterators (1-past the end on the right), while the indices
themselves were right-inclusive.
fixes#3142
I tested this by viewing CesiumMan with our `gltf_instances` sample app.
There is now a need for some general refactoring in gltfio. I feel that
the high-level objects have become too tightly coupled to each other.
Fixes#3137.
Only items older than a certain value were purged from the cache,
this allowed the cache to grow unbounded before this age limit was
reached.
We now purge the cache at each frame if it's above the size threshold.
Fixes#3381
don't use slog from a static variable, because it might not have been
constructed yet, due to static initialized order.
For some reason, this happens on aarch64 macs, but this was actually
a real problem.
By default, the demo now reflects the camera instead of the renderable.
However this can be changed via the command line. Users can now change
the backend too.
- add darwin-aarch64 support to bluegl
- remove all aarch64 conditions in our cmakefiles, the architecture
is better handled in the source files (to allow fat binaries later)
When we removed the old "ghetto bloom" demo, we ceased to have any
samples demonstrating the RenderTarget API. This demo is a fairly simple
demonstration of planar reflection.
The gltfio API allows users to destroy ResourceLoader or FilamentAsset
even when various asynchronous work (e.g. uploading buffers to the GPU)
has not yet been completed. This was achieved in an error-prone manner
using manual reference counting and an internal management object called
AssetPool.
This PR refactors gltfio by wrapping cgltf_data in shared_ptr, which I
usually try to avoid. However in this case it provides the precisely the
functionality that is needed.
I tested this PR for memory leaks and crashes by hacking gltf_viewer
and monitoring memory usage in Activity Monitor.
This fixes#3383 and makes it easier to implement some missing features,
such as animation support for instanced assets.
Bad texture files would cause the background decoder thread to never
finish and would generate textures with 0x0 dimensions, which eventually
triggers GL_INVALID_VALUE.
To recap, gltfio texture loading has two phases: the first phase is
synchronous and uses stbi_info to gather texture info. The second phase
is asynchronous and uses stbi_load to do the actual decoding.
During the first phase, we now check the return code from stbi_info
rather than assuming that it worked. :)
Fixes#3344
This makes the tgz consistent with the npm package. Fixes#3268.
Note that we already stopped packaging the old HTML docs. Going forward,
we would like to use the TS declarations as documentation because they
must be kept up to date anyway, and they already contain type
information. This was discussed in #3250.
* Add support for sheenColor and sheenRoughness
This work is necessary to support the glTF extension KHR_materials_sheen.
This change effectively adds the specular lobe from the cloth material
model to the base material model. The cloth model remains useful for
its extra subsurface color feature but also because it's cheaper.
* Add support for KHR_materials_sheen to gltfio
* Update documentation
* Document default shading values
This tool makes it easy to analyze the composition of Android
applications that use Filament.
- Filament materials are shown in the treemap if `resgen --json` was
used in the build.
- The input path can be a so file, folder, or zip archive (apk or aar).
- If the path is a zip or folder, helps you find the file to analyze.
- The generated web report is a self-contained HTML file.
- Reports the gzipped size of all Filament materials.
For example, from a mac, you can generate a self-contained HTML file by
typing this from the Filament repo root:
./tools/zbloat/zbloat.py ./android/filament-android
open index.html
This tool uses Python, `nm`, and `objdump`.
The `nm` tool works slightly differently between macOS and Linux, so a
`Dockerfile` is provided that installs dependencies inside a Linux
container. This is also convenient if you do not have both versions of
Python on your system.
The easy way to use docker is to invoke the helper bash script. Simply
type `zbloat.sh [args...]` instead of `zbloat.py [args...]`. The first
time you run it, it will be slow but subsequent times will be fast.
Many thanks to Evan Martin for his interactive treemap widget.
This option embeds a small JSON string inside the resgen blob that lists
all materials and their respective sizes. This is useful when analyzing
the footprint of the binary executable.
This fixes a bug Renderer clearing a render target multiple times when the first time and back again.
Usually the default RenderTarget is unintentionally cleared/discarded in the current behavior.
1) Renderer renders a view without custom RenderTarget having full-screen viewport,
2) Renderer renders a view with custom RenderTarget
3) And Renderer renders an another view without custom RenderTarget having different viewport from 1)
You may see junk or empty pixels in outside of the viewport of the view 3), depending on ClearOptions and the backend.
This fix make Renderer put cleared RenderTargets into a set and check them to be cleared only for the first time, instead of comparing the previous RenderTarget to the current RenderTarget.
We now export only two groups of symbols: (1) JNI and (2) dynamic linker
symbols used by the companion libraries.
This commit has the following impact:
- Shrinks the arm64 so from 1024 KiB to 954 KiB.
- Shrinks the arm64 aar from 560 KiB to 538 KiB.
Note that the patterns in the map file are tested against mangled names
and therefore should not be used to match the double-colon operator.
When passing only 1 fence to vkWaitForFences, the `waitAll` argument
should not have any effect, but SwiftShader seems to skip the wait
when this argument is set to VK_FALSE.
More specifically, the failure to wait in `acquireWorkCommandBuffer`
causes the subsequent destruction of an in-use fence, which causes
a TSAN failure with Google's internal tests.
I am consulting with the SwiftShader team on a real fix, meanwhile
we can commit this easy workaround.
We have 5 usages of vkWaitForFences, one of which uses multiple fences
and should have used VK_TRUE anyway.
This prevents a SwiftShader crash and/or a slew of "no texture bound"
warnings that would appear when the client provides an IBL without
providing reflections texture, which should be a valid thing to do.
Note that it is okay to declare a sampler in GLSL that never gets bound,
as long as it is never sampled from. Since we always sample from the
IBL specular texture, we should always bind something to it.
With Vulkan, this warning would sometimes be a false positive. It could
trigger for internal samplers like `ssao` and `structure`, even though
they were not declared in SPIR-V.
With OpenGL, this warning would never be a false positive because it has
the luxury of calling `glGetUniformLocation`.
This adds a private attribute to our samplers called `strict` that
indicates whether or not a sampler should always have a bound texture.
For now the only strict samplers are the custom ones declared in the
user's material.
At some point I think we should consider adding `spirv-reflect` to our
tree to help with problems like this.
This fixes a bug seen with client applications that use ClearOptions
instead of Skybox, and one or more offscreen RenderTarget objects.
These apps would see junk pixels because Filament would only clear the
first render target in the frame.
The fix is to factor some the flag-setting logic in `beginFrame()` into
a private method, and call this method from `render()` each time
the user-level RenderTarget has been changed.
I wrote a simple C++ demo to reproduce the issue and to verify that
this fix works.
Fence.cpp:
My previous fix to the fix was insufficient because a signed integer
overflow could still occur as follows (this was observed in an internal
test at Google).
If the conditional on line 87 is true, then a clamped value is passed
into `wait`, which causes the conditional on line 133 to fail, which
causes `wait_for` to be called inappropriately, which is where an
overflow would occur.
MetalHandles.mm:
This is more theoretical, but to prevent potential integer overflow
within STL, I think we should call `wait()` rather than `wait_for()`
when an infinite timeout is desired.
This is our fourth fix to fences in since November 2; see also dcca236,
e9c9e45, and 8969416. :)
FFence::wait() has some logic that tests if "timeout" is equal to
FENCE_WAIT_FOR_EVER, which is actually impossible because it would
be modified by the clamp in this situation.
In practice I think this oversight would not cause any problems. I
noticed it while reviewing the code.
To recap why the clamp exists: according to the ISO C++ spec, the
"nanoseconds" duration in chrono is at least a signed 64-bit type, but
our sentinel constant might not (and does not) fit within this range.
Note that this API is on the loader rather than the asset. This is
because the loader knows how to create Filament entities by traversing
a cgltf node hierarchy.
Animation on dynamically added instances is not yet supported.
We did not add destroyInstance() because gltfio favors flat arrays for
long term storage of entity lists and instance lists, which would be
slow to shift. We also wish to discourage create/destroy churn since it
is more efficient to pre-allocate instances and selectively add them
into the scene.
Fixes#3137.
Release builds do not call cgltf_validate() so it was possible to
read out-of-bounds animation data when encountering a badly formed glTF
file with mismatched counts between sampler inputs and outputs.
This fixes a slew of validation warnings and errors seen when multiple
subpasses are enabled, starting with:
Attachment 1 not written by fragment shader; undefined values will
be written to attachment
The Vulkan driver was using the same color attachment list for both
subpasses, so the first subpass had unused attachments.
Note that Vulkan makes a distinction between color attachments and input
attachments and requires separate lists to be supplied for each subpass,
but our Driver API consolidates everything into a single list. This
should perhaps be refactored at a later date.
This prepares for #3137 by moving the mesh cache and material instance
cache out of the loader (where they were transient anyway) and into the
actual asset. This paves the way for a `createInstance()` API.
This makes it so that the PixelBufferDescriptor callback triggers at a
time consistent with other backends.
ReadPixels is still asynchronous in the sense that the callback is
triggered on the main thread. However, it is now guaranteed to trigger
during (or before) flushAndWait(), which is less surprising behavior.
You can now build Filament with support for both X11 APIs, or neither.
If both are supported, run-time selection is achieved using a SwapChain
flag.
Supporting only one API at build time (or neither) is useful because our
list of "required" VkInstance extensions can vary according to which
API's are supported. During VkInstance creation, we do not have a priori
knowledge about what kinds of swap chains will be created. (headless vs
non-headless, XCB vs XLIB, etc)
Note that some Vulkan implementation (e.g. some builds of SwiftShader)
only support XCB.
This avoids the following validation error when clients create then
immediately destroy vertex buffers, index buffers, and uniform buffers.
VUID-vkDestroyBuffer-buffer-00922
Cannot free VkBuffer that is in use by a command buffer.
Buffers that are used across multiple frames were fine, but
create-and-destroy scenarios were problematic.
This fixes a regression introduced by 548b28c6e manifesting as
intermittent assertions. The VulkanDisposer gc() should only be called
from the driver thread.
This change fixes an issue where ImGuiHelper would crash on destruction if you created more than one instance at the same time.
This crash occurred when ImGui::DestroyContext() was called, because when the second instance was destroyed there was no current context causing it to crash.
This fixes it by making ImGuiHelper store and manage it's own context.
Having two instances of ImGuiHelper is useful in cases where you want to use imgui with multiple views.
This adds support for more format conversions and removes a bogus
assert that prevented ReadPixels within beginFrame / endFrame.
This was tested with:
backend_test_mac --api vulkan --gtest_filter=BackendTest.ReadPixels
This adds a Dockerfile and a new bash script that makes it
east to invoke the appopriate Docker commands.
This does not yet enable a GitHub Action because of intermittent
issues that we have not yet ironed out.
This allows clients to build the Vulkan backend with either XLIB or XCB
support. I did a quick smoke test of the XCB option, but for now we are
continuing to default to XLIB. Note that the native window type used to
create the swap chain differs between these two API's.
The non-const getSkybox() method is especially useful to client code
that needs to change the clear color, but does not have direct
access to the Renderer object.
If hardware_concurrency() returned 2 while UTILS_HAS_HYPER_THREADING was
enabled, `mThreadCount` was resulting in zero, so jobs (such as texture
decoding) would simply never start. This problem was noticed with
GitHub Actions.
I tested this fix locally by replacing `hardware_concurrency()` with
fixed values like 1 or 2, and verified that the hang went away.
This adds support for headless rendering as well as readPixels. These
features are necessary for automated testing.
NOTE: invoking readPixels with a non-headless SwapChain seems to fail
with MoltenVK. I will investigate this later.
The Filament View that gets passed to tick() is retained briefly when
screenshots are enabled, but it may be destroyed by the time the
PixelBufferDescriptor callback is invoked. So, we needed a way of
notifying the AutomationEngine.
This adds a `material` key to `Settings`, as a sister to `view`.
Here's an example of an automation spec that manipulates material
parameters:
[{
"name": "metallic_vs_roughness",
"permute": {
"material.scalar.roughnessFactor": [0.0, 0.5, 1.0],
"material.scalar.metallicFactor": [0.0, 1.0]
}
}]
Currently this is limited to float, vec3, and vec4 parameters.
This adds `AutomationEngine` to libs/viewer, which iterates through
`Settings` instances that were generated from a JSON spec and applies
them to a Filament `View`. It can be configured to sleep between tests
using a time delay or a frame count.
This also adds command line arguments and user-interface elements to
`gltf_viewer` for automated testing.
This lets us generate long lists of settings permutations by writing a
simple JSON spec. For example, the following spec would generate six
`Settings` objects, all of which have SSAO enabled. See the unit test
for a larger example.
```
{
"name": "viewopts",
"base": { "view.ssao.enabled": true }
"permute": {
"view.dithering": ["NONE", "TEMPORAL"],
"view.sampleCount": [1, 4, 8]
}
}
```
- Use lower depth LOD as the cone radius increases.
This is the same technique we use for SAO.
The better cache access significantly improve performance.
On a test on Pixel4 at 585MHz, SAO pass improves by 30%.
This also helps the algorithm scale with the shadow distance.
- Shadow direction/length no longer dependent on aspect-ratio and camera
orientation.
This is fixed by doing all the computations in screen-space instead of
normalized screen space.
- Shadow parameters are no longer dependent on the field of view.
- Also rename dominantLightShadowing.fs to ssct.fs
- remove zoom parameter, it wasn't very useful.
This introduces the `viewer::Settings` struct, and a JSON reader /
writer.
This will be used for automated testing and for client / server
communication.
Note that `viewer::Settings` is closely associated with the
`filament::View` API; when updating the latter we will often need to
update the former, as well as some serialization code. This increases
the maintenance burden and I think we should consider using a parser
library like libclang or a macro-based reflection utility.
This PR also migrates SimpleViewer into libs/viewer and un-inlines its
implementation. It does not belong in gltfio because it has an imgui
dependency.
This is a technique from Naughty Dog used in TLOU2, where we compute
the "ambient" shadowing of a dominant light in screen-space.
This is currently integrated to the SSAO pass.
The image barrier must wait until all write operations are complete;
this was not set up correctly but somehow did not cause problems.
Also tried to document this better, since using an image barrier for
the swap chain seems to be an unusual thing to do (e.g. the Sascha
Willems demos do not do this).
There's no really good solution, so this just keeps it simple and makes
is so that embind consumes an integer rather than an embind enum object.
Tested by hacking _createTextureFromImageFile.
Fixes#3028.
For example, this makes it so that the primary material in Sponza
is *always* "untitled 0", which makes it easier to figure out which
material to modify.
Recall that Ctrl + Up / Down navigates between materials while
Left / Right navigates between variants.
- Make this behavior more explicit in the documentation.
- Shortcuts now use the same ordering as the displayed list.
- Shortcuts now use Cmd on macOS instead of Ctrl to avoid conflict with
Mission Control defaults.
If the websocket message exceeds a certain size, we might receive it
in chunks and civetweb does not auto-consolidate for us.
Fixed this by adding a length prefix to the edit command.
This change also makes it so that matdbg shows a numeric suffix to help
with duplicated names, and fixes a bug with names that start with
non-alpha characters.
Block compression is currently only used when we invoke mipgen for the
suzanne demo. This PR makes it easy to disable.
Block compression is still enabled in our CMake build, but other build
systems can simply omit BlockCompression.{h,cpp} from imageio (as well
as the two third_party libs) and it will "just work".
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].
For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof(). This was a good change, but before that
particular change, we had a "two wrongs made a right" situation for
mirrored normals.
Fixes#3001.
The equality operator for MaterialKey was missing some fields (also, its
ordering was inconsistent with the struct), which caused faulty behavior
in the material cache.
I ran into this bug when testing against a Blender-exported model that
has some materials with texture transforms, and some without.
We borrow a page from the HBAO book here and allow to limit the angle
with the horizon of SSAO samples. This can help reducing the effects
of low tessellation, which tend to create unwanted creases with SSAO.
contact shadows wouldn't work if shadowmap-based shadows were not
enabled, in this case the (unneeded) shadow pass would run and
attempt to create the shadow-map with an incorrect size (0), which
would later crash/assert in the backend.
This is a bit of a hack but it helps a lot -- for some reason the
background layer often has a sharp transition to the in-focus plane and
because we're calculating the DoF at 1/4 resolution these transitions
are quite visible. We work around this by fading out the transition over
a 1 CoC unit, specifically between a CoC of 2 to 1 pixel. Below 1 pixel,
we currently clamp to 0.
The sidecar buffer for multisampled_render_to_texture emulation was
stored with the texture, instead of the rendertarget, this prevented
a single texture to be used as an attachment of multiple render targets
with different sample counts.
There was an inconsistency in the gles backend where non-sampleable,
non-MS textures failed (assert) if they were used with a render target
with MS (i.e. "magic resolve" case).
We fix this by taking the same code path for textures and renderbuffers,
the only difference being the calls to glFrameBufferRenderbuffer
instead of glFramebufferTexture2D.
resources structures where not cleared when destroyed, and some code
relies in the handles being set or not to decide if a texture should
be used. in this case, the texture would be set in the shader after
it was destroyed, because its handle wasn't cleared.
- inScatteringSize actually cannot be set to zero because it produces
a 0^0 in the shader. So with this change, in-scattering must be
strictly > 0 to enable.
- inScatteringSize on the java side had an incorrect default value of
zero (which of course, now doesn't matter anymore).
- also clamp the fog altitude to 1mm which simplifies the shader quite
a bit for the same result.
Fixes#3069
.blurScale was in fact a scale factor applied to the circle of
confusion (which makes it indeed a "blur scale", but let's use
a more precise language here).
Update comments to show how to use .cocScale to control the DoF
effect independently from the camera aperture, which can be useful for
artistic reasons.
- simulate a standard deviation of 8 by skipping every other pixel
when blurring the AO buffer at LOW or MEDIuM quality. This creates
a faint checker pattern, but does look much better than the low
frequency noise that is introduced otherwise.
- tweak AO parameters to give a more uniform and smooth AO effect by
default. This also makes AO even more consistant between quality
modes.
- add a simple dithering stage to AO blur to help eliminate banding
artifacts at higher sample counts.
e.g. `F_PI` is also available as `d::PI` and `f::PI` as `double` or
`float` respectively.
Most of our uses of those constants are `float` and it was error prone
and cumbersome to have to cast to that each time we used them.
The `F_` constants are intended to mimic `math.h`, however these new
constants are not, and all the "n over" constants are named
`N_OVER_` instead of `N_`, which helps avoiding the confusion that e.g.:
`F_2_PI` is actually `2/pi` and not `2*pi`.
Also added `F_TAU` which is 2 * PI.
all parameters of the bilateral blur can now be set from the CPU,
instead of being hardcoded -- this probably prevent the shader compiler
from unrolling the filter, but it's also probably not a big deal.
additionally, we now use a kernel size of 23 (12 samples) when the
SSAO quality is set to HIGH or more.
ssaogen is no longer needed
Higher quality levels used to darken the ssao a lot, now they all have
a consistant look.
Add quality control to material sandbox.
Slightly simplify shader code.
We add noise do the radius of the samples on the spiral
(instead of adding noise only to the angle), this reduces a visible
"echo", especially at higher radii.
- don't use frameUniform.time as the temporal noise seed because
this has a cycle to it. It's not very visible on dithering but
obvious when used for other things.
- don't use fract(time) since time was already in [0,1] -- though it's
moot now.
- instead of time pass a random number in [0,1] generated on the CPU
each frame.
This will also allow to control temporal noise more easily if
needed in the future (e.g. for accessibility or rendering tests)
- fix a recent typo that affected SSAO quality
- add a upsampling quality checkbox in material_sandbox
- make use of textureLodOffset instead of texelFetch, so that
we emulate more closely textureGather
- don't hardcode bilateral filter edge-distance in the shader
(still hardcoded on the cpu side)
this broke recently with the reverse-z, the froxel calculation relies
on the depth, which is now inverted.
we actually fix our getNormalizedViewportCorrd() public API, which the
froxel code uses.
Because initializing the backend can be relatively slow, creating an
Engine can block the main thread, is this is a problem, this new API
can be used instead; while a bit more complex, it allow the engine to
be initialized asynchronously.
This significantly improve the depth-buffer resolution utilization
through the near-infinity range on Metal and Vulkan.
On OpenGL, this benefit is only seen when glClipControl is available.
The user-facing clip plane is unchanged [-1,1], the conversion
happens in filament's vertex shaders.
The bulk of this change consists in:
- invert the clip space's z in the vertex shader
- clear the depth buffer with 0
- invert all depth function comparisons
- fix all screen-space effects, e.g. ssao, DoF
- fix shadows and shadow biases
- use floating-point depth
- add a driver API to query which clip-space is used
- add glClipControl support to the gl backend
the depth buffer wasn't resolved in this case. We fix this by always
creating a depth buffer resolve pass -- which is a lot more robust.
this pass automatically culled if the depth is not used (i.e. TAA or
DoF are off). The pass is a no-op if resolving is not needed.
- don't apply SSAO to blended objects
these are not drawn into the structure buffer, so they don't
participate in SSAO.
- remove unused code that was needed for the depth prepass, which
simplifies handling of blended objects.
- always treat alpha-masked objects as opaque.
This also adds a -t flag to the easy build script for convenience.
SwiftShader on Vulkan can now be used as follows.
git clone https://github.com/google/swiftshader.git
cd swiftshader/build
cmake .. && make -j && export SWIFTSHADER_LD_LIBRARY_PATH=`pwd`
cd ../filament
./build.sh -t debug && ./out/cmake-debug/samples/gltf_viewer -a vulkan
Note that third_party/swiftshader does not need to exist since we
already have Vulkan headers. I will remove it in a subsequent PR.
FrameGraphTexture::Descriptor uses "0" to mean "auto" but the
sample count that is passed to the backend should always be 1 or
greater.
See also #2957.
The depth buffer was always set with a sample count of 1, this was
mostly moot because we almost never need the depth buffer after the
color pass; except for refraction and DoF.
In the case of refraction, we need to preserve the MS depth buffer
(just like we preserve the MS color buffer), moreover "backward resolve"
is not supported. So in that case, the depth buffer needed to be set to
MSAA samples.
In the case of DoF, we need to access a resolved depth texture, and
there is 2 cases here:
1) without refraction, a magic resolve is adequate -- in this case
the depth MS count must be 1.
2) with refraction, we are forced in to a MS depth, so it needs a
special resolve pass to be accessible from DoF.
depth/stencil attachments must have the same MS sample count
than the FBO (rt) they're attached to.
this is because EXT_multisampled_render_to_texture[2] doesn't
resolve depth attachments. In this case, we can't use this extension.
This regressed when we added a callback argument, because the callback
cannot be bound.
This commit also modifies the helmet example to use the low-level API
for testing purposes.
Note that this omits the optional nanoseconds argument. JavaScript
does not support overloading and this argument probably cannot be
accurately provided anyway in a web environment.
Fixes#3002.
- more flexible linearization of depth, doesn't impact performance
at all in the shader, but takes into account 3 parameters of
the projection matrix instead of true. Mathematically identical
to before.
- use depth test "less or equal" for depth only passes to be consistant
with the color pass. Unsure if using "less" would be better.
- use textureLod() when sampling the skybox
- use mediump for all samplers in the shadowing.fs, which correspond to
their actual definition.
Filament calls createRenderTarget very frequently, so this PR has the
side effect of reducing a huge amount of create-destroy churn in other
Vulkan objects such as VkRenderPass and VkFramebuffer.
Marking a view with a custom render target will now disable blending
for that view but require an alpha channel for intermediate buffers.
Blending is disabled because it is meaningless.
fixes#2802
This fixes the long-standing "black rectangle" issue in our shadowtest
sample.
We were mistakenly constraining the clear to the viewport, which
is meant only to affect the vertex pipeline.
Also, we were needlessly setting the scissor rect in BeginRenderPass(),
since we already do so in Draw().
This is more similar to the Vulkan shader pipeline and less magical.
There are 3 places in our shader code where we perform fixups like this:
- main.vs
- depth_main.vs
- post_process_getters.vs
That last one needs no change since it does not involve Z.
Also cleanup all setImage() error reporting. All error checks are
changed from silent to NON_FATAL_ASSERT, which means they'll throw
if exceptions are enabled or do a no-op and log a message otherwise.
Also added more precondition checks.
* Add back proguard file for Android and update README.md
The proguard-rules.pro file provided by Jeff McGlynn (9fe60a636)
works perfectly for Android projects with minifyEnabled.
Add the config file back to the repository and update README.md
to help other Android users setup release build.
* Refine android proguard file and remove proguard section in README.md
The stride passed to Vulkan for query pools is the stride between
queries, not the stride between individual values. I realized this after
seeing the SwiftShader implementation of queries.
I also used log statements to confirm that this fixes bogus frame
skipping on my Pixel 4.
This fixes the visual hang that would occur after going to the task
switcher and back.
After recreating the swap chain, all of its associated fences and sync
objects become invalid. Since we were not tracking this, FrameSkipper
was going into an infinite wait after the swap chain was created.
This removes the old getClientExtent stuff that I added a while back,
and replaces it with the strategy espoused by the MoltenVK author found
here:
https://github.com/KhronosGroup/MoltenVK/issues/428
I tested this PR on macOS with Vulkan and Metal. I tested both on high
and low DPI displays. I also tried dragging the window between the two
displays.
Android still has issues with rotation, I will deal with that next.
cleanup
This fixes a lot of flickering when SSAO and TAA are enabled.
SSAO TAA shouldn't be done based on a jittered depth buffer, but
rather on jittered samples.
while this started as a sample to demonstrate how to use the new
frame history feature, this is now solid enough to become a feature.
this version of TAA doesn't use motion vectors, so it is prone to
various artifacts (e.g. ghosting). It also has the typical issues
TAA has (e.g. transparents).
with that said, performace is good and quality is overall superior
to FXAA or MSAAx4.
In retrospect, I should've exposed ints to JS instead of entities.
Making this fix is already a TODO, but it will be a tedious change. For
now, this PR fixes two issues that were causing tiny but frequent memory
leaks, according to the emscripten memory leak widget.
(1) Do not include Entity in the list of classes that should only be
passed around by pointer.
(2) Clients should always call delete() on returned Entities.
This example has fallen out of date, I tried to resurrect it but it
turned out to be non-trivial, given the special nature of emscripten's
generated JavaScript wrappers.
It might be better to provide an example that uses rollup, since that's
the bundler that model-viewer uses, or a simple TypeScript example.
For now, I think our simple HTML + raw JS samples are sufficient.
We can now save an arbitrary (but decided at compile time) number of
entries containing information about previous frames and it for while
drawing the current frame. Typically this is used for such effects as
TAA, screen-space reflection, building probes over time, etc...
Currently the frame history consists of one frame per View. FView
provides a new (internal) getFrameHistory() method used to access
previous frames entries as well as to save the current's frame
information.
The FrameGraphPassResources (which is available in the execute closure
of a FrameGraph pass) has a new detach() method which can be used to
remove that resource from the FrameGraph lifetime management, at which
point it becomes the responsibility of the caller. Typically this
resource will be stored in the frame history.
The FrameGraph cannot store pointers internally because all objects
are stored in vectors. Unfortunately we were storing the writer of
resources as a pointer.
This is fixed by storing an index instead.
Sets of post-process materials are in their own folder now.
Also moved fxaa.fs from shaders/ to materials/ so it's next to the
material that includes it. This file is not shared with any other
material.
This prevents strange behavior with semi-transparent render targets,
which the model viewer team discovered when testing against the Khronos
alpha test conformance model.
A much smaller alternative to `filamat-android` that can only generate OpenGL shaders. It does not provide validation or optimizations.
| Artifact | Description |
| ------------- | ------------- |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android) | The Filament rendering engine itself. |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android-debug) | Debug version of `filament-android`. |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android) | A glTF 2.0 loader for Filament, depends on `filament-android`. |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android) | KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`. |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android) | A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan. |
| [](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite) | A much smaller alternative to `filamat-android` that can only generate OpenGL shaders. It does not provide validation or optimizations. |
### iOS
iOS projects can use CocoaPods to install the latest release:
```
pod 'Filament', '~> 1.8.1'
```shell
pod 'Filament', '~> 1.53.1'
```
### Snapshots
@@ -74,7 +62,7 @@ steps:
1. Find the [commit](https://github.com/google/filament/commits/main) you're interested in.
2. Click the green check mark under the commit message.
3. Click on the _Details_ link for the platform you're interested in.
4. On the top right, click on the _Artifacts_ dropdown and choose an artifact.
4. On the top left click _Summary_, then in the _Artifacts_ section choose the desired artifact.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.