-
Notifications
You must be signed in to change notification settings - Fork 0
Shader Diffing
- Changes to the scene and/or primitive affect what the shader code should be for each primitive
- Multiple primitives may have the same or different shader code
- Switching shaders unnecessarily is expensive
- Generating and uploading a new shader is expensive
- Scene is serialisable (no references to shader)
- Scene is immutable (no direct lookups)
Conclusion: Shaders must be created only when necessary, based on the values of scene + primitives, and shared where relevant values match.
-
A plain object is derived for each scene and primitive, based on inspecting only shader-specific properties. The exact shape is different for the scene vs. primitive, but the concept is the same - a plain
shaderConfig
object. -
A hash is constructed for each
sceneShaderConfig
+primitiveShaderConfig
, resulting in ashaderHash
(just a plain string). -
This hash is used as the key for looking up a shader in a global
Map<string, Shader>
. -
If the shader is not found for that hash, it is compiled and stored. Compiling a shader requires passing the
data
andshaderConfig
objects (and nothing else)
This allows decoupling the shader lookup from referencing any particular instance of the scene or primitive, it only cares about the values that have changed.
All of this happens every tick (though of course cache misses are typically only on the first tick). Therefore, creating shaderConfig
and hashing it must be very fast (and they are - setting shaderConfig
is mostly unrolled settings of flags, and the hash is a hand-tuned approach that was tested against several other approaches).
This is one of the reasons why extensions are hardcoded rather than an open and flexible api (though conceptually they could be dynamically loaded and just append the hash string).
At this point from some minimal tests - it seems to support a few thousand gltf objects no problem. At that point the bottleneck is almost definitely somewhere else in the system rather than diffing/hashing. Since it's all pure data, this work could be offloaded to a separate thread as well.