* Optimize Shader LineDictionary with Variable-Length 3-Streams
This commit completely reorganizes the string dictionary compression
pipeline used by compiled Material Text Chunks and improves matinfo
dictionary output.
1. Multi-Base Variable-Length Scaling:
We replaced the static 16-bit indices overhead with a
bounded payload. Now, indices scale dynamically:
- 0 to 239 evaluate in 1 byte.
- 240 to 3584 leverage 0xF0-0xFD escapes evaluating in 2 bytes.
- 3584+ are locked behind a 0xFF marker to 3 bytes.
This natively eradicated the massive monolithic lengths and zero-padding
issues previously dominating shader packages.
2. Variable-Length 3-Stream Decoding:
To solve the Zstandard/Zlib entropy fragmentation that conventionally
plagues interleaved variable byte lengths (which previously inflated
our `filament.aar` boundary constraint by +2KB), we segregated the encoded
payloads.
By grouping high-entropy string boundaries into a `Base Stream`
and isolating offset digits inside an `Extension Stream`,
predictive LZ77 ZIP sliding-windows perfectly map
over both arrays independently without disruption.
3. Optimize Numeric Stream using LEB128
Prior to this change, numerical suffixes split from shader
variables (e.g., `param_1024` -> `param_` + `1024`) were fed back
into the localized String Dictionary. Because high-frequency numbers were
assigned disjointed localized IDs per shader variant, LZ77
failed to cross-reference their repetitive structures across
shipped `.aar` archives, fracturing compression sequences.
This patch implements a unified 3-Stream topology. It
extracts numerical primitives (< 32768) away from the baseline
String Dictionary, writing them into an isolated, contiguous
LEB128 array.
By using a dedicated `[254]` Escape Token within the primary stream, numerical
variables maintain exact 1-byte (`< 128`) or 2-byte (`>= 128`)
geometric layouts across all permutations.
The resulting deterministic alignment guarantees that Zlib sliding windows
can deduplicate highly repetitive variables across the
entire application binary block.
4. We use the ShaderStage information to create distinct index ranges, which
further help use 1-byte indices.
Verification Metrics:
`filament-android.aar`: -7,938 B
`gltfio-android.aar`: -290,939 B
`libfilament.a`: -18,464 B
* Optimize shader dictionary by decoding '_' for numeric literals
Most numbers extracted from the shader text are preceded by an
underscore (e.g., from `_`, `hp_copy_`), which previously caused
standalone `_` strings to heavily pollute the LineDictionary.
This change removes the standalone `_` from the dictionary index:
- `MaterialChunk` rehydrates the `_` prefix when decoding these numeric
literals.
This frees up dictionary indices, yielding massive byte savings across
uncompressed binaries (e.g., -28.4 KB for volume_masked.filamat).
* Optimize ShaderMinifier to strip explicit spacing
Spirv-cross outputs GLSL with explicit spacing around generic
operators (e.g., ` = `, `, `, ` ) * `). This padding consumes a
significant amount of uncompressed bytes across large ubershaders.
By applying targeted string replacements at the end of the `ShaderMinifier`
pass, we strip this extraneous padding down to its raw tokens
(e.g., `a=b`, `a,b`, `a*b`).
This optimization preserves isolating spaces where valuable, ensuring
line-dictionary tokens (such as raw `=` or `,`) remain deduplicated
instead of fusing into unpredictable variables.
Impact:
This saves roughly ~9.1 KB in `libfilament.a` and ~3.2 KB in
`volume_masked.filamat` uncompressed, with proportional gains across
the downstream LZ4 compressed archives.
* Fix out-of-bounds string read by verifying null-terminator existence
during extraction.
* Fix heap buffer overflow by validating dictionary string lengths
against target shader buffers before copying.
* Fix out-of-bounds array reads by validating chunk-provided lookup
indices against parsed dictionary sizes.
* Fix integer wrapping exploits by replacing pointer addition with
offset subtraction during chunk size verifications.
Add unit tests for these vulerabilities.
- Move filament tests (frontend) to arm linux build
- Move header check to arm linux build
- Move backend test and correctness to arm linux
- Disable a failing GL test (b/495913675) - only fails on arm.
* Refactor web examples and tutorials
- Consolidate web/docs and web/samples into web/examples
- Remove literal programming blocks from Markdown tutorials
- Replace tutorial_template.html with a fully embedded template in serve.py
- Move serve.py to web/examples/serve.py and update dependency rules
- Update filament-js wrapper to expose _malloc, _free and set GEN_MIPMAPPABLE usage
- Update sample materials and WebGL asset generation within web/examples/CMakeLists.txt
- Add python venv instructions and usage details to web/README.md
- Remove obsolete examples, Pipfile, and demo templates
* Transfer web tutorials and samples to docs_src
- Introduce copy_web_docs.py api to deploy and rewrite web sample outputs into the docs output tree
- Hook copy_web_docs into docs_src/build/run.py natively
- Configure duplicates.json to map WebGL outputs to embedded .md docs
- Strip html skeleton out of examples in run.py so they map into markdown cleanly
- Update update-docs workflow to pre-build the WebGL target
- Remove obsolete remote docs path from src_raw
- Add explanatory comments to copy_web_docs.py and run.py
- Add index page with thumbnails for Web Tutorials and samples
- Introduce `shiftRadius` to allow positional tolerances by searching
a local neighborhood, absorbing sub-pixel shifts and MSAA quirks.
- Introduce `blurRadius` to apply local area averaging, ignoring
high-frequency noise like hardware dithering.
- Enhance `ImageDiffResult` to include an `averageError` array and
a 10-bin `errorHistogram` for actionable failure debugging.
- Update Android JNI bindings (`ImageDiff.java` and `ImageDiff.cpp`)
to propagate the new error distribution statistics to Java callers.
- Update C++ unit tests to cover the new heuristic options.
- Document the new parameters and JSON result format in README.md.
- Add synthetic image generation tests in `tools/diffimg/tests/` to
validate the CLI tool's handling of spatial shifts and dithering.
The previous implementation allowed the backend thread to modify the
program state while it was still being cached on the compiler thread.
This could lead to potential data corruption or inconsistent cache
blobs.
To ensure data integrity, the program blob is now cached before the
signal is dispatched. This prevents the receiving thread from modifying
the program (e.g., via glUniformBlockBinding) until the caching process
is fully finalized.
BUGS=[491819760]
The previous eviction time is too large (40), then causes memory
to bloat over time. We set the default to 3 (as in triple
buffering), but make it a configurable option via VulkanPlatform.
Fixes#9786
- Update get-mesa.sh to query dpkg --print-architecture to install
the correct packages dynamically, enabling aarch64 support.
- Update get-vulkan-sdk.sh to install via apt-get on Linux
(libvulkan-dev, vulkan-validationlayers, glslang-tools,
spirv-tools) instead of downloading LunarG's x86_64 tarball.
- Add runner architecture to Mesa and Vulkan SDK GitHub Action cache
keys to prevent collision.
- Update test.sh and preamble.sh to detect aarch64 and point to
the appropriate aarch64-linux-gnu libraries.
- Fix typos and some renaming
Add the following information:
- Android build fingerprint, version
- GPU driver name, info, vendor name
- Time elapsed for test
- Rendered images (as oppose to diff image)
filament-utils:
- Add DeviceUtils to hook into Platform methods for reading out
strings about gpu vendor, driver.
Fix "tolerance" in test definition
For renderdiff, we compile mesa using brew's llvm/clang, but
we compile filament with the system clang (AppleClang).
This is to prevent compiling filament with brew's clang (which
can cause unexpected compilation error).
- Add reset functionality to ModelViewer
- We use this reset in render-validation to not have to reload
the scene in runs that use the same model.
- Fix a bug where the camera manipulator is disabling setting
the camera via view config.
Fixes a SIGSEGV crash that occurs during
`ExternalStreamManagerAndroid::release()` when users provide a custom
Platform instance during Engine creation.
When a custom Platform is used, ExternalStreamManagerAndroid is
instantiated on the application's thread. Its constructor was caching a
C++ reference (`VirtualMachineEnv& mVm`) to the `thread_local`
VirtualMachineEnv instance belonging to the application thread.
Later, when the Filament backend thread executed `release()`, it
accessed this cached reference. This caused the backend thread to
retrieve the `JNIEnv*` from the application thread's `thread_local`
instance, and subsequently call `env->DeleteGlobalRef()`. A thread must
use its own `JNIEnv` pointer, so using the application thread's pointer
from the backend thread resulted in a crash.
BUGS=[489814416]
- Simplify getting cmake, ninja for linux
- Move linux, web, webgpu builds to use arm (more cores for less)
- Android cannot be moved due to Android SDK not available on
arm linux yet.
- Add Arm Linux release artifacts
Fixes#8674
libfilament (including libutils and libmath) are 100% std::string
free.
std::string is pulled in the .so (on android) through libc++ for
exception handling, even if we're not using them. There is not much
we can do here, but at least, it's not because of us!
utils::ostream still references it but only as an inline function,
so if the inline is not called, std::string won't be pulled in.
It's also referenced from Path.cpp, but that's not included in
libfilament.
This made it nearly impossible to find the actual error. Now, we
output only the error from the compiler + the material name, variant
and shader stage all in one line.
The main thread invokes `getTimerQueryValue` synchronously, reading
`tq->state`. Meanwhile, the driver thread handles `createTimerQuery`
asynchronously and initializes `tq->state = std::make_shared<State>()`.
Eliminate this race by initializing the state in createTimerQueryS.
BUGS=[491522442]
- Move header check from postsubmit to presubmit
- Install third_party/getop if needed
- Modify check-headers test to use system getopt when it's available.
On certain linux, macOS environment, there is already a system
getopt. This often creates conflict when compiling filament.
Here we alias utils::getopt to either the system getopt (if
present) or third_party/getopt.
Fixes#7551
- Update python3 version to 3.12.13
- Use action/checkout instead of Bhacaz/checkout-files because action/checkout can
use the action/files of the current PR, where as checkout-files is checking out
a file on the main branch
- action/checkout seems to run in less than a minute, so acceptable performance
difference.
--------------------------------------------------------------------
Breakage is:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/jwt/algorithms.py", line 36, in <module>
from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm
ModuleNotFoundError: No module named 'cryptography'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/verify_release_notes.py", line 17, in <module>
from github import Github
File "/usr/local/lib/python3.10/site-packages/github/__init__.py", line 56, in <module>
from github.MainClass import Github, GithubIntegration
File "/usr/local/lib/python3.10/site-packages/github/MainClass.py", line 54, in <module>
import jwt
File "/usr/local/lib/python3.10/site-packages/jwt/__init__.py", line 1, in <module>
from .api_jwk import PyJWK, PyJWKSet
File "/usr/local/lib/python3.10/site-packages/jwt/api_jwk.py", line 8, in <module>
from .algorithms import get_default_algorithms, has_crypto, requires_cryptography
File "/usr/local/lib/python3.10/site-packages/jwt/algorithms.py", line 113, in <module>
from typing_extensions import Never
ModuleNotFoundError: No module named 'typing_extensions'
The previous conditional used
github.event.head_commit.verification.verified, which is not a
real field. Hence, the attempt to reduce presubmit runs did not
actually succeed. Here we replace it with a more correct
verification step.
We make two adjustments to make the presubmit workflows run less.
- Only run on commit merge when the commit is not "verified".
While not a 1-1 definition, "verified" commit typically implies
that the commit came from a PR merge (which requires that
presubmit passes). A commit could also be made by owners on
main directly, in which case, the commit would not be verified.
- Cancel any in progress presubmit runs are "overwritten" by an
update to the PR.
I recently added a new fuzz test for my Filament-based app, which creates a window and then rapidly issues changes such as toggling View features, changing the window size, and other operations that the users of my app can do.
It quickly found a crash when Bloom is enabled and the window dimensions get resized to weird aspect ratios on a large monitor. Eventually I narrowed it down to the Bloom buffer's width exceeding the Metal max texture dimension (on my machine, 16K). Applying this patch fixes the crash.