Compare commits

..
Author SHA1 Message Date
Benjamin Doherty 8ed10d77de Begin to refactor test_LoadImage to use SharedShaders 2025-08-12 17:39:26 -04:00
Ben Doherty e8e99a0de6 Fix: webgpu error regarding mismatched pipeline (#9056) 2025-08-11 17:30:07 -04:00
Ben Doherty 6630aa5f36 matp: Remove accidental switch fallthrough (#9082) 2025-08-11 17:26:46 -04:00
Powei Feng bc83ffdcd1 vk: make default render target independent of call order (#9065) 2025-08-11 20:27:53 +00:00
Powei Feng c21f211a13 Update java for Texture::Usage (#9055)
Also update samples and utils to use proper usage when
generating mipmaps.
2025-08-11 19:47:26 +00:00
Patrik Huber 58d4671c24 Fixes to frame_generator sample (#9050)
* [Fix] frame_generator sample: open ifstream with ios::binary
* [Fix] frame_generator sample: allocate storage for g_materialBuffer
   reserve() merely reserves memory, but does not actually change the size of the vector.
* [Fix] frame_generator sample: destroy materials/renderables during cleanup

Otherwise the sample crashes with a Filament error saying that the material is still associated with a renderable.
2025-08-11 19:21:05 +00:00
Mathias Agopian 93caca7245 fig materialparser assert when shader is not present 2025-08-11 11:11:42 -07:00
Mathias Agopian bf77c023b9 correctly set STENCIL Usage on color pass texture
the framegraph didn't set the Usage::Stencil on textures it created
for the color pass if stencil was requested. On the GL backend it
didn't matter because that bit is unused.
2025-08-11 11:11:22 -07:00
yein 95128d5f55 Follow up of material parser PR (#9029)
- Fix CMakeLists to correctly include src files in matp test
- Replace std::string to std::string_view
- Also update the test_includer.cpp
2025-08-11 18:05:10 +00:00
Powei Feng 6d17d858de vk: Fix bad layouts/formats when doing generateMipmaps (#9058)
- After genMipmap, transition to shader read layout
- Ensure that the staging image format is TRANSFER_SRC.
2025-08-11 17:49:15 +00:00
Sungun Park 05003ea358 mat: Add CRC32 validation for material packages (#9053)
This commit introduces a CRC32 checksum to material packages to ensure
data integrity.

When a material is loaded, this checksum is verified. If the check
fails, an error is logged, and the material fails to load. For older
material packages without a CRC32 checksum, a warning is logged and
proceed.

BUGS=[373396840]
2025-08-09 00:03:56 +00:00
Matthew Hoffman 98847d6509 Simplify backend tests' EXPECT_IMAGE invocation. (#9052) 2025-08-08 21:55:37 +00:00
Mathias Agopian d3828cdd1c fix the 3-parameters fresnel calculation
it would automatically degrade to the 2-parameters version in 
LOW_QUALITY mode, but some other code relied on the proper calculation,
in particular when specularFactor was used.


FIXES=[436866605]
2025-08-08 14:18:15 -07:00
Andy Hovingh 4beda6feee wgpu: fix Android build error 2025-08-08 15:32:18 -05:00
Juan Caldas 7cacef9509 Update GLSL for mip test (#9064) 2025-08-08 15:09:27 -04:00
Juan Caldas 5cd7de7318 Change fogReserved 2025-08-08 10:44:54 -07:00
Sungun Park 9c87e72a81 Correct warning message (#9059)
The subsequent call

`glGetShaderiv(shader, GL_COMPILE_STATUS, &status);`

will ensure the compilation is complete.
2025-08-07 22:35:26 -07:00
Filament Bot 652d973ad8 [automated] Updating /docs due to commit 8466177
Full commit hash is 84661777e7

DOCS_ALLOW_DIRECT_EDITS
2025-08-07 22:52:23 +00:00
Ben Doherty 84661777e7 Materials: add useDefaultDepthVariant flag (#9020) 2025-08-07 22:49:05 +00:00
Powei Feng c8ab2f335e Fix places where generateMipmaps is called without proper usage (#9054) 2025-08-07 22:24:40 +00:00
Mathias Agopian db14efc151 compress the DFG LUT with zstd
- use resgen to package the DFG LUT into filament, instead of using
  a large include of a C array.

- add a zstd compression step, which reduces the size from ~100KB to
  ~75KB.

The overhead of zstd is about 90KB uncompressed, however it will pay
for itself tenfold when we use it to compress material packages.
2025-08-07 14:58:18 -07:00
Mathias Agopian d1ca059dad resgen: add compression options
- with `-z` each resource is compressed individually
- with `-Z` the whole package is compressed
2025-08-07 14:58:18 -07:00
Mathias Agopian c71a22914f small improvements to cmgen
- when generating the DFG LUT as a text file, make sure to faithfully
  reproduce the command used in the comments

- add a "bin" format that will output a headerless raw binary of the
  LUT data.
2025-08-07 14:58:18 -07:00
Mathias Agopian 71d0723026 add zstd to the build 2025-08-07 14:58:18 -07:00
Powei Feng 5c371089f2 Add GEN_MIPMAPPABLE TextureUsage (#9042)
This will allow for more backend-specific usage mapping then before - where BLIT_SRC and BLIT_DST are assumed for textures whose mipmaps will be generated.

These mappings have been introduced in metal, vulkan, webgpu.
2025-08-07 18:14:49 +00:00
Konrad Piascik 2c7064e93d webgpu: skip PushConstants backend test for webgpu
We can revert this once dawn supports push constants
2025-08-07 11:07:02 -04:00
Filament Bot 3961989aca [automated] Updating /docs due to commit b92af35
Full commit hash is b92af357f7

DOCS_ALLOW_DIRECT_EDITS
2025-08-07 08:36:16 +00:00
Mathias Agopian b92af357f7 add a material option to use linear fog calculations (#9030)
The new `linearFog` material property, when set to `true` enables a
simplified fog calculation. The fog equation becomes linear which is
unrealistic, but more efficient to compute. In some situations with
a shallow fog range, it doesn't make a huge difference visually.

In this mode, height falloff and in-scattering are ignored.

The linear equation slope is calculated from the regular parameters to
match the slope of the real equation at a camera height. If 
`heightFalloff` is disabled, set to 0, the `density` parameter 
exactly corresponds to the slope of the equation in [1/m] units.
2025-08-07 01:33:36 -07:00
Mathias Agopian f2a1051df9 add CanonicalizePass optimization
this makes all spirv IDs much more stable which greatly improve the
utilization of the line dictionary.
2025-08-07 01:32:31 -07:00
Mathias Agopian 594ab3e9e3 spirv-tools update to vulkan-sdk-1.4.321.0 2025-08-07 01:32:31 -07:00
Mathias Agopian 7f18c7fd43 fix -d (matdbg) build option
There was two problems:
- tint was needed regardless of webgpu support
- libfilamat wasn't built on the android side
  (I don't know how it ever worked)
2025-08-06 17:29:51 -07:00
Powei Feng 9c1a252ba5 Fix two compilation errors (#9041)
- Include <limits> in bitset.h
- The type could not be inferred for Scene.cpp's `SharedState`
  line.  The failure came from clang version 1:14.0-55~exp2
2025-08-06 22:22:40 +00:00
Juan Caldas bf8e798b60 webgpu: Set Layercount to 1 instead of 0 (#9038)
part of BUGS = [424157731]
2025-08-06 22:00:25 +00:00
Eliza Velasquez b94e90416a Fix build breakage 2025-08-06 14:33:53 -07:00
Andy Hovingh e9fde8346e wgpu: fix test seg fault due to null descriptor set layout label 2025-08-06 16:31:44 -05:00
Andy Hovingh 3ae747b544 wgpu: remove assumption default render target is present in makeCurrent(...) 2025-08-06 16:31:44 -05:00
Eliza 5924633085 gl: amortize shader compilation over N frames (#8964)
* gl: amortize shader compilation over N frames

On platforms which don't support parallel shader compilation (e.g. Firefox), we
can sort of emulate it by queueing up any requests to `Material::compile()` and
compiling each shader over multiple frames.

Compiling over consecutive frames slows things quite noticeably. Instead, space
each compilation over a number of ticks (16 chosen arbitrarily).

If we need a program NOW, we can bump a program queued for much later to the
front. We also avoid compiling any queued programs on this same frame to limit
stuttering.

* gl: add flag to disable amortized shader compile

If this flag is on, the new amortized compile code should theoretically never be
executed.

* gl: add CompilerPriorityQueue docs, Java API

* gl: amortize shaders, z3moon feedback

* gl: update CompilerThreadPool
2025-08-06 21:09:27 +00:00
Juan Caldas a07c19e5b7 Add missing WebGPU checks (#9037)
part of BUGS = [424157731]
2025-08-06 16:18:18 -04:00
Filament Bot 59f4d1ba20 [automated] Updating /docs due to commit ac076e8
Full commit hash is ac076e872e

DOCS_ALLOW_DIRECT_EDITS
2025-08-06 06:03:06 +00:00
1034 changed files with 199826 additions and 8786 deletions
+1
View File
@@ -818,6 +818,7 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
add_subdirectory(${EXTERNAL}/perfetto/tnt)
add_subdirectory(${EXTERNAL}/zstd/tnt)
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
add_subdirectory(${LIBRARIES}/geometry)
+7
View File
@@ -7,3 +7,10 @@ We are chaning the way Vulkan buffers are handled. We need to switch over to a m
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- engine: add a `linearFog` material parameter. [⚠️ **New Material Version**]
- opengl: When `Material::compile()` is called on a platform which doesn't support parallel compilation, shaders are automatically compiled over a number of frames
- engine: Added `useDefaultDepthVariant` material parameter to force Filament to use its default variant for
depth-only passes. [**Requires recompiling materials**]
- material: fix specularFactor in `LOW_QUALITY` mode. [**Requires recompiling materials**] to take effect.
- material: Add CRC32 validation for material packages [⚠️ **New Material Version**]
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.63.1'
implementation 'com.google.android.filament:filament-android:1.63.0'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
pod 'Filament', '~> 1.63.1'
pod 'Filament', '~> 1.63.0'
```
## Documentation
+9
View File
@@ -67,6 +67,10 @@ add_library(abseil STATIC IMPORTED)
set_target_properties(abseil PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libabseil.a)
add_library(zstd STATIC IMPORTED)
set_target_properties(zstd PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libzstd.a)
if (FILAMENT_ENABLE_FGVIEWER)
add_library(fgviewer STATIC IMPORTED)
set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
@@ -74,6 +78,10 @@ if (FILAMENT_ENABLE_FGVIEWER)
endif()
if (FILAMENT_ENABLE_MATDBG)
add_library(filamat STATIC IMPORTED)
set_target_properties(filamat PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilamat.a)
add_library(matdbg STATIC IMPORTED)
set_target_properties(matdbg PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libmatdbg.a)
@@ -138,6 +146,7 @@ target_link_libraries(filament-jni
PRIVATE utils
PRIVATE perfetto
PRIVATE abseil
PRIVATE zstd
# libgeometry is PUBLIC because gltfio uses it.
PUBLIC geometry
@@ -239,8 +239,25 @@ public class Material {
FRONT_AND_BACK
}
/**
* Shader compiler priority queue
*
* On platforms which support parallel shader compilation, compilation requests will be
* processed in order of priority, then insertion order.
*
* See {@link #compile(CompilerPriorityQueue, int, Object, Runnable)}.
*/
public enum CompilerPriorityQueue {
/** We need this program NOW.
*
* When passed as an argument to {@link #compile(CompilerPriorityQueue, int, Object,
* Runnable)}, if the platform doesn't support parallel compilation, but does support
* amortized shader compilation, the given shader program will be synchronously compiled.
*/
CRITICAL,
/** We will need this program soon. */
HIGH,
/** We will need this program eventually. */
LOW
}
@@ -911,6 +911,10 @@ public class Texture {
public static final int BLIT_SRC = 0x40;
/** Texture can be used the destination of a blit() */
public static final int BLIT_DST = 0x80;
/** Texture can be used for protected content */
public static final int PROTECTED = 0x0100;
/** Texture can be used with generateMipmaps() */
public static final int GEN_MIPMAPPABLE = 0x0200;
/** by default textures are <code>UPLOADABLE</code> and <code>SAMPLEABLE</code>*/
public static final int DEFAULT = UPLOADABLE | SAMPLEABLE;
}
@@ -1561,7 +1561,9 @@ public class View {
}
/**
* Options to control large-scale fog in the scene
* Options to control large-scale fog in the scene. Materials can enable the `linearFog` property,
* which uses a simplified, linear equation for fog calculation; in this mode, the heightFalloff
* is ignored as well as the mipmap selection in IBL or skyColor mode.
*/
public static class FogOptions {
/**
@@ -1578,7 +1580,7 @@ public class View {
*/
public float cutOffDistance = Float.POSITIVE_INFINITY;
/**
* fog's maximum opacity between 0 and 1
* fog's maximum opacity between 0 and 1. Ignored in `linearFog` mode.
*/
public float maximumOpacity = 1.0f;
/**
@@ -1586,12 +1588,15 @@ public class View {
*/
public float height = 0.0f;
/**
* How fast the fog dissipates with altitude. heightFalloff has a unit of [1/m].
* How fast the fog dissipates with the altitude. heightFalloff has a unit of [1/m].
* It can be expressed as 1/H, where H is the altitude change in world units [m] that causes a
* factor 2.78 (e) change in fog density.
*
* A falloff of 0 means the fog density is constant everywhere and may result is slightly
* faster computations.
*
* In `linearFog` mode, only use to compute the slope of the linear equation. Completely
* ignored if set to 0.
*/
public float heightFalloff = 1.0f;
/**
@@ -1612,7 +1617,7 @@ public class View {
@NonNull @Size(min = 3)
public float[] color = {1.0f, 1.0f, 1.0f};
/**
* Extinction factor in [1/m] at altitude 'height'. The extinction factor controls how much
* Extinction factor in [1/m] at an altitude 'height'. The extinction factor controls how much
* light is absorbed and out-scattered per unit of distance. Each unit of extinction reduces
* the incoming light to 37% of its original value.
*
@@ -1621,10 +1626,15 @@ public class View {
* the composition of the fog/atmosphere.
*
* For historical reason this parameter is called `density`.
*
* In `linearFog` mode this is the slope of the linear equation if heightFalloff is set to 0.
* Otherwise, heightFalloff affects the slope calculation such that it matches the slope of
* the standard equation at the camera height.
*/
public float density = 0.1f;
/**
* Distance in world units [m] from the camera where the Sun in-scattering starts.
* Ignored in `linearFog` mode.
*/
public float inScatteringStart = 0.0f;
/**
@@ -1632,6 +1642,7 @@ public class View {
* is scattered (by the fog) towards the camera.
* Size of the Sun in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
* Smaller values result is a larger scattering size.
* Ignored in `linearFog` mode.
*/
public float inScatteringSize = -1.0f;
/**
@@ -1657,6 +1668,8 @@ public class View {
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* In `linearFog` mode mipmap level 0 is always used.
*
* @see Texture
* @see fogColorFromIbl
*/
@@ -1671,7 +1684,7 @@ public class View {
/**
* Options to control Depth of Field (DoF) effect in the scene.
*
* cocScale can be used to set the depth of field blur independently from the camera
* cocScale can be used to set the depth of field blur independently of the camera
* aperture, e.g. for artistic reasons. This can be achieved by setting:
* cocScale = cameraAperture / desiredDoFAperture
*
@@ -60,6 +60,7 @@ jlong nCreateHDRTexture(JNIEnv* env, jclass,
.height(image->getHeight())
.levels(0xff)
.sampler(Texture::Sampler::SAMPLER_2D)
.usage(Texture::Usage::DEFAULT | Texture::Usage::GEN_MIPMAPPABLE)
.format(textureFormat)
.build(*engine);
@@ -46,8 +46,8 @@ fun loadTexture(engine: Engine, resources: Resources, resourceId: Int, type: Tex
.height(bitmap.height)
.sampler(Texture.Sampler.SAMPLER_2D)
.format(internalFormat(type))
// This tells Filament to figure out the number of mip levels
.levels(0xff)
.levels(0xff) // This tells Filament to figure out the number of mip levels
.usage(Texture.Usage.DEFAULT or Texture.Usage.GEN_MIPMAPPABLE)
.build(engine)
// TextureHelper offers a method that skips the copy of the bitmap into a ByteBuffer
+1 -1
View File
@@ -120,7 +120,7 @@ set(GLTFIO_INCLUDE_DIRS
${FILAMENT_DIR}/include
../../filament/backend/include
../../libs/gltfio/include
../../third_party/basisu/zstd
../../third_party/zstd/lib
../../third_party/cgltf
../../third_party/meshoptimizer/src
../../third_party/robin-map
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.63.1
VERSION_NAME=1.63.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
@@ -276,6 +276,7 @@ public class MainActivity extends Activity
.width(bitmap.getWidth())
.height(bitmap.getHeight())
.sampler(Texture.Sampler.SAMPLER_2D)
.usage(Texture.Usage.DEFAULT | Texture.Usage.GEN_MIPMAPPABLE)
.format(Texture.InternalFormat.SRGB8_A8) // It is crucial to use an SRGB format.
.levels(0xff) // tells Filament to figure out the number of mip levels
.build(engine);
+57
View File
@@ -1199,6 +1199,24 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: linearFog
Type
: `boolean`
Value
: `true` or `false`. Defaults to `false`.
Description
: When set to `true`, a simplified fog equation is used for large-scale fog calculations. In this mode,
in-scattering is ignored as well as height falloff.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
linearFog : true
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: quality
Type
@@ -1263,6 +1281,45 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: useDefaultDepthVariant
Type
: `boolean`
Value
: `true` or `false`. Defaults to `false`.
Description
: This parameter forces Filament to use its default variant for depth passes, such as those used
in shadow rendering. This provides an optimization for materials with expensive custom vertex
shaders. For example, custom vertex shader computations intended to be consumed by the fragment
stage can be skipped during the depth-only pass. This parameter is only meaningful if the
material has a vertex block.
This parameter should not be set to `true` for vertex blocks that modify geometry (i.e.,
modifying `worldPosition`), otherwise shadows may render incorrectly.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
variables : [
customColor
],
useDefaultDepthVariant : true
}
vertex {
void materialVertex(inout MaterialVertexInputs material) {
material.customColor = /* expensive computation that can be skipped for depth-only passes */
}
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = variable_customColor;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Vertex and attributes: requires
Type
+3 -2
View File
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.62.2'
implementation 'com.google.android.filament:filament-android:1.63.0'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
@@ -196,7 +196,7 @@ dependencies {
</div>
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
<p>iOS projects can use CocoaPods to install the latest release:</p>
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.62.2'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.63.0'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>
@@ -501,6 +501,7 @@ and tools.</p>
<li><code>filamesh</code>: Mesh converter</li>
<li><code>glslminifier</code>: Minifies GLSL source code</li>
<li><code>matc</code>: Material compiler</li>
<li><code>filament-matp</code>: Material parser</li>
<li><code>matinfo</code> Displays information about materials compiled with <code>matc</code></li>
<li><code>mipgen</code> Generates a series of miplevels from a source image</li>
<li><code>normal-blending</code>: Tool to blend normal maps</li>
+3 -2
View File
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.62.2'
implementation 'com.google.android.filament:filament-android:1.63.0'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
@@ -196,7 +196,7 @@ dependencies {
</div>
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
<p>iOS projects can use CocoaPods to install the latest release:</p>
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.62.2'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.63.0'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>
@@ -501,6 +501,7 @@ and tools.</p>
<li><code>filamesh</code>: Mesh converter</li>
<li><code>glslminifier</code>: Minifies GLSL source code</li>
<li><code>matc</code>: Material compiler</li>
<li><code>filament-matp</code>: Material parser</li>
<li><code>matinfo</code> Displays information about materials compiled with <code>matc</code></li>
<li><code>mipgen</code> Generates a series of miplevels from a source image</li>
<li><code>normal-blending</code>: Tool to blend normal maps</li>
+103 -62
View File
@@ -235,36 +235,38 @@ counter-increment: h6;margin-right:10px}
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:constants" target="_self" class="level3"><span class="tocNumber">4.2.5&nbsp; </span>General: constants</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:variantfilter" target="_self" class="level3"><span class="tocNumber">4.2.6&nbsp; </span>General: variantFilter</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:flipuv" target="_self" class="level3"><span class="tocNumber">4.2.7&nbsp; </span>General: flipUV</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:quality" target="_self" class="level3"><span class="tocNumber">4.2.8&nbsp; </span>General: quality</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:instanced" target="_self" class="level3"><span class="tocNumber">4.2.9&nbsp; </span>General: instanced</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:vertexdomaindevicejittered" target="_self" class="level3"><span class="tocNumber">4.2.10&nbsp; </span>General: vertexDomainDeviceJittered</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:requires" target="_self" class="level3"><span class="tocNumber">4.2.11&nbsp; </span>Vertex and attributes: requires</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:variables" target="_self" class="level3"><span class="tocNumber">4.2.12&nbsp; </span>Vertex and attributes: variables</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" target="_self" class="level3"><span class="tocNumber">4.2.13&nbsp; </span>Vertex and attributes: vertexDomain</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" target="_self" class="level3"><span class="tocNumber">4.2.14&nbsp; </span>Vertex and attributes: interpolation</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" target="_self" class="level3"><span class="tocNumber">4.2.15&nbsp; </span>Blending and transparency: blending</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blendfunction" target="_self" class="level3"><span class="tocNumber">4.2.16&nbsp; </span>Blending and transparency: blendFunction</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" target="_self" class="level3"><span class="tocNumber">4.2.17&nbsp; </span>Blending and transparency: postLightingBlending</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" target="_self" class="level3"><span class="tocNumber">4.2.18&nbsp; </span>Blending and transparency: transparency</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" target="_self" class="level3"><span class="tocNumber">4.2.19&nbsp; </span>Blending and transparency: maskThreshold</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" target="_self" class="level3"><span class="tocNumber">4.2.20&nbsp; </span>Blending and transparency: refractionMode</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" target="_self" class="level3"><span class="tocNumber">4.2.21&nbsp; </span>Blending and transparency: refractionType</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:culling" target="_self" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Rasterization: culling</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:colorwrite" target="_self" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Rasterization: colorWrite</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthwrite" target="_self" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Rasterization: depthWrite</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthculling" target="_self" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Rasterization: depthCulling</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:doublesided" target="_self" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Rasterization: doubleSided</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:alphatocoverage" target="_self" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Rasterization: alphaToCoverage</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:reflections" target="_self" class="level3"><span class="tocNumber">4.2.28&nbsp; </span>Lighting: reflections</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" target="_self" class="level3"><span class="tocNumber">4.2.29&nbsp; </span>Lighting: shadowMultiplier</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:transparentshadow" target="_self" class="level3"><span class="tocNumber">4.2.30&nbsp; </span>Lighting: transparentShadow</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" target="_self" class="level3"><span class="tocNumber">4.2.31&nbsp; </span>Lighting: clearCoatIorChange</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" target="_self" class="level3"><span class="tocNumber">4.2.32&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" target="_self" class="level3"><span class="tocNumber">4.2.33&nbsp; </span>Lighting: specularAmbientOcclusion</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" target="_self" class="level3"><span class="tocNumber">4.2.34&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" target="_self" class="level3"><span class="tocNumber">4.2.35&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" target="_self" class="level3"><span class="tocNumber">4.2.36&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" target="_self" class="level3"><span class="tocNumber">4.2.37&nbsp; </span>Shading: customSurfaceShading</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:linearfog" target="_self" class="level3"><span class="tocNumber">4.2.8&nbsp; </span>General: linearFog</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:quality" target="_self" class="level3"><span class="tocNumber">4.2.9&nbsp; </span>General: quality</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:instanced" target="_self" class="level3"><span class="tocNumber">4.2.10&nbsp; </span>General: instanced</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:vertexdomaindevicejittered" target="_self" class="level3"><span class="tocNumber">4.2.11&nbsp; </span>General: vertexDomainDeviceJittered</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:usedefaultdepthvariant" target="_self" class="level3"><span class="tocNumber">4.2.12&nbsp; </span>General: useDefaultDepthVariant</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:requires" target="_self" class="level3"><span class="tocNumber">4.2.13&nbsp; </span>Vertex and attributes: requires</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:variables" target="_self" class="level3"><span class="tocNumber">4.2.14&nbsp; </span>Vertex and attributes: variables</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" target="_self" class="level3"><span class="tocNumber">4.2.15&nbsp; </span>Vertex and attributes: vertexDomain</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" target="_self" class="level3"><span class="tocNumber">4.2.16&nbsp; </span>Vertex and attributes: interpolation</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" target="_self" class="level3"><span class="tocNumber">4.2.17&nbsp; </span>Blending and transparency: blending</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blendfunction" target="_self" class="level3"><span class="tocNumber">4.2.18&nbsp; </span>Blending and transparency: blendFunction</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" target="_self" class="level3"><span class="tocNumber">4.2.19&nbsp; </span>Blending and transparency: postLightingBlending</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" target="_self" class="level3"><span class="tocNumber">4.2.20&nbsp; </span>Blending and transparency: transparency</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" target="_self" class="level3"><span class="tocNumber">4.2.21&nbsp; </span>Blending and transparency: maskThreshold</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" target="_self" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Blending and transparency: refractionMode</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" target="_self" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Blending and transparency: refractionType</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:culling" target="_self" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Rasterization: culling</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:colorwrite" target="_self" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Rasterization: colorWrite</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthwrite" target="_self" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Rasterization: depthWrite</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthculling" target="_self" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Rasterization: depthCulling</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:doublesided" target="_self" class="level3"><span class="tocNumber">4.2.28&nbsp; </span>Rasterization: doubleSided</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:alphatocoverage" target="_self" class="level3"><span class="tocNumber">4.2.29&nbsp; </span>Rasterization: alphaToCoverage</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:reflections" target="_self" class="level3"><span class="tocNumber">4.2.30&nbsp; </span>Lighting: reflections</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" target="_self" class="level3"><span class="tocNumber">4.2.31&nbsp; </span>Lighting: shadowMultiplier</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:transparentshadow" target="_self" class="level3"><span class="tocNumber">4.2.32&nbsp; </span>Lighting: transparentShadow</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" target="_self" class="level3"><span class="tocNumber">4.2.33&nbsp; </span>Lighting: clearCoatIorChange</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" target="_self" class="level3"><span class="tocNumber">4.2.34&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" target="_self" class="level3"><span class="tocNumber">4.2.35&nbsp; </span>Lighting: specularAmbientOcclusion</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" target="_self" class="level3"><span class="tocNumber">4.2.36&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" target="_self" class="level3"><span class="tocNumber">4.2.37&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" target="_self" class="level3"><span class="tocNumber">4.2.38&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" target="_self" class="level3"><span class="tocNumber">4.2.39&nbsp; </span>Shading: customSurfaceShading</a><br/>
&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock" target="_self" class="level2"><span class="tocNumber">4.3&nbsp; </span>Vertex block</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock/materialvertexinputs" target="_self" class="level3"><span class="tocNumber">4.3.1&nbsp; </span>Material vertex inputs</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock/customvertexattributes" target="_self" class="level3"><span class="tocNumber">4.3.2&nbsp; </span>Custom vertex attributes</a><br/>
@@ -731,7 +733,7 @@ Note that the <code>normal</code> property affects the <em class="underscore">ba
<p>
<p>The <code>bentNormal</code> property defines the average unoccluded direction at a point on the surface. It is
used to improve the accuracy of indirect lighting. Bent normals can also improve the quality of
specular ambient occlusion (see section <a href="#toc4.2.33" target="_self">4.2.33</a> about
specular ambient occlusion (see section <a href="#toc4.2.35" target="_self">4.2.35</a> about
<code>specularAmbientOcclusion</code>).</p>
</p><p>
Bent normals can greatly increase the visual fidelity of an asset with various cavities and concave
@@ -810,7 +812,7 @@ light to bend further away from the initial path.
</table><center><div class="tablecaption"><b style="font-style:normal;">Table&nbsp;6:</b> Index of refraction of common materials</div></center></div>
</p><p>
The appearance of a refractive material will greatly depend on the <code>refractionType</code> and
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.21" target="_self">4.2.21</a> and section <a href="#toc4.2.20" target="_self">4.2.20</a>
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.23" target="_self">4.2.23</a> and section <a href="#toc4.2.22" target="_self">4.2.22</a>
for more information.
</p><p>
The effect of <code>ior</code> when <code>refractionMode</code> is set to <code>cubemap</code> and <code>refractionType</code> is set to <code>solid</code>
@@ -1400,7 +1402,16 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> flipUV <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="general:quality">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:quality">&nbsp;</a><a class="target" name="toc4.2.8">&nbsp;</a><h3 id="general-quality"><a class="header" href="#general-quality">General: quality</a></h3>
<a class="target" name="general:linearfog">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:linearfog">&nbsp;</a><a class="target" name="toc4.2.8">&nbsp;</a><h3 id="general-linearfog"><a class="header" href="#general-linearfog">General: linearFog</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
</p></dd><dt>Description</dt><dd><p> When set to <code>true</code>, a simplified fog equation is used for large-scale fog calculations. In this mode,
in-scattering is ignored as well as height falloff.
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> linearFog <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="general:quality">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:quality">&nbsp;</a><a class="target" name="toc4.2.9">&nbsp;</a><h3 id="general-quality"><a class="header" href="#general-quality">General: quality</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>low</code>, <code>normal</code>, <code>high</code>, <code>default</code>. Defaults to <code>default</code>.
@@ -1411,7 +1422,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> quality <span class="hljs-punctuation">:</span> default
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="general:instanced">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:instanced">&nbsp;</a><a class="target" name="toc4.2.9">&nbsp;</a><h3 id="general-instanced"><a class="header" href="#general-instanced">General: instanced</a></h3>
<a class="target" name="general:instanced">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:instanced">&nbsp;</a><a class="target" name="toc4.2.10">&nbsp;</a><h3 id="general-instanced"><a class="header" href="#general-instanced">General: instanced</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1423,7 +1434,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> instanced <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="general:vertexdomaindevicejittered">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:vertexdomaindevicejittered">&nbsp;</a><a class="target" name="toc4.2.10">&nbsp;</a><h3 id="general-vertexdomaindevicejittered"><a class="header" href="#general-vertexdomaindevicejittered">General: vertexDomainDeviceJittered</a></h3>
<a class="target" name="general:vertexdomaindevicejittered">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:vertexdomaindevicejittered">&nbsp;</a><a class="target" name="toc4.2.11">&nbsp;</a><h3 id="general-vertexdomaindevicejittered"><a class="header" href="#general-vertexdomaindevicejittered">General: vertexDomainDeviceJittered</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1437,7 +1448,37 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> vertexDomainDeviceJittered <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="vertexandattributes:requires">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires">&nbsp;</a><a class="target" name="toc4.2.11">&nbsp;</a><h3 id="vertex-and-attributes-requires"><a class="header" href="#vertex-and-attributes-requires">Vertex and attributes: requires</a></h3>
<a class="target" name="general:usedefaultdepthvariant">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:usedefaultdepthvariant">&nbsp;</a><a class="target" name="toc4.2.12">&nbsp;</a><h3 id="general-usedefaultdepthvariant"><a class="header" href="#general-usedefaultdepthvariant">General: useDefaultDepthVariant</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
</p></dd><dt>Description</dt><dd><p> This parameter forces Filament to use its default variant for depth passes, such as those used
in shadow rendering. This provides an optimization for materials with expensive custom vertex
shaders. For example, custom vertex shader computations intended to be consumed by the fragment
stage can be skipped during the depth-only pass. This parameter is only meaningful if the
material has a vertex block.
This parameter should not be set to <code>true</code> for vertex blocks that modify geometry (i.e.,
modifying <code>worldPosition</code>), otherwise shadows may render incorrectly.
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> variables <span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
<span class="line"></span> customColor
<span class="line"></span> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
<span class="line"></span> useDefaultDepthVariant <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span>
<span class="line"></span>
<span class="line"></span>vertex <span class="hljs-punctuation">{</span>
<span class="line"></span> void materialVertex(inout MaterialVertexInputs material) <span class="hljs-punctuation">{</span>
<span class="line"></span> material.customColor = <span class="hljs-comment">/* expensive computation that can be skipped for depth-only passes */</span>
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span>
<span class="line"></span>
<span class="line"></span>fragment <span class="hljs-punctuation">{</span>
<span class="line"></span> void material(inout MaterialInputs material) <span class="hljs-punctuation">{</span>
<span class="line"></span> prepareMaterial(material);
<span class="line"></span> material.baseColor = variable_customColor;
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="vertexandattributes:requires">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires">&nbsp;</a><a class="target" name="toc4.2.13">&nbsp;</a><h3 id="vertex-and-attributes-requires"><a class="header" href="#vertex-and-attributes-requires">Vertex and attributes: requires</a></h3>
<p>
<dl><dt>Type</dt><dd><p> array of <code>string</code>
</p></dd><dt>Value</dt><dd><p> Each entry must be any of <code>uv0</code>, <code>uv1</code>, <code>color</code>, <code>position</code>, <code>tangents</code>, <code>custom0</code>
@@ -1470,7 +1511,7 @@ non-shader data.</p>
<span class="line"></span> material.baseColor.rgb *= getCustom0().rgb;
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="vertexandattributes:variables">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables">&nbsp;</a><a class="target" name="toc4.2.12">&nbsp;</a><h3 id="vertex-and-attributes-variables"><a class="header" href="#vertex-and-attributes-variables">Vertex and attributes: variables</a></h3>
<a class="target" name="vertexandattributes:variables">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables">&nbsp;</a><a class="target" name="toc4.2.14">&nbsp;</a><h3 id="vertex-and-attributes-variables"><a class="header" href="#vertex-and-attributes-variables">Vertex and attributes: variables</a></h3>
<p>
<dl><dt>Type</dt><dd><p> array of <code>string</code>
</p></dd><dt>Value</dt><dd><p> Up to 5 strings, each must be a valid GLSL identifier.
@@ -1525,7 +1566,7 @@ non-shader data.</p>
<span class="line"></span> material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix()<span class="hljs-punctuation">,</span> u);
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="toc4.2.13">&nbsp;</a><h3 id="vertex-and-attributes-vertexdomain"><a class="header" href="#vertex-and-attributes-vertexdomain">Vertex and attributes: vertexDomain</a></h3>
<a class="target" name="vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="toc4.2.15">&nbsp;</a><h3 id="vertex-and-attributes-vertexdomain"><a class="header" href="#vertex-and-attributes-vertexdomain">Vertex and attributes: vertexDomain</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>object</code>, <code>world</code>, <code>view</code>, <code>device</code>. Defaults to <code>object</code>.
@@ -1547,7 +1588,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> vertexDomain <span class="hljs-punctuation">:</span> device
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="vertexandattributes:interpolation">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation">&nbsp;</a><a class="target" name="toc4.2.14">&nbsp;</a><h3 id="vertex-and-attributes-interpolation"><a class="header" href="#vertex-and-attributes-interpolation">Vertex and attributes: interpolation</a></h3>
<a class="target" name="vertexandattributes:interpolation">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation">&nbsp;</a><a class="target" name="toc4.2.16">&nbsp;</a><h3 id="vertex-and-attributes-interpolation"><a class="header" href="#vertex-and-attributes-interpolation">Vertex and attributes: interpolation</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>smooth</code>, <code>flat</code>. Defaults to <code>smooth</code>.
@@ -1558,7 +1599,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> interpolation <span class="hljs-punctuation">:</span> flat
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:blending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending">&nbsp;</a><a class="target" name="toc4.2.15">&nbsp;</a><h3 id="blending-and-transparency-blending"><a class="header" href="#blending-and-transparency-blending">Blending and transparency: blending</a></h3>
<a class="target" name="blendingandtransparency:blending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending">&nbsp;</a><a class="target" name="toc4.2.17">&nbsp;</a><h3 id="blending-and-transparency-blending"><a class="header" href="#blending-and-transparency-blending">Blending and transparency: blending</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>opaque</code>, <code>transparent</code>, <code>fade</code>, <code>add</code>, <code>masked</code>, <code>multiply</code>, <code>screen</code>, <code>custom</code>. Defaults to <code>opaque</code>.
@@ -1597,7 +1638,7 @@ non-shader data.</p>
</p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> blending <span class="hljs-punctuation">:</span> transparent
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:blendfunction">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blendfunction">&nbsp;</a><a class="target" name="toc4.2.16">&nbsp;</a><h3 id="blending-and-transparency-blendfunction"><a class="header" href="#blending-and-transparency-blendfunction">Blending and transparency: blendFunction</a></h3>
<a class="target" name="blendingandtransparency:blendfunction">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blendfunction">&nbsp;</a><a class="target" name="toc4.2.18">&nbsp;</a><h3 id="blending-and-transparency-blendfunction"><a class="header" href="#blending-and-transparency-blendfunction">Blending and transparency: blendFunction</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>object</code>
</p></dd><dt>Fields</dt><dd><p> <code>srcRGB</code>, <code>srcA</code>, <code>dstRGB</code>, <code>dstA</code>
@@ -1618,7 +1659,7 @@ non-shader data.</p>
<span class="line"></span> dstA<span class="hljs-punctuation">:</span> oneMinusSrcAlpha
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span> <span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="toc4.2.17">&nbsp;</a><h3 id="blending-and-transparency-postlightingblending"><a class="header" href="#blending-and-transparency-postlightingblending">Blending and transparency: postLightingBlending</a></h3>
<a class="target" name="blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="toc4.2.19">&nbsp;</a><h3 id="blending-and-transparency-postlightingblending"><a class="header" href="#blending-and-transparency-postlightingblending">Blending and transparency: postLightingBlending</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>opaque</code>, <code>transparent</code>, <code>add</code>. Defaults to <code>transparent</code>.
@@ -1641,7 +1682,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> postLightingBlending <span class="hljs-punctuation">:</span> add
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:transparency">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency">&nbsp;</a><a class="target" name="toc4.2.18">&nbsp;</a><h3 id="blending-and-transparency-transparency"><a class="header" href="#blending-and-transparency-transparency">Blending and transparency: transparency</a></h3>
<a class="target" name="blendingandtransparency:transparency">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency">&nbsp;</a><a class="target" name="toc4.2.20">&nbsp;</a><h3 id="blending-and-transparency-transparency"><a class="header" href="#blending-and-transparency-transparency">Blending and transparency: transparency</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>default</code>, <code>twoPassesOneSide</code> or <code>twoPassesTwoSides</code>. Defaults to <code>default</code>.
@@ -1674,7 +1715,7 @@ non-shader data.</p>
<center><div class="image" style=""><a class="target" name="figure_transparencytwopassestwosides">&nbsp;</a><a href="../images/screenshot_twopasses_twosides.png" target="_blank"><img class="markdeep" src="../images/screenshot_twopasses_twosides.png" /></a><center><span class="imagecaption"><b style="font-style:normal;">Figure&nbsp;35:</b> In <code>twoPassesTwoSides</code> mode, both set of faces are visible
</span></center></div></center>
</p>
<a class="target" name="blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="toc4.2.19">&nbsp;</a><h3 id="blending-and-transparency-maskthreshold"><a class="header" href="#blending-and-transparency-maskthreshold">Blending and transparency: maskThreshold</a></h3>
<a class="target" name="blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="toc4.2.21">&nbsp;</a><h3 id="blending-and-transparency-maskthreshold"><a class="header" href="#blending-and-transparency-maskthreshold">Blending and transparency: maskThreshold</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>number</code>
</p></dd><dt>Value</dt><dd><p> A value between <code>0.0</code> and <code>1.0</code>. Defaults to <code>0.4</code>.
@@ -1686,7 +1727,7 @@ non-shader data.</p>
<span class="line"></span> blending <span class="hljs-punctuation">:</span> masked<span class="hljs-punctuation">,</span>
<span class="line"></span> maskThreshold <span class="hljs-punctuation">:</span> <span class="hljs-number">0.5</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="toc4.2.20">&nbsp;</a><h3 id="blending-and-transparency-refractionmode"><a class="header" href="#blending-and-transparency-refractionmode">Blending and transparency: refractionMode</a></h3>
<a class="target" name="blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3 id="blending-and-transparency-refractionmode"><a class="header" href="#blending-and-transparency-refractionmode">Blending and transparency: refractionMode</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>none</code>, <code>cubemap</code>, <code>screenspace</code>. Defaults to <code>none</code>.
@@ -1702,7 +1743,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> refractionMode <span class="hljs-punctuation">:</span> cubemap<span class="hljs-punctuation">,</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="toc4.2.21">&nbsp;</a><h3 id="blending-and-transparency-refractiontype"><a class="header" href="#blending-and-transparency-refractiontype">Blending and transparency: refractionType</a></h3>
<a class="target" name="blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3 id="blending-and-transparency-refractiontype"><a class="header" href="#blending-and-transparency-refractiontype">Blending and transparency: refractionType</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>solid</code>, <code>thin</code>. Defaults to <code>solid</code>.
@@ -1716,7 +1757,7 @@ non-shader data.</p>
<span class="line"></span> refractionMode <span class="hljs-punctuation">:</span> cubemap<span class="hljs-punctuation">,</span>
<span class="line"></span> refractionType <span class="hljs-punctuation">:</span> thin<span class="hljs-punctuation">,</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:culling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:culling">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3 id="rasterization-culling"><a class="header" href="#rasterization-culling">Rasterization: culling</a></h3>
<a class="target" name="rasterization:culling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:culling">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3 id="rasterization-culling"><a class="header" href="#rasterization-culling">Rasterization: culling</a></h3>
<p>
<dl><table><tr valign=top><td><dt>Type</dt></td><td><dd><p> <code>string</code>
</p></dd></td></tr><tr valign=top><td><dt>Value</dt></td><td><dd><p> Any of <code>none</code>, <code>front</code>, <code>back</code>, <code>frontAndBack</code>. Defaults to <code>back</code>.
@@ -1725,7 +1766,7 @@ non-shader data.</p>
</p></dd></td></tr></table></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> culling <span class="hljs-punctuation">:</span> none
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:colorwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3 id="rasterization-colorwrite"><a class="header" href="#rasterization-colorwrite">Rasterization: colorWrite</a></h3>
<a class="target" name="rasterization:colorwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3 id="rasterization-colorwrite"><a class="header" href="#rasterization-colorwrite">Rasterization: colorWrite</a></h3>
<p>
<dl><table><tr valign=top><td><dt>Type</dt></td><td><dd><p> <code>boolean</code>
</p></dd></td></tr><tr valign=top><td><dt>Value</dt></td><td><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>true</code>.
@@ -1733,7 +1774,7 @@ non-shader data.</p>
</p></dd></td></tr></table></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> colorWrite <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:depthwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3 id="rasterization-depthwrite"><a class="header" href="#rasterization-depthwrite">Rasterization: depthWrite</a></h3>
<a class="target" name="rasterization:depthwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3 id="rasterization-depthwrite"><a class="header" href="#rasterization-depthwrite">Rasterization: depthWrite</a></h3>
<p>
<dl><table><tr valign=top><td><dt>Type</dt></td><td><dd><p> <code>boolean</code>
</p></dd></td></tr><tr valign=top><td><dt>Value</dt></td><td><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>true</code> for opaque materials, <code>false</code> for transparent materials.
@@ -1741,7 +1782,7 @@ non-shader data.</p>
</p></dd></td></tr></table></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> depthWrite <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:depthculling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3 id="rasterization-depthculling"><a class="header" href="#rasterization-depthculling">Rasterization: depthCulling</a></h3>
<a class="target" name="rasterization:depthculling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3 id="rasterization-depthculling"><a class="header" href="#rasterization-depthculling">Rasterization: depthCulling</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>true</code>.
@@ -1750,7 +1791,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> depthCulling <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:doublesided">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3 id="rasterization-doublesided"><a class="header" href="#rasterization-doublesided">Rasterization: doubleSided</a></h3>
<a class="target" name="rasterization:doublesided">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided">&nbsp;</a><a class="target" name="toc4.2.28">&nbsp;</a><h3 id="rasterization-doublesided"><a class="header" href="#rasterization-doublesided">Rasterization: doubleSided</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1770,7 +1811,7 @@ non-shader data.</p>
<span class="line"></span> material.baseColor = materialParams.albedo;
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="rasterization:alphatocoverage">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:alphatocoverage">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3 id="rasterization-alphatocoverage"><a class="header" href="#rasterization-alphatocoverage">Rasterization: alphaToCoverage</a></h3>
<a class="target" name="rasterization:alphatocoverage">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:alphatocoverage">&nbsp;</a><a class="target" name="toc4.2.29">&nbsp;</a><h3 id="rasterization-alphatocoverage"><a class="header" href="#rasterization-alphatocoverage">Rasterization: alphaToCoverage</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1792,7 +1833,7 @@ non-shader data.</p>
<span class="line"></span> material.baseColor = materialParams.albedo;
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="lighting:reflections">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:reflections">&nbsp;</a><a class="target" name="toc4.2.28">&nbsp;</a><h3 id="lighting-reflections"><a class="header" href="#lighting-reflections">Lighting: reflections</a></h3>
<a class="target" name="lighting:reflections">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:reflections">&nbsp;</a><a class="target" name="toc4.2.30">&nbsp;</a><h3 id="lighting-reflections"><a class="header" href="#lighting-reflections">Lighting: reflections</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> <code>default</code> or <code>screenspace</code>. Defaults to <code>default</code>.
@@ -1804,7 +1845,7 @@ non-shader data.</p>
<span class="line"></span> name <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Glossy metal&quot;</span><span class="hljs-punctuation">,</span>
<span class="line"></span> reflections <span class="hljs-punctuation">:</span> screenspace
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.29">&nbsp;</a><h3 id="lighting-shadowmultiplier"><a class="header" href="#lighting-shadowmultiplier">Lighting: shadowMultiplier</a></h3>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.31">&nbsp;</a><h3 id="lighting-shadowmultiplier"><a class="header" href="#lighting-shadowmultiplier">Lighting: shadowMultiplier</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1826,7 +1867,7 @@ non-shader data.</p>
<span class="line"></span> material.baseColor = vec4(<span class="hljs-number">0.0</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.0</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.0</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.7</span>);
<span class="line"></span> <span class="hljs-punctuation">}</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="lighting:transparentshadow">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow">&nbsp;</a><a class="target" name="toc4.2.30">&nbsp;</a><h3 id="lighting-transparentshadow"><a class="header" href="#lighting-transparentshadow">Lighting: transparentShadow</a></h3>
<a class="target" name="lighting:transparentshadow">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow">&nbsp;</a><a class="target" name="toc4.2.32">&nbsp;</a><h3 id="lighting-transparentshadow"><a class="header" href="#lighting-transparentshadow">Lighting: transparentShadow</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1852,7 +1893,7 @@ non-shader data.</p>
<center><div class="image" style=""><a class="target" name="figure_transparentshadow">&nbsp;</a><a href="../images/screenshot_transparent_shadows.jpg" target="_blank"><img class="markdeep" src="../images/screenshot_transparent_shadows.jpg" /></a><center><span class="imagecaption"><b style="font-style:normal;">Figure&nbsp;36:</b> Objects rendered with transparent shadows and blurry VSM with a
</span></center></div></center>
</p>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.31">&nbsp;</a><h3 id="lighting-clearcoatiorchange"><a class="header" href="#lighting-clearcoatiorchange">Lighting: clearCoatIorChange</a></h3>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.33">&nbsp;</a><h3 id="lighting-clearcoatiorchange"><a class="header" href="#lighting-clearcoatiorchange">Lighting: clearCoatIorChange</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>true</code>.
@@ -1866,7 +1907,7 @@ non-shader data.</p>
<center><div class="image" style=""><a class="target" name="figure_clearcoatiorchange">&nbsp;</a><a href="../images/screenshot_clear_coat_ior_change.jpg" target="_blank"><img class="markdeep" src="../images/screenshot_clear_coat_ior_change.jpg" /></a><center><span class="imagecaption"><b style="font-style:normal;">Figure&nbsp;37:</b> The same rough metallic ball with a clear coat layer rendered
</span></center></div></center>
</p>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.32">&nbsp;</a><h3 id="lighting-multibounceambientocclusion"><a class="header" href="#lighting-multibounceambientocclusion">Lighting: multiBounceAmbientOcclusion</a></h3>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.34">&nbsp;</a><h3 id="lighting-multibounceambientocclusion"><a class="header" href="#lighting-multibounceambientocclusion">Lighting: multiBounceAmbientOcclusion</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code> on mobile, <code>true</code> on desktop.
@@ -1886,7 +1927,7 @@ non-shader data.</p>
<center><div class="image" style=""><a class="target" name="figure_multibounceaoanimated">&nbsp;</a><a href="../images/screenshot_multi_bounce_ao.gif" target="_blank"><img class="markdeep" src="../images/screenshot_multi_bounce_ao.gif" /></a><center><span class="imagecaption"><b style="font-style:normal;">Figure&nbsp;39:</b> Brick texture rendered with multi-bounce ambient
</span></center></div></center>
</p>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.33">&nbsp;</a><h3 id="lighting-specularambientocclusion"><a class="header" href="#lighting-specularambientocclusion">Lighting: specularAmbientOcclusion</a></h3>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.35">&nbsp;</a><h3 id="lighting-specularambientocclusion"><a class="header" href="#lighting-specularambientocclusion">Lighting: specularAmbientOcclusion</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> <code>none</code>, <code>simple</code> or <code>bentNormals</code>. Defaults to <code>none</code> on mobile, <code>simple</code> on desktop. For
@@ -1905,7 +1946,7 @@ non-shader data.</p>
<center><div class="image" style=""><a class="target" name="figure_specularao">&nbsp;</a><a href="../images/screenshot_specular_ao.gif" target="_blank"><img class="markdeep" src="../images/screenshot_specular_ao.gif" /></a><center><span class="imagecaption"><b style="font-style:normal;">Figure&nbsp;40:</b> Comparison of specular ambient occlusion on and off. The effect is
</span></center></div></center>
</p>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.34">&nbsp;</a><h3 id="anti-aliasing-specularantialiasing"><a class="header" href="#anti-aliasing-specularantialiasing">Anti-aliasing: specularAntiAliasing</a></h3>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.36">&nbsp;</a><h3 id="anti-aliasing-specularantialiasing"><a class="header" href="#anti-aliasing-specularantialiasing">Anti-aliasing: specularAntiAliasing</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>boolean</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
@@ -1917,7 +1958,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> specularAntiAliasing <span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.35">&nbsp;</a><h3 id="anti-aliasing-specularantialiasingvariance"><a class="header" href="#anti-aliasing-specularantialiasingvariance">Anti-aliasing: specularAntiAliasingVariance</a></h3>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.37">&nbsp;</a><h3 id="anti-aliasing-specularantialiasingvariance"><a class="header" href="#anti-aliasing-specularantialiasingvariance">Anti-aliasing: specularAntiAliasingVariance</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>float</code>
</p></dd><dt>Value</dt><dd><p> A value between 0 and 1, set to 0.15 by default.
@@ -1927,7 +1968,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> specularAntiAliasingVariance <span class="hljs-punctuation">:</span> <span class="hljs-number">0.2</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.36">&nbsp;</a><h3 id="anti-aliasing-specularantialiasingthreshold"><a class="header" href="#anti-aliasing-specularantialiasingthreshold">Anti-aliasing: specularAntiAliasingThreshold</a></h3>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.38">&nbsp;</a><h3 id="anti-aliasing-specularantialiasingthreshold"><a class="header" href="#anti-aliasing-specularantialiasingthreshold">Anti-aliasing: specularAntiAliasingThreshold</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>float</code>
</p></dd><dt>Value</dt><dd><p> A value between 0 and 1, set to 0.2 by default.
@@ -1936,7 +1977,7 @@ non-shader data.</p>
</p></dd></dl></p><pre class="listing tilde"><code><span class="line"></span>material <span class="hljs-punctuation">{</span>
<span class="line"></span> specularAntiAliasingThreshold <span class="hljs-punctuation">:</span> <span class="hljs-number">0.1</span>
<span class="line"></span><span class="hljs-punctuation">}</span></code></pre>
<a class="target" name="shading:customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading">&nbsp;</a><a class="target" name="toc4.2.37">&nbsp;</a><h3 id="shading-customsurfaceshading"><a class="header" href="#shading-customsurfaceshading">Shading: customSurfaceShading</a></h3>
<a class="target" name="shading:customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading">&nbsp;</a><a class="target" name="toc4.2.39">&nbsp;</a><h3 id="shading-customsurfaceshading"><a class="header" href="#shading-customsurfaceshading">Shading: customSurfaceShading</a></h3>
<p>
<dl><dt>Type</dt><dd><p> <code>bool</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+57
View File
@@ -1199,6 +1199,24 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: linearFog
Type
: `boolean`
Value
: `true` or `false`. Defaults to `false`.
Description
: When set to `true`, a simplified fog equation is used for large-scale fog calculations. In this mode,
in-scattering is ignored as well as height falloff.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
linearFog : true
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: quality
Type
@@ -1263,6 +1281,45 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: useDefaultDepthVariant
Type
: `boolean`
Value
: `true` or `false`. Defaults to `false`.
Description
: This parameter forces Filament to use its default variant for depth passes, such as those used
in shadow rendering. This provides an optimization for materials with expensive custom vertex
shaders. For example, custom vertex shader computations intended to be consumed by the fragment
stage can be skipped during the depth-only pass. This parameter is only meaningful if the
material has a vertex block.
This parameter should not be set to `true` for vertex blocks that modify geometry (i.e.,
modifying `worldPosition`), otherwise shadows may render incorrectly.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
variables : [
customColor
],
useDefaultDepthVariant : true
}
vertex {
void materialVertex(inout MaterialVertexInputs material) {
material.customColor = /* expensive computation that can be skipped for depth-only passes */
}
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = variable_customColor;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Vertex and attributes: requires
Type
+26 -11
View File
@@ -152,6 +152,7 @@ set(SRCS
src/fg/PassNode.cpp
src/fg/ResourceNode.cpp
src/fsr.cpp
src/ZstdHelper.cpp
)
set(PRIVATE_HDRS
@@ -235,6 +236,7 @@ set(PRIVATE_HDRS
src/materials/fsr/ffx_a.h
src/materials/fsr/ffx_fsr1.h
src/materials/fsr/ffx_fsr1_mobile.fs
src/ZstdHelper.h
)
set(MATERIAL_SRCS
@@ -605,6 +607,28 @@ add_custom_command(
APPEND
)
file(MAKE_DIRECTORY "${GENERATION_ROOT}/generated/data/")
set(output_path_dfg_bin "${GENERATION_ROOT}/generated/data/dfg.bin")
add_custom_command(
OUTPUT ${output_path_dfg_bin}
COMMAND cmgen --quiet --size=${DFG_LUT_SIZE} --ibl-dfg-multiscatter --ibl-dfg-cloth --ibl-dfg=${output_path_dfg_bin}
DEPENDS cmgen
COMMENT "Generating DFG LUT to ${output_path_dfg_bin}"
)
set(dfg_package_name "dfg")
get_resgen_vars(${RESOURCE_DIR} ${dfg_package_name})
add_custom_command(
OUTPUT ${RESGEN_OUTPUTS}
COMMAND resgen ${RESGEN_FLAGS} -Z ${output_path_dfg_bin}
DEPENDS resgen
DEPENDS ${output_path_dfg_bin}
COMMENT "Generating DFG resource package for ${dfg_package_name}"
)
list(APPEND GENERATED_RESOURCE_HDRS ${RESGEN_HEADER})
list(APPEND GENERATED_RESOURCE_SRCS ${RESGEN_SOURCE})
# Add the generated resource files to the source and header lists.
list(APPEND PRIVATE_HDRS ${GENERATED_RESOURCE_HDRS})
list(APPEND SRCS ${GENERATED_RESOURCE_SRCS})
@@ -613,16 +637,6 @@ if (DEFINED RESGEN_SOURCE_FLAGS)
set_source_files_properties(${GENERATED_RESOURCE_SRCS} PROPERTIES COMPILE_FLAGS ${RESGEN_SOURCE_FLAGS})
endif()
file(MAKE_DIRECTORY "${GENERATION_ROOT}/generated/data/")
set(output_path "${GENERATION_ROOT}/generated/data/dfg.inc")
add_custom_command(
OUTPUT ${output_path}
COMMAND cmgen --quiet --size=${DFG_LUT_SIZE} --ibl-dfg-multiscatter --ibl-dfg-cloth --ibl-dfg=${output_path}
DEPENDS cmgen
COMMENT "Generating DFG LUT ${output_path}"
)
list(APPEND DATA_BINS ${output_path})
# ==================================================================================================
# Includes & target definition
@@ -633,7 +647,7 @@ include_directories(${GENERATION_ROOT})
include_directories(src)
# we're building a library
add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS} ${DATA_BINS})
add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS})
# specify where the public headers of this library are
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
@@ -650,6 +664,7 @@ target_link_libraries(${TARGET} PUBLIC math)
target_link_libraries(${TARGET} PUBLIC utils)
target_link_libraries(${TARGET} PUBLIC filaflat)
target_link_libraries(${TARGET} PUBLIC filabridge)
target_link_libraries(${TARGET} PRIVATE zstd)
if (FILAMENT_USE_ABSEIL_LOGGING)
target_link_libraries(${TARGET} PUBLIC absl::log)
@@ -672,9 +672,21 @@ enum class Precision : uint8_t {
/**
* Shader compiler priority queue
*
* On platforms which support parallel shader compilation, compilation requests will be processed in
* order of priority, then insertion order. See Material::compile().
*/
enum class CompilerPriorityQueue : uint8_t {
/** We need this program NOW.
*
* When passed as an argument to Material::compile(), if the platform doesn't support parallel
* compilation, but does support amortized shader compilation, the given shader program will be
* synchronously compiled.
*/
CRITICAL,
/** We will need this program soon. */
HIGH,
/** We will need this program eventually. */
LOW
};
@@ -1056,6 +1068,7 @@ enum class TextureUsage : uint16_t {
BLIT_SRC = 0x0040, //!< Texture can be used the source of a blit()
BLIT_DST = 0x0080, //!< Texture can be used the destination of a blit()
PROTECTED = 0x0100, //!< Texture can be used for protected content
GEN_MIPMAPPABLE = 0x0200, //!< Texture can be used with generateMipmaps()
DEFAULT = UPLOADABLE | SAMPLEABLE, //!< Default texture usage
ALL_ATTACHMENTS = COLOR_ATTACHMENT | DEPTH_ATTACHMENT | STENCIL_ATTACHMENT | SUBPASS_INPUT, //!< Mask of all attachments
};
+7 -1
View File
@@ -152,6 +152,12 @@ public:
*/
bool disableParallelShaderCompile = false;
/**
* Set to `true` to forcibly disable amortized shader compilation in the backend.
* Currently only honored by the GL backend.
*/
bool disableAmortizedShaderCompile = false;
/**
* Disable backend handles use-after-free checks.
*/
@@ -220,7 +226,7 @@ public:
* @param sharedContext an optional shared context. This is not meaningful with all graphic
* APIs and platforms.
* For EGL platforms, this is an EGLContext.
*
*
* @param driverConfig specifies driver initialization parameters
*
* @return nullptr on failure, or a pointer to the newly created driver.
+1 -1
View File
@@ -80,7 +80,7 @@ public:
Program& operator=(const Program& rhs) = delete;
Program(Program&& rhs) noexcept;
Program& operator=(Program&& rhs) noexcept = delete;
Program& operator=(Program&& rhs) noexcept;
~Program() noexcept;
+2 -1
View File
@@ -32,6 +32,7 @@ CompilerThreadPool::~CompilerThreadPool() noexcept {
assert_invariant(mCompilerThreads.empty());
assert_invariant(mQueues[0].empty());
assert_invariant(mQueues[1].empty());
assert_invariant(mQueues[2].empty());
}
void CompilerThreadPool::init(uint32_t threadCount,
@@ -55,7 +56,7 @@ void CompilerThreadPool::init(uint32_t threadCount,
});
FILAMENT_TRACING_VALUE(FILAMENT_TRACING_CATEGORY_FILAMENT, "CompilerThreadPool Jobs",
mQueues[0].size() + mQueues[1].size());
mQueues[0].size() + mQueues[1].size() + mQueues[2].size());
if (UTILS_LIKELY(!mExitRequested)) {
Job job;
+1 -2
View File
@@ -59,7 +59,7 @@ private:
bool mExitRequested{ false };
utils::Mutex mQueueLock;
utils::Condition mQueueCondition;
std::array<Queue, 2> mQueues;
std::array<Queue, 3> mQueues;
// lock must be held for methods below
std::pair<Queue&, Queue::iterator> find(program_token_t const& token);
};
@@ -67,4 +67,3 @@ private:
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_COMPILERTHREADPOOL_H
+2
View File
@@ -37,6 +37,8 @@ Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
Program::Program(Program&& rhs) noexcept = default;
Program& Program::operator=(Program&& rhs) noexcept = default;
Program::~Program() noexcept = default;
Program& Program::priorityQueue(CompilerPriorityQueue priorityQueue) noexcept {
@@ -102,6 +102,9 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
if (any(usage & TextureUsage::BLIT_SRC)) {
u |= MTLTextureUsageShaderRead;
}
if (any(usage & TextureUsage::GEN_MIPMAPPABLE)) {
u |= (MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead);
}
return MTLTextureUsage(u);
}
+11 -1
View File
@@ -2421,7 +2421,17 @@ bool OpenGLDriver::isStereoSupported() {
}
bool OpenGLDriver::isParallelShaderCompileSupported() {
return mShaderCompilerService.isParallelShaderCompileSupported();
// We emulate parallel compilation even on platforms that don't support it by amortizing the
// cost of shader compilation over N frames. It would be nice to move this behavior out of the
// OpenGL into a generic system usable by all backends. However, the behavior of async shader
// compilation is closely coupled to the internals of ShaderCompilerService, which is
// GL-specific. It would also be nice to inform the engine that they're working with this fake
// amortized system, but this fact will become implicit when we generalize this feature for all
// backends.
if (mDriverConfig.disableAmortizedShaderCompile) {
return mShaderCompilerService.isParallelShaderCompileSupported();
}
return true;
}
bool OpenGLDriver::isDepthStencilResolveSupported() {
@@ -60,6 +60,11 @@ namespace filament::backend {
using namespace utils;
// How many ticks do we wait in between compiling non-IMMEDIATE programs synchronously?
constexpr uint32_t NUM_TICKS_BETWEEN_PROGRAMS = 16;
// How many non-IMMEDIATE synchronous programs are we allowed to compile on the same tick?
constexpr uint32_t MAX_NUM_SYNCHRONOUS_PROGRAMS_PER_FRAME = 1;
// ------------------------------------------------------------------------------------------------
static std::string to_string(bool const b) { return b ? "true" : "false"; }
@@ -265,6 +270,7 @@ void ShaderCompilerService::terminate() noexcept {
mCompilerThreadPool.terminate();
mRunAtNextTickOps.clear();
mPendingSynchronousPrograms.clear();
// We could have some pending callbacks here, we need to execute them.
// This is equivalent to calling cancelTickOp() on all active tokens.
@@ -274,6 +280,7 @@ void ShaderCompilerService::terminate() noexcept {
ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
CString const& name, Program&& program) {
auto& gl = mDriver.getContext();
CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();
// Create a token. A callback condition (handle) is internally created upon token creation.
auto token = std::make_shared<OpenGLProgramToken>(*this, name);
@@ -281,7 +288,33 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
token->attributes = std::move(program.getAttributes());
}
// Initiate program compilation.
if (mMode == Mode::SYNCHRONOUS) {
if (priorityQueue == CompilerPriorityQueue::CRITICAL ||
shouldCompileSynchronousProgramThisTick()) {
// We should immediately compile this program this frame.
compileProgram(token, std::move(program));
} else {
// We already exceeded the number of non-IMMEDIATE synchronous programs we're allowed to
// create this frame. Queue it for a future frame, sorted by priority.
auto const pos = std::lower_bound(mPendingSynchronousPrograms.begin(),
mPendingSynchronousPrograms.end(), priorityQueue,
[](PendingSynchronousProgram const& lhs,
CompilerPriorityQueue const priorityQueue) {
return std::get<1>(lhs).getPriorityQueue() < priorityQueue;
});
mPendingSynchronousPrograms.emplace(pos, token, std::move(program));
}
} else {
// Truly asynchronous platforms can always begin compiling immediately.
compileProgram(token, std::move(program));
}
return token;
}
void ShaderCompilerService::compileProgram(
program_token_t const& token, Program&& program) noexcept {
auto& gl = mDriver.getContext();
CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();
switch (mMode) {
case Mode::THREAD_POOL: {
@@ -330,6 +363,8 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
}
case Mode::SYNCHRONOUS:
mNumProgramsCreatedSynchronouslyThisTick++;
UTILS_FALLTHROUGH;
case Mode::ASYNCHRONOUS: {
// Try retrieving the program from the cache first. If no program found,
// a normal compilation/linking process is performed.
@@ -365,8 +400,6 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
assert_invariant(false);
}
}
return token;
}
GLuint ShaderCompilerService::getProgram(program_token_t& token) {
@@ -400,6 +433,7 @@ GLuint ShaderCompilerService::getProgram(program_token_t& token) {
}
} else {
token->compiler.cancelTickOp(token);
token->compiler.cancelPendingSynchronousProgram(token);
}
token = nullptr; // This will try submitting a callback handle to the callback manager.
@@ -411,6 +445,9 @@ void ShaderCompilerService::tick() {
} else {
executeTickOps();
}
if (UTILS_UNLIKELY(mMode == Mode::SYNCHRONOUS)) {
compilePendingSynchronousPrograms();
}
}
CallbackManager::Handle ShaderCompilerService::issueCallbackHandle() const noexcept {
@@ -487,9 +524,9 @@ void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
// just log warnings here instead of repeatedly checking compile status. If this turns
// out to be a real issue later, we would need to consider doing the canonical way.
if (!isCompileCompleted(token)) {
LOG(WARNING)
LOG(INFO)
<< "Shader compilation for OpenGL program " << token->name.c_str_safe()
<< " is not completed yet. The following program link may not succeed.";
<< " is not completed yet. The following program link may be slow.";
}
linkProgram(mDriver.getContext(), token);
@@ -497,9 +534,12 @@ void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
}
case Mode::SYNCHRONOUS: {
// We must not have called the TickOp yet until now. Call now to have
// `token->gl.program` ready to use.
tick();
// This program might still be in the queue, so try to compile it now.
compilePendingSynchronousProgramNow(token);
// If the program was just compiled on the above line, or the program was compiled but
// the tick ops weren't yet executed, we must execute them to populate
// `token->gl.program`.
executeTickOps();
break;
}
@@ -591,6 +631,65 @@ void ShaderCompilerService::executeTickOps() noexcept {
FILAMENT_TRACING_VALUE(FILAMENT_TRACING_CATEGORY_FILAMENT, "ShaderCompilerService Jobs", ops.size());
}
bool ShaderCompilerService::shouldCompileSynchronousProgramThisTick() const noexcept {
return mDriver.getDriverConfig().disableAmortizedShaderCompile ||
(mNumProgramsCreatedSynchronouslyThisTick < MAX_NUM_SYNCHRONOUS_PROGRAMS_PER_FRAME &&
mNumTicksUntilNextSynchronousProgram == 0);
}
void ShaderCompilerService::compilePendingSynchronousPrograms() noexcept {
if (mDriver.getDriverConfig().disableAmortizedShaderCompile) {
return;
}
auto it = mPendingSynchronousPrograms.begin();
while (it != mPendingSynchronousPrograms.end() && shouldCompileSynchronousProgramThisTick()) {
compileProgram(std::get<0>(*it), std::move(std::get<1>(*it)));
it = mPendingSynchronousPrograms.erase(it);
}
if (mNumProgramsCreatedSynchronouslyThisTick) {
mNumTicksUntilNextSynchronousProgram = NUM_TICKS_BETWEEN_PROGRAMS;
mNumProgramsCreatedSynchronouslyThisTick = 0u;
} else if (mNumTicksUntilNextSynchronousProgram) {
mNumTicksUntilNextSynchronousProgram--;
}
}
void ShaderCompilerService::compilePendingSynchronousProgramNow(
program_token_t const& token) noexcept {
if (mDriver.getDriverConfig().disableAmortizedShaderCompile) {
return;
}
auto pos = std::find_if(mPendingSynchronousPrograms.begin(),
mPendingSynchronousPrograms.end(), [&](PendingSynchronousProgram const& item) {
return std::get<0>(item) == token;
});
if (pos != mPendingSynchronousPrograms.end()) {
compileProgram(std::get<0>(*pos), std::move(std::get<1>(*pos)));
mPendingSynchronousPrograms.erase(pos);
}
}
void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t const& token) noexcept {
if (mDriver.getDriverConfig().disableAmortizedShaderCompile) {
return;
}
// We do a linear search here, but this is rare, and we know the list is pretty small.
auto const pos = std::find_if(mPendingSynchronousPrograms.begin(),
mPendingSynchronousPrograms.end(), [&](const auto& item) {
return std::get<0>(item) == token;
});
if (pos != mPendingSynchronousPrograms.end()) {
mPendingSynchronousPrograms.erase(pos);
return;
}
FILAMENT_TRACING_CONTEXT(FILAMENT_TRACING_CATEGORY_FILAMENT);
FILAMENT_TRACING_VALUE(FILAMENT_TRACING_CATEGORY_FILAMENT,
"ShaderCompilerService Pending Programs", mPendingSynchronousPrograms.size());
}
/* static */ void ShaderCompilerService::compileShaders(OpenGLContext& context,
Program::ShaderSource shadersSource,
FixedCapacityVector<Program::SpecializationConstant> const& specializationConstants,
@@ -17,8 +17,6 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_SHADERCOMPILERSERVICE_H
#define TNT_FILAMENT_BACKEND_OPENGL_SHADERCOMPILERSERVICE_H
#include "gl_headers.h"
#include "CallbackManager.h"
#include "CompilerThreadPool.h"
#include "OpenGLBlobCache.h"
@@ -35,7 +33,6 @@
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <tuple>
#include <utility>
#include <vector>
@@ -136,6 +133,12 @@ private:
std::vector<ContainerType> mRunAtNextTickOps;
std::list<program_token_t> mCanceledTokens;
// These members are only ever accessed on the main thread and are completely unused when mMode
// is not SYNCHRONOUS.
uint32_t mNumProgramsCreatedSynchronouslyThisTick = 0u;
uint32_t mNumTicksUntilNextSynchronousProgram = 0u;
using PendingSynchronousProgram = std::tuple<program_token_t, Program>;
std::vector<PendingSynchronousProgram> mPendingSynchronousPrograms;
GLuint initialize(program_token_t& token);
void ensureTokenIsReady(program_token_t const& token);
@@ -149,6 +152,13 @@ private:
void executeTickOps() noexcept;
bool cancelTickOp(program_token_t const& token) noexcept;
bool shouldCompileSynchronousProgramThisTick() const noexcept;
void compilePendingSynchronousPrograms() noexcept;
void compilePendingSynchronousProgramNow(program_token_t const& token) noexcept;
void cancelPendingSynchronousProgram(program_token_t const& token) noexcept;
void compileProgram(program_token_t const& token, Program&& program) noexcept;
// Compile shaders with the given `shaderSource`. `gl.shaders` is always populated with valid
// shader IDs after this method. But this doesn't necessarily mean the shaders are successfully
// compiled. Errors can be checked by calling `checkCompileStatus` later.
+1
View File
@@ -499,6 +499,7 @@ io::ostream& operator<<(io::ostream& out, ShaderStage shaderStage) {
io::ostream& operator<<(io::ostream& out, CompilerPriorityQueue compilerPriorityQueue) {
switch (compilerPriorityQueue) {
CASE(CompilerPriorityQueue, CRITICAL)
CASE(CompilerPriorityQueue, HIGH)
CASE(CompilerPriorityQueue, LOW)
}
+11 -4
View File
@@ -37,10 +37,16 @@ inline void blitFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect, V
const VkOffset3D srcRect[2], const VkOffset3D dstRect[2]) {
VkCommandBuffer const cmdbuf = commands->buffer();
if constexpr (FVK_ENABLED(FVK_DEBUG_BLITTER)) {
FVK_LOGD << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
<< " layout=" << src.getLayout()
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
<< " layout=" << dst.getLayout();
FVK_LOGE << "Fast blit from=" << src.texture->getVkImage() << ", level=" << (int) src.level
<< ", layer=" << (int) src.layer
<< ", layout=" << src.getLayout()
<< ", src-rect=(" << srcRect[0].x << "," << srcRect[0].y << "," << srcRect[0].z << ")"
<< "->(" << srcRect[1].x << "," << srcRect[1].y << "," << srcRect[1].z << ")"
<< " to=" << dst.texture->getVkImage() << ", level=" << (int) dst.level
<< ", layer=" << (int) dst.layer
<< ", layout=" << dst.getLayout()
<< ", dst-rect=(" << dstRect[0].x << "," << dstRect[0].y << "," << dstRect[0].z << ")"
<< "->(" << dstRect[1].x << "," << dstRect[1].y << "," << dstRect[1].z << ")";
}
VkImageSubresourceRange const srcRange = src.getSubresourceRange();
@@ -69,6 +75,7 @@ inline void blitFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect, V
if (oldDstLayout == VulkanLayout::UNDEFINED) {
oldDstLayout = dst.texture->getDefaultLayout();
}
src.texture->transitionLayout(commands, srcRange, oldSrcLayout);
dst.texture->transitionLayout(commands, dstRange, oldDstLayout);
}
+15 -2
View File
@@ -206,6 +206,11 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context,
: mPlatform(platform),
mResourceManager(driverConfig.handleArenaSize, driverConfig.disableHandleUseAfterFreeCheck,
driverConfig.disableHeapHandleTags),
// Note that we always create the default rendertarget before createDefaultRenderTarget(). We
// swap the content later when createDefaultRenderTarget() is called. This frees
// createDefaultRenderTarget() from being ordered with makeCurrent().
mDefaultRenderTarget(
fvkmemory::resource_ptr<VulkanRenderTarget>::construct(&mResourceManager)),
mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(),
mPlatform->getDevice())),
mContext(context),
@@ -698,8 +703,11 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
}
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
assert_invariant(!mDefaultRenderTarget);
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth);
assert_invariant(mDefaultRenderTarget); // Default render target should already exist.
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth,
std::move(std::move(*mDefaultRenderTarget.get())));
mDefaultRenderTarget = renderTarget;
}
@@ -775,6 +783,7 @@ void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
auto rt = resource_ptr<VulkanRenderTarget>::cast(&mResourceManager, rth);
if (UTILS_UNLIKELY(rt == mDefaultRenderTarget)) {
// Note that this should only happen on driver shutdown.
mDefaultRenderTarget = {};
} else {
rt.dec();
@@ -1366,6 +1375,10 @@ void VulkanDriver::generateMipmaps(Handle<HwTexture> th) {
srcw = dstw;
srch = dsth;
} while ((srcw > 1 || srch > 1) && ++level < t->levels - 1);
VulkanCommandBuffer* commandBuffer = &mCommands.get();
// Here we transition to the whole image to the most likely next layout.
t->transitionLayout(commandBuffer, t->getPrimaryViewRange(), t->getDefaultLayout());
}
void VulkanDriver::compilePrograms(CompilerPriorityQueue priority,
+16 -1
View File
@@ -308,6 +308,15 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
// Creates a special "default" render target (i.e. associated with the swap chain)
explicit VulkanRenderTarget();
VulkanRenderTarget(VulkanRenderTarget&& target) {
swap(std::move(target));
}
VulkanRenderTarget& operator=(VulkanRenderTarget&& target) {
swap(std::move(target));
return *this;
}
void transformClientRectToPlatform(VkRect2D* bounds) const;
void transformViewportToPlatform(VkViewport* bounds) const;
@@ -355,6 +364,12 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
void emitBarriersEndRenderPass(VulkanCommandBuffer& commands);
private:
void swap(VulkanRenderTarget&& target) {
std::swap(mOffscreen, target.mOffscreen);
std::swap(mProtected, target.mProtected);
std::swap(mInfo, target.mInfo);
}
struct Auxiliary {
static constexpr int8_t UNDEFINED_INDEX = -1;
@@ -368,7 +383,7 @@ private:
int8_t msaaDepthIndex = UNDEFINED_INDEX;
int8_t msaaIndex = UNDEFINED_INDEX;
};
bool const mOffscreen;
bool mOffscreen;
bool mProtected;
std::unique_ptr<Auxiliary> mInfo;
@@ -207,16 +207,11 @@ fvkmemory::resource_ptr<VulkanStageImage::Resource> VulkanStagePool::acquireImag
VulkanStageImage* stageImage = new VulkanStageImage(
vkformat, width, height, memory, image, mCurrentFrame);
// We use VK_IMAGE_LAYOUT_GENERAL here because the spec says:
// "Host access to image memory is only well-defined for linear images and for image
// subresources of those images which are currently in either the
// VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL layout. Calling
// vkGetImageSubresourceLayout for a linear image returns a subresource layout mapping that is
// valid for either of those image layouts."
fvkutils::transitionLayout(cmdbuffer, {
.image = stageImage->image(),
.oldLayout = VulkanLayout::UNDEFINED,
.newLayout = VulkanLayout::STAGING, // (= VK_IMAGE_LAYOUT_GENERAL)
// TRANSFER_SRC because we're about to blit this to the actual texture.
.newLayout = VulkanLayout::TRANSFER_SRC,
.subresources = { aspectFlags, 0, 1, 0, 1 },
});
@@ -117,12 +117,14 @@ inline VulkanLayout getDefaultLayoutImpl(TextureUsage usage) {
if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) {
if (any(usage & TextureUsage::SAMPLEABLE)) {
return VulkanLayout::DEPTH_SAMPLER;
} else {
return VulkanLayout::DEPTH_ATTACHMENT;
}
return VulkanLayout::DEPTH_ATTACHMENT;
}
if (any(usage & TextureUsage::COLOR_ATTACHMENT)) {
if (any(usage & TextureUsage::SAMPLEABLE)) {
return VulkanLayout::FRAG_READ;
}
return VulkanLayout::COLOR_ATTACHMENT;
}
// Finally, the layout for an immutable texture is optimal read-only.
@@ -162,6 +164,10 @@ VkImageUsageFlags getUsage(VulkanContext const& context, uint8_t samples,
usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
if (any(tusage & TextureUsage::GEN_MIPMAPPABLE)) {
usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
// Determine if we can use the transient usage flag combined with lazily allocated memory.
const bool useTransientAttachment =
// Lazily allocated memory is available.
@@ -64,7 +64,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
std::string baseLabel;
if (std::holds_alternative<utils::StaticString>(layout.label)) {
const auto& temp = std::get_if<utils::StaticString>(&layout.label);
baseLabel = temp->c_str();
baseLabel = temp->c_str() == nullptr ? "" : temp->c_str();
} else if (std::holds_alternative<utils::CString>(layout.label)) {
const auto& temp = std::get_if<utils::CString>(&layout.label);
baseLabel = temp->c_str();
+31 -17
View File
@@ -64,6 +64,28 @@ using namespace std::chrono_literals;
namespace filament::backend {
namespace {
void setDefaultTargetFlags(WebGPURenderTarget& defaultRenderTarget,
WebGPUSwapChain const& swapChain) {
const wgpu::TextureFormat depthFormat{ swapChain.getDepthFormat() };
TargetBufferFlags newTargetFlags{ filament::backend::TargetBufferFlags::NONE };
// Assuming Color always present in default render target.
newTargetFlags |= filament::backend::TargetBufferFlags::COLOR;
if (depthFormat != wgpu::TextureFormat::Undefined) {
if (hasDepth(depthFormat)) {
newTargetFlags |= filament::backend::TargetBufferFlags::DEPTH;
}
if (hasStencil(depthFormat)) {
newTargetFlags |= filament::backend::TargetBufferFlags::STENCIL;
}
}
defaultRenderTarget.setTargetFlags(newTargetFlags);
}
} // namespace
Driver* WebGPUDriver::create(WebGPUPlatform& platform, const Platform::DriverConfig& driverConfig) noexcept {
constexpr size_t defaultSize = FILAMENT_WEBGPU_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
Platform::DriverConfig validConfig {driverConfig};
@@ -384,6 +406,9 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
"rebuilding Filament with that flag, e.g. ./build.sh -x "
<< FWGPU_PRINT_SYSTEM << " ...";
#endif
if (mDefaultRenderTarget) {
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
}
}
void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
@@ -392,6 +417,9 @@ void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
mSwapChain = constructHandle<WebGPUSwapChain>(sch, extent, mAdapter,
mDevice, flags);
assert_invariant(mSwapChain);
if (mDefaultRenderTarget) {
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
}
}
void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vertexBufferInfoHandle,
@@ -488,6 +516,9 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> renderTarge
assert_invariant(!mDefaultRenderTarget);
mDefaultRenderTarget = constructHandle<WebGPURenderTarget>(renderTargetHandle);
assert_invariant(mDefaultRenderTarget);
if (mSwapChain) {
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
}
}
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
@@ -1187,23 +1218,6 @@ void WebGPUDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
assert_invariant(mTextureView);
assert_invariant(mDefaultRenderTarget);
wgpu::TextureFormat depthFormat = mSwapChain->getDepthFormat();
TargetBufferFlags newTargetFlags = filament::backend::TargetBufferFlags::NONE;
//Assuming Color always present in default render target.
newTargetFlags |= filament::backend::TargetBufferFlags::COLOR;
if (depthFormat != wgpu::TextureFormat::Undefined) {
if (hasDepth(depthFormat)) {
newTargetFlags |= filament::backend::TargetBufferFlags::DEPTH;
}
if (hasStencil(depthFormat)) {
newTargetFlags |= filament::backend::TargetBufferFlags::STENCIL;
}
}
mDefaultRenderTarget->setTargetFlags(newTargetFlags);
if (!mCommandEncoder) {
wgpu::CommandEncoderDescriptor commandEncoderDescriptor = { .label = "frame_command_encoder" };
mCommandEncoder = mDevice.CreateCommandEncoder(&commandEncoderDescriptor);
@@ -125,7 +125,7 @@ WebGPURenderTarget::WebGPURenderTarget(const uint32_t width, const uint32_t heig
mDefaultRenderTarget{ false },
mTargetFlags{ targetFlags },
mSamples{ samples },
mLayerCount{ layerCount },
mLayerCount{ layerCount <= 0 ? static_cast<uint8_t>(1) : layerCount },
mColorAttachments{ colorAttachmentsMRT },
mDepthAttachment{ depthAttachmentInfo },
mStencilAttachment{ stencilAttachmentInfo },
@@ -140,7 +140,9 @@ WebGPURenderTarget::WebGPURenderTarget(const uint32_t width, const uint32_t heig
WebGPURenderTarget::WebGPURenderTarget()
: HwRenderTarget{ 0, 0 },
mDefaultRenderTarget{ true },
mTargetFlags{ TargetBufferFlags::NONE },
// starting with the initial assumption that the default render target has a single color
// attachment and a depth attachment, not necessarily a depth attachment
mTargetFlags{ TargetBufferFlags::COLOR0 | TargetBufferFlags::DEPTH },
mSamples{ 1 },
mLayerCount{ 1 },
mSampleCountPerAttachment{ 1 } {}
+2 -2
View File
@@ -256,7 +256,7 @@ template<typename WebGPUPrintable>
|| FWGPU_ENABLED(FWGPU_DEBUG_UPDATE_IMAGE) \
|| FWGPU_ENABLED(FWGPU_DEBUG_BLIT) \
|| FWGPU_ENABLED(FWGPU_DEBUG_BIND_GROUPS)
[[nodiscard]] std::string webGPUTextureToString(wgpu::Texture const& texture) {
[[nodiscard]] inline std::string webGPUTextureToString(wgpu::Texture const& texture) {
if (texture == nullptr) {
return "nullptr (no wgpu::Texture)";
}
@@ -411,7 +411,7 @@ template<typename WebGPUPrintable>
}
}
[[nodiscard]] std::string filamentTextureUsageFlagsToString(const TextureUsage flags) {
[[nodiscard]] inline std::string filamentTextureUsageFlagsToString(const TextureUsage flags) {
if (flags == TextureUsage::NONE) {
return "NONE";
}
@@ -143,11 +143,13 @@ namespace {
retUsage |= wgpu::TextureUsage::RenderAttachment;
}
if (any(TextureUsage::BLIT_SRC & fUsage)) {
retUsage |= wgpu::TextureUsage::RenderAttachment;
retUsage |= wgpu::TextureUsage::TextureBinding;
}
if (any(TextureUsage::BLIT_DST & fUsage)) {
retUsage |= wgpu::TextureUsage::RenderAttachment;
retUsage |= wgpu::TextureUsage::TextureBinding;
}
if (any(TextureUsage::GEN_MIPMAPPABLE & fUsage)) {
retUsage |= (wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding);
}
// WGPU Render attachment covers either color or stencil situation dependant
// NOTE: Depth attachment isn't used this way in Vulkan but logically maps to WGPU docs. If
+30 -5
View File
@@ -36,14 +36,16 @@
namespace test {
ScreenshotParams::ScreenshotParams(int width, int height, std::string fileName,
uint32_t expectedHash, bool isSrgb, int numAllowedDeviations, int pixelMatchThreshold)
uint32_t expectedHash, bool isSrgb, int numAllowedDeviations, int pixelMatchThreshold,
std::optional<float> forceAlphaValue)
: mWidth(width),
mHeight(height),
mIsSrgb(isSrgb),
mExpectedPixelHash(expectedHash),
mFileName(std::move(fileName)),
mAllowedPixelDeviations(numAllowedDeviations),
mPixelMatchThreshold(pixelMatchThreshold) {}
mPixelMatchThreshold(pixelMatchThreshold),
mForceAlphaValue(forceAlphaValue) {}
int ScreenshotParams::width() const {
return mWidth;
@@ -61,6 +63,10 @@ uint32_t ScreenshotParams::expectedHash() const {
return mExpectedPixelHash;
}
std::optional<float> ScreenshotParams::forceAlphaValue() const {
return mForceAlphaValue;
}
std::filesystem::path ScreenshotParams::actualDirectoryPath() {
return BackendTest::binaryDirectory().append("images/actual_images");
}
@@ -177,9 +183,29 @@ RenderTargetDump::RenderTargetDump(filament::backend::DriverApi& api,
const size_t size = mInternal->params.width() * mInternal->params.height() * 4;
mInternal->bytes.resize(size);
using filament::backend::PixelDataFormat;
using filament::backend::PixelDataType;
constexpr PixelDataFormat readPixelFormat = PixelDataFormat::RGBA;
constexpr PixelDataType readPixelType = PixelDataType::UBYTE;
auto cb = [](void* buffer, size_t size, void* user) {
auto* internal = static_cast<RenderTargetDump::Internal*>(user);
internal->bytesFilled = true;
// If requested, we overwrite the alpha value.
// If the read pixel format or type changes, this logic must be updated.
static_assert(readPixelFormat == PixelDataFormat::RGBA);
static_assert(readPixelType == PixelDataType::UBYTE);
if (auto alphaValue = internal->params.forceAlphaValue(); alphaValue) {
const int pixelCount = internal->params.width() * internal->params.height();
const int channels = 4;
constexpr int kAlphaChannel = 3;
uint8_t* pixelBuffer = static_cast<uint8_t*>(buffer);
for (int p = 0; p < pixelCount; p++) {
pixelBuffer[p * channels + kAlphaChannel] = *alphaValue * 255.0f;
}
}
#ifndef FILAMENT_IOS
image::LinearImage image;
if (internal->params.isSrgb()) {
@@ -203,9 +229,8 @@ RenderTargetDump::RenderTargetDump(filament::backend::DriverApi& api,
filePath);
#endif
};
filament::backend::PixelBufferDescriptor pb(mInternal->bytes.data(), size,
filament::backend::PixelDataFormat::RGBA, filament::backend::PixelDataType::UBYTE, cb,
(void*)mInternal.get());
filament::backend::PixelBufferDescriptor pb(mInternal->bytes.data(), size, readPixelFormat,
readPixelType, cb, (void*) mInternal.get());
api.readPixels(renderTarget, 0, 0, mInternal->params.width(), mInternal->params.height(),
std::move(pb));
}
+65 -3
View File
@@ -19,6 +19,7 @@
#include <filesystem>
#include <vector>
#include <optional>
#include "gtest/gtest.h"
@@ -27,9 +28,9 @@
// Arguments are (RenderTargetHandle renderTarget, ImageExpectations& expectations,
// ScreenshotParams screenshotParams)
#define EXPECT_IMAGE(renderTarget, expectations, screenshotParams) \
#define EXPECT_IMAGE(renderTarget, screenshotParams) \
do { \
expectations.addExpectation( \
getExpectations().addExpectation( \
__FILE__, \
__LINE__, \
renderTarget, \
@@ -45,12 +46,72 @@ class ScreenshotParams {
public:
// TODO(b/422804941): Add a set of environments where this test should use a different golden.
ScreenshotParams(int width, int height, std::string fileName, uint32_t expectedPixelHash,
bool isSrgb = false, int numAllowedDeviations = 0, int pixelMatchThreshold = 0);
bool isSrgb = false, int numAllowedDeviations = 0, int pixelMatchThreshold = 0,
std::optional<float> forceAlphaValue = std::nullopt);
class Builder {
public:
Builder& width(int width) {
mWidth = width;
return *this;
}
Builder& height(int height) {
mHeight = height;
return *this;
}
Builder& fileName(std::string fileName) {
mFileName = fileName;
return *this;
}
Builder& expectedPixelHash(uint32_t pixelHash) {
mExpectedPixelHash = pixelHash;
return *this;
}
Builder& isSrgb(bool isSrgb) {
mIsSrgb = isSrgb;
return *this;
}
Builder& numAllowedDeviations(int numAllowedDeviations) {
mNumAllowedDeviations = numAllowedDeviations;
return *this;
}
Builder& pixelMatchTheshold(int pixelMatchTheshold) {
mPixelMatchThreshold = pixelMatchTheshold;
return *this;
}
Builder& forceAlphaValue(float alphaValue) {
mForceAlphaValue = alphaValue;
return *this;
}
ScreenshotParams build() {
return ScreenshotParams(mWidth, mHeight, mFileName, mExpectedPixelHash, mIsSrgb,
mNumAllowedDeviations, mPixelMatchThreshold, mForceAlphaValue);
}
private:
int mWidth;
int mHeight;
std::string mFileName;
uint32_t mExpectedPixelHash;
bool mIsSrgb;
int mNumAllowedDeviations;
int mPixelMatchThreshold;
std::optional<float> mForceAlphaValue;
};
int width() const;
int height() const;
bool isSrgb() const;
uint32_t expectedHash() const;
std::optional<float> forceAlphaValue() const;
static std::filesystem::path actualDirectoryPath();
std::string actualFileName() const;
@@ -70,6 +131,7 @@ private:
std::string mFileName;
int mAllowedPixelDeviations;
int mPixelMatchThreshold;
std::optional<float> mForceAlphaValue;
};
/**
@@ -173,6 +173,7 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader(ShaderStage stage, std::s
return { (uint8_t*)spirv.data(), (uint8_t*)(spirv.data() + spirv.size()) };
} else if (backend == Backend::WEBGPU){
filamat::GLSLPostProcessor::spirvToWgsl(&spirv, &result);
return { result.c_str(), result.c_str() + result.length() + 1 };
}
return {};
+32 -6
View File
@@ -47,7 +47,7 @@ layout(location = 0) in vec4 mesh_position;
void main() {
gl_Position = vec4(mesh_position.xy, 0.0, 1.0);
#if defined(TARGET_VULKAN_ENVIRONMENT)
// In Vulkan, clip space is Y-down. In OpenGL and Metal, clip space is Y-up.
// In Vulkan, clip space is Y-down. In OpenGL, Metal and WebGPU, clip space is Y-up.
gl_Position.y = -gl_Position.y;
#endif
})" };
@@ -64,7 +64,7 @@ void main() {
params.scaleMinusOne.z + 1.0,
1.0);
#if defined(TARGET_VULKAN_ENVIRONMENT)
// In Vulkan, clip space is Y-down. In OpenGL and Metal, clip space is Y-up.
// In Vulkan, clip space is Y-down. In OpenGL, Metal and WebGPU, clip space is Y-up.
gl_Position.y = -gl_Position.y;
#endif
})" };
@@ -80,7 +80,7 @@ void main() {
gl_Position = vec4(mesh_position.xy, 0.0, 1.0);
uv = (mesh_position.xy * 0.5 + 0.5);
#if defined(TARGET_VULKAN_ENVIRONMENT)
// In Vulkan, clip space is Y-down. In OpenGL and Metal, clip space is Y-up.
// In Vulkan, clip space is Y-down. In OpenGL, Metal and WebGPU, clip space is Y-up.
gl_Position.y = -gl_Position.y;
#endif
})" };
@@ -158,9 +158,19 @@ layout(binding = 0, set = 0) uniform Params {
} params;
)";
}
case ShaderUniformType::Sampler: {
case ShaderUniformType::Sampler2D: {
return R"(
layout(location = 0, set = 0) uniform sampler2D test_tex;
)";
}
case ShaderUniformType::ISampler2D: {
return R"(
layout(location = 0, set = 0) uniform isampler2D test_tex;
)";
}
case ShaderUniformType::USampler2D: {
return R"(
layout(location = 0, set = 0) uniform usampler2D test_tex;
)";
}
default:
@@ -179,7 +189,7 @@ std::vector<UniformConfig> GetUniformConfig(ShaderUniformType type) {
case ShaderUniformType::SimpleWithPadding: {
return {{ "Params" }};
}
case ShaderUniformType::Sampler: {
case ShaderUniformType::Sampler2D: {
filament::SamplerInterfaceBlock::SamplerInfo samplerInfo{
"backend_test", "test_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::FLOAT, Precision::HIGH, false };
@@ -187,6 +197,22 @@ std::vector<UniformConfig> GetUniformConfig(ShaderUniformType type) {
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
}};
}
case ShaderUniformType::ISampler2D: {
filament::SamplerInterfaceBlock::SamplerInfo samplerInfo{
"backend_test", "test_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::INT, Precision::HIGH, false };
return {{
"test_tex", DescriptorType::SAMPLER_2D_INT, samplerInfo
}};
}
case ShaderUniformType::USampler2D: {
filament::SamplerInterfaceBlock::SamplerInfo samplerInfo{
"backend_test", "test_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::UINT, Precision::HIGH, false };
return {{
"test_tex", DescriptorType::SAMPLER_2D_INT, samplerInfo
}};
}
default:
abort();
}
@@ -252,4 +278,4 @@ std::string SharedShaders::getFragmentShaderText(FragmentShaderType fragment,
return fragmentText->withUniform(*uniformText);
}
} // namespace test
} // namespace test
@@ -23,7 +23,9 @@ enum class ShaderUniformType : uint8_t {
None,
Simple,
SimpleWithPadding,
Sampler,
Sampler2D,
ISampler2D,
USampler2D,
};
struct SimpleMaterialParams {
+6 -6
View File
@@ -199,7 +199,7 @@ TEST_F(BlitTest, ColorMagnify) {
{
RenderFrame frame(api);
EXPECT_IMAGE(dstRenderTargets[0], getExpectations(),
EXPECT_IMAGE(dstRenderTargets[0],
ScreenshotParams(kDstTexWidth, kDstTexHeight, "ColorMagnify", 0x410bdd31));
api.commit(swapChain);
}
@@ -255,7 +255,7 @@ TEST_F(BlitTest, ColorMinify) {
{ 0, 0, kSrcTexWidth >> srcLevel, kSrcTexHeight >> srcLevel },
SamplerMagFilter::LINEAR);
EXPECT_IMAGE(dstRenderTargets[0], getExpectations(),
EXPECT_IMAGE(dstRenderTargets[0],
ScreenshotParams(kDstTexWidth, kDstTexHeight, "ColorMinify", 0xf3d9c53f));
}
@@ -336,7 +336,7 @@ TEST_F(BlitTest, ColorResolve) {
srcRenderTarget, { 0, 0, kSrcTexWidth, kSrcTexHeight },
SamplerMagFilter::NEAREST);
EXPECT_IMAGE(dstRenderTarget, getExpectations(),
EXPECT_IMAGE(dstRenderTarget,
ScreenshotParams(kDstTexWidth, kDstTexHeight, "ColorResolve", 531759687));
}
@@ -403,7 +403,7 @@ TEST_F(BlitTest, Blit2DTextureArray) {
{
RenderFrame frame(api);
EXPECT_IMAGE(dstRenderTarget, getExpectations(),
EXPECT_IMAGE(dstRenderTarget,
ScreenshotParams(kDstTexWidth, kDstTexHeight, "Blit2DTextureArray",
0x8de7d55b));
api.commit(swapChain);
@@ -479,7 +479,7 @@ TEST_F(BlitTest, BlitRegion) {
RenderFrame frame(api);
// TODO: for some reason, this test has very, very slight (as in one pixel) differences
// between OpenGL and Metal. So disable golden checking for now.
// EXPECT_IMAGE(dstRenderTarget, expectations, ScreenshotParams(kDstTexWidth,
// EXPECT_IMAGE(dstRenderTarget, ScreenshotParams(kDstTexWidth,
// kDstTexHeight, "BlitRegion", 0x74fa34ed));
api.commit(swapChain);
}
@@ -546,7 +546,7 @@ TEST_F(BlitTest, BlitRegionToSwapChain) {
// TODO: for some reason, this test has been disabled. It needs to be tested on all
// machines.
// EXPECT_IMAGE(dstRenderTarget, expectations,
// EXPECT_IMAGE(dstRenderTarget,
// ScreenshotParams(kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain", 0x0));
}
+2 -3
View File
@@ -237,9 +237,8 @@ TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
}
EXPECT_IMAGE(renderTarget, getExpectations(),
ScreenshotParams(screenWidth(), screenHeight(), "BufferObjectUpdateWithOffset",
2320747245));
EXPECT_IMAGE(renderTarget, ScreenshotParams(screenWidth(), screenHeight(),
"BufferObjectUpdateWithOffset", 2320747245));
api.flush();
api.commit(swapChain);
+1 -1
View File
@@ -247,7 +247,7 @@ TEST_F(BackendTest, FeedbackLoops) {
// NOTE: Calling glReadPixels on any miplevel other than the base level
// seems to be un-reliable on some GPU's.
if (frame == kNumFrames - 1) {
EXPECT_IMAGE(renderTargets[0], getExpectations(),
EXPECT_IMAGE(renderTargets[0],
ScreenshotParams(kTexWidth, kTexHeight, "FeedbackLoops", 4192780705));
}
+30 -16
View File
@@ -287,9 +287,9 @@ TEST_F(LoadImageTest, UpdateImage2D) {
// Test integer format uploads.
// TODO: These cases fail on OpenGL and Vulkan.
// TODO: These cases now also fail on Metal, but at some point previously worked.
testCases.emplace_back("RGB_INTEGER UBYTE to RGB8UI", PixelDataFormat::RGB_INTEGER, PixelDataType::UBYTE, TextureFormat::RGB8UI);
testCases.emplace_back("RGB_INTEGER USHORT to RGB16UI", PixelDataFormat::RGB_INTEGER, PixelDataType::USHORT, TextureFormat::RGB16UI);
testCases.emplace_back("RGB_INTEGER INT to RGB32I", PixelDataFormat::RGB_INTEGER, PixelDataType::INT, TextureFormat::RGB32I);
testCases.emplace_back("RGB_INTEGER UBYTE to RGB8UI", PixelDataFormat::RGB_INTEGER, PixelDataType::UBYTE, TextureFormat::RGB8UI);
testCases.emplace_back("RGB_INTEGER USHORT to RGB16UI", PixelDataFormat::RGB_INTEGER, PixelDataType::USHORT, TextureFormat::RGB16UI);
testCases.emplace_back("RGB_INTEGER INT to RGB32I", PixelDataFormat::RGB_INTEGER, PixelDataType::INT, TextureFormat::RGB32I);
// Test uploads with buffer padding.
// TODO: Vulkan crashes with "Assertion failed: (offset + size <= allocationSize)"
@@ -319,14 +319,23 @@ TEST_F(LoadImageTest, UpdateImage2D) {
auto defaultRenderTarget = cleanup.add(api.createDefaultRenderTarget(0));
// Create a program.
filament::SamplerInterfaceBlock::SamplerInfo samplerInfo { "test", "tex", 0,
SamplerType::SAMPLER_2D, getSamplerFormat(t.textureFormat), Precision::HIGH, false };
std::string const fragment = getFormattedFragment(fragmentTemplate, t.textureFormat);
Shader shader(api, cleanup, ShaderConfig{
.vertexShader = mVertexShader,
.fragmentShader= fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
ShaderUniformType uniformType;
switch (getSamplerFormat(t.textureFormat)) {
case SamplerFormat::FLOAT:
case SamplerFormat::SHADOW: // not used for tests, but must cover all cases
uniformType = ShaderUniformType::Sampler2D;
break;
case SamplerFormat::INT:
uniformType = ShaderUniformType::ISampler2D;
break;
case SamplerFormat::UINT:
uniformType = ShaderUniformType::USampler2D;
break;
}
Shader shader = SharedShaders::makeShader(api, cleanup, {
.mVertexType = VertexShaderType::Textured,
.mFragmentType = FragmentShaderType::Textured,
.mUniformType = uniformType,
});
// Create a Texture.
@@ -374,8 +383,13 @@ TEST_F(LoadImageTest, UpdateImage2D) {
api.draw2(0, 3, 1);
api.endRenderPass();
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
ScreenshotParams(kTexSize, kTexSize, t.name, expectedHash));
EXPECT_IMAGE(defaultRenderTarget, ScreenshotParams::Builder()
.width(kTexSize)
.height(kTexSize)
.fileName(t.name)
.expectedPixelHash(expectedHash)
.forceAlphaValue(1.0f)
.build());
api.commit(swapChain);
api.endFrame(0);
@@ -463,7 +477,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
api.draw2(0, 3, 1);
api.endRenderPass();
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
EXPECT_IMAGE(defaultRenderTarget,
ScreenshotParams(kTexSize, kTexSize, "UpdateImageSRGB", 3300305265));
api.commit(swapChain);
@@ -539,7 +553,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
api.endRenderPass();
}
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
EXPECT_IMAGE(defaultRenderTarget,
ScreenshotParams(kTexSize, kTexSize, "UpdateImageMipLevel", 1875922935));
api.commit(swapChain);
@@ -625,7 +639,7 @@ TEST_F(LoadImageTest, UpdateImage3D) {
api.draw2(0, 3, 1);
api.endRenderPass();
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
EXPECT_IMAGE(defaultRenderTarget,
ScreenshotParams(kTexSize, kTexSize, "UpdateImage3D", 1875922935));
}
+3 -3
View File
@@ -40,7 +40,7 @@ std::string fragmentTexturedLod (R"(#version 450 core
layout(location = 0) out vec4 fragColor;
layout(location = 0) in vec2 uv;
layout(location = 0, set = 0) uniform sampler2D backend_test_sib_tex;
layout(binding = 0, set = 0) uniform sampler2D backend_test_sib_tex;
void main() {
fragColor = textureLod(backend_test_sib_tex, uv, 1);
@@ -69,12 +69,12 @@ TEST_F(BackendTest, TextureViewLod) {
Shader whiteShader = SharedShaders::makeShader(api, cleanup, ShaderRequest {
.mVertexType = VertexShaderType::Textured,
.mFragmentType = FragmentShaderType::White,
.mUniformType = ShaderUniformType::Sampler
.mUniformType = ShaderUniformType::Sampler2D
});
// Create a program that samples a texture.
std::string vertexShader = SharedShaders::getVertexShaderText(
VertexShaderType::Textured, ShaderUniformType::Sampler);
VertexShaderType::Textured, ShaderUniformType::Sampler2D);
filament::SamplerInterfaceBlock::SamplerInfo samplerInfo {
"backend_test", "sib_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::FLOAT, Precision::HIGH, false };
+3 -3
View File
@@ -105,6 +105,7 @@ void initPushConstants() {
TEST_F(BackendTest, PushConstants) {
SKIP_IF(Backend::OPENGL, "Push constants not supported on OpenGL");
SKIP_IF(Backend::WEBGPU, "Push constants not supported on WebGPU");
initPushConstants();
@@ -178,9 +179,8 @@ TEST_F(BackendTest, PushConstants) {
api.endRenderPass();
EXPECT_IMAGE(renderTarget, getExpectations(),
ScreenshotParams(params.viewport.width, params.viewport.height, "pushConstants",
3575588741));
EXPECT_IMAGE(renderTarget, ScreenshotParams(params.viewport.width, params.viewport.height,
"pushConstants", 3575588741));
api.commit(swapChain);
api.endFrame(0);
@@ -40,7 +40,7 @@ Shader createShader(DriverApi& api, Cleanup& cleanup, Backend backend) {
return SharedShaders::makeShader(api, cleanup, ShaderRequest{
.mVertexType = VertexShaderType::Textured,
.mFragmentType = FragmentShaderType::Textured,
.mUniformType = ShaderUniformType::Sampler
.mUniformType = ShaderUniformType::Sampler2D
});
}
@@ -199,7 +199,7 @@ TEST_F(BackendTest, RenderExternalImage) {
api.flush();
api.commit(swapChain);
api.endFrame(0);
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
EXPECT_IMAGE(defaultRenderTarget,
ScreenshotParams(screenWidth(), screenHeight(), "RenderExternalImage", 1206264951));
api.stopCapture(0);
+2 -2
View File
@@ -132,7 +132,7 @@ TEST_F(BackendTest, ScissorViewportRegion) {
api.draw2(0, 3, 1);
api.endRenderPass();
EXPECT_IMAGE(fullRenderTarget, getExpectations(),
EXPECT_IMAGE(fullRenderTarget,
ScreenshotParams(kSrcTexWidth >> 1, kSrcTexHeight >> 1, "scissor", 15842520));
api.commit(swapChain);
@@ -224,7 +224,7 @@ TEST_F(BackendTest, ScissorViewportEdgeCases) {
api.draw2(0, 3, 1);
api.endRenderPass();
EXPECT_IMAGE(renderTarget, getExpectations(),
EXPECT_IMAGE(renderTarget,
ScreenshotParams(512, 512, "ScissorViewportEdgeCases", 2199186852));
api.commit(swapChain);
+4 -5
View File
@@ -144,7 +144,7 @@ TEST_F(BasicStencilBufferTest, StencilBuffer) {
RunTest(renderTarget);
EXPECT_IMAGE(renderTarget, getExpectations(),
EXPECT_IMAGE(renderTarget,
ScreenshotParams(screenWidth(), screenHeight(), "StencilBuffer", 0x3B1AEF0F));
flushAndWait();
@@ -170,7 +170,7 @@ TEST_F(BasicStencilBufferTest, DepthAndStencilBuffer) {
RunTest(renderTarget);
EXPECT_IMAGE(renderTarget, getExpectations(),
EXPECT_IMAGE(renderTarget,
ScreenshotParams(screenWidth(), screenHeight(), "DepthAndStencilBuffer", 0x3B1AEF0F));
flushAndWait();
@@ -266,9 +266,8 @@ TEST_F(BasicStencilBufferTest, StencilBufferMSAA) {
api.stopCapture(0);
api.endFrame(0);
EXPECT_IMAGE(renderTarget1, getExpectations(),
ScreenshotParams(screenWidth(), screenHeight(), "StencilBufferAutoResolve",
3353562179));
EXPECT_IMAGE(renderTarget1, ScreenshotParams(screenWidth(), screenHeight(),
"StencilBufferAutoResolve", 3353562179));
flushAndWait();
getDriver().purge();
+18 -5
View File
@@ -164,7 +164,9 @@ struct BloomOptions {
};
/**
* Options to control large-scale fog in the scene
* Options to control large-scale fog in the scene. Materials can enable the `linearFog` property,
* which uses a simplified, linear equation for fog calculation; in this mode, the heightFalloff
* is ignored as well as the mipmap selection in IBL or skyColor mode.
*/
struct FogOptions {
/**
@@ -183,7 +185,7 @@ struct FogOptions {
float cutOffDistance = INFINITY;
/**
* fog's maximum opacity between 0 and 1
* fog's maximum opacity between 0 and 1. Ignored in `linearFog` mode.
*/
float maximumOpacity = 1.0f;
@@ -193,12 +195,15 @@ struct FogOptions {
float height = 0.0f;
/**
* How fast the fog dissipates with altitude. heightFalloff has a unit of [1/m].
* How fast the fog dissipates with the altitude. heightFalloff has a unit of [1/m].
* It can be expressed as 1/H, where H is the altitude change in world units [m] that causes a
* factor 2.78 (e) change in fog density.
*
* A falloff of 0 means the fog density is constant everywhere and may result is slightly
* faster computations.
*
* In `linearFog` mode, only use to compute the slope of the linear equation. Completely
* ignored if set to 0.
*/
float heightFalloff = 1.0f;
@@ -220,7 +225,7 @@ struct FogOptions {
LinearColor color = { 1.0f, 1.0f, 1.0f };
/**
* Extinction factor in [1/m] at altitude 'height'. The extinction factor controls how much
* Extinction factor in [1/m] at an altitude 'height'. The extinction factor controls how much
* light is absorbed and out-scattered per unit of distance. Each unit of extinction reduces
* the incoming light to 37% of its original value.
*
@@ -229,11 +234,16 @@ struct FogOptions {
* the composition of the fog/atmosphere.
*
* For historical reason this parameter is called `density`.
*
* In `linearFog` mode this is the slope of the linear equation if heightFalloff is set to 0.
* Otherwise, heightFalloff affects the slope calculation such that it matches the slope of
* the standard equation at the camera height.
*/
float density = 0.1f;
/**
* Distance in world units [m] from the camera where the Sun in-scattering starts.
* Ignored in `linearFog` mode.
*/
float inScatteringStart = 0.0f;
@@ -242,6 +252,7 @@ struct FogOptions {
* is scattered (by the fog) towards the camera.
* Size of the Sun in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
* Smaller values result is a larger scattering size.
* Ignored in `linearFog` mode.
*/
float inScatteringSize = -1.0f;
@@ -269,6 +280,8 @@ struct FogOptions {
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* In `linearFog` mode mipmap level 0 is always used.
*
* @see Texture
* @see fogColorFromIbl
*/
@@ -283,7 +296,7 @@ struct FogOptions {
/**
* Options to control Depth of Field (DoF) effect in the scene.
*
* cocScale can be used to set the depth of field blur independently from the camera
* cocScale can be used to set the depth of field blur independently of the camera
* aperture, e.g. for artistic reasons. This can be achieved by setting:
* cocScale = cameraAperture / desiredDoFAperture
*
+47 -13
View File
@@ -16,32 +16,66 @@
#include "DFG.h"
#include "ZstdHelper.h"
#include "details/Engine.h"
#include "details/Texture.h"
#include <filament/Texture.h>
#include <backend/DriverEnums.h>
#include <utils/debug.h>
#include <utils/compiler.h>
#include <utils/Panic.h>
#include <cstdlib>
#include <cstdint>
#include <cstddef>
#include <utility>
#include "generated/resources/dfg.h"
namespace filament {
const uint16_t DFG::DFG_LUT[] = {
#include "generated/data/dfg.inc"
};
void DFG::init(FEngine& engine) noexcept {
void DFG::init(FEngine& engine) {
constexpr size_t fp16Count = DFG_LUT_SIZE * DFG_LUT_SIZE * 3;
constexpr size_t byteCount = fp16Count * sizeof(uint16_t);
static_assert(sizeof(DFG_LUT) == byteCount, "DFG_LUT_SIZE doesn't match size of the DFG LUT");
Texture* lut = Texture::Builder()
Texture::Builder builder = Texture::Builder()
.width(DFG_LUT_SIZE)
.height(DFG_LUT_SIZE)
.format(backend::TextureFormat::RGB16F)
.build(engine);
.format(backend::TextureFormat::RGB16F);
Texture::PixelBufferDescriptor buffer(DFG_LUT, byteCount,
Texture::Format::RGB, Texture::Type::HALF);
if (ZstdHelper::isCompressed(DFG_PACKAGE, DFG_DFG_SIZE)) {
const size_t decodedSize = ZstdHelper::getDecodedSize(DFG_PACKAGE, byteCount);
assert_invariant(decodedSize == byteCount);
lut->setImage(engine, 0, std::move(buffer));
// If the LUT is Zstd compressed, decompress it.
void* decodedData = malloc(decodedSize);
FILAMENT_CHECK_POSTCONDITION(decodedData)
<< "Couldn't allocate " << decodedSize << " bytes for DFG LUT decompression.";
if (UTILS_LIKELY(decodedData)) {
bool const success = ZstdHelper::decompress(
decodedData, decodedSize, DFG_PACKAGE, byteCount);
FILAMENT_CHECK_POSTCONDITION(success) << "Couldn't decompress DFG LUT.";
// Use decodedData for the texture
Texture* lut = builder.build(engine);
lut->setImage(engine, 0, { decodedData, decodedSize,
Texture::Format::RGB, Texture::Type::HALF,
+[](void* buffer, size_t, void*) { free(buffer); } });
mLUT = downcast(lut);
return;
}
}
assert_invariant(DFG_DFG_SIZE == byteCount);
Texture* lut = builder.build(engine);
lut->setImage(engine, 0, { DFG_PACKAGE, byteCount, Texture::Format::RGB, Texture::Type::HALF });
mLUT = downcast(lut);
}
+4 -4
View File
@@ -23,6 +23,9 @@
#include <utils/compiler.h>
#include <cstdint>
#include <cstddef>
namespace filament {
class FEngine;
@@ -40,7 +43,7 @@ public:
DFG& operator=(DFG const& rhs) = delete;
DFG& operator=(DFG&& rhs) = delete;
void init(FEngine& engine) noexcept;
void init(FEngine& engine);
size_t getLutSize() const noexcept {
return DFG_LUT_SIZE;
@@ -61,9 +64,6 @@ private:
// make sure to use the right size here
static constexpr size_t DFG_LUT_SIZE = FILAMENT_DFG_LUT_SIZE;
// this lookup table is generated with cmgen
static const uint16_t DFG_LUT[];
};
#undef FILAMENT_DFG_LUT_SIZE
+4
View File
@@ -363,6 +363,10 @@ bool MaterialParser::getStereoscopicType(StereoscopicType* value) const noexcept
return mImpl.getFromSimpleChunk(MaterialStereoscopicType, reinterpret_cast<uint8_t*>(value));
}
bool MaterialParser::getMaterialCrc32(uint32_t* value) const noexcept {
return mImpl.getFromSimpleChunk(MaterialCrc32, value);
}
bool MaterialParser::getRequiredAttributes(AttributeBitset* value) const noexcept {
uint32_t rawAttributes = 0;
if (!mImpl.getFromSimpleChunk(MaterialRequiredAttributes, &rawAttributes)) {
+1
View File
@@ -126,6 +126,7 @@ public:
bool getSpecularAntiAliasingVariance(float* value) const noexcept;
bool getSpecularAntiAliasingThreshold(float* value) const noexcept;
bool getStereoscopicType(backend::StereoscopicType*) const noexcept;
bool getMaterialCrc32(uint32_t* value) const noexcept;
bool getShader(filaflat::ShaderContent& shader, backend::ShaderModel shaderModel,
Variant variant, backend::ShaderStage stage) noexcept;
+2 -1
View File
@@ -198,7 +198,8 @@ FMaterial* PostProcessManager::PostProcessMaterial::getMaterial(FEngine& engine,
if (UTILS_UNLIKELY(mSize)) {
loadMaterial(engine);
}
mMaterial->prepareProgram(Variant{ Variant::type_t(variant) });
mMaterial->prepareProgram(Variant{ Variant::type_t(variant) },
CompilerPriorityQueue::CRITICAL);
return mMaterial;
}
+1 -1
View File
@@ -243,7 +243,7 @@ void RenderPass::appendCommands(FEngine const& engine,
for (Command const* first = curr, *last = curr + commandCount ; first != last ; ++first) {
if (UTILS_LIKELY((first->key & CUSTOM_MASK) == uint64_t(CustomCommand::PASS))) {
auto ma = first->info.mi->getMaterial();
ma->prepareProgram(first->info.materialVariant);
ma->prepareProgram(first->info.materialVariant, CompilerPriorityQueue::CRITICAL);
}
}
}
+5 -2
View File
@@ -112,6 +112,8 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
const bool canAutoResolveDepth = engine.getDriverApi().isAutoDepthResolveSupported();
FrameGraphTexture::Usage depthStencilUsage = FrameGraphTexture::Usage::DEPTH_ATTACHMENT;
if (!data.depth) {
// clear newly allocated depth/stencil buffers, regardless of given clear flags
clearDepthFlags = TargetBufferFlags::DEPTH;
@@ -151,6 +153,7 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
.format = format,
});
if (config.enabledStencilBuffer) {
depthStencilUsage |= FrameGraphTexture::Usage::STENCIL_ATTACHMENT;
data.stencil = data.depth;
}
}
@@ -172,10 +175,10 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
// We set a "read" constraint on these attachments here because we need to preserve them
// when the color pass happens in several passes (e.g. with SSR)
data.color = builder.read(data.color, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
data.depth = builder.read(data.depth, FrameGraphTexture::Usage::DEPTH_ATTACHMENT);
data.depth = builder.read(data.depth, depthStencilUsage);
data.color = builder.write(data.color, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
data.depth = builder.write(data.depth, FrameGraphTexture::Usage::DEPTH_ATTACHMENT);
data.depth = builder.write(data.depth, depthStencilUsage);
/*
* There is a bit of magic happening here regarding the viewport used.
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ZstdHelper.h"
#include <zstd.h>
#include <cstddef>
#include <cstdint>
namespace filament {
bool ZstdHelper::isCompressed(const void* src, size_t src_size) noexcept {
if (src_size < 4) {
return false;
}
const uint32_t magic = *static_cast<const uint32_t*>(src);
return magic == ZSTD_MAGICNUMBER;
}
size_t ZstdHelper::getDecodedSize(const void* src, size_t src_size) noexcept {
return ZSTD_getFrameContentSize(src, src_size);
}
size_t ZstdHelper::decompress(void* dst, size_t dst_size, const void* src, size_t src_size) noexcept {
return ZSTD_decompress(dst, dst_size, src, src_size);
}
} // namespace filament
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_ZSTD_HELPER_H
#define TNT_FILAMENT_ZSTD_HELPER_H
#include <stddef.h>
namespace filament {
class ZstdHelper {
public:
/**
* Checks if the given binary blob is Zstd compressed.
* @param src Pointer to the source data.
* @param src_size Size of the source data.
* @return True if the data is Zstd compressed, false otherwise.
*/
static bool isCompressed(const void* src, size_t src_size) noexcept;
/**
* Returns the decompressed size of a Zstd compressed blob.
* @param src Pointer to the source data.
* @param src_size Size of the source data.
* @return The decompressed size, or 0 if an error occurs.
*/
static size_t getDecodedSize(const void* src, size_t src_size) noexcept;
/**
* Decompresses a Zstd compressed blob into a pre-allocated buffer.
* @param dst Pointer to the destination buffer.
* @param dst_size Size of the destination buffer.
* @param src Pointer to the source data.
* @param src_size Size of the source data.
* @return The number of bytes decompressed, or 0 if an error occurs.
*/
static size_t decompress(void* dst, size_t dst_size, const void* src, size_t src_size) noexcept;
};
} // namespace filament
#endif // TNT_FILAMENT_ZSTD_HELPER_H
+2
View File
@@ -101,6 +101,8 @@ backend::Platform::DriverConfig getDriverConfig(FEngine* instance) {
.handleArenaSize = instance->getRequestedDriverHandleArenaSize(),
.metalUploadBufferSizeBytes = instance->getConfig().metalUploadBufferSizeBytes,
.disableParallelShaderCompile = instance->features.backend.disable_parallel_shader_compile,
.disableAmortizedShaderCompile =
instance->features.backend.disable_amortized_shader_compile,
.disableHandleUseAfterFreeCheck =
instance->features.backend.disable_handle_use_after_free_check,
.disableHeapHandleTags = instance->features.backend.disable_heap_handle_tags,
+19 -1
View File
@@ -733,6 +733,8 @@ public:
CORRECTNESS_ASSERTION_DEFAULT;
bool assert_material_instance_texture_descriptor_set_compatible =
CORRECTNESS_ASSERTION_DEFAULT;
bool assert_texture_format_mipmappable = CORRECTNESS_ASSERTION_DEFAULT;
bool assert_texture_can_generate_mipmap = CORRECTNESS_ASSERTION_DEFAULT;
} debug;
} engine;
struct {
@@ -746,15 +748,22 @@ public:
bool enable_staging_buffer_bypass = false;
} vulkan;
bool disable_parallel_shader_compile = false;
bool disable_amortized_shader_compile = false;
bool disable_handle_use_after_free_check = false;
bool disable_heap_handle_tags = true; // FIXME: this should be false
} backend;
struct {
bool check_crc32_after_loading = false;
} material;
} features;
std::array<FeatureFlag, sizeof(features)> const mFeatures{{
{ "backend.disable_parallel_shader_compile",
"Disable parallel shader compilation in GL and Metal backends.",
&features.backend.disable_parallel_shader_compile, true },
{ "backend.disable_amortized_shader_compile",
"Disable amortized shader compilation in GL backend.",
&features.backend.disable_amortized_shader_compile, true },
{ "backend.disable_handle_use_after_free_check",
"Disable Handle<> use-after-free checks.",
&features.backend.disable_handle_use_after_free_check, true },
@@ -783,11 +792,20 @@ public:
"Assert that the attribute stride of a vertex buffer is a multiple of 4.",
&features.engine.debug.assert_vertex_buffer_attribute_stride_mult_of_4, false },
{ "backend.vulkan.enable_staging_buffer_bypass",
"vulkan: enable a staging bypass logic for unified memory architecture",
"vulkan: enable a staging bypass logic for unified memory architecture.",
&features.backend.vulkan.enable_staging_buffer_bypass, false },
{ "engine.debug.assert_material_instance_texture_descriptor_set_compatible",
"Assert that the textures in a material instance are compatible with descriptor set.",
&features.engine.debug.assert_material_instance_texture_descriptor_set_compatible, false },
{ "engine.debug.assert_texture_format_mipmappable",
"Assert if a texture (with levels > 1) that the format is mipmappable.",
&features.engine.debug.assert_texture_format_mipmappable, false },
{ "engine.debug.assert_texture_can_generate_mipmap",
"Assert if a texture has the correct usage set for generating mipmaps.",
&features.engine.debug.assert_texture_can_generate_mipmap, false },
{ "material.check_crc32_after_loading",
"Verify the checksum of package data when a material is loaded.",
&features.material.check_crc32_after_loading, false },
}};
utils::Slice<const FeatureFlag> getFeatureFlags() const noexcept {
+24 -2
View File
@@ -188,6 +188,28 @@ Material* Material::Builder::build(Engine& engine) const {
return nullptr;
}
// Try checking CRC32 value for the package and skip if it's unavailable.
if (downcast(engine).features.material.check_crc32_after_loading) {
uint32_t parsedCrc32 = 0;
materialParser->getMaterialCrc32(&parsedCrc32);
constexpr size_t crc32ChunkSize = sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t);
const size_t originalSize = mImpl->mSize - crc32ChunkSize;
assert_invariant(mImpl->mSize > crc32ChunkSize);
std::vector<uint32_t> crc32Table;
hash::crc32GenerateTable(crc32Table);
uint32_t expectedCrc32 = hash::crc32Update(0, mImpl->mPayload, originalSize, crc32Table);
if (parsedCrc32 != expectedCrc32) {
CString name;
materialParser->getName(&name);
LOG(ERROR) << "The material '" << name.c_str_safe()
<< "' is corrupted: crc32_expected=" << expectedCrc32
<< ", crc32_parsed=" << parsedCrc32;
return nullptr;
}
}
uint32_t v = 0;
materialParser->getShaderModels(&v);
bitset32 shaderModels;
@@ -223,7 +245,7 @@ Material* Material::Builder::build(Engine& engine) const {
materialParser->getName(&name);
LOG(WARNING) << "The stereoscopic type in the compiled material '"
<< name.c_str_safe() << "' is " << (int) materialStereoscopicType
<< ", which is not compatiable with the engine's setting "
<< ", which is not compatible with the engine's setting "
<< (int) engineStereoscopicType << ".";
}
}
@@ -1164,7 +1186,7 @@ void FMaterial::precacheDepthVariants(FEngine& engine) {
}
assert_invariant(Variant::isValidDepthVariant(variant));
if (hasVariant(variant)) {
prepareProgram(variant);
prepareProgram(variant, CompilerPriorityQueue::HIGH);
}
}
return;
+1 -1
View File
@@ -142,7 +142,7 @@ public:
// Must be called outside of backend render pass.
// Must be called before getProgram() below.
void prepareProgram(Variant const variant,
backend::CompilerPriorityQueue const priorityQueue = CompilerPriorityQueue::HIGH) const noexcept {
backend::CompilerPriorityQueue const priorityQueue) const noexcept {
// prepareProgram() is called for each RenderPrimitive in the scene, so it must be efficient.
if (UTILS_UNLIKELY(!isCached(variant))) {
prepareProgramSlow(variant, priorityQueue);
+26 -10
View File
@@ -242,16 +242,29 @@ Texture* Texture::Builder::build(Engine& engine) {
if (mImpl->mUsage == TextureUsage::NONE) {
mImpl->mUsage = TextureUsage::DEFAULT;
if (mImpl->mLevels > 1 &&
(mImpl->mWidth > 1 || mImpl->mHeight > 1) &&
!mImpl->mExternal) {
const bool formatMipmappable =
downcast(engine).getDriverApi().isTextureFormatMipmappable(mImpl->mFormat);
if (formatMipmappable) {
// by default mipmappable textures have the BLIT usage bits set
mImpl->mUsage |= TextureUsage::BLIT_SRC | TextureUsage::BLIT_DST;
}
}
}
auto const& featureFlags = downcast(engine).features.engine.debug;
bool const formatMipmappable =
downcast(engine).getDriverApi().isTextureFormatMipmappable(mImpl->mFormat);
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(mImpl->mLevels == 1 || formatMipmappable,
featureFlags.assert_texture_format_mipmappable)
<< "Texture levels is > 1 (levels=" << +mImpl->mLevels
<< " dim=" << mImpl->mWidth << "x" << mImpl->mHeight
<< ", but the format ("
<< int(mImpl->mFormat) << ") "
<< " is not mipmppable";
// TODO: This exists for backwards compatibility, but should remove when safe.
if (!featureFlags.assert_texture_can_generate_mipmap &&
// Guess whether GEN_MIPMAPPABLE should be added or not based the following criteria.
(formatMipmappable &&
mImpl->mLevels > 1 &&
(mImpl->mWidth > 1 || mImpl->mHeight > 1) &&
!mImpl->mExternal)) {
mImpl->mUsage |= TextureUsage::GEN_MIPMAPPABLE;
}
// TODO: remove in a future filament release.
@@ -640,6 +653,9 @@ void FTexture::generateMipmaps(FEngine& engine) const noexcept {
FILAMENT_CHECK_PRECONDITION(formatMipmappable)
<< "Texture format " << (unsigned)mFormat << " is not mipmappable.";
FILAMENT_CHECK_PRECONDITION(any(mUsage & TextureUsage::GEN_MIPMAPPABLE))
<< "Texture usage does not have GEN_MIPMAPPABLE set";
if (mLevelCount < 2 || (mWidth == 1 && mHeight == 1)) {
return;
}
+22 -6
View File
@@ -19,8 +19,6 @@
#include "Froxelizer.h"
#include "PerViewDescriptorSetUtils.h"
#include "HwDescriptorSetLayoutFactory.h"
#include "ShadowMapManager.h"
#include "TypedUniformBuffer.h"
#include "components/LightManager.h"
@@ -30,10 +28,8 @@
#include "details/IndirectLight.h"
#include "details/Texture.h"
#include <filament/Engine.h>
#include <filament/Exposure.h>
#include <filament/Options.h>
#include <filament/TextureSampler.h>
#include <filament/MaterialEnums.h>
#include <filament/Viewport.h>
@@ -56,9 +52,11 @@
#include <algorithm>
#include <array>
#include <cmath>
#include <cstring>
#include <cstddef>
#include <limits>
#include <random>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -243,6 +241,22 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_LINEAR
});
// Fog calculation details:
// Optical path: (
// f = heightFalloff
// Te(y, z) = z * density * (exp(-f * eye_y) - exp(-f * eye_y - f * y)) / (f * y)
// Transmittance:
// t(y , z) = exp(-Te(y, z))
// In Linear Mode, formally the slope of the linear equation is: dt(y,z)/dz(0, eye_y)
// (the derivative of the transmittance at distance 0 and camera height). When the height
// falloff is disabled, the density parameter exactly represents this value.
constexpr double EPSILON = std::numeric_limits<float>::epsilon();
double const f = heightFalloff;
double const eye = userCameraPosition.y - options.height;
double const dt = options.density * (f <= EPSILON ? 1.0 : (std::exp(-f * eye) - std::exp(-2.0 * f * eye)) / (f * eye));
float const fogEndLinear = float(1.0 / dt);
s.fogStart = options.distance;
s.fogMaxOpacity = options.maximumOpacity;
s.fogHeightFalloff = heightFalloff;
@@ -253,6 +267,8 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer
s.fogInscatteringSize = options.inScatteringSize;
s.fogColorFromIbl = fogColorTextureHandle ? 1.0f : 0.0f;
s.fogFromWorldMatrix = mat3f{ cof(fogFromWorld) };
s.fogLinearParams = { 1.0f / (fogEndLinear - options.distance),
-options.distance / (fogEndLinear - options.distance) };
}
void ColorPassDescriptorSet::prepareSSAO(Handle<HwTexture> ssao,
@@ -332,7 +348,7 @@ void ColorPassDescriptorSet::prepareDirectionalLight(FEngine& engine,
}
}
void ColorPassDescriptorSet::prepareAmbientLight(FEngine& engine, FIndirectLight const& ibl,
void ColorPassDescriptorSet::prepareAmbientLight(FEngine const& engine, FIndirectLight const& ibl,
float const intensity, float const exposure) noexcept {
auto& s = mUniforms.edit();
+1 -1
View File
@@ -115,7 +115,7 @@ public:
void prepareDirectionalLight(FEngine& engine, float exposure,
math::float3 const& sceneSpaceDirection, LightManagerInstance instance) noexcept;
void prepareAmbientLight(FEngine& engine,
void prepareAmbientLight(FEngine const& engine,
FIndirectLight const& ibl, float intensity, float exposure) noexcept;
void prepareDynamicLights(Froxelizer& froxelizer) noexcept;
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.63.1"
spec.version = "1.63.0"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.63.1/filament-v1.63.1-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.63.0/filament-v1.63.0-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
+1 -1
View File
@@ -21,7 +21,7 @@ targetTemplates:
base:
OTHER_LDFLAGS: ["-lfilament", "-lbackend", "-lfilaflat", "-lktxreader",
"-lfilabridge", "-lutils", "-lsmol-v", "-lgeometry", "-libl",
"-labseil"]
"-labseil", "-lzstd"]
ENABLE_BITCODE: NO
CLANG_CXX_LANGUAGE_STANDARD: gnu++17
# This allows users to not have to specify a unique bundle ID when building the sample apps.
@@ -255,6 +255,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilamat",
"-force_load ../../../out/ios-debug/filament/lib/arm64/libbackend_test.a",
);
@@ -363,6 +364,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilamat",
"-force_load ../../../out/ios-debug/filament/lib/arm64/libbackend_test.a",
);
@@ -464,6 +466,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilamat",
"-force_load ../../../out/ios-debug/filament/lib/arm64/libbackend_test.a",
);
@@ -510,6 +513,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilamat",
"-force_load ../../../out/ios-debug/filament/lib/arm64/libbackend_test.a",
);
@@ -426,6 +426,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -482,6 +483,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -600,6 +602,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -656,6 +659,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -293,6 +293,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -340,6 +341,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -449,6 +451,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -613,6 +616,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -329,6 +329,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -382,6 +383,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -607,6 +609,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -660,6 +663,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lgltfio_core",
"-luberarchive",
"-limage",
@@ -310,6 +310,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -357,6 +358,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -404,6 +406,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -561,6 +564,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
"-lfilameshio",
"-lmeshoptimizer",
"-limage",
@@ -232,6 +232,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.hello-triangle";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -338,6 +339,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.hello-triangle";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -382,6 +384,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.hello-triangle";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -536,6 +539,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.hello-triangle";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -394,6 +394,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.transparent-rendering";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -438,6 +439,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.transparent-rendering";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -482,6 +484,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.transparent-rendering";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -526,6 +529,7 @@
"-lgeometry",
"-libl",
"-labseil",
"-lzstd",
);
PRODUCT_BUNDLE_IDENTIFIER = "${SAMPLE_CODE_DISAMBIGUATOR}.google.filament.transparent-rendering";
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
@@ -98,6 +98,8 @@ enum UTILS_PUBLIC ChunkType : uint64_t {
DictionaryText = charTo64bitNum("DIC_TEXT"),
DictionarySpirv = charTo64bitNum("DIC_SPIR"),
DictionaryMetalLibrary = charTo64bitNum("DIC_MLIB"),
MaterialCrc32 = charTo64bitNum("MAT_CRC "),
};
} // namespace filamat
@@ -177,6 +177,8 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
float fogOneOverFarMinusNear;
float fogNearOverFarMinusNear;
std140::mat33 fogFromWorldMatrix;
math::float2 fogLinearParams; // { 1/(end-start), -start/(end-start) }
math::float2 fogReserved0;
// --------------------------------------------------------------------------------------------
// Screen-space reflections [variant: SSR (i.e.: VSM | SRE)]
@@ -202,7 +204,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
float es2Reserved2;
// bring PerViewUib to 2 KiB
math::float4 reserved[40];
math::float4 reserved[39];
};
// 2 KiB == 128 float4s
+4
View File
@@ -54,6 +54,10 @@ bool MaterialChunk::initialize(filamat::ChunkType materialTag) {
}
auto [start, end] = mContainer.getChunkRange(materialTag);
if (start == end) {
return false;
}
Unflattener unflattener(start, end);
mUnflattener = unflattener;
+1 -1
View File
@@ -148,7 +148,7 @@ install(DIRECTORY ${PUBLIC_HDR_DIR}/filamat DESTINATION include)
# Need to install libtint for filamat on Android.
# See libs/filamat/CMakeLists.txt and android/filamat-android/CMakeLists.txt.
if (ANDROID)
if (ANDROID AND FILAMENT_SUPPORTS_WEBGPU)
target_link_libraries(${TARGET} libtint_combined)
endif()
@@ -532,6 +532,9 @@ public:
//! Enable / disable flipping of the Y coordinate of UV attributes, enabled by default.
MaterialBuilder& flipUV(bool flipUV) noexcept;
//! Enable / disable the cheapest linear fog, disabled by default.
MaterialBuilder& linearFog(bool enabled) noexcept;
//! Enable / disable multi-bounce ambient occlusion, disabled by default on mobile.
MaterialBuilder& multiBounceAmbientOcclusion(bool multiBounceAO) noexcept;
@@ -635,6 +638,12 @@ public:
//! specify compute kernel group size
MaterialBuilder& groupSize(filament::math::uint3 groupSize) noexcept;
/**
* Force Filament to use its default variant for depth passes. Useful if a material provides a
* custom vertex shader which can be skipped during depth-only passes.
*/
MaterialBuilder& useDefaultDepthVariant() noexcept;
/**
* Build the material. If you are using the Filament engine with this library, you should use
* the job system provided by Engine.
@@ -948,6 +957,7 @@ private:
bool mClearCoatIorChange = true;
bool mFlipUV = true;
bool mLinearFog = false;
bool mMultiBounceAO = false;
bool mMultiBounceAOSet = false;
@@ -968,6 +978,8 @@ private:
filament::UserVariantFilterMask mVariantFilter = {};
bool mNoSamplerValidation = false;
bool mUseDefaultDepthVariant = false;
};
} // namespace filamat
+2
View File
@@ -1090,6 +1090,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
RegisterPass(CreateDeadBranchElimPass());
RegisterPass(CreateBlockMergePass());
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
RegisterPass(CreateCanonicalizeIdsPass());
}
void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& config) {
@@ -1132,6 +1133,7 @@ void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& c
RegisterPass(CreateRedundancyEliminationPass());
RegisterPass(CreateAggressiveDCEPass());
RegisterPass(CreateCFGCleanupPass());
RegisterPass(CreateCanonicalizeIdsPass());
}
} // namespace filamat
+31 -4
View File
@@ -404,6 +404,11 @@ MaterialBuilder& MaterialBuilder::groupSize(math::uint3 const groupSize) noexcep
return *this;
}
MaterialBuilder& MaterialBuilder::useDefaultDepthVariant() noexcept {
mUseDefaultDepthVariant = true;
return *this;
}
MaterialBuilder& MaterialBuilder::materialDomain(
MaterialDomain const materialDomain) noexcept {
mMaterialDomain = materialDomain;
@@ -539,6 +544,11 @@ MaterialBuilder& MaterialBuilder::flipUV(bool const flipUV) noexcept {
return *this;
}
MaterialBuilder& MaterialBuilder::linearFog(bool const enabled) noexcept {
mLinearFog = enabled;
return *this;
}
MaterialBuilder& MaterialBuilder::customSurfaceShading(bool const customSurfaceShading) noexcept {
mCustomSurfaceShading = customSurfaceShading;
return *this;
@@ -708,6 +718,7 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept {
info.specularAntiAliasing = mSpecularAntiAliasing;
info.clearCoatIorChange = mClearCoatIorChange;
info.flipUV = mFlipUV;
info.linearFog = mLinearFog;
info.requiredAttributes = mRequiredAttributes;
info.blendingMode = mBlendingMode;
info.postLightingBlendingMode = mPostLightingBlendingMode;
@@ -925,7 +936,8 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
mMaterialVertexCode.getResolved(), mMaterialVertexCode.getLineOffset(),
mMaterialDomain);
container.emplace<bool>(MaterialHasCustomDepthShader, needsStandardDepthProgram());
container.emplace<bool>(MaterialHasCustomDepthShader,
needsStandardDepthProgram() && !mUseDefaultDepthVariant);
std::atomic_bool cancelJobs(false);
bool firstJob = true;
@@ -1374,10 +1386,25 @@ error:
goto error;
}
// Flatten all chunks in the container into a Package.
Package package(container.getSize());
// Flatten all container chunks into a single package and compute its CRC32 value, storing it as
// a separate chunk.
constexpr size_t crc32ChunkSize = sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t);
const size_t originalContainerSize = container.getSize();
const size_t signedContainerSize = originalContainerSize + crc32ChunkSize;
Package package(signedContainerSize);
Flattener f{ package.getData() };
container.flatten(f);
size_t flattenSize = container.flatten(f);
std::vector<uint32_t> crc32Table;
hash::crc32GenerateTable(crc32Table);
uint32_t crc = hash::crc32Update(0, f.getStartPtr(), flattenSize, crc32Table);
f.writeUint64(static_cast<uint64_t>(MaterialCrc32));
f.writeUint32(static_cast<uint32_t>(sizeof(crc)));
f.writeUint32(static_cast<uint32_t>(crc));
assert_invariant(flattenSize == originalContainerSize);
assert_invariant(signedContainerSize == f.getBytesWritten());
return package;
}
+5 -2
View File
@@ -62,6 +62,9 @@ public:
return mStart == (uint8_t*) FAKE_DRY_RUNNER_START_ADDR;
}
uint8_t* getStartPtr() {
return mStart;
}
size_t getBytesWritten() {
return mCursor - mStart;
}
@@ -183,7 +186,7 @@ public:
return size;
}
void writeOffsetplaceholder(size_t index) {
void writeOffsetPlaceholder(size_t index) {
mOffsetPlaceholders.insert(std::pair<size_t, uint8_t*>(index, mCursor));
if (!isDryRunner()) {
mCursor[0] = 0x0;
@@ -228,7 +231,7 @@ public:
mCursor += 4;
}
void writePlaceHoldValue(size_t v) {
void writeValue(size_t v) {
assert(!mValuePlaceholders.empty());
if (v > UINT32_MAX) {
+2 -2
View File
@@ -57,7 +57,7 @@ void compressShader(std::string_view src, Flattener &f, const LineDictionary& di
cur++;
}
f.writePlaceHoldValue(numLines);
f.writeValue(numLines);
}
void MaterialTextChunk::flatten(Flattener& f) {
@@ -90,7 +90,7 @@ void MaterialTextChunk::flatten(Flattener& f) {
for (size_t i = 0; i < mEntries.size(); i++) {
writeEntryAttributes(i, f);
const ShaderMapping& mapping = mDuplicateMap[i];
f.writeOffsetplaceholder(mapping.isDup ? mapping.dupOfIndex : i);
f.writeOffsetPlaceholder(mapping.isDup ? mapping.dupOfIndex : i);
}
// Write all strings
@@ -250,6 +250,8 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out,
CodeGenerator::generateDefine(out, "LEGACY_MORPHING", material.useLegacyMorphing);
}
if (stage == ShaderStage::FRAGMENT) {
CodeGenerator::generateDefine(out, "FILAMENT_LINEAR_FOG",
material.linearFog);
CodeGenerator::generateDefine(out, "MATERIAL_HAS_CUSTOM_DEPTH",
material.userMaterialHasCustomDepth);
}
+1
View File
@@ -44,6 +44,7 @@ struct UTILS_PUBLIC MaterialInfo {
bool specularAntiAliasing;
bool clearCoatIorChange;
bool flipUV;
bool linearFog;
bool multiBounceAO;
bool multiBounceAOSet;
bool specularAOSet;
@@ -189,6 +189,8 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
{ "fogOneOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH },
{ "fogNearOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH },
{ "fogFromWorldMatrix", 0, Type::MAT3, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 },
{ "fogLinearParams", 0, Type::FLOAT2, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 },
{ "fogReserved0", 0, Type::FLOAT2, Precision::HIGH },
// ------------------------------------------------------------------------------------
// Screen-space reflections [variant: SSR (i.e.: VSM | SRE)]
+2
View File
@@ -65,4 +65,6 @@ add_executable(${TARGET} ${SRCS})
target_link_libraries(${TARGET} matp gtest)
target_include_directories(${TARGET} PRIVATE ${matp_SOURCE_DIR}/src)
set_target_properties(test_matp PROPERTIES FOLDER Tests)
@@ -18,7 +18,6 @@
#ifndef TNT_MATERIALPARSER_H
#define TNT_MATERIALPARSER_H
#include <string>
#include <unordered_map>
#include "Config.h"
@@ -82,12 +81,14 @@ private:
using MaterialConfigProcessor = bool (MaterialParser::*)
(const MaterialLexeme&, filamat::MaterialBuilder& builder) const;
// Map used to store Command pattern function pointers.
std::unordered_map<std::string, MaterialConfigProcessor> mConfigProcessor;
// Using string_view is generally not recommended in a map, but the string keys are program constants,
// which guarantees that the strings will outlive lifetime of the map. See MaterialParser.cpp
std::unordered_map<std::string_view, MaterialConfigProcessor> mConfigProcessor;
// The same, but for pure JSON syntax
using MaterialConfigProcessorJSON = bool (MaterialParser::*)
(const JsonishValue*, filamat::MaterialBuilder& builder) const;
std::unordered_map<std::string, MaterialConfigProcessorJSON> mConfigProcessorJSON;
std::unordered_map<std::string_view, MaterialConfigProcessorJSON> mConfigProcessorJSON;
};
} // namespace matp
-2
View File
@@ -16,8 +16,6 @@
#include "JsonishParser.h"
#include <stdlib.h>
#include <iostream>
#include <string.h>
+1 -1
View File
@@ -368,7 +368,7 @@ bool MaterialParser::parseMaterial(const char* buffer, size_t size,
identifier = lexeme.getStringValue();
if (mConfigProcessor.find(identifier) == mConfigProcessor.end()) {
std::cerr << "Unknown identifier '"
<< lexeme.getStringValue()
<< identifier
<< "' at line:" << lexeme.getLine()
<< " position:" << lexeme.getLinePosition() << std::endl;
return false;
@@ -1185,6 +1185,11 @@ static bool processFlipUV(MaterialBuilder& builder, const JsonishValue& value) {
return true;
}
static bool processLinearFog(MaterialBuilder& builder, const JsonishValue& value) {
builder.linearFog(value.toJsonBool()->getBool());
return true;
}
static bool processMultiBounceAO(MaterialBuilder& builder, const JsonishValue& value) {
builder.multiBounceAmbientOcclusion(value.toJsonBool()->getBool());
return true;
@@ -1350,6 +1355,13 @@ static bool processVariantFilter(MaterialBuilder& builder, const JsonishValue& v
return true;
}
static bool processUseDefaultDepthVariant(MaterialBuilder& builder, const JsonishValue& value) {
if (value.toJsonBool()->getBool()) {
builder.useDefaultDepthVariant();
}
return true;
}
ParametersProcessor::ParametersProcessor() {
using Type = JsonishValue::Type;
mParameters["name"] = { &processName, Type::STRING };
@@ -1397,6 +1409,8 @@ ParametersProcessor::ParametersProcessor() {
mParameters["featureLevel"] = { &processFeatureLevel, Type::NUMBER };
mParameters["groupSize"] = { &processGroupSizes, Type::ARRAY };
mParameters["stereoscopicType"] = { &processStereoscopicType, Type::STRING };
mParameters["useDefaultDepthVariant"] = { &processUseDefaultDepthVariant, Type::BOOL };
mParameters["linearFog"] = { &processLinearFog, Type::BOOL };
}
bool ParametersProcessor::process(MaterialBuilder& builder, const JsonishObject& jsonObject) {
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include "../src/DirIncluder.h"
#include "DirIncluder.h"
using namespace utils;
using namespace filamat;
+5 -3
View File
@@ -18,10 +18,12 @@
#include "TestMaterialParser.h"
#include <filamat/MaterialBuilder.h>
#include <filament-matp/MaterialParser.h>
#include "../src/JsonishLexer.h"
#include "../src/JsonishParser.h"
#include "../src/MaterialLexer.h"
#include "JsonishLexer.h"
#include "JsonishParser.h"
#include "MaterialLexer.h"
class MaterialLexer: public ::testing::Test {
protected:

Some files were not shown because too many files have changed in this diff Show More