Compare commits

...

297 Commits

Author SHA1 Message Date
yein
5f13abd0bd Fix missing dep in CompressedStringChunk (#9534) 2025-12-22 12:07:33 -07:00
Sungun Park
78944b4062 Bump version to 1.68.3 2025-12-16 14:57:49 -08:00
Sungun Park
c4802f7683 Release Filament 1.68.2 2025-12-16 14:57:34 -08:00
Ben Doherty
b582b2d64e Revert "Set the minimum required Metal version (#9425)" (#9527)
This reverts commit f5071b2aae.
2025-12-16 19:54:24 +00:00
Ben Doherty
9c4edf56ca Metal: fix compiler crash when running iOS apps under Mac Catalyst (#9524) 2025-12-16 10:41:14 -08:00
Mathias Agopian
e24fdb3a9d Workaround for harmless warning about descriptor sets (#9519)
* Workaround for harmless warning about descriptor sets

The proper fix is difficult and will be handled later. Here we simply
suppress the warning at FL0.


BUGS=[468072646]

* Apply suggestions from code review
2025-12-15 13:11:00 -08:00
Sungun Park
05f24516dd Fix Build.builder.feature() for Java bindings (#9517)
The "const char*" used for the string literal parameter of the `feature`
method becomes invalid once it passes outside the Java binding scope,
leading to invalid data access. This fix ensures the string is safely
stored.

Add support for heterogeneous lookup in associative containers that
use CString keys. Add conversion operators for std::string_view and
raw string literals to CString.
2025-12-15 21:04:36 +00:00
Mathias Agopian
a3708b2616 fix mat33 in UBOs at feature level 0 (#9510)
When emulating UBOs for feature level 0, we need to use packed
mat33 as source of glUniformMatrix3fv which doesn't expect the std140
alignments of UBOs.

FIXES=[468092808]
2025-12-15 12:43:25 -08:00
Powei Feng
ee514df722 docs: fix freezing when generating docs (#9521)
For reasons unknown, selenium will freeze when trying to make
request to the local server serving the markdown files. We add
a delay between the server and the selenium driver to hopefully
address this.

DOCS_FORCE
2025-12-15 10:50:00 -08:00
Run Yu
924c416644 webgpu: refactor WebGPUPlatform (#9516)
webgpu: refactors WebGPU Platform so each OS environment has its own WebGPU Platform 
class derived from the same base, and use virtual functions for their own implementations.
2025-12-12 19:24:41 -05:00
Powei Feng
597cf9a3ae docs: fix broken markdeep generation (#9514)
The breakage is due to breaking changes in the latest version.
We use the repo checked-in version instead.

Also make sure postsubmit.sh script exits on any error
2025-12-12 23:02:28 +00:00
Powei Feng
316c8376d3 Revert "[automated] Updating /docs due to commit f701c1e"
This reverts commit c300f77151.
2025-12-12 14:27:17 -08:00
Patrick Ribas
672ddddafc Added material name to createParser error logs (#9505) 2025-12-12 14:20:39 -08:00
Mathias Agopian
a8ee48c4b7 a series of CL to add RenderTarget support for external textures (#9504)
* add support for AHardwareBuffer to the java bindings

Texture.setEXternalIamge() now can take a AHArdwreBuffer Java object
as a parameter.

* add an API to set the priority of the Skybox

by default the skybox is always drawn last (priority 7) in order to
reduce overdraw. however, when depth culling is not enabled, it
needs to be drawn first. The new Builder::priority() allows to set
an arbitrary priority for the skybox.

* add rendertarget support for external textures

This was in fact mostly already supported, we just were artificially
preventing that usage. It is supported by the EGL_external_image
extension.

It's the responsibility of the caller/user to not attempt to use an
incompatible format, which has undefined behavior.

FIXES=[466395306]

* add a new android sample to test the AHardwareBuffer as render target

---------

Co-authored-by: Powei Feng <powei@google.com>
2025-12-12 14:15:58 -08:00
Filament Bot
c300f77151 [automated] Updating /docs due to commit f701c1e
Full commit hash is f701c1e1b5

DOCS_ALLOW_DIRECT_EDITS
2025-12-12 22:00:55 +00:00
Mathias Agopian
16734fc767 EMSCRIPTEN always supports fences, even at feature level 0 (#9507)
FIXES=[467783405]
2025-12-12 13:59:51 -08:00
Nemi
f701c1e1b5 Implement KHR_materials_dispersion (#9471)
This change adds support for the KHR_materials_dispersion glTF extension, which introduces a dispersion property for refractive materials.

The dispersion property controls the angular separation of colors transmitting through a refractive object, allowing for more realistic rendering of materials like glass and diamonds.

  Changes include:
   - Added a dispersion property to the material definition.
   - Updated the shaders to incorporate the dispersion effect in the refraction calculations.
   - Added a new test case for dispersion.
   - Updated the material documentation to include the new dispersion property.
2025-12-12 13:55:25 -08:00
Mathias Agopian
98cec207ce don't trigger an assert failure when getFenceStatus fails (#9511)
this is not an error that should warrant an assertion, since it's
possible for fences to not be supported at all.

FIXES=[467782111]

Co-authored-by: Powei Feng <powei@google.com>
2025-12-12 13:38:55 -08:00
Powei Feng
3ecdf71917 test: use backend NOOP for material tests 2025-12-12 13:04:17 -08:00
Powei Feng
ebba65e558 test: disable tests that tries to have a real backend 2025-12-12 12:40:06 -08:00
Powei Feng
177d23b3ac test: remove test_material_parser from CI
Seems to actually be initializing an engine

Failed with

reason: /Users/runner/work/filament/filament/filament/backend/src/opengl/platforms/PlatformCocoaGL.mm:177: failed assertion 'success == kCVReturnSuccess'
2025-12-12 12:19:39 -08:00
Powei Feng
cfd402f424 test: fix broken filament test again 2025-12-12 12:01:40 -08:00
Powei Feng
b7e492d674 test: fix missing dep filamat in test 2025-12-12 11:34:31 -08:00
Powei Feng
d7e0202f37 github: fix race condition for windows build (#9513)
A. Move filament_test_material.cpp to be part of test_filament
    (This won't be triggered during the windows build)
 B. Add chaining dependencies in third_party/draco/tnt so that
    there is no race in writing/reading generate.stamp

-------------
Failures
-------------
A.

C:\a\filament\filament\out\cmake-mtd\filament\test\resources\filament_test_resources.c(1,1): error C1083: Cannot open source file: 'C:\a\filament\filament\out\cmake-mtd\filament\test\resources\filament_test_resources.c': Permission denied [C:\a\filament\filament\out\cmake-mtd\filament\test\test_material_parser.vcxproj]

B.

CUSTOMBUILD : CMake error : Cannot restore timestamp "C:/a/filament/filament/out/cmake-mtd/third_party/draco/tnt/CMakeFiles/generate.stamp": Access is denied. [C:\a\filament\filament\out\cmake-mtd\third_party\draco\tnt\draco_compression_bit_coders.vcxproj]
2025-12-12 19:16:09 +00:00
Doris Wu
4227d04eb7 Add label for PlotLines calls (#9506)
Co-authored-by: Powei Feng <powei@google.com>
2025-12-12 16:32:41 +08:00
Powei Feng
272ed14737 github: fix brew dependency failure (#9512)
The failure is included below.  The reason for the failure is
because we caches ~/Library/Caches/Homebrew, but this might
present a mismatch with the latests homebrew.

We bump the cache version.

------------------------------------
failure
------------------------------------
Error: missing keywords: :date, :because
/opt/homebrew/Library/Homebrew/formula.rb:4631:in 'deprecate!'
/opt/homebrew/Library/Homebrew/formulary.rb:290:in 'block in Formulary.load_formula_from_json!'
/opt/homebrew/Library/Homebrew/formulary.rb:228:in 'Class#initialize'
/opt/homebrew/Library/Homebrew/formulary.rb:228:in 'Class#new'
/opt/homebrew/Library/Homebrew/formulary.rb:228:in 'Formulary.load_formula_from_json!'
/opt/homebrew/Library/Homebrew/formulary.rb:959:in 'Formulary::FromAPILoader#load_from_api'
/opt/homebrew/Library/Homebrew/formulary.rb:943:in 'Formulary::FromAPILoader#klass'
/opt/homebrew/Library/Homebrew/formulary.rb:524:in 'Formulary::FormulaLoader#get_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:1045:in 'Formulary.factory'
/opt/homebrew/Library/Homebrew/formula.rb:2447:in 'Formula.[]'
/opt/homebrew/Library/Homebrew/formula.rb:671:in 'block in Formula#versioned_formulae'
/opt/homebrew/Library/Homebrew/formula.rb:670:in 'Array#each'
/opt/homebrew/Library/Homebrew/formula.rb:670:in 'Enumerable#filter_map'
/opt/homebrew/Library/Homebrew/formula.rb:670:in 'Formula#versioned_formulae'
/opt/homebrew/Library/Homebrew/unlink.rb:9:in 'Homebrew::Unlink.unlink_versioned_formulae'
/opt/homebrew/Library/Homebrew/formula_installer.rb:1166:in 'FormulaInstaller#link'
/opt/homebrew/Library/Homebrew/formula_installer.rb:955:in 'FormulaInstaller#finish'
/opt/homebrew/Library/Homebrew/formula_installer.rb:905:in 'FormulaInstaller#install_dependency'
/opt/homebrew/Library/Homebrew/formula_installer.rb:816:in 'block in FormulaInstaller#install_dependencies'
/opt/homebrew/Library/Homebrew/formula_installer.rb:816:in 'Array#each'
/opt/homebrew/Library/Homebrew/formula_installer.rb:816:in 'FormulaInstaller#install_dependencies'
/opt/homebrew/Library/Homebrew/formula_installer.rb:569:in 'FormulaInstaller#install'
/opt/homebrew/Library/Homebrew/install.rb:493:in 'Homebrew::Install.install_formula'
/opt/homebrew/Library/Homebrew/install.rb:420:in 'block in Homebrew::Install.install_formulae'
/opt/homebrew/Library/Homebrew/install.rb:417:in 'Array#each'
/opt/homebrew/Library/Homebrew/install.rb:417:in 'Homebrew::Install.install_formulae'
/opt/homebrew/Library/Homebrew/cmd/install.rb:396:in 'Homebrew::Cmd::InstallCmd#run'
/opt/homebrew/Library/Homebrew/brew.rb:101:in '<main>'
2025-12-12 01:26:06 +00:00
Powei Feng
223a754200 Revert "[automated] Updating /docs due to commit 32fcc1a"
This reverts commit 27c268f865.
2025-12-11 17:09:26 -08:00
Powei Feng
af480a58c4 Reapply "build: improve build.sh for Android with documentation (#9500)"
This reverts commit 192738ecb9.
2025-12-11 17:09:20 -08:00
Powei Feng
192738ecb9 Revert "build: improve build.sh for Android with documentation (#9500)"
This reverts commit 32fcc1a81b.
2025-12-11 16:55:49 -08:00
Filament Bot
27c268f865 [automated] Updating /docs due to commit 32fcc1a
Full commit hash is 32fcc1a81b

DOCS_ALLOW_DIRECT_EDITS
2025-12-12 00:52:05 +00:00
Powei Feng
32fcc1a81b build: improve build.sh for Android with documentation (#9500)
- Fix Android build in build.sh so that the tools dir are
   properly set to corresponding folders for debug vs. release.
 - Update/consolidate documentation to explain the Android Studio
   workflow better.
 - Move documentation from outdated apps folder to BUILDING.md
2025-12-12 00:46:00 +00:00
Powei Feng
621eca340e matdbg/matinfo: add column labels for output (#9502)
- Identify the columns that are being printed out when using
   matinfo to print out a material
- Add constant of blank space offset
2025-12-11 23:56:16 +00:00
Powei Feng
ee6c8c3e76 vk: unconditionally enable systrace for group markers (#9501) 2025-12-11 09:09:38 -08:00
Powei Feng
dcf7621c35 Revert "[automated] Updating /docs due to commit d4efef9"
This reverts commit 6a8193ea80.
2025-12-10 12:16:51 -08:00
Filament Bot
6a8193ea80 [automated] Updating /docs due to commit d4efef9
Full commit hash is d4efef9a9b

DOCS_ALLOW_DIRECT_EDITS
2025-12-10 19:12:21 +00:00
Benjamin Doherty
d4efef9a9b Release Filament 1.68.1 2025-12-10 11:04:56 -08:00
yein
cdffc9eaa0 Allow embedding material source in cmat (#9484)
* Allow embedding material source in cmat
* Compress material string
2025-12-10 10:31:51 -08:00
Sungun Park
a162a65dce Add JobQueue (#9480)
JobQueue is a thread-safe producer-consumer queue, which will be used
for asynchronous operations.
2025-12-10 18:00:58 +00:00
Ben Doherty
369bab4744 Implement setPresentationTime for Metal (#9470) 2025-12-09 14:54:06 -08:00
Powei Feng
c98038b2d7 vk: remove precondition for createStreamNative (#9497)
Keep it's original behavior of no-op
2025-12-09 13:48:38 -08:00
yrcloud
849c4bb8c5 webgpu: manage a pool of staging buffers for updateGPUBuffer (#9486)
- only MapAsync the staging buffers that are not being used by any command anymore (the commands have finished executing on GPU)
- additionally, in WebGPUQueueManager, create a blank new submission state when a new command encoder is generated instead of in submit()

BUGS=450620535
2025-12-09 12:20:03 -05:00
Mathias Agopian
ee64322d76 improve the memcpy benchmark (#9490)
- remove the multi-threaded tests, they added too much noise
- added a memset test
- make sure we allocate the buffer aligned to 16KB
2025-12-08 21:23:51 -08:00
Mathias Agopian
79d65a768a Fix(FrameInfo): fix typos and endFrame logic (#9499)
When the frame history's circular queue is full and the oldest
frame is not yet ready to be processed, we must skip the current
frame.

This change ensures that if `beginFrame` is skipped, the
corresponding `endFrame` is also skipped. This prevents data
corruption in the frame history.
2025-12-09 01:17:42 +00:00
Doris Wu
37610dc8f3 Unify zstd dependency for basisu (#9493) 2025-12-09 01:00:38 +00:00
Mathias Agopian
2e31dc20e4 Fix(FrameInfo): Improve robustness of frame info history management (#9496)
Address potential issues in FrameInfoImpl and FrameInfoManager:
 - Modify FrameInfoManager::beginFrame to handle cases where the 
   circular queue is full and the oldest frame is not yet ready, 
   logging a warning and skipping the frame. 
   This prevents potential use-after-free or data corruption by 
   ensuring only ready frames are removed from the history.

FIXES=[466081317]
2025-12-08 15:28:58 -08:00
Mathias Agopian
ae3d98fb47 fix use-after-free of the EGL swapchain (#9495)
PlatformEGLAndroid holds onto the current swapchain in order to use
it when beginFrame is called. Usually the swapchain is set just before
beginFrame is called. However, that's not the case for standalone
views. These are independent of the swapchain and doing "swapchain
stuff" for them is nonsensical.

So make sure that:

1. PlatfromEGLAndroid doesn't hold onto a dangling pointer when the 
   swapchain is destroyed. And add proper null checks.
2. Don't do the "swapchain stuff" when beginFrame is called in the
   context of a standalone view.
   We now reserve frameID 0 for that purpose (meaning the frameid is
   non sensical for these).

We're currently relying on frameID to not wrap-around. At 120 fps, 
that's about 1 year. This will be addressed in a later PR.

FIXES=[462827028, 461399487]
2025-12-08 14:54:34 -08:00
rafadevai
a938a790fa VK: Do memcpy if the uniform buffer is WRITE_SHARED (#9491)
With UBO batching, the frontend guarantees that
doing a memcpy to the buffer if safe.
2025-12-08 17:52:53 +00:00
dependabot[bot]
71d556dddf Bump urllib3 in /docs_src/build in the pip group across 1 directory (#9494)
Bumps the pip group with 1 update in the /docs_src/build directory: [urllib3](https://github.com/urllib3/urllib3).


Updates `urllib3` from 2.5.0 to 2.6.0
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.6.0
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Powei Feng <powei@google.com>
2025-12-08 17:35:27 +00:00
Powei Feng
d61227b2fd material: remove checked-in .filamat for transform name test (#9487)
filament_test_material should not need to depend on a "fixed"
(or checked in) material.

Now the dependent .filamat is generated as needed as is
packaged with the checked-in test_material.filamat as before.
2025-12-07 00:39:41 +00:00
dependabot[bot]
612a6b00e4 Bump urllib3 in /test/renderdiff/src in the pip group across 1 directory (#9492)
Bumps the pip group with 1 update in the /test/renderdiff/src directory: [urllib3](https://github.com/urllib3/urllib3).


Updates `urllib3` from 2.5.0 to 2.6.0
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.6.0
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-06 16:21:41 -08:00
Ben Doherty
b3353b518c Metal: ensure framebuffer fetch is only used on macOS 11.0+ (#9481) 2025-12-05 13:39:52 -08:00
Patrick Ribas
0b44761d43 Allow PlatformEGLHeadless to load GLES (#9488) 2025-12-05 13:37:51 -08:00
yein
c7979e4023 update test materials to 68 (#9485) 2025-12-05 12:20:48 -08:00
Mathias Agopian
e00904e100 Update NDK version to 29 (latest) (#9489)
also 
- update the android build script to pull the version from 
  build/common/versions

- remove the ability to specify your own ndk version (this was
  undocumented and not fully implemented)

The NDK version now needs to appear in two place (unfortunately):
1. build/common/versions
2. build/android/build.sh
2025-12-05 11:29:02 -08:00
Sungun Park
96e2366569 Add config option for asynchronous mode (#9462) 2025-12-05 02:48:22 +00:00
Mathias Agopian
e76624862d don't use the -mcpu compiler flag (#9483)
`-mcpu` is intended to target a specific CPU instruction set and
optimization. That's not what we want to do here. What we want is
target an architecture, specifically armv8-a. So we use `-march` 
instead.  On 64 bits builds, we tune for cortex-a78, which is the
df the Pixel7 era. This doesn't mater much, but might give a little
boost on newer CPU cores. The idea here is that we care "less" about
older CPUs.
2025-12-04 11:29:19 -08:00
Powei Feng
c5c83a61d3 vk: fix spurious VK_ERROR_OUT_OF_DATE_KHR on swapchain resize (#9482)
Fixes #9476
Fixes #8604
2025-12-04 19:24:29 +00:00
Powei Feng
ccf0d6205f Fix a couple of CI errors (#9477)
- Make sure that renderdiff fails when either building or
   rendering fails (the previous problem was in the use of &&
   that masked the non-zero exit).
 - Make sure that golden branch is properly parsed in
   postsubmit.yml
 - Disable vk loader debug by default
2025-12-04 18:40:05 +00:00
Powei Feng
f482c1d702 Fix texture leak in ImGuiHelper on shutdown (#9479) 2025-12-03 14:48:56 -08:00
Vignan Jitta
a4c056e822 Fix Wayland window data invalidation in NativeWindowHelperLinux (#9461) 2025-12-03 19:27:07 +00:00
Evan Mezeske
f5071b2aae Set the minimum required Metal version (#9425) 2025-12-03 19:10:00 +00:00
Sungun Park
0fa13ee43d Fix race condition with garbage collection (#9465)
This change fixes an intermittent crash caused by a thread race
condition.

The crash happened when a CallbackHandler::Callback (triggered by
engine.flush()) attempted to create an instance of a Structure of Arrays
(SoA) like TransformManager, which adds items to SoA) at the same time
that the garbage collection job (FEngine::gc, which removes items from
SoA) was running.

This conflict is resolved by modifying the logic to ensure that the
garbage collection task completes synchronously before the callback
operations begin.
2025-12-03 16:14:39 +00:00
Doris Wu
1d2b8a08fa Refactor the API usage for UBO batching (#9443) 2025-12-03 21:54:30 +08:00
rafadevai
0c06744450 Cleanup code related to stream transform matrix (#9464)
Clean up all the code related to setting a transform
matrix for a stream.
2025-12-03 00:47:56 -08:00
Powei Feng
4ada29fbc3 Revert "Add flag to guard camera near/far assertion (#9472)"
This reverts commit 3a92cdab3a.
2025-12-02 20:58:12 -08:00
Filament Bot
76182231dd [automated] Updating /docs due to commit 8cd6915
Full commit hash is 8cd6915b9d

DOCS_ALLOW_DIRECT_EDITS
2025-12-03 00:20:02 +00:00
Powei Feng
8cd6915b9d Release Filament 1.68.0 2025-12-02 16:17:24 -08:00
Mathias Agopian
f90de26bc2 fix disable_gpu_frame_complete_metric flag (#9473)
- set the flag to true (metrics disabled) until downstream is ready
- make sure to exit the JobQueue thread before destroying it

BUGS=[464370498]
2025-12-02 15:02:52 -08:00
Powei Feng
cc2e661aab Update ImGui to 1.92.5 (#9463) 2025-12-02 22:42:35 +00:00
Powei Feng
3a92cdab3a Add flag to guard camera near/far assertion (#9472)
BUGS=465516676
2025-12-02 22:22:38 +00:00
Powei Feng
b367982c23 platform: fix PlatformEGLAndroid include (#9469)
Only need AndroidNdk (already included) and not AndroidNativeWindow
2025-12-02 21:46:48 +00:00
Sungun Park
a4f4dc617e Support null initialization for Invocable (#9466)
This allows for code like:

Invocable<void()> inv = []() { /*do something*/ };
inv = nullptr;
2025-12-02 21:29:14 +00:00
dependabot[bot]
2eb0f11d05 Bump werkzeug (#9467)
Bumps the pip group with 1 update in the /test/renderdiff/src directory: [werkzeug](https://github.com/pallets/werkzeug).


Updates `werkzeug` from 3.1.3 to 3.1.4
- [Release notes](https://github.com/pallets/werkzeug/releases)
- [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/werkzeug/compare/3.1.3...3.1.4)

---
updated-dependencies:
- dependency-name: werkzeug
  dependency-version: 3.1.4
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-02 18:39:19 +00:00
Doris Wu
6694df991c Use vector instead of unordered_set in FenceManager (#9458) 2025-12-02 13:44:27 +08:00
imadr
8b2bfa7e9d Fix build on windows when vulkan is not supported (#9439)
Co-authored-by: Sungun Park <sungunpark@google.com>
2025-12-02 02:22:38 +00:00
Serge Metral
7386220325 Stream API Vulkan Backend (#9164)
* Adding the begin frame message for later xtrace post processing.

* First commit

* This is not needed

* Bypass the AHB* issue.

* Typo: Forgot to remove the function.

* Typo: No const specifier.

* Removing the const.

* no exception

* Feedback from discussions with Powei.

* Making the changes discussed with the team.

* Removing useless comments.

* Adding the required methods for allocation.

* Forgot one more switch case.

* Moving the resource to –fvkmemory::Resource type.

* Adding streamed set.

* Allocating every frame for streamed textures.

* Changing the binding logic.

* Proper checks for the streamed texture.

* Cleanup.

* Chaning the logic of the state tracking for streamed textures.

* Fixed full screen bug.

* Refactoring of the code.

* Typo.

* GitHub feedback.

* Github feedback

* feedback.

* Typo

* Feedback.

* Feedback.

* Feedback

* Feedback

* Feedback

* Fixing the Android path.

* Fixing the Android path.

* Feedback.

* feedback

* Feedback.

* Nit

* Feedback

* Feedback

* Feedback

* vk: fix update after bind (wrt descriptor set) validation error

In filament, once a descriptor set is bound, we no longer make updates
to it. However, this guarrantee was broken in the external sampler/image
because a colorspace change might necessitate a layout change, and
thereby a new descriptor needs to be generated with the appropriate
externally sampled image updated in the new set.

Another use case is the Stream API, where each frame we might be
getting a different AHardwareBuffer, meaning we need to update one
or multiple sampler bindings in a set that might have been bound in
a previous frame.

In this change, we always create a new set when there's a change
in the image currently bound to an existing set (while accounting for
whether we need to use a new externally sampled layout or not).

* Removing the decision on whether to use external format or not out of the streamed texture manager. The issue is that all textures are external, not all are using external format. But it's more robust to let the external format image manager rely on the AHB* to decide if the format is external or not. Regardless (because the memory is external) we need to send this to the external image manager.

* Fixing the validation layer in the Stream CL.

* Typo and comment clarification.

---------

Co-authored-by: Powei Feng <powei@google.com>
2025-12-01 11:13:47 -08:00
Sungun Park
000faeaca7 Fix bindVAO for OpenGL (#9453)
Currently bindVertexArray call generates an object for the default VAO,
which is not originally intended.
2025-12-01 18:55:02 +00:00
Powei Feng
3f9783ac02 Bump MATERIAL_VERSION to 68 2025-12-01 10:28:23 -08:00
rafadevai
4e6dc67ae8 VK: Disable depth testing in some cases (#9455)
Depth testing come with a cost, so when the depth
test is marked to always pass and writting to depth
buffer is disable, just disable the feature.

This will also match the GL backend behavior.
2025-12-01 09:40:26 -08:00
Doris Wu
666140bb73 Fix ios x86 build (#9459) 2025-12-01 09:04:09 -08:00
Doris Wu
56050de5cd metal: implement memory mapping (#9454) 2025-11-27 11:05:07 +08:00
Mathias Agopian
772136decd fix a typo/bad merge that broke setPresentationTime (#9452)
FIXES=[462533574]
2025-11-21 11:40:17 -08:00
Powei Feng
f664601c51 android: add readPixels callback for ModelViewer (#9440) 2025-11-21 19:33:36 +00:00
Ben Doherty
f06b27b7fb Fix getter methods (#9450) 2025-11-21 00:37:28 +00:00
Mathias Agopian
ef53ce88d4 don't assume compositor and frame timing are always available (#9449)
- this is not true fro headless swapchains
- and potentially some timings might not be available on a given nativewindow

Previously the code would handle these errors gracefully, but the 
errors were still generated. Now, we query the availability and only
make the calls  if supported.

Also on EGL, we don't attempt to use private APIs -- this code path
should never be used anyways.
2025-11-20 15:32:02 -08:00
Mathias Agopian
ef18030e1a frameId must be monotonic in the SwapChain (#9447)
The frameId coming from a Renderer must be monotonic when seen from
a SwapChain (Specifically a ANativeWindow on Android), if it's not
the case, we must clear that part of the history.

This can happen if a SwapChain is used with two different Renderer; at
this point that SwapChain's history is no longer connected to that
Renderer.
2025-11-20 13:23:58 -08:00
Doris Wu
f07176c0a2 Try to fix test_UboBatching (#9448) 2025-11-20 15:14:19 +08:00
Doris Wu
15db141c7a Add some unit tests for UboManager (#9446) 2025-11-20 14:28:13 +08:00
Doris Wu
d4bbb7c591 buffer update opt: Some optimizations (#9438) 2025-11-20 00:52:04 +00:00
Sungun Park
92e620d2ad Simplify buffer object creation (#9436)
Simplify the buffer object creation logic to streamline and help make
the future integration of asynchronous features easier.
2025-11-19 22:03:05 +00:00
Mathias Agopian
311104da97 update google benchmark library to 1.9.4 (#9441)
* benchmark: update README and add update script

* update google benchmark library to 1.9.4

* update tnt CMakeLists to match the library new version
2025-11-19 11:50:34 -08:00
Filament Bot
3127632f96 [automated] Updating /docs due to commit 59f611b
Full commit hash is 59f611bfde

DOCS_ALLOW_DIRECT_EDITS
2025-11-19 19:32:56 +00:00
Sungun Park
59f611bfde Release Filament 1.67.1 2025-11-19 11:30:16 -08:00
Sungun Park
2d556bdca2 Workaround for screen space reflections artifacts fix (#9444)
This is a workaround for Samsung Galaxy S24 device failing to link this change.
ea608d409e
2025-11-19 19:03:00 +00:00
Ben Doherty
65e7dba8b8 Log GPU errors through Platform debugStat API (#9434) 2025-11-19 10:42:42 -08:00
Mathias Agopian
6550a63056 Fix android helper header usage (#9442)
These headers are private but were used by public headers. 
Refactor the platform code so that these headers stay private.

AndroidNdk.h is treated differently, it is now made public because
it simplifies a lot of things to be able to have the platform concrete
implementation derive from it.
2025-11-19 10:20:37 -08:00
Doris Wu
aa4e2c56b5 buffer update opt: Skip releaseFreeSlots when no frees are pending (#9437) 2025-11-15 10:23:27 +08:00
Powei Feng
aa4f1910b8 android: add static annotation for Utils.init() (#9435)
This allows for static call from java, e.g.:

```
static {
    Utils.init();
}
```
2025-11-13 22:01:49 +00:00
Mathias Agopian
223a4b18a8 Fix several problems with RenderPass descriptor sets (#9431)
The root of the problem is that in the main rendering loop we need
to set the correct per-view descriptor-set based on the material and
variants.

But we have two cases, either the descriptor set is always constant, 
which is the case with ssr, structure, shadows and postfx passes, or
it need to be dynamically changed based on the material & variant.

In the 2nd case, where was a problem where the postfx descriptor set
could be used, which is wrong (e.g. while rendering shadows we need
the shadow UBO, even with a postfx material), and would corrupt the
correct descriptor set, which would never be set back.

Another issue was related to running a custom command, it could 
change the state without updating the local copy, causing corruptions
or validation errors.

In this CL we:
- use the same descriptorsetlayout for both postfx and depth
- invalidate the state after a custom command
- only switch to postfx descriptor set in dynamic mode (color pass)


This fixes setChannelDepthClearEnabled() which could cause 
validation error, corruption or crashes.

FIXES=[459567258]
2025-11-13 12:07:16 -08:00
rafadevai
57ef534acd VK: Add support for getting pipeline creation stats (#9422)
* VK: Add support for getting pipeline creation stats

When debugging is pipeline compilation related hitches
is useful to know more information about what happened
when building a new pipeline.

By levering the VK_EXT_pipeline_creation_feedback
extension, we can know if the pipeline creation was
speed up because of a cache hit, how much time it spent
creating it and also the stats related to each
pipeline stage.

This is only available when using the debug flag
FVK_DEBUG_SHADER_MODULE.

* Fix the unused build error
2025-11-13 09:01:02 -08:00
rafadevai
719914fb84 VK: Better support for renderdoc captures (#9423)
Doing a renderdoc capture when using transient memory
or importing AHardwareBuffers into Vulkan, makes it fail,
crash or not replay properly.

To improve the capture support, added a new constant to let the
backend know when renderdoc is expected to be used and configure
things appropietly.

- In the case of transient attachments that uses lazy allocated
memory, it will be disabled.
- In the case of AHardwareBuffers, a more robust memory heap
selection algorithm will be used.

Also a new VulkanPlatform function will be added, to let other
subclasses know that the transient attachments are enabled or not.
2025-11-13 07:40:51 -08:00
Powei Feng
080f958da3 android: remove checked in asset (#9426)
For sample-gltf-viewer, an asset was checked into the source tree.
But other assets are generated or copied from asset directories.

We remove the checked in gltf and copy the asset over during
build (as with other existing files).
2025-11-13 06:29:45 +00:00
Doris Wu
7547aa3807 buffer update opt: Integrate UboManager into the engine (#9397) 2025-11-13 02:19:48 +00:00
Sungun Park
67a0c6e0e1 fix a typo in VertexBuffer (#9427) 2025-11-12 15:31:55 -08:00
Ben Doherty
37cb842993 Fix possible null string crash inside TextWriter (#9428) 2025-11-12 12:07:16 -08:00
Doris Wu
ad27d48fd3 buffer update opt: refactor UboManager and introduce FenceManager (#9418) 2025-11-11 16:56:06 +08:00
Mathias Agopian
3a503976c8 add View::getLastDynamicResolutionScale() (#9419)
* add View::getLastDynamicResolutionScale()

This method return the last dynamic resolution scaling factor used
by the view.

FIXES=[457753622]
2025-11-10 14:49:23 -08:00
Mathias Agopian
ce6fa82026 improve camera precondition checks and default state (#9420)
* improve camera precondition checks and default state

- Camera is now initialized with a default projection matrix with
left/right, top/bottom set to (-1,1) and near/far set to (0.1,1).

- setLensProjection() and setProjection(FOV) now check the near/far
precondition (near>0 and far>near).

- sanitize user's light near/far to avoid infs and nans during
  froxelization

- finally froxelizer asserts that near>0 and far>near on debug builds.

FIXES=[458030186]
2025-11-10 14:48:48 -08:00
Mathias Agopian
e8349ab5cc AndroidNativeWindow must also work on 32-bits architectures (#9424) 2025-11-10 14:44:52 -08:00
yein
4773fc4647 Move the include resolution functionality to matp (#9414)
* Move the include resolution functionality to matp

- matp::MaterialParser now has a function resolveIncludes that returns a pair of status and resolve string.
- all the include resolution classes are moved to matp private src.
- matp::resolveIncludes is renamed to matp::resolveIncludesRecursively and only used internally.
- added insertLineDirectives and insertLineDirectiveChecks in Config; add those in the CommandlineConfig.
- moved output format to public use.

Note: MaterialParser::resolveIncludes could take a includer instead of the materialFilePath, but i decided
to go with the materialFilePath because the most common use case is resolving from the file's directory.
This allows the parser to just create the default DirIncluder internally, and we don't need to expose it publicly.

* add const to the buffer param
2025-11-07 15:23:54 -08:00
Rafael Marinho de Araújo
d47a69a529 add overload of loadTexture that loads bitmap from ByteArray (#9416)
Co-authored-by: rma6 <rafaelmarinhoa@gmail.com>
2025-11-07 10:11:23 -08:00
Powei Feng
d3b74e96b4 vk: fix thread-safety wrt queryFrameTimestamps() (#9415)
queryFrameTimestamps() and queryCompositorTiming() are both
synchronous APIs, but VuklanSwapchain is not a thread-safe
ref-counted handle (i.e. fvkmemory::ThreadSafeResource). We move
the Platform::SwapChain* pointers to a thread-safe map that is
mapped by the handle id.
2025-11-07 18:00:01 +00:00
Mathias Agopian
209d3f7550 Fix a race condition when tearing down FrameInfo (#9413)
* HandleAllocator::deallocate() was unsafe

It needs to know the concrete type to call the proper destructor, so
if it was given a base type handle (e.g. Handle<HwFoo>) it would not
destroy it properly.

* add AsyncJobQueue::cancelAll()

* Fix a race condition when tearing down FrameInfo

It is actually invalid to destroy a Handle<HwFence> while inside
fenceWait().

Updated the HwFence implementations so that they don't pretend they can
handle being destroyed during fenceWait(), they can't.

FrameInfo now cancels all the pending callbacks and waits for the 
currently executing one to terminate, *before* destroying the
handles.

Reenable the gpuFrameComplete metric, as it should be working now.
2025-11-06 16:50:08 -08:00
Mathias Agopian
92e65cb3fd Properly use SDK 26+ APIs (#9417)
With minSDK less than 26, it's unsafe to use APIs in nativewindow.h 
that appeared at API 26 or more, even when using the weak symbol
technique. This is because pre 26, libnativewindow.h didn't exist and
therefore the build system cannot link against it.

Currently Filament's minSdk is 21, which means we should never use
nativewindow.h API after 26.

In this PR we chose the strategy at compile time; either the more
modern weak symbol or the old way with dlsym based on __ANDROID_API__.
2025-11-06 16:49:28 -08:00
Powei Feng
a4945939de vk: fix leaking swapchains again (#9410)
- Adjust order of destroy call in both headless and platform
   swapchains.  We need to be careful of the order due to
   assumptions made by the base class's destroy().
 - remove `=0` since VulkanPlatformSwapChainBase::destroy() has
   an implementation.

Fixes #9403
2025-11-05 22:10:05 -08:00
Benjamin Doherty
086760b307 Add missing mutex header 2025-11-05 15:35:29 -08:00
Powei Feng
ce1b63ce38 gltf_viewer: fix accidentally removed FilamentAppVulkanPlatform 2025-11-05 15:26:47 -08:00
Mathias Agopian
b7b8983653 add a feature flag for FrameInfo::gpuFrameComplete (#9409)
There are several race conditions caused by this feature. So we add
this flag and disable it by default, for now.
2025-11-05 15:22:43 -08:00
Powei Feng
d52fb1f4fd vk: refactor to use polymorphism for platform specialization (#9398)
We refactor VulkanPlatform so that getSwapchainInstanceExtensions()
and createVkSurfaceKHR() are virtual functions that are implemented
by each platform. This will enable the use of polymorphism for
platform-dependent bits.
2025-11-05 19:44:39 +00:00
Powei Feng
901c87761b gltfio: add null check for when image is not provided (#9407)
Fixes #9402
2025-11-05 19:26:24 +00:00
Benjamin Doherty
081fe6a434 Bump MATERIAL_VERSION to 67 2025-11-05 10:35:14 -08:00
Benjamin Doherty
b84c6ace8d Release Filament 1.67.0 2025-11-05 10:33:15 -08:00
yein
2113e04aba Support returning a .mat file from matc (#9399) 2025-11-05 10:17:55 -08:00
Doris Wu
84fdf36ed9 buffer update opt: New android sample for material instance stress test (#9396) 2025-11-05 03:24:56 +00:00
Doris Wu
dc1de994e0 buffer update opt: Initialize UboManager class (#9331) 2025-11-05 02:47:28 +00:00
Mathias Agopian
7c6479020e use choreographer to access the system's expected present time (#9393)
* use choreographer to access the system's expected present time

* more Android specific code into VulkanPlatformAndroid

* Fix race-condition between init() and terminate()

it was possible for the thread to not have been ready by the time
we call terminate.

* fix build and minor fixes
2025-11-04 14:17:50 -08:00
yein
a5f949d30c Move resolving #includes from MaterialBuilder to MaterialCompiler (#9374)
* Move resolving #includes from MaterialBuilder to MaterialCompiler, before parsing the material.

- resolving #includes was happening after parsing, now moving before parsing.
this is because we could offload this resolution at build time for RuntimeMaterialCompiler
- filamat::resolveIncludes used to have an assumption where the given text was already
a shader block. this assumption is now broken so it finds the line offset internally.
thus the line offset field is removed from IncludeResult.

* Move include related classes to matc
2025-11-04 14:14:43 -08:00
haroonq
6c867c692b Add flags for supporting externally defined dependencies. (#9355) 2025-11-04 13:36:01 -08:00
Benn Herrera
bd735fbab8 updated cgltf to 1.15 and broke out commands from README into utility script. (#9369) 2025-11-04 13:35:21 -08:00
Benn Herrera
b4c4ce9e17 Add Optional Inclusion of libwebp in Third Party Libaries (#9371)
* adds third_party/libwebp and cmake option to enable building it.

* disable simd and default disable pthreads for webgl builds.

* ensure non-empty config var value

* Added notes on libwebp change to NEW_RELEASE_NOTES.md

* Update NEW_RELEASE_NOTES.md
2025-11-04 13:34:57 -08:00
rafadevai
138cc55d3b Don't always associate transformName to a stream (#9404)
Before the transformName field was expected to be
used together with the stream API, that is not the
case anymore.

In the scenario that isn't using the stream API,
filament will try to associate the transformName
field to a stream that doesn't exist, causing a
crash.
2025-11-04 13:34:14 -08:00
Powei Feng
3d6db313bd vk: swapchain destroy must call through to base class (#9405)
Fixes #9403
2025-11-04 20:15:52 +00:00
Powei Feng
faa565c3ff vk: remove unused shaders (#9394)
The BlitDepth shaders were no longer referenced in the blit code
and hence are removed.
2025-11-04 17:45:57 +00:00
yrcloud
2a2caad1bf webgpu: use staging buffers for updateGPUBuffer (#9360)
BUGS=450620535
2025-11-03 17:28:59 -05:00
Anish Goyal
804ee87356 Check for null fences to avoid segfault in tests (#9389)
* Check for null fences to avoid segfault in tests

In some test environments, creating a sync or fence backed by an Android
fence returns null. In order to avoid NPEs, cover this scenario with a
null check.

* Address PR - add log statement

Log that native fences are not supported when unable to create a native
sync fence.
2025-11-03 19:28:15 +00:00
Filament Bot
f5c9d973dc [automated] Updating /docs due to commit 778cbe0
Full commit hash is 778cbe09d1

DOCS_ALLOW_DIRECT_EDITS
2025-10-31 22:25:27 +00:00
Powei Feng
778cbe09d1 build: allow building tools separately (#9384)
Building tools separately is necessary for the existing
cross-complation usecase.  We generalize this by introducing
two cmake vars that enable exporting and importing
prebuilt tools.

The intended usecase is to enable ASAN-built filament without
having to run ASAN-built matc (which is prohibitively slow).

build.sh has been modified to add a `-y` flag forprebuilding
tools.
2025-10-31 22:23:15 +00:00
Mathias Agopian
bf6c51bae6 Fix GLES2 UBO emulation (#9392)
The binding cache didn't take into account the UBO offset.

FIXES=[456802974]
2025-10-31 14:28:45 -07:00
Powei Feng
cb3933b349 Guard MonotonicRingMap.MonotonicityDeathTest with GTEST_HAS_DEATH_TEST (#9388) 2025-10-31 20:45:32 +00:00
Mathias Agopian
4e9d691d9d fix transparent picking (#9390)
FIXES=[456489383]
2025-10-31 13:39:31 -07:00
Mathias Agopian
fe5f8547f7 Add frame history support to the Vulkan backend on Android (#9386) 2025-10-31 13:13:48 -07:00
Powei Feng
3207c31721 renderdiff: disable webgpu + bloom due to flake (#9368)
WebGPU's rendering of bloom sems to be non-deterministic.  This
is not expected.  For now, we disable bloom+webgpu to avoid
hitting flakes in our CI.

This required a slight refactoring of the test configuration
parsing and execution scripts.

RDIFF_BRANCH=pf/renderdiff-disable-bloom-webgpu
2025-10-31 06:55:44 +00:00
Mathias Agopian
236d650ed7 Add display present time as well as compositor timings to FrameInfo (#9378)
* Use a custom, non-allocating map for frame ids

* use memory_order_relaxed for the id of heap allocated handles

* Added displayPresent time to FrameInfo

To do this, we added support for queryFrameTiming() to the backend,
as a synchronous API. Then FrameInfo uses it to update the
corresponding history entry.

displayPresent time can be used to detect "buffer stuffing", i.e.
when the GPU gets too much ahead of the display. Currently
the information is returned to the user only. Eventually filament will
make use of it to determine if a frame skip is mandated.

* API BREAK: rename frameTime to gpuFrameDuration

* FrameInfo now contains compositor timings

- the presentation deadline
- the refresh rate from the display
- the composition-display latency

* set FrameInfo data to INVALID if feature is not supported

report presentDeadline properly.
2025-10-30 15:33:26 -07:00
Mathias Agopian
294b79b321 vkWaitForFences() must be called with the read-lock held (#9385) 2025-10-30 15:31:05 -07:00
Ben Doherty
0dc392a760 Refactor Metal command buffer error logging (#9383) 2025-10-30 15:03:09 -07:00
Ben Doherty
06fa370491 Metal: support MSAA SwapChain flag (#9361) 2025-10-30 11:08:08 -07:00
Mathias Agopian
6fdd7398b6 fix a possible deadlock on exit (#9377)
The deadlock happened because FrameInfoManager needs to wait that all
fences have signaled before it can be destroyed. 

The fix here is simply to destroy the fence without waiting (for safety
we do wait after we destroy them).

This uncovered another problem where all backends didn't handle this 
correctly.

We now explicitly handle this when destroying a fence: we make sure it
unblocks all the waiters and returns an error.
2025-10-30 09:30:27 -07:00
Mathias Agopian
32a89a9017 Disable producer throttling on Vulkan (#9381)
This allows vkPresentKHR to not block.
2025-10-30 09:30:02 -07:00
Mathias Agopian
ddb2d89e6c creating a cubemap with mip levels was incorrect (#9382)
the miplevels where not specified with the correct size.
2025-10-30 09:29:33 -07:00
Mathias Agopian
ea608d409e fix artifacts with screen space reflections (#9380)
on mobile h/w, strong highlights generated by the lighting stages can
turn into +inf and eventually to NaN if more math is performed on them.
Some h/w will kill a while tile or even primitive when that happens,
resulting in strong visual artifacts.

We fix this by clamping to MEDIUMP_FLT_MAX.
2025-10-29 17:00:49 -07:00
rafadevai
494e454f38 GL: Fix importing non srgb using the external image API (#9343)
* GL: Fix importing non srgb using the external image API

When importing a non srgb AHB but setting the srgb as true,
makes the eglCreateImageKHR function to fail because it tries
to set the colorspace as srgb for non srgb formats.

Example:
createExternalImage(yuv_ahardwaredbuffer, /*sRGB=*/true);

The fix is to only make sure that flag is set to true
if the corresponding filament format requires sRGB and
false otherwise.

* Fix mapToFilamentFormat to return the correct srgb formats

* fix build error on android

---------

Co-authored-by: Serge Metral <sergemetral@google.com>
2025-10-29 15:50:03 -07:00
Filament Bot
a9bbb0bf3b [automated] Updating /docs due to commit 21c7fa6
Full commit hash is 21c7fa6253

DOCS_ALLOW_DIRECT_EDITS
2025-10-29 18:13:20 +00:00
Powei Feng
21c7fa6253 Release Filament 1.66.2 2025-10-29 11:09:30 -07:00
Powei Feng
df453dab89 webgpu: fix index buffer handle allocation (#9379)
Handle allocation was using HwIndexBuffer, which is much smaller
than WebGPUIndexBuffer. This can lead to memory corruption.
2025-10-29 17:27:38 +00:00
Powei Feng
629f35f5f7 gltfio: fix stack-use-after-free issue (#9376) 2025-10-29 06:50:34 +00:00
Powei Feng
6e93fc1b44 webgpu: fix two stack-use-after-free issues (#9375)
There are a few structs that are used as parameters in webgpu
calls that are scoped to the wrong block.
2025-10-29 04:38:27 +00:00
Doris Wu
379b63d11b buffer update opt: Add new API for getting uniform buffer offset alignment (#9347) 2025-10-29 11:29:31 +08:00
Mathias Agopian
bfd23fcb4f Use the new setProducerThrottling API (#9362) 2025-10-28 10:44:02 -07:00
Mathias Agopian
9c8aea115c editing a program in matdbg should not crash the target (#9373)
fix a couple assert in the OpenGL backend. these should not terminate 
the process when a program fails to compile, in MAT_DGB mode.
2025-10-28 10:42:48 -07:00
Powei Feng
ca038169c6 webgpu: fix FrameScheduled callback and test (#9370)
Fix the callback by using a shared_ptr to store the callback.
The same logic exists in all other backends.

Re-enable corresponding backend test for webgpu.

Remove viewport size check in beingRenderPass. There is no similar
check in other backends.
2025-10-28 16:16:24 +00:00
Powei Feng
0c5a0b3399 Revert "webgpu: fix FrameScheduled callback and test"
This reverts commit 896246ba7c.
2025-10-27 13:49:59 -07:00
Powei Feng
896246ba7c webgpu: fix FrameScheduled callback and test
Fix the callback by using a shared_ptr to store the callback.
The same logic exists in all other backends.

Re-enable corresponding backend test for webgpu.

Remove viewport size check in beingRenderPass. There is no similar
check in other backends.
2025-10-27 13:47:44 -07:00
Sungun Park
3021f8d0a2 Shared context support for GLX (#9359) 2025-10-27 17:33:16 +00:00
Powei Feng
9e437ea588 backend-test: fix clean up ordering (#9353)
Previously, Cleanup is scoped to the testing function, which will
go out of scope before BackendTest's destructor is called.  We
need to order the cleanup (destruction of resources) to after
the readPixels and previous commands are complete - which is
in the destructor of BackendTest.

Additionally, we need to cleanup before the destruction of the
driver.  This means we need to be able to order the destruction
of Cleanup (and not rely on RAII). This is done by having a
unique_ptr holding a Cleanup instance.
2025-10-27 17:04:15 +00:00
Filament Bot
556da0ed0b [automated] Updating /docs due to commit ee1921a
Full commit hash is ee1921ab3a

DOCS_ALLOW_DIRECT_EDITS
2025-10-24 22:20:19 +00:00
Benjamin Doherty
ee1921ab3a Update Sonatype link 2025-10-24 15:17:06 -07:00
Mathias Agopian
2b8fe35a70 new frame and compositor timing APIs for Platform (#9354)
* Add Compositor Timing APIs to Platform

These APIs are currently modeled after Android capabilities, but a lot of
the concepts are generic enough to map to other system with a compositor.

This adds Platfrom::queryCompositorTiming() which is currently only
implementd by PlaftormEGLAndroid. Vulkan and WebGPU will come later.
The functionality is implement via EGL, but a new NativeWindow
helper is provided to access the same data from non-EGL backends.
Also to be on the safe side, PlatformEGLAndroid reverts to using
the ANativeWindow if EGL fails.

This CL also cleans-up PlatformEGLAndroid to accomodate those changes.

* Add queryFrameTimestamps() API to Platform.

This API allows to query very precise timing information of
past frames on a given swapchain. This information is provided
by the Android framework via EGL or ANativeWindow (albeit
through private APIs).
Currently only implemented by PlatformEGLAndroid.
2025-10-24 18:03:38 +00:00
Mathias Agopian
624b05f838 cleanup PlatformEGL swapchain (#9349)
SwapChainEGL is now implemented more idiomatically. It has a
constructor that does the initialization. This allows subclasses
to be implemented properly and safely.

PlatformEGL::createSwapChain() now just constructs SwapChainEGL and
does nothing else, which allows a subclass of PlatformEGL to "add" to
the PlatformEGL swapchain, buy simply subclassing from it and
constructing it normally.

The SwapChain doesn't need to have a vtable because polymorphism
is handled by the concrete Platform implementation.

Here we also implement a no-op SwapChainEGLAndroid to show how easy
it is to extend the swapchain. This functionality will be used soon.
2025-10-24 10:41:10 -07:00
Filament Bot
8a23ed91c0 [automated] Updating /docs due to commit db477e0
Full commit hash is db477e0549

DOCS_ALLOW_DIRECT_EDITS
2025-10-24 16:51:10 +00:00
Powei Feng
db477e0549 docs: update remote UI (#9358)
- Also modify update script
   - Renamed to update_remote_ui
   - Repair path inside sciprt
 - Ensure update script is not copied over to /docs
 - Add requirements.txt (for python/pip dependencies)
2025-10-24 16:47:40 +00:00
Doris Wu
ef3c391978 buffer update opt: Add material instances stress test sample (#9345) 2025-10-24 03:04:00 +00:00
Powei Feng
4547b69ccc backend-test: fix breakages on linux (#9350)
- On webgpu, do not error on linux when we're building headless
   only (without platform support for surface).
- For test/backend/test.sh, enable path for building on
   Linux + 64-bit x86
2025-10-23 21:12:25 +00:00
rafadevai
326bc4c311 Fix comments for TextureSampler::setAnisotropy (#9357)
The default value for no anisotropy must be 1
instead of 0.
2025-10-23 11:14:33 -07:00
haroonq
44ceee1f90 Disable unsupported flags when compiling with GCC. (#9356) 2025-10-23 09:56:40 -07:00
Mathias Agopian
b646700ccc fix a rare swapchain leak in PlatformEGL (#9348)
If createSwapChain() fails, a SwapChain object is always returned
(this might itself be a problem, but we can address that later),
however in that case, destroySwapChain() would leak the EGLSwapChain
structure.
2025-10-22 10:25:20 -07:00
Powei Feng
6caf88d3aa github: add backend tests to presbumit (gl/vk) (#9344)
This commit enables running the backend tests for opengl and
vulkan on github CI. The script is located in test/backend.

We also add exceptions (SKIP_TEST) for the currently failing
tests.  Issues have been filed to track addressing these failed
tests.

We also disable a series of broken webgpu tests.
2025-10-22 10:21:55 -07:00
Doris Wu
8d6e8b8b3c buffer update opt: Add engine config for default shared Ubo size (#9340) 2025-10-22 03:48:18 +00:00
rafadevai
9da29e3ab7 Add new public API to query a sampler transform name field. (#9320)
* Add new public API to query a sampler transform name field.

This new API will let filament users query a Material object
the value of the `transformName` field of a specified sampler
parameter.

The transformName is an optional field, so if its not defined
by the user, it will return a nullptr value.

- A new test was added to test_filamat to validate the serialization.
- A new parameter was added to the test sandboxLit material to
validate the parsing a material with the new field.

* Addressing review comments

- Add java and js bindings for the new API
- Tests for querying the getParameterTransformName

* Use utils::ImmutableCString for transformName

* Updating release notes

* Review comments

* Addressing more review comments

- Fix comments
- For the java binding return an empty string when the
transform is not present.
2025-10-21 23:55:25 +00:00
haroonq
e60280e79d Add a FILAMENT_ENABLE_EXPERIMENTAL_GCC_SUPPORT cmake flag. (#9339)
Adds support for compiling filament libraries with GCC. Since GCC is not
officially supported, we prefer to disable warnings (incl. not treating
warnings as errors) rather than updating the code in order to compile
cleanly.

This flag is disabled by default.
2025-10-21 16:34:04 -07:00
Powei Feng
70db8e241b vk: use virutal methods in platform Swapchain implementation (#9337) 2025-10-21 21:21:13 +00:00
Filament Bot
7f43cf2f23 [automated] Updating /docs due to commit d3f4e91
Full commit hash is d3f4e91be2

DOCS_ALLOW_DIRECT_EDITS
2025-10-21 19:59:20 +00:00
Sungun Park
d3f4e91be2 Release Filament 1.66.1 2025-10-21 12:56:30 -07:00
Powei Feng
3602864c43 vk & webgpu: Fix timepoint overflow (#9342)
nanosecond is long long and `timeout` is uint64_t.  This creates
an overflow when timeout is too large (for example
timeout = std::numeric_limits<uint64_t>::max() when waiting
forver).
2025-10-21 12:51:26 -07:00
Sungun Park
ff3bd4dc4d Fix TSAN for VulkanAsyncHandles (#9338) 2025-10-20 19:21:14 -07:00
haroonq
b950598d11 Various fixes to support gcc compilation. (#9323)
* Add missing includes.

* Add parenthesis around operators to suppress compiler warning.

* Remove duplicate definition of is_supported_aux_t.

* Explicitly create descriptions.

* Remove usage of anonymous struct with non-trivially constructible members.

This is an error on some compilers (e.g. gcc).

* Remove unnecessary rvalue-reference on pointer type.

* Explicitly construct SamplerParams to suppress compiler warnings.

* Place attribute specifier before declaration.

* Remove usage of anonymous struct with a non-trivially constructible member.

Replace the `array` union member with an `operator[]` to provide similar
functionality.

Some compilers (e.g. gcc) do not support this non-standard use-case.

* Use same warning settings as main filament project.
2025-10-20 09:10:08 -07:00
Powei Feng
0e1e5fb381 renderdiff: disable SSR for transmission (#9336)
SSR is not required for transmission tests, and it seems to be
flaky.

RDIFF_BRANCH=pf/renderdiff-disable-transmission
2025-10-17 13:51:35 -07:00
Filament Bot
40d533ada1 [automated] Updating /docs due to commit b6df2b9
Full commit hash is b6df2b9b35

DOCS_ALLOW_DIRECT_EDITS
2025-10-17 06:20:51 +00:00
Powei Feng
b6df2b9b35 renderdiff: add transmission and ssao tests (#9232)
- Add transmission and ssao tests
 - Small mods to README.md
 - Add transmission models to gltf list
 - Change focal length to zoom in for more details

RDIFF_BRANCH=pf/renderdiff-add-transmission
2025-10-16 23:17:07 -07:00
Powei Feng
c379b31267 webgpu: fix picking (#9318)
Context:
 - Picking has switched to use integer textures and this texture
   is meant to have only RG components (#8917).
 - WebGPU only supports 4 component textures, and so we need to
   to a blit-based transform to turn 2 components into 4.
 - WebGPUBlitter supports only float textures

In this commit, we add support for integer textures to
WebGPUBlitter. In doing so, we refactor parts of the shader
construction code in the blitter class and introduce a couple
helper functions for texture formats.

This fixes picking (verifiable with gltf_viewer)

Co-authored-by: Ben Doherty <bendoherty@google.com>
2025-10-17 04:44:12 +00:00
Powei Feng
b03909c07a github: add hash id to commit message action (#9334)
We add the commit hash as output of get-commit-msg
2025-10-17 04:05:52 +00:00
Doris Wu
712c03b17b buffer update opt: Add uniform batching option for Material Instances (#9324) 2025-10-17 00:22:00 +00:00
Mathias Agopian
9dae0748d5 update perfetto sdk to 51.2 and add update script (#9335) 2025-10-16 16:00:25 -07:00
Powei Feng
fa02a7fa3b backend: add two command line arguments to backend test (#9329)
`--headless_only`
Headless-only mode indicates that we will only use headless
swapchains.  This is particularly useful if we want to test in
a CI (continuous integration) environment.

`--ci`
Having CONTINUOUS_INTEGRATION as an OS will allow us to have
CI-only temporary exceptions. Though it's expected that some
exceptions will be unfixable and will remain as workarounds.
2025-10-16 18:54:38 +00:00
Powei Feng
a068d3df79 github: fix get-commit-msg (#9330)
If we assign the message (which might contain quotes) to an
environment variable and then echo it, this should prevent the
problem of having a double quote (").

Also fix a problem in docs script for checking TAGs in commits.
2025-10-16 11:33:12 -07:00
Powei Feng
f64c087ffe backend: fix mapped buffer test for vk (#9328)
The descriptor set needs to be rebound when rendering two
separate render passes.
2025-10-16 06:26:51 +00:00
Doris Wu
9561137d53 buffer update opt: Change to use feature flag instead of engine flag (#9327)
* Revert "buffer update opt: Add a flag to guard the feature (#9322)"

This reverts commit 49c4a5d62c.

* Update feature flags

* feedback

* Update naming
2025-10-16 07:13:30 +08:00
Powei Feng
d0efda21ad webgpu: fix deadlock for readPixels (#9319)
To enable the readPixels callback to be called, we need to make
move to 'AllowSpontaneous' mode in order to not have to call
Instance::ProcessEvents() to force process the callback.
2025-10-15 11:11:05 -07:00
Mathias Agopian
a5b047f93d fix matc's -l option (#9321)
MaterialParser did the feature level check (-l) too early, before the
material was parsed, so -l0 would always fail.
2025-10-15 09:42:19 -07:00
Doris Wu
06c4ed4e6b fix: material sandbox scene crashes during shutdown (#9325) 2025-10-15 15:34:50 +00:00
Doris Wu
49c4a5d62c buffer update opt: Add a flag to guard the feature (#9322) 2025-10-15 23:14:53 +08:00
Doris Wu
c757cc3629 buffer update opt: Introduce BufferAllocator and its tests (#9304)
* Introduce AllocationStrategy and its tests

* feedback

* feedback

* Add stress test

* Fix the build

* Minor fix

* Rename the class

* Rename

* Make const
2025-10-15 06:25:42 +00:00
rafadevai
dbdf8f672b GL: Check if GL_EXT_texture_filter_anisotropic in supported in GLES (#9317)
In GLES the anisotropic filtering featuring is always
disabled even in the cases where is supported by the hardware
because the check for the extension is missing.
2025-10-14 23:03:25 -07:00
Filament Bot
54bd888374 [automated] Updating /docs due to commit b7dea28
Full commit hash is b7dea28cc5

DOCS_ALLOW_DIRECT_EDITS
2025-10-14 21:28:53 +00:00
Benjamin Doherty
b7dea28cc5 Release Filament 1.66.0 2025-10-14 14:25:20 -07:00
Benjamin Doherty
9aa8e7780b Fix NEW_RELEASE_NOTES 2025-10-14 14:24:52 -07:00
Ben Doherty
271e639abe Revert "Make check-headers test use c++20" (#9316) 2025-10-14 14:12:34 -07:00
Ben Doherty
082a79eebc Fix, revert to C++17 string_view constructor (#9315) 2025-10-13 15:01:40 -07:00
Ben Doherty
7a10c09954 Fix, Abseil compilation error with StaticString (#9314) 2025-10-13 15:01:39 -07:00
Filament Bot
3139a37cc7 [automated] Updating /docs due to commit f8e8c27
Full commit hash is f8e8c27c04

DOCS_ALLOW_DIRECT_EDITS
2025-10-13 19:56:08 +00:00
Mathias Agopian
f8e8c27c04 Add a Renderer API to force skipping frames (#9313)
* Add a Renderer API to force skipping frames

Renderer::skipNextFrames(size_t) can be used to force filament to
pretend the next N frames must be skipped. This is mostly useful for
debugging.

* Add DebugOptions to Settings

We still need to move the "Debug" features of gltf_viewer to this,
but this give us a framework to do it. 
Currently there is one debug option that allows to set a number of
frames to skip.

ViewerGui propose a button to skip 10 frames using this framework

* Update libs/viewer/src/Settings.cpp

Co-authored-by: Powei Feng <powei@google.com>

* Update libs/viewer/src/Settings.cpp

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2025-10-13 12:52:17 -07:00
Mathias Agopian
c79d695ffb fix wasm build. (#9312)
The new AsyncJobQueue can't work with wasm, which doesn't support 
threads.
2025-10-13 12:18:28 -07:00
David Neto
ad6f6cf149 filamat: remove call to Glslang's SPIR-V remapper (#9310)
The Glslang SPIR-V remapper was removed, and replaced by the CanonicalizeIds
pass in spirv-opt.  See https://github.com/KhronosGroup/SPIRV-Tools/pull/6174

Filament's GLSL post-optimization algorithm already runs CanonicalizeIds.

Bug: b:450891564
2025-10-13 09:46:07 -07:00
Mathias Agopian
8506e94f10 Improvements to FrameInfo (#9293)
* fix a possible deadlock in AsyncJobQueue

drainAndExit() could get stuck because it waited for the job
queue to be empty, but that was not signaled.
in fact, drainAndExit() didn't need to do that.

* Improvements to FrameInfo 

- return the GPU Complete timestamp
- return the app VSYNC timestamp
- works TimerQueries are not supported

The VSYNC time is just a convenience as it is the same value
provided by the application during Renderer::beginFrame() or via
Renderer::setVsyncTime().
2025-10-10 21:40:28 +00:00
Mathias Agopian
5db8e0b9ab fix a regression in FMaterial::setConstant() (#9308)
it used to return false when setting the same value for the constant,
which other code used to invalidate the material or not. but it
was recently changed to always return true on success.

this reestablish the previous behavior.
2025-10-10 12:43:32 -07:00
Powei Feng
da55574b32 webgpu: refactor blitter to use struct as keys (#9300)
Using struct as keys simplifies the parameter definitions of the
relevant pipeline, pipelinelayout, shader module methods. This
enables adding or removing fields without adding major changes
to method definitions.

Using utils::hash::MurmurHashFn also aligns with the style of
the rest of filament.
2025-10-10 17:31:47 +00:00
yein
736fed00b3 handle StatusCode::UNSUPPORTED in << operator (#9307) 2025-10-10 00:06:57 +00:00
Evan Mezeske
9b200fc33a Some trivial changes to compile under most recent MSVC as a CMake sub-project (#9275)
* Add a workaround for Filament's breaking change to add_subdirectory for Abseil, see: https://github.com/google/filament/issues/8611

* Fix #pragma warning syntax for MSVC

* Only search for an external Abseil dependency if a new option FILAMENT_USE_EXTERNAL_ABSL is set
2025-10-09 23:06:18 +00:00
yein
fa436f1d12 Make JsonishParser use utils::Status (#9302)
* Make JsonishParser use utils::Status

- add unsupported error in utils::Status
- add invalid case in the test

* return a pair of Status and string in resolveEscapes;
use initializer list for JsonishString and move that to the header.
2025-10-09 15:44:03 -07:00
Powei Feng
837b2715a0 Update MATERIAL_VERSION to 66 2025-10-09 11:29:16 -07:00
Jordan Rupprecht
1a04312986 Add missing #include <ios> (#9305)
This is needed to instantiate `std::streampos`. It currently relies on transitive header inclusion to get that, which is going away for libc++ in ebcf1bf2ec.
2025-10-09 10:24:00 -07:00
Filament Bot
a89711b006 [automated] Updating /docs due to commit 6d061b5
Full commit hash is 6d061b5d01

DOCS_ALLOW_DIRECT_EDITS
2025-10-08 20:04:04 +00:00
Powei Feng
6d061b5d01 renderdiff: add two params to local_test.sh (#9301)
- --no_rebuild will skip building the gltf_viewer again
 - --num_threads will limit the number of threads used in running
   the rendering test.

Both of these options are meant for debugging locally.
2025-10-08 13:01:09 -07:00
Powei Feng
53ddb3dd1c renderdiff: [viewer] enable frontend to be used with runID (#9277) 2025-10-08 18:36:30 +00:00
Powei Feng
c7b0a7f441 webgpu: fix queue submission and fence (#9299)
- Add WebGPUQeuueManager to manage queue submissions
 - The manager will keep a "last status" field that will track
   the status of the last submission.
 - Any created HwFence will be associated with a status object.
 - The object updates in a callback that indicates that the
   submitted workfload has been completed.
2025-10-08 17:30:19 +00:00
Filament Bot
d7b44a2585 [automated] Updating /docs due to commit caf886d
Full commit hash is caf886df6b

DOCS_ALLOW_DIRECT_EDITS
2025-10-07 22:58:22 +00:00
Powei Feng
caf886df6b Release Filament 1.65.4 2025-10-07 15:54:13 -07:00
Sungun Park
287984dd7f gl: Enable shared contexts for Windows (#9298)
This change addresses a platform-specific issue on Windows where shared
OpenGL contexts must be created on the same thread as the primary
context.

To resolve this, we now pre-create a pool of shared contexts when the
driver is initialized. These contexts are then distributed to other
threads as needed, ensuring shared context creation requirement on
Windows. This allows us to be able to use THREAD_POOL mode for shader
compiler service on Windows. So Windows build uses THREAD_POOL mode
instead of ASYNCHRONOUS mode as of this change.

This change also refactors the shader compiler service to catch and
report errors in the same thread where the program compilation and
linking actually performed as it's the correct way to use shared
contexts. Otherwise it may crashes.
2025-10-07 19:30:42 +00:00
Powei Feng
3294bb64a5 Revert "Make matc workarounds default to NONE again" (#9295)
This reverts commit d11a6b4467.

Breakage detailed in following bug

BUGS=449740720
2025-10-07 18:50:34 +00:00
yein
f52476a323 Use utils::Status in MaterialParser (#9285)
* Use utils::Status in MaterialParser

* Use utils::sstream instead of std::stringstream

* Remove remaining std::cerr and dep; update MaterialParser::reflectParameters

* make error message in utils::Status more generic

---------

Co-authored-by: Powei Feng <powei@google.com>
2025-10-07 11:27:11 -07:00
Powei Feng
c839915a00 Add missing optional include for MaterialParser (#9296) 2025-10-06 22:50:02 -07:00
Mathias Agopian
2deafc6b81 fix matc -E (preprocessor) option (#9292)
this option was ignored and treated as -O0.
2025-10-03 20:15:05 -07:00
Powei Feng
fdec0f79a2 renderdiff: [viewer] fix magnifier (#9290)
- Fix the magnifier positioning for both compare and standalone
   mode. Simplified a lot of the logic and streamlined passing
   of states between components.
- Slight css adjustments
2025-10-03 21:44:53 +00:00
Mathias Agopian
31d66002a9 optional per-channel depth clear (#9287)
- increase the number of channels from 4 to 8
- new api on View to enable per-channel depth clear
FIXES=[447648764]
2025-10-03 14:25:02 -07:00
Mathias Agopian
f2ed382cf1 New ImmutableCString string class (#9291)
ImmutableCString is a string class similar to CString except it's
immutable. ImmutableCString occupies 16 bytes instead of 8 for CString.

However, ImmutableCString is able to avoid memory allocation when
constructed from a string literal, and in that way it us similar
to StaticString.

ImmutableCString can be auto converted from StaticString.

The backend tag tracking is updated to use ImmutableCString and
the FrameGraph resource manager us updated to use StaticString.

Together these changes significantly cut down heap allocations due to
internal tagging.


We also add optional tracking to {Immutable}CString.
2025-10-03 14:23:36 -07:00
yein
a4746eab0c Minor changes in utils::Status (#9288)
* Minor changes in utils::Status

- << operator doesn't have to be friend
- simplify getErrorMessage to not use strlen internally

* Replace std::ostream to utils::io::ostream
2025-10-03 12:53:46 -07:00
Filament Bot
0b011fae7d [automated] Updating /docs due to commit a6c9922
Full commit hash is a6c9922d33

DOCS_ALLOW_DIRECT_EDITS
2025-10-03 18:40:22 +00:00
Eliza
a6c9922d33 internal: fix some editor indentation rules (#9289)
* internal: fix some editor indentation rules

* internal: update CODE_STYLE.md
2025-10-03 11:38:01 -07:00
Eliza
7fe1ee3fd5 utils: RefCountedInternPool/RefCountedMap (#9284)
* utils: RefCountedInternPool/RefCountedMap

First, introduce RefCountedInternPool, a reference counted intern pool of
Slice<const T>. Just acquire() a slice that you want and you're guaranteed to
get exactly one canonical value-equal Slice<const T> back.

Additionally, introduce the concept of NullValue to RefCountedMap. A NullValue
defines what should be considered an uninitialized value; by default, it's the
default value of that type (0 for ints, nullptr for pointers, etc). This allows
us to lazily-initialize values in the map. A client can acquire() a bunch of
different resources which will be initialized only when get(factory) is called.
If a client attempts to get() a value without specifying a factory, and the
value is not initialized (i.e. equal to NullValue{}()), RefCountedMap will
panic.

* utils: add unit tests for ref-counted collections

* utils: remove C++20 features, fix memory issue

* utils: remove RefCounted from InternPool
2025-10-03 11:21:02 -07:00
Eliza
075726db8b engine: change spec constants to simple list (#9283)
* engine: change spec constants to simple list

For a shader program cache to be keyed on the set of spec constants that a
program has set, we need to know full exact list of constants, including their
default values. If we're going to always hold a list of all constants all the
time, then we may as well store them as a simple list where each index is the ID
number of the spec constant.

As part of this change, we now write the default values of spec constants into
the material file metadata.

* fix indent

* engine: fix sRGB swapchain emulation
2025-10-02 23:48:11 +00:00
Mathias Agopian
b22ff3bebb fix exceptions (#9281) 2025-10-02 16:22:01 -07:00
Sungun Park
bc794bbf7b Fix public headers check on github (#9286) 2025-10-01 23:36:26 -07:00
Sungun Park
9c29c3d192 Fix memory leaks for xlib (#9282)
This change frees memory returned by `glXGetFBConfigs` and
`glXChooseFBConfig` using `XFree`.
2025-10-01 23:09:55 +00:00
Eliza
8e5dabfa8e utils: split Slice into mutable and constant types (#9276)
* slice: fix memory semantics

* slice: prefer passing slice by value

This lets us do nice things like coercing Slice<T> to Slice<const T>, etc.

* slice: fix unit tests

* slice: fix copy/assignment, hash function

Don't attempt to define a copy constructor/assignment operator which would
convert a constant type to a mutable type.

Additionally, fix the hash function such that we're hashing U instead of const
U.
2025-10-01 22:40:50 +00:00
Mathias Agopian
e974989a95 new utility AsyncJobQueue (#9278)
* new utility AsyncJobQueue

this is a very simple job queue, it spawns a thread and runs the jobs
pushed to the queue in sequence.

* use AsyncJobQueue in OpenGLTimerQuery
2025-10-01 14:54:34 -07:00
yein
057ce2ea4b Introduce utils::Status (#9279)
* Introduce utils::Status

* Replace std::string with utils::CString in utils::Status

* Update unit tests
2025-10-01 14:53:51 -07:00
Martin Valgur
2e920f2780 Fix an invalid USE_EXTERNAL_GLES3 define (#9280)
Should be FILAMENT_USE_EXTERNAL_GLES3 to match its usage in code.
2025-10-01 10:59:55 -07:00
Mathias Agopian
b41e6dfd5c fix several issues CircularQueue (#9271)
- pop_back() didn't call the object's dtor
- added a dtor so objects can't be leaked
- made it moveable but not copiable
- added unit tests
2025-09-30 16:06:58 -07:00
Filament Bot
8413c84284 [automated] Updating /docs due to commit 10e63bf
Full commit hash is 10e63bf2cf

DOCS_ALLOW_DIRECT_EDITS
2025-09-30 21:44:09 +00:00
Powei Feng
10e63bf2cf renderdiff: [viewer] add Run ID as a way to pull artifacts (#9272)
The viewer supports pulling artifacts based on PR number, and now
we support providing Run ID as an alternative to identify the
renderdiff run on Github CI.
2025-09-30 21:32:36 +00:00
Filament Bot
73ba8fc753 [automated] Updating /docs due to commit f07a44e
Full commit hash is f07a44eb15

DOCS_ALLOW_DIRECT_EDITS
2025-09-30 18:53:20 +00:00
Sungun Park
f07a44eb15 Release Filament 1.65.3 2025-09-30 18:50:39 +00:00
Sungun Park
3dc3c78901 Support C++17 for RefCountedMap (#9274)
Some of our users are sticking to C++17 for a while.
2025-09-30 11:45:51 -07:00
Sungun Park
db099033e8 Fix compile issues (#9273) 2025-09-30 10:48:35 -07:00
lyriccoder
14a460961c Signal handler calls non-async-safe function (std::cout) (#9227)
In the current implementation, the function std::cout is used inside a                                                                                                                                                                signal handler. This is problematic because std::cout is not
async-signal-safe. According to POSIX standards, only a small set of
functions are guaranteed to be safe when called from signal handlers,
and std::cout is not one of them. Using non-async-signal-safe functions
inside signal handlers leads to undefined behavior and can cause
crashes, deadlocks, or other unpredictable issues.

By making these changes, we avoid undefined behavior and ensure the
program can handle signals safely.
2025-09-30 00:23:09 -07:00
Mathias Agopian
b467690ac7 new fenceWait() API in the backend (#9267)
* new fenceWait() API in the backend

* correct implementation of fenceWait() for GL and WebGPU

- fenceWait() now works correctly if called before the fence is
  created on the backend side

- the STL's condition wait_for() is actually a wait_until, which
  means we have to make sure now() + timeout doesn't overflow.

- also we make sure to keep a reference to the fence internal state
  while we wait so that we're safe if it's destroyed during that time.

* Implement fenceWait() properly on vulkan


On Vulkan, unfortunately, the implementation is complicated, as we
need three levels of "wait".

First we need to wait using a mutex/condition that the shared fence
is created (this is because on vulkan, all HwFence share the same
"state" associated to the same command buffer).

Once we have that, we need to wait for the VkFence to be submitted,
this is done using a read/write lock and condition variable. The
read/write lock is not needed at this stage, but in the next.

Once the fence is submitted, we can now wait using vkWaitForFences,
however, external host synchronization is needed. Multiple 
vkWaitForFences can be issued together (and use the read lock), but
must be mutually exclusive with vkResetFences and vkQueueSubmit.
By construction, we know that this can't happen during vkQueueSubmit
due to the "2nd level" of wait, however we need to prevent
simultaneous calls to  vkResetFences, this is done using a write lock.

By construction, we're guaranteed that when vkResetFences is called,
the fence has signaled, we just need to wait for all vkWaitForFences to
return.

A side effect of this change is that fenceGetStatus() has a better
implementation, since it's just a wait with timeout of 0.

* Update filament/backend/src/vulkan/VulkanDriver.cpp

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2025-09-29 13:09:43 -07:00
Mathias Agopian
b02bb0eaf6 assert sampler function only when it's not NONE.
FIXES=[437172017]
2025-09-29 13:08:54 -07:00
Sungun Park
436dffcbb3 Fix a crash for MaterialCache
The parser object was accessed to generate a key after being passed to
the lambda using std::move(). This led to a crash on certain platforms
(at least on Windows).

This change fixes it by creating key first before moving the parser
object into the lambda.
2025-09-27 00:03:32 -07:00
Mathias Agopian
95935b38bc enable timer queries on Mali drivers known to be good
FIXES=[273759031]
2025-09-27 00:02:09 -07:00
Powei Feng
0fa3de5ac7 renderdiff: add magnification glass of rendering (#9265)
- Show magnifying glass when diffing between two images
- Add checkbox to enable or disable feature
2025-09-27 00:19:26 +00:00
Powei Feng
d8e8aafad7 vk: fix VulkanPlatform CString usage (#9266) (#9260)
Since #9259, CString in VulkanPlatform fall into the literal
constructor path. But we really want the null-terminated
(char const*) path.  So we cast the strings to (char const*)
to enforce null-teriminated behavior.

RDIFF_BRANCH=pf/renderdiff-add-tolerance
2025-09-26 23:42:56 +00:00
Powei Feng
33a4ab3d88 vk: fix VulkanPlatform CString usage (#9266)
Since #9259, CString in VulkanPlatform fall into the literal
constructor path. But we really want the null-terminated
(char const*) path.  So we cast the strings to (char const*)
to enforce null-teriminated behavior.
2025-09-26 15:37:33 -07:00
rafadevai
bcaf5e9da5 VK: Allow memcpy of vertex/index static buffers in UMA (#9258)
* VK: Allow memcpy of vertex/index buffers in UMA

- Renamed VulkanBufferUsage to VulkanBufferBinding
to avoid confusion with the BufferUsage enum.
- In UMA all buffers are persistently memory mapped.
- In the case of static buffers that are memory mapped
use memcpy directly to update their contents.

* PR Comments
2025-09-26 14:07:00 -07:00
Mathias Agopian
98f8c93950 in-place CString replace when possible 2025-09-26 08:07:55 -07:00
Mathias Agopian
d11a6b4467 Make matc workarounds default to NONE again 2025-09-25 16:37:50 -07:00
Mathias Agopian
91d4e0e688 Workaround a rendering corruption on Mali
The corruption seems to be triggered with a combination of using:
- spirv-opt
- RGBA16F (as opposed to e.g. RGBA8)
- framebuffer_fetch

In this CL we disable framebuffer_fetch for drivers we know have the
issue.

FIXES=[445721121]
Fix #7794
2025-09-25 16:37:50 -07:00
Mathias Agopian
8af1cb3489 fix build warning (#9263) 2025-09-25 16:37:24 -07:00
Filament Bot
456ae4cabe [automated] Updating /docs due to commit f233b20
Full commit hash is f233b20427

DOCS_ALLOW_DIRECT_EDITS
2025-09-25 21:20:43 +00:00
Powei Feng
f233b20427 renderdiff: add a filter option for local testing (#9257)
This option will allow for rendering and comparing a single
image or files that match a wildcard-style string.

README.md has been updated
2025-09-25 21:18:35 +00:00
Mathias Agopian
a1b825b5b4 performance improvements to CString (#9259)
- make sure CString("foo") calls the literal constructor
- avoid memory allocations when comparing to a literal
2025-09-25 13:57:53 -07:00
Powei Feng
f9beffe3dc vk: add pool for VkSemaphore for re-use and lifetime tracking (#9254)
- Add a VulkanSemaphore ref-counted class to track the references
   of a semamphore - i.e. in a command buffer or in a present.
 - Add a VulkanSemaphoreManager class to keep a pool of
   VkSempahores for better re-use.

This fixes a validation error where we were re-using a semaphore
that is associated with a command buffer while its being used
in a present (as a wait signal).
Error ris VUID-vkQueueSubmit-pSignalSemaphores-00067
2025-09-25 13:39:25 -07:00
Mathias Agopian
db96b262a2 fix another matdbg build breakage (#9255) 2025-09-24 23:13:10 -07:00
Eliza
c0ab447ef7 material cache: address comments (#9253)
* material cache: address comments

* material cache: simplify CRC32 comparison

* material cache: == if same address

* material cache: use plain type for cached crc32
2025-09-24 17:00:14 -07:00
rafadevai
855a8f0b49 Refactor backend getShaderLanguage functions. (#9204)
Allow returning a list of supported shader languages
instead of only one.

Notify the backend which is the preferred language.
In the case of metal, the preferred language will be
the first element in the list.

This change will allow a backend to support multiple
languages as needed, in the case of the noop driver,
it will support a material with any shader languages.
2025-09-24 16:23:42 -07:00
Mathias Agopian
9c455e856d Fix matdbg build 2025-09-24 14:36:55 -07:00
Filament Bot
009de921e2 [automated] Updating /docs due to commit 7663ca8
Full commit hash is 7663ca8dfe

DOCS_ALLOW_DIRECT_EDITS
2025-09-24 18:55:45 +00:00
Powei Feng
7663ca8dfe Release Filament 1.65.2 2025-09-24 11:53:16 -07:00
Powei Feng
ee51c054b9 gl: disable fb fetch for llvmpipe (#9240) 2025-09-24 11:47:19 -07:00
Mathias Agopian
884b7590cb Update remote UI (#9247) 2025-09-24 09:53:49 -07:00
Powei Feng
decf316802 Make check-headers test use c++20 2025-09-23 21:28:37 -07:00
Eliza
5516cd92e7 materials: introduce MaterialCache (#9205)
* materials: introduce MaterialCache

Presently, Filament Materials are instantiated by first parsing a bunch of
read-only data from a material file, then applying a bunch of options from its
Builder before settling on a final, immutable Material object. If two different
Material instances need to be parameterized differently, e.g. setting their spec
constants independently, each has to do all of these steps independently for
each variation.

This change introduces two new concepts: MaterialDefinition, representing the
deserialized, read-only state of a material file, and MaterialCache, a
reference-counted system responsible for managing the lifetimes of
MaterialDefinitions. Now, each Material asks the cache if a MaterialDefinition
exists for the particular UUID of the data it's trying to read; if not,
MaterialCache creates a new entry transparently. If a hundred different
Materials all try to load the same material data, only one
MaterialDefinition (and its associated GPU resources) will be created.

This first PR is the least possible invasive implementation of this feature.
There are a lot of room for improvements (and more planned). For example, each
Material still manages its own compiled shader program cache, but we can easily
move this to the MaterialCache in future PRs, further enabling the planned
mutable spec constants feature.

Additionally, there's room here to add a Material::toBuilder() method, which
could take an extant material and create a Builder object from it already
parameterized with all of the same options, a la the prototype design pattern.

* material cache: key on crc32

* material cache: make materialParser private

* move RefCountedMap to utils and add unit tests

* material cache: make create functions private

* material cache: fix broken tests on iOS/web

* material cache: address more comments
2025-09-24 00:35:59 +00:00
Mathias Agopian
77d6092890 Fix build. broken due to a bad merge (#9249) 2025-09-23 17:14:28 -07:00
Mathias Agopian
4ad619439a use RG32UI for picking instead of RG32F (#8917)
The reason for this is that according to the GLES 3.0 spec, RG32UI is 
guaranteed to be supported for writing, unlike RG32F.

We also use RGBA_INTEGER / UINT for readPixels() which is also a
guaranteed format.

Attempt to Fix #8762
2025-09-23 16:20:57 -07:00
Mathias Agopian
143d59a991 add support for memory mapped buffers in the backend (#9217)
* reorder backend methods

* add new "shared" buffer APIs to backends

We add the equivalent of GL's glMapBufferRange. The new APIs are:
- new "SHARED" flags when creating a BufferObject 
- a new HwMemoryMappedBuffer handle
- mapBuffer() maps a range of the buffer to memory
- unmapBuffer() unmaps the range
- copyToMemoryMappedBuffer() is basically a deferred memcpy, where the
  destination is a HwMemoryMappedBuffer and the source is a
  BufferDecriptor

The actual implementation doesn't have to actually map/unmap the range
on mapBuffer/unmapBuffer. e.g. on Vulkan these method are used mostly
to set offsets (for copyToMemoryMappedBuffer) and trigger the necessary
synchronizations.

Added some basic unit tests.

* add basic support for MemoryMappedBuffer in vk and metal

we implement copyToMemoryMappedBuffer() by calling updateBufferObject(),
which is enough to satisfy the API (And pass the tests).
2025-09-23 16:15:28 -07:00
Mathias Agopian
2a62518e5c imgui: new readme and update script 2025-09-23 16:13:37 -07:00
Powei Feng
edb17200d0 android: fix hello-cam sample appID
Make the application id and namespace consistent.
2025-09-23 16:10:39 -07:00
Ben Doherty
2afd0bd7f7 Metal: add debug labels to Metal resources (#9187) 2025-09-23 10:57:15 -07:00
Ben Doherty
bf2459540e Add Java bindings for setFrameScheduledCallback (#9182) 2025-09-22 18:40:42 -07:00
Powei Feng
09bb9828a2 Update .gitignore for renderdiff deps (#9242) 2025-09-22 21:40:20 +00:00
Sungun Park
8fda29657a Cache isMSAASwapChainSupported() result for EGL (#9235)
This change introduces a caching mechanism to store the results of MSAA
support queries.
2025-09-22 14:10:08 -07:00
Ben Doherty
c53195fa9a Fix frame scheduled callbacks not being latched (#9243) 2025-09-22 14:08:20 -07:00
Powei Feng
1e59032396 vk: guard export fence creation 2025-09-22 12:36:44 -07:00
Ben Doherty
9e79be419d Metal: log command buffer errors (#9224) 2025-09-22 12:10:30 -07:00
Powei Feng
a81d3217e7 github: make linux machines consistent (#9241) 2025-09-22 11:20:23 -07:00
Powei Feng
aa67faefab vk: remove renderstandalone workaround (#9236)
The bug might have been addressed by PR #8952. This workaround
is no longer needed.
2025-09-22 05:38:06 +00:00
Mathias Agopian
e982d8a3c6 pass backend tags by && reference
This saves a CString copy on the backend side and this forces the
frontend to make a copy explicitly.

In theory the CString should now ever be copied just once.
2025-09-19 15:25:31 -07:00
Mathias Agopian
9267563af2 fix clang-tidy warnings 2025-09-19 15:25:31 -07:00
Filament Bot
333d01a0a5 [automated] Updating /docs due to commit 24a6bd3
Full commit hash is 24a6bd30f9

DOCS_ALLOW_DIRECT_EDITS
2025-09-19 15:46:12 +00:00
1325 changed files with 217634 additions and 27434 deletions

View File

@@ -65,4 +65,6 @@ SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
PackConstructorInitializers: Never
PackConstructorInitializers: Never
ConstructorInitializerIndentWidth: 8
IndentWrappedFunctionNames: true

View File

@@ -1,43 +1,53 @@
# This action retrieves the latest commit message from a push or pull_request event
# and makes it available as an output variable named 'msg'.
name: 'Get commit message'
outputs:
msg:
value: ${{ steps.action_output.outputs.msg }}
hash:
value: ${{ steps.action_output.outputs.hash }}
runs:
using: "composite"
steps:
- name: Find commit message (on push)
if: github.event_name == 'push'
shell: bash
env:
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
run: |
AUTHOR_NAME="${{ github.event.head_commit.author.name }}"
AUTHOR_EMAIL="${{ github.event.head_commit.author.email }}"
TSTAMP="${{ github.event.head_commit.timestamp }}"
echo "commit ${{ github.event.head_commit.id }}" >> /tmp/commit_msg.txt
HASH="${{ github.event.head_commit.id }}"
echo "commit $HASH" >> /tmp/commit_msg.txt
echo "Author: ${AUTHOR_NAME}<${AUTHOR_EMAIL}>" >> /tmp/commit_msg.txt
echo "Date: ${TSTAMP}" >> /tmp/commit_msg.txt
echo "" >> /tmp/commit_msg.txt
echo "${{ github.event.head_commit.message }}" >> /tmp/commit_msg.txt
echo "$COMMIT_MESSAGE" >> /tmp/commit_msg.txt
echo "$HASH" > /tmp/commit_hash.txt
- name: Find commit message (PR)
shell: bash
id: checkout_code
if: github.event_name == 'pull_request'
run: |
echo "+++++ head commit message +++++"
echo "$(git log -1 --no-merges)"
echo "+++++++++++++++++++++++++++++++"
echo "hash=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
git checkout ${{ github.event.pull_request.head.sha }}
echo "$(git log -1 --no-merges)" >> /tmp/commit_msg.txt
BEFORE_HASH=$(git rev-parse HEAD)
echo "hash=$BEFORE_HASH" >> "$GITHUB_OUTPUT"
# Next we will checkout the actual head (not the merge commits) of the PR
AFTER_HASH="${{ github.event.pull_request.head.sha }}"
git checkout $AFTER_HASH
COMMIT_MESSAGE=$(git log -1 --no-merges)
echo "$COMMIT_MESSAGE" > /tmp/commit_msg.txt
echo "$AFTER_HASH" > /tmp/commit_hash.txt
- shell: bash
id: action_output
run: |
# Get the commit message
DELIMITER="EOF_FILE_CONTENT_$(date +%s)" # Using timestamp to make it more unique
echo "msg<<$DELIMITER" >> "$GITHUB_OUTPUT"
cat /tmp/commit_msg.txt >> "$GITHUB_OUTPUT"
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
echo "----- got commit message ---"
cat /tmp/commit_msg.txt
echo "----------------------------"
# Get the commit hash
echo "hash=$(cat /tmp/commit_hash.txt)" >> "$GITHUB_OUTPUT"
- name: Cleanup Find commit message (PR)
shell: bash
if: github.event_name == 'pull_request'

View File

@@ -15,7 +15,7 @@ runs:
uses: actions/cache@v4 # Use a specific version
with:
path: ~/Library/Caches/Homebrew
key: ${{ runner.os }}-brew-20250424
key: ${{ runner.os }}-brew-20251211
- name: Install Mac Prerequisites
shell: bash
run: |

View File

@@ -12,7 +12,7 @@ jobs:
name: build-android
# We intentially use a larger runner here to enable larger disk space
# (standard linux runner will fail on disk space and faster build time).
runs-on: 'ubuntu-24.04-32core'
runs-on: 'ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6

View File

@@ -21,9 +21,10 @@ jobs:
- name: Run update script
env:
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
COMMIT_MESSAGE: ${{ steps.get_commit_msg.outputs.msg }}
run: |
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 test/renderdiff/src/commit_msg.py)
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
GOLDEN_BRANCH=$(echo "${COMMIT_MESSAGE}" | python3 test/renderdiff/src/commit_msg.py)
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
git config --global user.email "filament.bot@gmail.com"
git config --global user.name "Filament Bot"
@@ -51,7 +52,7 @@ jobs:
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
run: |
bash docs_src/build/install_mdbook.sh && source ~/.bashrc
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
git config --global user.email "filament.bot@gmail.com"
git config --global user.name "Filament Bot"
git config --global credential.helper cache

View File

@@ -26,7 +26,7 @@ jobs:
build-desktop-linux:
name: build-linux
runs-on: ubuntu-22.04-16core
runs-on: 'ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -108,8 +108,7 @@ jobs:
uses: ./.github/actions/get-commit-msg
- name: Check for manual edits to /docs
run: |
COMMIT_ID=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
bash docs_src/build/presubmit_check.sh ${COMMIT_ID}
bash docs_src/build/presubmit_check.sh ${{ steps.get_commit_msg.outputs.hash }}
test-renderdiff:
name: test-renderdiff
@@ -121,7 +120,7 @@ jobs:
- uses: ./.github/actions/mac-prereq
- uses: ./.github/actions/get-gltf-assets
- uses: ./.github/actions/get-mesa
- uses: ./.github/actions/get-vulkan-sdk
- uses: ./.github/actions/get-vulkan-sdk
- id: get_commit_msg
uses: ./.github/actions/get-commit-msg
- name: Prerequisites
@@ -132,19 +131,20 @@ jobs:
shell: bash
- name: Render and compare
id: render_compare
env:
COMMIT_MESSAGE: ${{ steps.get_commit_msg.outputs.msg }}
run: |
ls ./gltf/Models
TEST_DIR=test/renderdiff
source ${TEST_DIR}/src/preamble.sh
start_
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 ${TEST_DIR}/src/commit_msg.py)
bash ${TEST_DIR}/generate.sh && \
python3 ${TEST_DIR}/src/golden_manager.py \
set -eux
GOLDEN_BRANCH=$(echo "${COMMIT_MESSAGE}" | python3 ${TEST_DIR}/src/commit_msg.py)
bash ${TEST_DIR}/generate.sh
python3 ${TEST_DIR}/src/golden_manager.py \
--branch=${GOLDEN_BRANCH} \
--output=${GOLDEN_OUTPUT_DIR}
# Note that we need to upload the output even if comparison fails, so we undo `set -ex`
end_
# Note that we need to upload the output even if comparison fails, so we undo `set -eux`
set +eux
python3 ${TEST_DIR}/src/compare.py \
--src=${GOLDEN_OUTPUT_DIR} \
@@ -157,6 +157,7 @@ jobs:
cat compare_output.txt >> "$GITHUB_OUTPUT"
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
fi
shell: bash
- uses: actions/upload-artifact@v4
with:
name: presubmit-renderdiff-result
@@ -171,14 +172,14 @@ jobs:
validate-wgsl-webgpu:
name: validate-wgsl-webgpu
runs-on: 'ubuntu-24.04-8core'
runs-on: 'ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/linux-prereq
- name: Run build script
run: ./build.sh -W debug test_filamat filament
run: ./build.sh -W debug test_filamat filament gltf_viewer
- name: Run test
run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
@@ -202,3 +203,23 @@ jobs:
./build.sh -p desktop debug gltf_viewer
- name: Run test
run: bash test/code-correctness/test.sh
test-backend:
name: test-backend
runs-on: macos-14-xlarge
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- uses: ./.github/actions/get-mesa
- uses: ./.github/actions/get-vulkan-sdk
- name: Prerequisites
run: |
# Must have at least clang-16 for a webgpu/dawn build.
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
shell: bash
- name: Run backend tests
shell: bash
run: |
bash test/backend/test.sh

View File

@@ -31,7 +31,7 @@ on:
jobs:
build-linux:
name: build-linux
runs-on: ubuntu-22.04-32core
runs-on: 'ubuntu-24.04-16core'
if: github.event_name == 'release' || github.event.inputs.platform == 'desktop'
steps:

6
.gitignore vendored
View File

@@ -18,3 +18,9 @@ test*.json
results
/compile_commands.json
/.cache
# For /test/renderdiff dependencies
/mesa
/gltf
/filament-assets
/venv

View File

@@ -62,6 +62,11 @@ force a clean build by adding the `-c` flag in that case.
To install the libraries and executables in `out/debug/` and `out/release/`, add the `-i` flag.
The script offers more features described by executing `build.sh -h`.
For more specialized options, please also consider the following pages:
- `-d`: [`matdbg`](https://google.github.io/filament/dup/matdbg.html)
- `-t`: [`fgviewer`](https://google.github.io/filament/dup/fgviewer.html)
- `-b` and `-y`: [ASAN/UBSAN builds](https://google.github.io/filament/notes/asan_ubsan.html)
### Filament-specific CMake Options
The following CMake options are boolean options specific to Filament:
@@ -237,6 +242,12 @@ foremost for `arm64-v8a`.
To build Android on Windows machines, see [android/Windows.md](android/Windows.md).
#### Important: SDK location
Either ensure your `ANDROID_HOME` environment variable is set or make sure the root project
contains a `local.properties` file with the `sdk.dir` property pointing to your installation of
the Android SDK.
#### Easy Android build
The easiest way to build Filament for Android is to use `build.sh` and the
@@ -246,8 +257,45 @@ The easiest way to build Filament for Android is to use `build.sh` and the
./build.sh -p android release
```
To build a sample (such as `android/samples/sample-hello-triangle`) for an ARM 64-bit phone, you would run
```shell
./build.sh -p android -q arm64-v8a -k sample-hello-triangle release
```
The output APK can be found in `android/samples/sample-hello-triangle/build/outputs/apk/release/sample-hello-triangle-release-unsigned.apk`
Run `build.sh -h` for more information.
#### Android Studio
You must use the latest stable release of Android Studio.
The Android build of filament is separated into java/kotlin client APIs, a layer of jni bindings
that bridges java/kotlin with native code, and Filament and other component code that have been compiled
into architecture-specific libraries. Our default Android Studio gradle setup can compile java/kotlin and
the jni bindings for you, but it will treat the filament libraries as already compiled and present on
the system.
Therefore, before compiling the sample app or any other targets, you must
make sure that the native filament libraries have been compiled and are located at a prescribed location
so that the jni bindings can link against them. You can do so by using the easy build script
```shell
./build.sh -p android release -q arm64-v8a
```
Note that the above step will also install host machine tools into prescribed locations. These tools are
required for compiling Filament assets such as materials and environment maps.
Now we are ready to compile the apps. To open the project, point Studio to the `android` folder.
After opening the project and syncing with Gradle, select the sample of your choice
using the drop-down widget in the toolbar. Additionally, you will need to select a deployment target.
By doing so, Android Studio will automatically try to compile the app only for that specific
device's architecture. So if you are targeting a new Pixel phone, make sure that the step above
(compiling the library) is targeting ARM 64-bit (`-q arm64-v8a` ), and if you are running the app on
an emulator on a Linux machine with an x86 64-bit chipset, you would indicate (`-q x86_64`) in the above step.
#### Manual builds
Invoke CMake in a build directory of your choice, inside of filament's directory. The commands
@@ -391,7 +439,7 @@ Alternatively, if you have node installed you can use the
[live-server](https://www.npmjs.com/package/live-server) package, which automatically refreshes the
web page when it detects a change.
Each sample app has its own handwritten html file. Additionally the server folder contains assets
Each sample app has its own handwritten html file. Additionally, the server folder contains assets
such as meshes, textures, and materials.
## Running the native samples

View File

@@ -56,6 +56,10 @@ option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
option(FILAMENT_USE_ABSEIL_LOGGING "Use Abseil to log, may increase binary size" OFF)
option(FILAMENT_ENABLE_EXPERIMENTAL_GCC_SUPPORT "Enable GCC support (unsupported)" OFF)
option(FILAMENT_SUPPORTS_WEBP_TEXTURES "Enable webp texture support for Filament (builds libwebp when ON)" OFF)
# This is to disable GTAO for the short-term while we investigate a way to better manage size increases.
# On the regular filament build (where size is of less concern), we enable GTAO by default.
option(FILAMENT_DISABLE_GTAO "Disable GTAO" OFF)
@@ -295,15 +299,10 @@ set(TOOLS ${CMAKE_CURRENT_SOURCE_DIR}/tools)
# ==================================================================================================
set(MIN_CLANG_VERSION "6.0")
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
if (CMAKE_C_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
message(FATAL_ERROR "Detected C compiler Clang ${CMAKE_C_COMPILER_VERSION} < ${MIN_CLANG_VERSION}")
endif()
elseif (NOT MSVC)
message(FATAL_ERROR "Detected C compiler ${CMAKE_C_COMPILER_ID} is unsupported")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(FILAMENT_USING_GCC OFF)
if (CMAKE_C_COMPILER_ID MATCHES "GNU" AND FILAMENT_ENABLE_EXPERIMENTAL_GCC_SUPPORT)
set(FILAMENT_USING_GCC ON)
elseif (CMAKE_C_COMPILER_ID MATCHES "Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
message(FATAL_ERROR "Detected CXX compiler Clang ${CMAKE_CXX_COMPILER_VERSION} < ${MIN_CLANG_VERSION}")
endif()
@@ -344,14 +343,18 @@ if (MSVC)
set(CXX_STANDARD "/std:c++latest")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /W0 /Zc:__cplusplus")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function -Wno-deprecated-declarations")
if(FILAMENT_USING_GCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -Wno-changes-meaning -Wno-return-type -Wno-attributes -Wno-unknown-pragmas -Wno-class-memaccess -Wno-multichar -Wno-deprecated-declarations -Wno-subobject-linkage -Wno-invalid-constexpr")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function -Wno-deprecated-declarations")
endif()
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nullability-extension")
endif()
endif()
if (FILAMENT_USE_EXTERNAL_GLES3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_EXTERNAL_GLES3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFILAMENT_USE_EXTERNAL_GLES3")
endif()
if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
@@ -365,10 +368,14 @@ endif()
if (LINUX)
option(USE_STATIC_LIBCXX "Link against the static runtime libraries." ON)
if (${USE_STATIC_LIBCXX})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
link_libraries("-static-libgcc -static-libstdc++")
link_libraries(libc++.a)
link_libraries(libc++abi.a)
if (FILAMENT_USING_GCC)
link_libraries("-static-libgcc -static-libstdc++")
else ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
link_libraries("-static-libgcc -static-libstdc++")
link_libraries(libc++.a)
link_libraries(libc++abi.a)
endif()
endif()
# Only linux, clang doesn't want to use a shared library that is not PIC.
@@ -393,8 +400,8 @@ if (MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE")
endif()
# Add colors to ninja builds
if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
# Add colors to ninja builds (when not using gcc)
if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja" AND NOT FILAMENT_USING_GCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
endif()
@@ -748,12 +755,61 @@ function(combine_static_libs TARGET OUTPUT DEPS)
endfunction()
# ==================================================================================================
# Configuration for CMAKE_CROSSCOMPILING.
# Configuration importing/exporting prebuilt "/tools" executables
# ==================================================================================================
# In certain cases, we want the ability to separate the build type/flags (release, debug) of tools
# (matc, resgen, etc...) from filament. Cross compilation is one such case (e.g. building material
# with matc running on host while building filament for Android) [1]. Another example is when client
# wants to enable ASAN for filament but not the tool [2].
#
# Here are the varibles that are used to determine behavior is such flows:
# - CMAKE_CROSSCOMPILING : Set by cmake to indicate the build's target platform is different
# from the host platform.
# - IMPORT_EXECUTABLES_DIR : This is the directory containing the /ImportExecutables-type.cmake
# which are then included in other CMakeLists.txt to enable finding targets that have been
# prebuilt. This is set by the client in their `cmake` invocation.
# - IMPORT_EXECUTABLES : Path to a file to for 1) exporting the prebuilt targets or 2)
# importing a previously exported targets. (Used internally and should not be set by client).
# - FILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR : A path set by the client to indicate that
# they wish to export the tools as prebuilts, and the corresponding targets will be recorded
# in a cmake file (i.e IMPORT_EXECUTABLES). IMPORT_EXECUTABLES will be set relative to the the
# given path. This will set FILAMENT_EXPORT_PREBUILT_EXECUTABLES=ON.
# - FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR : A path set by the client to indicate that they wish
# to import the tools as prebuilts from a .cmake file. The location (IMPORT_EXECUTABLES) of the
# file is relative to the path given. This will set FILAMENT_IMPORT_PREBUILT_EXECUTABLES=ON.
# - IMPORT_PREBUILT_EXECUTABLES and EXPORT_PREBUILT_EXECUTABLES are internal booleans set to
# ON based on the prescence of FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR and
# FILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR.
#
# In conclusion, for cases
# - [1] (crosscompiling), the client must set IMPORT_EXECUTABLES_DIR for both when they are building
# the tools and when they are building the target-platform filament.
# - [2] (all other instances), the client must set FILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR in
# the prebuilt exporting step, and set FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR in the importing
# step.
# TODO: Fold the cross compilation case into the more general FILAMENT_IMPORT/EXPORT variables.
if (FILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR)
set(FILAMENT_EXPORT_PREBUILT_EXECUTABLES ON)
set(IMPORT_EXECUTABLES_DIR ${FILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR})
endif()
if (FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR)
set(FILAMENT_IMPORT_PREBUILT_EXECUTABLES ON)
set(IMPORT_EXECUTABLES_DIR ${FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR})
endif()
if (WEBGL)
set(IMPORT_EXECUTABLES ${FILAMENT}/${IMPORT_EXECUTABLES_DIR}/ImportExecutables-Release.cmake)
else()
set(IMPORT_EXECUTABLES ${FILAMENT}/${IMPORT_EXECUTABLES_DIR}/ImportExecutables-${CMAKE_BUILD_TYPE}.cmake)
if (FILAMENT_EXPORT_PREBUILT_EXECUTABLES OR FILAMENT_IMPORT_PREBUILT_EXECUTABLES)
set(IMPORT_EXECUTABLES_BUILD_TYPE Prebuilt)
else()
set(IMPORT_EXECUTABLES_BUILD_TYPE ${CMAKE_BUILD_TYPE})
endif()
set(IMPORT_EXECUTABLES ${FILAMENT}/${IMPORT_EXECUTABLES_DIR}/ImportExecutables-${IMPORT_EXECUTABLES_BUILD_TYPE}.cmake)
endif()
# ==================================================================================================
@@ -816,7 +872,9 @@ add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${LIBRARIES}/viewer)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/abseil/tnt)
add_subdirectory(${EXTERNAL}/basisu/tnt)
# Add zstd before basisu to force it to use the external zstd target,
# preventing a duplicate symbol conflict with its bundled version.
add_subdirectory(${EXTERNAL}/zstd/tnt)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
add_subdirectory(${EXTERNAL}/robin-map/tnt)
@@ -830,7 +888,8 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
add_subdirectory(${EXTERNAL}/perfetto/tnt)
add_subdirectory(${EXTERNAL}/zstd/tnt)
add_subdirectory(${EXTERNAL}/basisu/tnt)
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
add_subdirectory(${LIBRARIES}/geometry)
@@ -854,6 +913,11 @@ if (FILAMENT_ENABLE_FGVIEWER)
add_subdirectory(${LIBRARIES}/fgviewer)
endif()
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
add_subdirectory(${EXTERNAL}/libwebp/tnt)
add_definitions(-DFILAMENT_SUPPORTS_WEBP_TEXTURES)
endif()
if (FILAMENT_SUPPORTS_VULKAN)
add_subdirectory(${LIBRARIES}/bluevk)
add_subdirectory(${EXTERNAL}/vkmemalloc/tnt)
@@ -912,6 +976,6 @@ if (IS_HOST_PLATFORM)
endif()
# Generate exported executables for cross-compiled builds (Android, WebGL, and iOS)
if (NOT CMAKE_CROSSCOMPILING)
if ((NOT CMAKE_CROSSCOMPILING AND NOT FILAMENT_IMPORT_PREBUILT_EXECUTABLES) OR FILAMENT_EXPORT_PREBUILT_EXECUTABLES)
export(TARGETS matc cmgen filamesh mipgen resgen uberz glslminifier FILE ${IMPORT_EXECUTABLES})
endif()

View File

@@ -20,7 +20,7 @@ The guiding principles of the filament code style and code formatting can be res
- class access modifiers are not indented
- last line of `.cpp` or `.h` file must be an empty line
```
```c++
for (int i = 0; i < max; i++) {
}
@@ -73,12 +73,24 @@ src/data.inc
- `public` class attributes *are not* prefixed
- class attributes and methods are lower camelcase
```
```c++
extern int gGlobalWarming;
class FooBar {
public:
void methodName();
FooBar(int attributeName, int sizeInBytes)
: mAttributeName(attributeName),
sizeInBytes(sizeInBytes) {}
void reallyLongMethodNameWithLotsOfArguments(bool argument1,
int someSecondArgument, int bestArgument) {
std::pair<bool, int> pair = {
argument1,
argument2,
};
// etc
}
int sizeInBytes;
private:
int mAttributeName;
@@ -97,7 +109,7 @@ private:
- always include the copyright notice at the top of every file
- make sure the date is correct
```
```c++
/*
* Copyright (C) 2018 The Android Open Source Project
*
@@ -139,7 +151,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
*Sorting the headers is important to help catching missing `#include` directives.*
```
```c++
/*
* Copyright (C) 2018 The Android Open Source Project
*
@@ -183,7 +195,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
### Misc
- Use `auto` only when the type appears on the same line or with iterators and lambdas.
```
```c++
auto foo = new Foo();
for (auto& i : collection) { }
```

View File

@@ -1,7 +1,6 @@
# Filament Release Notes log
**If you are merging a PR into main**: please add the release note below, under the *Release notes
We are chaning the way Vulkan buffers are handled. We need to switch over to a managed (or view-based) model where the data stored inside the object is a proxy to a Vulkan object that can dynamically be swapped around.
**If you are cherry-picking a commit into an rc/ branch**: add the release note under the
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.65.1'
implementation 'com.google.android.filament:filament-android:1.68.3'
}
```
@@ -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.65.1'
pod 'Filament', '~> 1.68.3'
```
## Documentation

View File

@@ -7,6 +7,54 @@ A new header is inserted each time a *tag* is created.
Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
## v1.68.3
- materials: added support for the glTF `KHR_materials_dispersion` extension, which adds dispersion for refractive objects
## v1.68.2
- Support `setPresentationTime` with the Metal backend.
## v1.68.1
## v1.68.0
- engine: add `View::getLastDynamicResolutionScale()` (b/457753622)
- Metal: report GPU errors to the platform via `debugUpdateStat` (b/431665753).
- materials: Make Material Instances' UBO descriptor use dynamic offsets. [⚠️ **Recompile Materials**]
## v1.67.1
- Metal: Add support for the `SwapChain::CONFIG_MSAA_4_SAMPLES` flag.
- third_party: Optionally add libwebp to build
- controlled by cmake flag FILAMENT_SUPPORTS_WEBP_TEXTURES, defaults to OFF
- actual webp texture support for libs/gltfio coming in subsequent change
## v1.67.0
- materials: Add a new API getParameterTransformName that will return the value of the transformName field of a sampler
parameter. [⚠️ **Recompile Materials**]
## v1.66.2
## v1.66.1
- filamat: Removed a dependency on Glslang's deprecated SPIR-V remapper.
The functionality is already implemented by calling the CanonicalizeIds pass
in the SPIRV-Tools, and should be a non-functional change.
## v1.66.0
- materials: include default values of spec constants in material metadata [⚠️ **Recompile Materials**]
## v1.65.4
## v1.65.3
## v1.65.2

View File

@@ -100,7 +100,7 @@ buildscript {
'kotlin': '2.0.21',
'kotlin_coroutines': '1.9.0',
'buildTools': '35.0.0',
'ndk': '27.0.11718014',
'ndk': '29.0.14206865',
'androidx_core': '1.13.1',
'androidx_annotations': '1.9.0'
]
@@ -124,6 +124,7 @@ buildscript {
ext.cmakeArgs = [
"--no-warn-unused-cli",
"-DANDROID_WEAK_API_DEFS=ON",
"-DANDROID_PIE=ON",
"-DANDROID_PLATFORM=21",
"-DANDROID_STL=c++_static",

View File

@@ -51,10 +51,6 @@ add_library(bluevk STATIC IMPORTED)
set_target_properties(bluevk PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbluevk.a)
add_library(vkshaders STATIC IMPORTED)
set_target_properties(vkshaders PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libvkshaders.a)
if (FILAMENT_SUPPORTS_WEBGPU)
add_library(webgpu_dawn STATIC IMPORTED)
set_target_properties(webgpu_dawn PROPERTIES IMPORTED_LOCATION
@@ -138,6 +134,7 @@ target_include_directories(filament-jni PRIVATE
../../filament/backend/include
../../third_party/robin-map
../../third_party/perfetto
../../libs/bluevk/include
../../libs/utils/include)
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
@@ -165,10 +162,15 @@ target_link_libraries(filament-jni
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:smol-v>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:webgpu_dawn>
)
# Force a relink when the version script is changed:
set_target_properties(filament-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
if (FILAMENT_SUPPORTS_VULKAN)
add_definitions(-DFILAMENT_SUPPORTS_VULKAN=1)
else()
add_definitions(-DFILAMENT_SUPPORTS_VULKAN=0)
endif()

View File

@@ -557,7 +557,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
jboolean disableHandleUseAfterFreeCheck,
jint preferredShaderLanguage,
jboolean forceGLES2Context, jboolean assertNativeWindowIsValid,
jint gpuContextPriority) {
jint gpuContextPriority,
jlong sharedUboInitialSizeInBytes) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
Engine::Config config = {
.commandBufferSizeMB = (uint32_t) commandBufferSizeMB,
@@ -576,6 +577,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
.forceGLES2Context = (bool) forceGLES2Context,
.assertNativeWindowIsValid = (bool) assertNativeWindowIsValid,
.gpuContextPriority = (Engine::GpuContextPriority) gpuContextPriority,
.sharedUboInitialSizeInBytes = (uint32_t) sharedUboInitialSizeInBytes,
};
builder->config(&config);
}

View File

@@ -25,7 +25,7 @@ using namespace filament;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount, jint shadowQuality) {
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount, jint shadowQuality, jint uboBatchingMode) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, buffer_, size);
auto builder = Material::Builder();
@@ -33,6 +33,7 @@ Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
builder.sphericalHarmonicsBandCount(shBandCount);
}
builder.shadowSamplingQuality((Material::Builder::ShadowSamplingQuality)shadowQuality);
builder.uboBatching((Material::UboBatchingMode)uboBatchingMode);
Material* material = builder
.package(buffer.getData(), buffer.getSize())
.build(*engine);
@@ -279,6 +280,17 @@ Java_com_google_android_filament_Material_nHasParameter(JNIEnv* env, jclass,
return (jboolean) hasParameter;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_google_android_filament_Material_nGetParameterTransformName(JNIEnv* env, jclass,
jlong nativeMaterial, jstring samplerName_) {
Material* material = (Material*) nativeMaterial;
const char* samplerName = env->GetStringUTFChars(samplerName_, 0);
const char* transformName = material->getParameterTransformName(samplerName);
jstring transformName_ = env->NewStringUTF(transformName ? transformName : "");
env->ReleaseStringUTFChars(samplerName_, samplerName);
return transformName_;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_Material_nCompile(JNIEnv *env, jclass clazz,

View File

@@ -208,3 +208,19 @@ Java_com_google_android_filament_Renderer_nSetVsyncTime(JNIEnv *, jclass,
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->setVsyncTime(steadyClockTimeNano);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSkipNextFrames(JNIEnv *, jclass ,
jlong nativeRenderer, jint frameCount) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->skipNextFrames(frameCount);
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Renderer_nGetFrameToSkipCount(JNIEnv *, jclass ,
jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;
return renderer->getFrameToSkipCount();
}

View File

@@ -63,6 +63,14 @@ Java_com_google_android_filament_Skybox_nBuilderColor(JNIEnv *, jclass,
builder->color({r, g, b, a});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_Skybox_nBuilderPriority(JNIEnv *, jclass,
jlong nativeSkyBoxBuilder, jint priority) {
Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder;
builder->priority(uint8_t(priority));
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type,
jlong nativeSkyBoxBuilder, jlong nativeEngine) {

View File

@@ -28,9 +28,8 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en
jlong nativeSwapChain, jobject handler, jobject runnable) {
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
auto* callback = JniCallback::make(env, handler, runnable);
swapChain->setFrameCompletedCallback(nullptr, [callback](SwapChain* swapChain) {
JniCallback::postToJavaAndDestroy(callback);
});
swapChain->setFrameCompletedCallback(callback->getHandler(),
[callback](SwapChain* swapChain) { JniCallback::postToJavaAndDestroy(callback); });
}
extern "C" JNIEXPORT jboolean JNICALL
@@ -53,3 +52,22 @@ Java_com_google_android_filament_SwapChain_nIsProtectedContentSupported(
Engine* engine = (Engine*) nativeEngine;
return (jboolean)SwapChain::isProtectedContentSupported(*engine);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SwapChain_nSetFrameScheduledCallback(JNIEnv* env, jclass,
jlong nativeSwapChain, jobject handler, jobject runnable) {
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
auto* callback = JniCallback::make(env, handler, runnable);
swapChain->setFrameScheduledCallback(callback->getHandler(),
[callback](backend::PresentCallable) {
// Ignore PresentCallable, which is only meaningful with the Metal backend.
JniCallback::postToJavaAndDestroy(callback);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_SwapChain_nIsFrameScheduledCallbackSet(
JNIEnv *, jclass, jlong nativeSwapChain) {
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
return (jboolean)swapChain->isFrameScheduledCallbackSet();
}

View File

@@ -21,6 +21,11 @@
#ifdef __ANDROID__
#include <android/bitmap.h>
#include <android/hardware_buffer_jni.h>
#include <backend/platforms/PlatformEGLAndroid.h>
# if FILAMENT_SUPPORTS_VULKAN
# include <backend/platforms/VulkanPlatformAndroid.h>
# endif
#endif
#include <filament/Engine.h>
@@ -388,6 +393,57 @@ Java_com_google_android_filament_Texture_nSetExternalImage(JNIEnv*, jclass, jlon
texture->setExternalImage(*engine, (void*)eglImage);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Texture_nSetExternalImageByAHB(JNIEnv *env, jclass clazz,
jlong nativeTexture, jlong nativeEngine, jobject ahb) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
#ifdef __ANDROID__
Platform* platform = engine->getPlatform();
AHardwareBuffer* nativeBuffer = nullptr;
if (__builtin_available(android 26, *)) {
nativeBuffer = AHardwareBuffer_fromHardwareBuffer(env, ahb);
}
if (!nativeBuffer) {
// either we're not on Android 26, or ahb wasn't a AHardwareBuffer
return JNI_FALSE;
}
if (engine->getBackend() == Backend::OPENGL) {
// CAVEAT: we assume that Backend::OPENGL on Android implies PlatformEGLAndroid.
#if UTILS_HAS_RTTI
if (!dynamic_cast<PlatformEGLAndroid*>(platform)) {
return JNI_FALSE;
}
#endif
auto* eglPlatform = (PlatformEGLAndroid*) platform;
auto ref = eglPlatform->createExternalImage(nativeBuffer, false);
texture->setExternalImage(*engine, ref);
}
#if FILAMENT_SUPPORTS_VULKAN
else if (engine->getBackend() == Backend::VULKAN) {
// CAVEAT: we assume that Backend::VULKAN on Android implies VulkanPlatformAndroid.
#if UTILS_HAS_RTTI
if (!dynamic_cast<VulkanPlatformAndroid*>(platform)) {
return JNI_FALSE;
}
#endif
auto* vulkanPlatform = (VulkanPlatformAndroid*) platform;
auto ref = vulkanPlatform->createExternalImage(nativeBuffer, false);
texture->setExternalImage(*engine, ref);
}
#endif // FILAMENT_SUPPORTS_VULKAN
// success!
return JNI_TRUE;
#else
// other platforms could come here
return JNI_FALSE;
#endif // __ANDROID__
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nSetExternalStream(JNIEnv*, jclass,
jlong nativeTexture, jlong nativeEngine, jlong nativeStream) {
@@ -607,3 +663,4 @@ Java_com_google_android_filament_android_TextureHelper_nSetBitmapWithCallback(JN
}
#endif

View File

@@ -147,6 +147,15 @@ Java_com_google_android_filament_View_nSetDynamicResolutionOptions(JNIEnv*, jcla
view->setDynamicResolutionOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nGetLastDynamicResolutionScale(JNIEnv *env, jclass, jlong nativeView, jfloatArray out_) {
jfloat* out = env->GetFloatArrayElements(out_, nullptr);
View *view = (View *) nativeView;
math::float2 result = view->getLastDynamicResolutionScale();
std::copy_n(result.v, 2, out);
env->ReleaseFloatArrayElements(out_, out, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetShadowType(JNIEnv*, jclass, jlong nativeView, jint type) {
View* view = (View*) nativeView;
@@ -356,6 +365,7 @@ Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong na
view->setFogOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nativeView, jint blendMode) {
View* view = (View*) nativeView;
@@ -554,3 +564,20 @@ Java_com_google_android_filament_View_nClearFrameHistory(JNIEnv *env, jclass cla
Engine *engine = (Engine *) nativeEngine;
view->clearFrameHistory(*engine);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetChannelDepthClearEnabled(JNIEnv *, jclass ,
jlong nativeView, jint channel, jboolean enabled) {
View* view = (View*) nativeView;
view->setChannelDepthClearEnabled((uint8_t) channel, (bool) enabled);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_View_nIsChannelDepthClearEnabled(JNIEnv *env, jclass clazz,
jlong nativeView, jint channel) {
// TODO: implement nIsChannelDepthClearEnabled()
View* view = (View*) nativeView;
return (jboolean)view->isChannelDepthClearEnabled((uint8_t) channel);
}

View File

@@ -99,6 +99,15 @@ final class Asserts {
}
}
@NonNull @Size(min = 2)
static float[] assertFloat2(@Nullable float[] out) {
if (out == null) out = new float[2];
else if (out.length < 2) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 2");
}
return out;
}
@NonNull @Size(min = 4)
static float[] assertFloat4(@Nullable float[] out) {
if (out == null) out = new float[4];

View File

@@ -264,7 +264,8 @@ public class Engine {
config.disableHandleUseAfterFreeCheck,
config.preferredShaderLanguage.ordinal(),
config.forceGLES2Context, config.assertNativeWindowIsValid,
config.gpuContextPriority.ordinal());
config.gpuContextPriority.ordinal(),
config.sharedUboInitialSizeInBytes);
return this;
}
@@ -525,6 +526,16 @@ public class Engine {
* GPU context priority level. Controls GPU work scheduling and preemption.
*/
public GpuContextPriority gpuContextPriority = GpuContextPriority.DEFAULT;
/**
* The initial size in bytes of the shared uniform buffer used for material instance batching.
*
* If the buffer runs out of space during a frame, it will be automatically reallocated
* with a larger capacity. Setting an appropriate initial size can help avoid runtime
* reallocations, which can cause a minor performance stutter, at the cost of higher
* initial memory usage.
*/
public long sharedUboInitialSizeInBytes = 256 * 64;
}
private Engine(long nativeEngine, Config config) {
@@ -1529,7 +1540,8 @@ public class Engine {
boolean disableHandleUseAfterFreeCheck,
int preferredShaderLanguage,
boolean forceGLES2Context, boolean assertNativeWindowIsValid,
int gpuContextPriority);
int gpuContextPriority,
long sharedUboInitialSizeInBytes);
private static native void nSetBuilderFeatureLevel(long nativeBuilder, int ordinal);
private static native void nSetBuilderSharedContext(long nativeBuilder, long sharedContext);
private static native void nSetBuilderPaused(long nativeBuilder, boolean paused);

View File

@@ -261,6 +261,20 @@ public class Material {
LOW
}
/**
* Defines whether a material instance should use UBO batching or not.
*/
public enum UboBatchingMode {
/**
* For default, it follows the engine settings.
* If UBO batching is enabled on the engine and the material domain is SURFACE, it
* turns on the UBO batching. Otherwise, it turns off the UBO batching.
*/
DEFAULT,
/** Disable the Ubo Batching for this material */
DISABLED
}
public static class UserVariantFilterBit {
/** Directional lighting */
public static int DIRECTIONAL_LIGHTING = 0x01;
@@ -372,6 +386,7 @@ public class Material {
private int mSize;
private int mShBandCount = 0;
private ShadowSamplingQuality mShadowSamplingQuality = ShadowSamplingQuality.LOW;
private UboBatchingMode mUboBatchingMode = UboBatchingMode.DEFAULT;
/**
@@ -416,6 +431,17 @@ public class Material {
return this;
}
/**
* Set the batching mode of the instances created from this material.
* @param uboBatchingMode
* @return Reference to this Builder for chaining calls.
*/
@NonNull
public Builder uboBatching(UboBatchingMode mode) {
mUboBatchingMode = mode;
return this;
}
/**
* Creates and returns the Material object.
*
@@ -428,7 +454,7 @@ public class Material {
@NonNull
public Material build(@NonNull Engine engine) {
long nativeMaterial = nBuilderBuild(engine.getNativeObject(),
mBuffer, mSize, mShBandCount, mShadowSamplingQuality.ordinal());
mBuffer, mSize, mShBandCount, mShadowSamplingQuality.ordinal(), mUboBatchingMode.ordinal());
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
return new Material(nativeMaterial);
}
@@ -787,6 +813,21 @@ public class Material {
return nHasParameter(getNativeObject(), name);
}
/**
*
* Returns the name of the transform parameter associated with the given sampler parameter.
* In the case the parameter doesn't have a transform name field, it will return an empty string.
*
* @param samplerName the name of the sampler parameter to query.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/general:parameters">
* General: parameters</a>
*/
public String getParameterTransformName(@NonNull String samplerName) {
return nGetParameterTransformName(getNativeObject(), samplerName);
}
/**
* Sets the value of a bool parameter on this material's default instance.
*
@@ -1079,7 +1120,7 @@ public class Material {
mNativeObject = 0;
}
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount, int shadowQuality);
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount, int shadowQuality, int uboBatchingMode);
private static native long nCreateInstance(long nativeMaterial);
private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name);
private static native long nGetDefaultInstance(long nativeMaterial);
@@ -1111,4 +1152,5 @@ public class Material {
private static native int nGetRequiredAttributes(long nativeMaterial);
private static native boolean nHasParameter(long nativeMaterial, @NonNull String name);
private static native String nGetParameterTransformName(long nativeMaterial, @NonNull String samplerName);
}

View File

@@ -332,7 +332,7 @@ public class RenderableManager {
}
/**
* Set the channel this renderable is associated to. There can be 4 channels.
* Set the channel this renderable is associated to. There can be 8 channels.
*
* <p>All renderables in a given channel are rendered together, regardless of anything else.
* They are sorted as usual within a channel.</p>
@@ -342,7 +342,7 @@ public class RenderableManager {
* <p>Channels 0 and 1 may not have render primitives using a material with `refractionType`
* set to `screenspace`.</p>
*
* @param channel clamped to the range [0..3], defaults to 2.
* @param channel clamped to the range [0..7], defaults to 2.
*
* @return Builder reference for chaining calls.
*
@@ -351,7 +351,7 @@ public class RenderableManager {
* @see RenderableManager::setBlendOrderAt()
*/
@NonNull
public Builder channel(@IntRange(from = 0, to = 3) int channel) {
public Builder channel(@IntRange(from = 0, to = 7) int channel) {
nBuilderChannel(mNativeBuilder, channel);
return this;
}
@@ -730,7 +730,7 @@ public class RenderableManager {
*
* @see Builder#channel
*/
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 3) int channel) {
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 7) int channel) {
nSetChannel(mNativeObject, i, channel);
}

View File

@@ -732,6 +732,22 @@ public class Renderer {
nResetUserTime(getNativeObject());
}
/**
* Requests the next frameCount frames to be skipped. For Debugging.
* @param frameCount number of frames to skip.
*/
public void skipNextFrames(int frameCount) {
nSkipNextFrames(getNativeObject(), frameCount);
}
/**
* Remainder count of frame to be skipped
* @return remaining frames to be skipped
*/
public int getFrameToSkipCount() {
return nGetFrameToSkipCount(getNativeObject());
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Renderer");
@@ -773,4 +789,7 @@ public class Renderer {
float interval, float headRoomRatio, float scaleRate, int history);
private static native void nSetClearOptions(long nativeRenderer,
float r, float g, float b, float a, boolean clear, boolean discard);
private static native void nSkipNextFrames(long nativeObject, int frameCount);
private static native int nGetFrameToSkipCount(long nativeObject);
}

View File

@@ -155,6 +155,24 @@ public class Skybox {
return this;
}
/**
* Set the rendering priority of the Skybox. By default, it is set to the lowest
* priority (7) such that the Skybox is always rendered after the opaque objects,
* to reduce overdraw when depth culling is enabled.
*
* @param priority clamped to the range [0..7], defaults to 4; 7 is lowest priority
* (rendered last).
*
* @return Builder reference for chaining calls.
*
* @see RenderableManager.Builder#priority
*/
@NonNull
public Builder priority(@IntRange(from = 0, to = 7) int priority) {
nBuilderPriority(mNativeBuilder, priority);
return this;
}
/**
* Creates a <code>Skybox</code> object
*
@@ -262,6 +280,7 @@ public class Skybox {
private static native void nBuilderShowSun(long nativeSkyboxBuilder, boolean show);
private static native void nBuilderIntensity(long nativeSkyboxBuilder, float intensity);
private static native void nBuilderColor(long nativeSkyboxBuilder, float r, float g, float b, float a);
private static native void nBuilderPriority(long nativeSkyboxBuilder, int priority);
private static native long nBuilderBuild(long nativeSkyboxBuilder, long nativeEngine);
private static native void nSetLayerMask(long nativeSkybox, int select, int value);
private static native int nGetLayerMask(long nativeSkybox);

View File

@@ -139,6 +139,78 @@ public class SwapChain {
nSetFrameCompletedCallback(getNativeObject(), handler, callback);
}
/**
* FrameScheduledCallback is a callback function that notifies an application about the status
* of a frame after Filament has finished its processing.
*
* <p>
* The exact timing and semantics of this callback differ depending on the graphics backend in
* use.
* </p>
*
* <h3>Metal Backend</h3>
* <p>
* With the Metal backend, this callback signifies that Filament has completed all CPU-side
* processing for a frame and the frame is ready to be scheduled for presentation.
* </p>
*
* <p>
* Typically, Filament is responsible for scheduling the frame's presentation to the SwapChain.
* If a FrameScheduledCallback is set, however, the application bears the responsibility of
* scheduling the frame for presentation by calling the PresentCallable passed to the callback
* function. In this mode, Filament will not automatically schedule the frame for presentation.
* </p>
*
* <p>
* When using the Metal backend, if your application delays the call to the PresentCallable
* (e.g., by invoking it on a separate thread), you must ensure all PresentCallables have been
* called before shutting down the Filament Engine. You can guarantee this by calling
* Engine.flushAndWait() before Engine.shutdown(). This is necessary to ensure the Engine has
* a chance to clean up all memory related to frame presentation.
* </p>
*
* <h3>Other Backends (OpenGL, Vulkan, WebGPU)</h3>
* <p>
* On other backends, this callback serves as a notification that Filament has completed all
* CPU-side processing for a frame. Filament proceeds with its normal presentation logic
* automatically, and the PresentCallable passed to the callback is a no-op that can be safely
* ignored.
* </p>
*
* <h3>General Behavior</h3>
* <p>
* A FrameScheduledCallback can be set on an individual SwapChain through
* setFrameScheduledCallback. Each SwapChain can have only one callback set per frame. If
* setFrameScheduledCallback is called multiple times on the same SwapChain before
* Renderer.endFrame(), the most recent call effectively overwrites any previously set callback.
* </p>
*
* <p>
* The callback set by setFrameScheduledCallback is "latched" when Renderer.endFrame() is
* executed. At this point, the callback is fixed for the frame that was just encoded.
* Subsequent calls to setFrameScheduledCallback after endFrame() will apply to the next frame.
* </p>
*
* <p>
* Use setFrameScheduledCallback() (with default arguments) to unset the callback.
* </p>
*
* @param handler A {@link java.util.concurrent.Executor Executor}.
* @param callback The Runnable callback to invoke when frame processing is complete.
*/
public void setFrameScheduledCallback(@NonNull Object handler, @NonNull Runnable callback) {
nSetFrameScheduledCallback(getNativeObject(), handler, callback);
}
/**
* Returns whether this SwapChain currently has a FrameScheduledCallback set.
*
* @return true, if the last call to setFrameScheduledCallback set a callback
*/
public boolean isFrameScheduledCallbackSet() {
return nIsFrameScheduledCallbackSet(getNativeObject());
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed SwapChain");
@@ -151,6 +223,8 @@ public class SwapChain {
}
private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback);
private static native void nSetFrameScheduledCallback(long nativeSwapChain, Object handler, Runnable callback);
private static native boolean nIsFrameScheduledCallbackSet(long nativeSwapChain);
private static native boolean nIsSRGBSwapChainSupported(long nativeEngine);
private static native boolean nIsMSAASwapChainSupported(long nativeEngine, int samples);
private static native boolean nIsProtectedContentSupported(long nativeEngine);

View File

@@ -71,6 +71,16 @@ import static com.google.android.filament.Texture.Type.COMPRESSED;
* @see MaterialInstance#setParameter(String, Texture, TextureSampler)
*/
public class Texture {
private static Class<?> HardwareBufferClass = null;
static {
try {
HardwareBufferClass = Class.forName("android.hardware.HardwareBuffer");
} catch (ClassNotFoundException ignored) {
}
}
private static final Sampler[] sSamplerValues = Sampler.values();
private static final InternalFormat[] sInternalFormatValues = InternalFormat.values();
@@ -1172,6 +1182,38 @@ public class Texture {
nSetExternalImage(getNativeObject(), engine.getNativeObject(), eglImage);
}
/**
* Specifies the external image to associate with this <code>Texture</code>.
*
* <p>Typically, the external image is OS specific, and can be a video or camera frame.
* There are many restrictions when using an external image as a texture, such as:</p>
* <ul>
* <li> only the level of detail (lod) 0 can be specified</li>
* <li> only nearest or linear filtering is supported</li>
* <li> the size and format of the texture is defined by the external image</li>
* <li> only the CLAMP_TO_EDGE wrap mode is supported</li>
* </ul>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param externalImageRef An OS specific Object. On Android it must be a
* <code>android.hardware.HardwareBuffer</code>
*/
public void setExternalImage(@NonNull Engine engine, Object externalImageRef) {
if (HardwareBufferClass != null) {
if (!HardwareBufferClass.isInstance(externalImageRef)) {
throw new IllegalArgumentException("externalImageRef must be a AHardwareBuffer");
}
if (!nSetExternalImageByAHB(getNativeObject(), engine.getNativeObject(), externalImageRef)) {
throw new IllegalStateException("Error setting AHardwareBuffer as external image");
}
} else {
throw new UnsupportedOperationException(
"setExternalImage(Engine, Object) not supported on this platform");
}
}
/**
* Specifies the external stream to associate with this <code>Texture</code>.
*
@@ -1364,6 +1406,8 @@ public class Texture {
private static native void nSetExternalImage(
long nativeObject, long nativeEngine, long eglImage);
private static native boolean nSetExternalImageByAHB(long nativeTexture, long nativeObject, Object ahb);
private static native void nSetExternalStream(long nativeTexture,
long nativeEngine, long nativeStream);

View File

@@ -294,8 +294,8 @@ public class TextureSampler {
/**
* This controls anisotropic filtering.
*
* @param anisotropy Amount of anisotropy, should be a power-of-two. The default is 0.
* The maximum permissible value is 7.
* @param anisotropy Amount of anisotropy, should be a power-of-two. The default is 1.
* The maximum permissible value is 128.
*/
public void setAnisotropy(float anisotropy) {
mSampler = nSetAnisotropy(mSampler, anisotropy);

View File

@@ -25,7 +25,6 @@ import java.util.EnumSet;
import static com.google.android.filament.Asserts.assertFloat3In;
import static com.google.android.filament.Asserts.assertFloat4In;
import static com.google.android.filament.Colors.LinearColor;
import com.google.android.filament.proguard.UsedByNative;
@@ -291,6 +290,25 @@ public class View {
return mViewport;
}
/**
* Sets whether a channel must clear the depth buffer before all primitives are rendered.
* Channel depth clear is off by default for all channels.
* This is orthogonal to Renderer::setClearOptions().
* @param channel between 0 and 7
* @param enabled true to enable clear, false to disable
*/
void setChannelDepthClearEnabled(@IntRange(from = 0, to = 7) int channel, boolean enabled) {
nSetChannelDepthClearEnabled(getNativeObject(), channel, enabled);
}
/**
* @param channel between 0 and 7
* @return true if this channel has depth clear enabled.
*/
boolean isChannelDepthClearEnabled(@IntRange(from = 0, to = 7) int channel) {
return nIsChannelDepthClearEnabled(getNativeObject(), channel);
}
/**
* Sets the blending mode used to draw the view into the SwapChain.
*
@@ -655,6 +673,21 @@ public class View {
return mDynamicResolution;
}
/**
* Returns the last dynamic resolution scale factor used by this view. This value is updated
* when Renderer::render(View*) is called
* @param out A 2-float array where the value will be stored, or null in which case the array is
* allocated.
* @return A 2-float array containing the horizontal and the vertical scale factors
* @see Renderer#render(View)
*/
@NonNull @Size(min = 2)
public float[] getLastDynamicResolutionScale(@Nullable @Size(min = 2) float[] out) {
out = Asserts.assertFloat2(out);
nGetLastDynamicResolutionScale(getNativeObject(), out);
return out;
}
/**
* Sets the rendering quality for this view (e.g. color precision).
*
@@ -1298,6 +1331,7 @@ public class View {
private static native void nSetDithering(long nativeView, int dithering);
private static native int nGetDithering(long nativeView);
private static native void nSetDynamicResolutionOptions(long nativeView, boolean enabled, boolean homogeneousScaling, float minScale, float maxScale, float sharpness, int quality);
private static native void nGetLastDynamicResolutionScale(long nativeView, float[] out);
private static native void nSetRenderQuality(long nativeView, int hdrColorBufferQuality);
private static native void nSetDynamicLightingOptions(long nativeView, float zLightNear, float zLightFar);
private static native void nSetShadowType(long nativeView, int type);
@@ -1318,6 +1352,8 @@ public class View {
boolean lensFlare, boolean starburst, float chromaticAberration, int ghostCount, float ghostSpacing, float ghostThreshold, float haloThickness, float haloRadius, float haloThreshold);
private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float cutOffDistance, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, long skyColorNativeObject, boolean enabled);
private static native void nSetStereoscopicOptions(long nativeView, boolean enabled);
private static native void nSetChannelDepthClearEnabled(long nativeView, int channel, boolean enabled);
private static native boolean nIsChannelDepthClearEnabled(long nativeView, int channel);
private static native void nSetBlendMode(long nativeView, int blendMode);
private static native void nSetDepthOfFieldOptions(long nativeView, float cocScale, float maxApertureDiameter, boolean enabled, int filter,
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
@@ -1615,7 +1651,7 @@ public class View {
*
* This value is used as a tint instead, when fogColorFromIbl is enabled.
*
* @see fogColorFromIbl
* @see #fogColorFromIbl
*/
@NonNull @Size(min = 3)
public float[] color = {1.0f, 1.0f, 1.0f};
@@ -1656,7 +1692,7 @@ public class View {
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* @see skyColor
* @see #skyColor
*/
public boolean fogColorFromIbl = false;
/**
@@ -1674,7 +1710,7 @@ public class View {
* In `linearFog` mode mipmap level 0 is always used.
*
* @see Texture
* @see fogColorFromIbl
* @see #fogColorFromIbl
*/
@Nullable
public Texture skyColor = null;
@@ -1796,7 +1832,8 @@ public class View {
/**
* Structure used to set the precision of the color buffer and related quality settings.
*
* @see setRenderQuality, getRenderQuality
* @see #setRenderQuality
* @see #getRenderQuality
*/
public static class RenderQuality {
/**
@@ -1814,7 +1851,7 @@ public class View {
/**
* Options for screen space Ambient Occlusion (SSAO) and Screen Space Cone Tracing (SSCT)
* @see setAmbientOcclusionOptions()
* @see #setAmbientOcclusionOptions
*/
public static class AmbientOcclusionOptions {
public enum AmbientOcclusionType {
@@ -1966,7 +2003,7 @@ public class View {
/**
* Options for Multi-Sample Anti-aliasing (MSAA)
* @see setMultiSampleAntiAliasingOptions()
* @see #setMultiSampleAntiAliasingOptions
*/
public static class MultiSampleAntiAliasingOptions {
/**
@@ -1996,7 +2033,7 @@ public class View {
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
*
* @see setTemporalAntiAliasingOptions()
* @see #setTemporalAntiAliasingOptions
*/
public static class TemporalAntiAliasingOptions {
public enum BoxType {
@@ -2098,7 +2135,7 @@ public class View {
/**
* Options for Screen-space Reflections.
* @see setScreenSpaceReflectionsOptions()
* @see #setScreenSpaceReflectionsOptions
*/
public static class ScreenSpaceReflectionsOptions {
/**
@@ -2132,7 +2169,9 @@ public class View {
/**
* List of available post-processing anti-aliasing techniques.
* @see setAntiAliasing, getAntiAliasing, setSampleCount
* @see #setAntiAliasing
* @see #getAntiAliasing
* @see #setSampleCount
*/
public enum AntiAliasing {
/**
@@ -2161,7 +2200,7 @@ public class View {
/**
* List of available shadow mapping techniques.
* @see setShadowType
* @see #setShadowType
*/
public enum ShadowType {
/**
@@ -2185,7 +2224,7 @@ public class View {
/**
* View-level options for VSM Shadowing.
* @see setVsmShadowOptions()
* @see #setVsmShadowOptions
* @warning This API is still experimental and subject to change.
*/
public static class VsmShadowOptions {
@@ -2226,7 +2265,7 @@ public class View {
/**
* View-level options for DPCF and PCSS Shadowing.
* @see setSoftShadowOptions()
* @see #setSoftShadowOptions
* @warning This API is still experimental and subject to change.
*/
public static class SoftShadowOptions {

View File

@@ -16,6 +16,9 @@
package com.google.android.filament.utils
import android.graphics.Bitmap
import android.os.Handler
import android.os.Looper
import android.view.MotionEvent
import android.view.Surface
import android.view.SurfaceView
@@ -26,6 +29,7 @@ import com.google.android.filament.android.UiHelper
import com.google.android.filament.gltfio.*
import kotlinx.coroutines.*
import java.nio.Buffer
import java.nio.ByteBuffer
private const val kNearPlane = 0.05f // 5 cm
private const val kFarPlane = 1000.0f // 1 km
@@ -119,6 +123,8 @@ class ModelViewer(
private val target = DoubleArray(3)
private val upward = DoubleArray(3)
private var debugFrameCallback: ((Bitmap) -> Unit)? = null
init {
renderer = engine.createRenderer()
scene = engine.createScene()
@@ -305,10 +311,39 @@ class ModelViewer(
// Render the scene, unless the renderer wants to skip the frame.
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
renderer.render(view)
debugFrameCallback?.let {
val viewport = view.viewport
val bitmap = Bitmap.createBitmap(viewport.width, viewport.height,
Bitmap.Config.ARGB_8888)
val buffer = ByteBuffer.allocateDirect(viewport.width * viewport.height * 4)
val handler = Handler(Looper.getMainLooper())
val pixelBufferDescriptor = Texture.PixelBufferDescriptor(buffer,
Texture.Format.RGBA, Texture.Type.UBYTE, 1, 0, 0, 0, handler) {
buffer.rewind()
bitmap.copyPixelsFromBuffer(buffer)
it(bitmap)
}
renderer.readPixels(viewport.left, viewport.bottom, viewport.width,
viewport.height, pixelBufferDescriptor)
debugFrameCallback = null
}
renderer.endFrame()
}
}
/*
* Sets a callback that will be invoked with the next rendered frame as a Bitmap. Note that this
* is a one-time callback.
*
* @param callback callback to be invoked with a rendered frame as [Bitmap]
*/
fun debugGetNextFrameCallback(callback: (Bitmap) -> Unit) {
debugFrameCallback = callback
}
private fun populateScene(asset: FilamentAsset) {
val rcm = engine.renderableManager
var count = 0

View File

@@ -40,7 +40,21 @@ fun loadTexture(engine: Engine, resources: Resources, resourceId: Int, type: Tex
options.inPremultiplied = type == TextureType.COLOR
val bitmap = BitmapFactory.decodeResource(resources, resourceId, options)
return buildTexture(engine, bitmap, type)
}
fun loadTexture(engine: Engine, bytes: ByteArray, type: TextureType, offset: Int = 0, length: Int = bytes.size): Texture {
val options = BitmapFactory.Options()
// Color is the only type of texture we want to pre-multiply with the alpha channel
// Pre-multiplication is the default behavior, so we need to turn it off here
options.inPremultiplied = type == TextureType.COLOR
val bitmap = BitmapFactory.decodeByteArray(bytes, offset, length, options)
return buildTexture(engine, bitmap, type)
}
private fun buildTexture(engine: Engine, bitmap: Bitmap, type: TextureType): Texture {
val texture = Texture.Builder()
.width(bitmap.width)
.height(bitmap.height)

View File

@@ -22,6 +22,7 @@ object Utils {
/**
* Initializes the utils JNI layer. Must be called before using any utils functionality.
*/
@JvmStatic
fun init() {
// Load Filament first to ensure that the NioUtils Java class is available in the JNIEnv.
Filament.init()

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.65.1
VERSION_NAME=1.68.3
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -80,54 +80,12 @@ frame and the external texture are perfectly synchronized.
![Stream Test](../../docs/images/samples/sample_stream_test.jpg)
## Prerequisites
## Building Samples
Before you start, make sure to read [Filament's README](../../README.md). You need to be able to
compile Filament's native library and Filament's AAR for this project. The easiest way to proceed
is to install all the required dependencies and to run the following commands at the root of the
source tree:
source tree.
```shell
./build.sh -p desktop -i release
./build.sh -p android release
```
To build the samples, please follow the steps described in [BUILDING.md](../../BUILDING.md#android)
This will build all the native components and the AAR required by this sample application.
If you do not use the build script, you must set the `filament_tools_dir` property when invoking
Gradle, either from the command line or from `local.properties`. This property must point to the
distribution/install directory for desktop (produced by make/ninja install). This directory must
contain `bin/matc` and `bin/cmgen`.
Example:
```shell
./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
```
## Important: SDK location
Either ensure your `ANDROID_HOME` environment variable is set or make sure the root project
contains a `local.properties` file with the `sdk.dir` property pointing to your installation of
the Android SDK.
## Compiling
### Android Studio
You must use the latest stable release of Android Studio. To open the project, point Studio to the
`android` folder. After opening the project and syncing to gradle, select the sample of your choice
using the drop-down widget in the toolbar.
To compile and run each sample make sure you have selected the appropriate build variant
(arm7, arm8, x86 or x86_64). If you are not sure you can simply select the "universal"
variant which includes all the other ones.
### Command Line
From the `android` directory in the project root:
```shell
./gradlew :samples:sample-hello-triangle:installDebug
```
Replace `sample-hello-triangle` with your preferred project.

View File

@@ -17,12 +17,20 @@ filamentTools {
}
// don't forget to update MainACtivity.kt when/if changing this.
tasks.register('copyMesh', Copy) {
tasks.register('copyDamagedHelmetGltf', Copy) {
from file("../../../third_party/models/DamagedHelmet/DamagedHelmet.glb")
into file("src/main/assets/models")
rename {String fileName -> "helmet.glb"}
}
// don't forget to update MainACtivity.kt when/if changing this.
tasks.register('copyBusterGltf', Copy) {
from "../../../third_party/models/BusterDrone"
into "src/main/assets/models"
}
preBuild.dependsOn copyMesh
preBuild.dependsOn copyDamagedHelmetGltf
preBuild.dependsOn copyBusterGltf
clean.doFirst {
delete "src/main/assets"

View File

@@ -24,7 +24,7 @@ android {
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.hellocamera"
applicationId "com.google.android.filament.hellocam"
minSdkVersion 23
targetSdkVersion versions.targetSdk
}

View File

@@ -0,0 +1,12 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build
/captures
/src/main/assets
.externalNativeBuild

View File

@@ -0,0 +1,52 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
}
clean.doFirst {
delete "src/main/assets"
}
android {
namespace 'com.google.android.filament.materialinstancestress'
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.materialinstancestress"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
}
// NOTE: This is a workaround required because the AGP task collectReleaseDependencies
// is not configuration-cache friendly yet; this is only useful for Play publication
dependenciesInfo {
includeInApk = false
}
// We use the .filamat extension for materials compiled with matc
// Telling aapt to not compress them allows to load them efficiently
aaptOptions {
noCompress 'filamat', 'ktx'
}
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
}
dependencies {
implementation deps.kotlin
implementation project(':filament-android')
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:exported="true"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,532 @@
/*
* 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.
*/
package com.google.android.filament.materialinstancestress
import android.animation.ValueAnimator
import android.app.Activity
import android.opengl.Matrix
import android.os.Bundle
import android.view.Choreographer
import android.view.Surface
import android.view.SurfaceView
import android.view.animation.LinearInterpolator
import com.google.android.filament.*
import com.google.android.filament.RenderableManager.*
import com.google.android.filament.VertexBuffer.*
import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.Channels
import kotlin.math.cos
import kotlin.math.sin
class MainActivity : Activity() {
// Make sure to initialize Filament first
// This loads the JNI library needed by most API calls
companion object {
init {
Filament.init()
}
private const val NUM_CUBES = 1000
private const val GRID_SIZE = 10
private const val SPACING = 2.5f
}
// The View we want to render into
private lateinit var surfaceView: SurfaceView
// UiHelper is provided by Filament to manage SurfaceView and SurfaceTexture
private lateinit var uiHelper: UiHelper
// DisplayHelper is provided by Filament to manage the display
private lateinit var displayHelper: DisplayHelper
// Choreographer is used to schedule new frames
private lateinit var choreographer: Choreographer
// Engine creates and destroys Filament resources
// Each engine must be accessed from a single thread of your choosing
// Resources cannot be shared across engines
private lateinit var engine: Engine
// A renderer instance is tied to a single surface (SurfaceView, TextureView, etc.)
private lateinit var renderer: Renderer
// A scene holds all the renderable, lights, etc. to be drawn
private lateinit var scene: Scene
// A view defines a viewport, a scene and a camera for rendering
private lateinit var view: View
// Should be pretty obvious :)
private lateinit var camera: Camera
private lateinit var material: Material
private lateinit var vertexBuffer: VertexBuffer
private lateinit var indexBuffer: IndexBuffer
// Filament entity representing a renderable object
@Entity private val renderables = IntArray(NUM_CUBES)
private val materialInstances = arrayOfNulls<MaterialInstance>(NUM_CUBES)
private val translationMatrices = Array(NUM_CUBES) { FloatArray(16) }
@Entity private var light = 0
// A swap chain is Filament's representation of a surface
private var swapChain: SwapChain? = null
private var cameraRadius = 42.7f // Initial distance (calculated from original 15Y, 40Z)
private var cameraTheta = 0.0f // Azimuth (horizontal) in radians
private var cameraPhi = 0.358f // Elevation (vertical) in radians (from original 15Y, 40Z)
private var mLastX = 0.0f
private var mLastY = 0.0f
private val DRAG_SPEED = 0.005f
// Performs the rendering and schedules new frames
private val frameScheduler = FrameCallback()
private val animator = ValueAnimator.ofFloat(0.0f, 360.0f)
private val animatorListener = object : ValueAnimator.AnimatorUpdateListener {
// Pre-allocate matrix to avoid GC churn
private val transformMatrix = FloatArray(16)
override fun onAnimationUpdate(a: ValueAnimator) {
val tcm = engine.transformManager
val time = a.animatedFraction // 0.0 to 1.0
// Calculate the sine wave scale factor.
// sin(time * 2 * PI) oscillates between -1.0 and 1.0.
// We multiply by 0.5f (so it's -0.5 to 0.5) and add 1.0f.
// This makes the final 'scale' oscillate between 0.5 and 1.5.
val scale = 1.0f + sin(time * 2.0 * Math.PI).toFloat() * 0.5f
val localScale = (scale - 0.5f) * 0.5f + 0.5f
for (i in 0 until NUM_CUBES) {
val inst = tcm.getInstance(renderables[i])
val materialInst = materialInstances[i] ?: continue
// Get the cube's base position from its stored matrix
// The translation is in elements 12 (x), 13 (y), and 14 (z)
val baseX = translationMatrices[i][12]
val baseY = translationMatrices[i][13]
val baseZ = translationMatrices[i][14]
// Set the transformMatrix to a new translation matrix,
// scaled from the center (0,0,0)
Matrix.setIdentityM(transformMatrix, 0)
Matrix.translateM(transformMatrix, 0,
baseX * scale,
baseY * scale,
baseZ * scale)
Matrix.scaleM(transformMatrix, 0, localScale, localScale, localScale)
tcm.setTransform(inst, transformMatrix)
// Vary roughness
val roughness = 0.5f + 0.5f * sin(time * 2.0 * Math.PI + i * 0.1).toFloat()
materialInst.setParameter("roughness", roughness)
// Vary color (using linear RGB)
val r = 0.5f + 0.5f * cos(time * 2.0 * Math.PI + i * 0.5).toFloat()
val g = 0.5f + 0.5f * sin(time * 2.0 * Math.PI + i * 0.3).toFloat()
val b = 0.5f + 0.5f * cos(time * 2.0 * Math.PI + i * 0.1).toFloat()
materialInst.setParameter("baseColor", Colors.RgbType.LINEAR, r, g, b)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surfaceView = SurfaceView(this)
setContentView(surfaceView)
surfaceView.setOnTouchListener(touchListener)
choreographer = Choreographer.getInstance()
displayHelper = DisplayHelper(this)
setupSurfaceView()
setupFilament()
setupView()
setupScene()
}
private fun setupSurfaceView() {
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
uiHelper.renderCallback = SurfaceCallback()
uiHelper.attachTo(surfaceView)
}
private fun setupFilament() {
engine = Engine.create()
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine)
view.camera = camera
view.scene = scene
}
private fun setupScene() {
loadMaterial()
createMesh()
val tcm = engine.transformManager
val center = (GRID_SIZE - 1) * 0.5f
for (i in 0 until NUM_CUBES) {
// Calculate grid position
val x = (i % GRID_SIZE) - center
val y = ((i / GRID_SIZE) % GRID_SIZE) - center
val z = (i / (GRID_SIZE * GRID_SIZE)) - center
val posX = x * SPACING
val posY = y * SPACING
val posZ = z * SPACING
// Create material instance for this cube
materialInstances[i] = material.createInstance()
// Set initial parameters (will be overwritten by animator, but good practice)
materialInstances[i]?.setParameter("baseColor", Colors.RgbType.SRGB, 1.0f, 0.85f, 0.57f)
materialInstances[i]?.setParameter("metallic", 0.0f)
materialInstances[i]?.setParameter("roughness", 0.3f)
// Create the renderable entity
renderables[i] = EntityManager.get().create()
// Create the renderable component
RenderableManager.Builder(1)
.boundingBox(Box(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f))
.geometry(0, PrimitiveType.TRIANGLES, vertexBuffer, indexBuffer, 0, 6 * 6)
.material(0, materialInstances[i]!!)
.build(engine, renderables[i])
// Add to scene
scene.addEntity(renderables[i])
// Set its initial transform
// Store the base translation matrix
Matrix.setIdentityM(translationMatrices[i], 0)
Matrix.translateM(translationMatrices[i], 0, posX, posY, posZ)
// Get the transform component instance
val inst = tcm.getInstance(renderables[i])
tcm.setTransform(inst, translationMatrices[i])
}
// We now need a light, let's create a directional light
light = EntityManager.get().create()
val (r, g, b) = Colors.cct(5_500.0f)
LightManager.Builder(LightManager.Type.DIRECTIONAL)
.color(r, g, b)
.intensity(110_000.0f)
.direction(0.0f, -0.5f, -1.0f)
.castShadows(true)
.build(engine, light)
scene.addEntity(light)
camera.setExposure(16.0f, 1.0f / 125.0f, 100.0f)
updateCamera()
startAnimation()
}
private fun loadMaterial() {
readUncompressedAsset("materials/lit.filamat").let {
material = Material.Builder().payload(it, it.remaining()).build(engine)
}
}
private fun createMesh() {
val floatSize = 4
val shortSize = 2
val vertexSize = 3 * floatSize + 4 * floatSize
// A vertex is a position + a tangent frame:
// 3 floats for XYZ position, 4 floats for normal+tangents (quaternion)
@Suppress("ArrayInDataClass")
data class Vertex(val x: Float, val y: Float, val z: Float, val tangents: FloatArray)
fun ByteBuffer.put(v: Vertex): ByteBuffer {
putFloat(v.x)
putFloat(v.y)
putFloat(v.z)
v.tangents.forEach { putFloat(it) }
return this
}
// 6 faces, 4 vertices per face
val vertexCount = 6 * 4
// Create tangent frames, one per face
val tfPX = FloatArray(4)
val tfNX = FloatArray(4)
val tfPY = FloatArray(4)
val tfNY = FloatArray(4)
val tfPZ = FloatArray(4)
val tfNZ = FloatArray(4)
MathUtils.packTangentFrame( 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, tfPX)
MathUtils.packTangentFrame( 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, tfNX)
MathUtils.packTangentFrame(-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, tfPY)
MathUtils.packTangentFrame(-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, tfNY)
MathUtils.packTangentFrame( 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, tfPZ)
MathUtils.packTangentFrame( 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, tfNZ)
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
// It is important to respect the native byte order
.order(ByteOrder.nativeOrder())
// Face -Z
.put(Vertex(-1.0f, -1.0f, -1.0f, tfNZ))
.put(Vertex(-1.0f, 1.0f, -1.0f, tfNZ))
.put(Vertex( 1.0f, 1.0f, -1.0f, tfNZ))
.put(Vertex( 1.0f, -1.0f, -1.0f, tfNZ))
// Face +X
.put(Vertex( 1.0f, -1.0f, -1.0f, tfPX))
.put(Vertex( 1.0f, 1.0f, -1.0f, tfPX))
.put(Vertex( 1.0f, 1.0f, 1.0f, tfPX))
.put(Vertex( 1.0f, -1.0f, 1.0f, tfPX))
// Face +Z
.put(Vertex(-1.0f, -1.0f, 1.0f, tfPZ))
.put(Vertex( 1.0f, -1.0f, 1.0f, tfPZ))
.put(Vertex( 1.0f, 1.0f, 1.0f, tfPZ))
.put(Vertex(-1.0f, 1.0f, 1.0f, tfPZ))
// Face -X
.put(Vertex(-1.0f, -1.0f, 1.0f, tfNX))
.put(Vertex(-1.0f, 1.0f, 1.0f, tfNX))
.put(Vertex(-1.0f, 1.0f, -1.0f, tfNX))
.put(Vertex(-1.0f, -1.0f, -1.0f, tfNX))
// Face -Y
.put(Vertex(-1.0f, -1.0f, 1.0f, tfNY))
.put(Vertex(-1.0f, -1.0f, -1.0f, tfNY))
.put(Vertex( 1.0f, -1.0f, -1.0f, tfNY))
.put(Vertex( 1.0f, -1.0f, 1.0f, tfNY))
// Face +Y
.put(Vertex(-1.0f, 1.0f, -1.0f, tfPY))
.put(Vertex(-1.0f, 1.0f, 1.0f, tfPY))
.put(Vertex( 1.0f, 1.0f, 1.0f, tfPY))
.put(Vertex( 1.0f, 1.0f, -1.0f, tfPY))
// Make sure the cursor is pointing in the right place in the byte buffer
.flip()
// Declare the layout of our mesh
vertexBuffer = VertexBuffer.Builder()
.bufferCount(1)
.vertexCount(vertexCount)
// Because we interleave position and color data we must specify offset and stride
// We could use de-interleaved data by declaring two buffers and giving each
// attribute a different buffer index
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, vertexSize)
.attribute(VertexAttribute.TANGENTS, 0, AttributeType.FLOAT4, 3 * floatSize, vertexSize)
.build(engine)
// Feed the vertex data to the mesh
// We only set 1 buffer because the data is interleaved
vertexBuffer.setBufferAt(engine, 0, vertexData)
// Create the indices
val indexData = ByteBuffer.allocate(6 * 2 * 3 * shortSize)
.order(ByteOrder.nativeOrder())
repeat(6) {
val i = (it * 4).toShort()
indexData
.putShort(i).putShort((i + 1).toShort()).putShort((i + 2).toShort())
.putShort(i).putShort((i + 2).toShort()).putShort((i + 3).toShort())
}
indexData.flip()
// 6 faces, 2 triangles per face,
indexBuffer = IndexBuffer.Builder()
.indexCount(vertexCount * 2)
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
.build(engine)
indexBuffer.setBuffer(engine, indexData)
}
private fun updateCamera() {
// Calculate eye position from spherical coordinates
val eyeY = cameraRadius * sin(cameraPhi)
val horizontalRadius = cameraRadius * cos(cameraPhi)
val eyeX = horizontalRadius * sin(cameraTheta)
val eyeZ = horizontalRadius * cos(cameraTheta)
// Point the camera at the center (0,0,0)
camera.lookAt(eyeX.toDouble(), eyeY.toDouble(), eyeZ.toDouble(), // eye
0.0, 0.0, 0.0, // center
0.0, 1.0, 0.0) // up
}
private val touchListener = object : android.view.View.OnTouchListener {
override fun onTouch(v: android.view.View?, event: android.view.MotionEvent?): Boolean {
if (event == null) return false
when (event.action) {
android.view.MotionEvent.ACTION_DOWN -> {
mLastX = event.x
mLastY = event.y
return true
}
android.view.MotionEvent.ACTION_MOVE -> {
val dx = event.x - mLastX
val dy = event.y - mLastY
cameraTheta -= dx * DRAG_SPEED
cameraPhi += dy * DRAG_SPEED
// Clamp vertical angle to avoid flipping over
cameraPhi = cameraPhi.coerceIn(-1.5f, 1.5f)
updateCamera()
mLastX = event.x
mLastY = event.y
return true
}
}
return v?.onTouchEvent(event) ?: false
}
}
private fun startAnimation() {
animator.interpolator = LinearInterpolator()
animator.duration = 6000
animator.repeatMode = ValueAnimator.RESTART
animator.repeatCount = ValueAnimator.INFINITE
animator.addUpdateListener(animatorListener)
animator.start()
}
override fun onResume() {
super.onResume()
choreographer.postFrameCallback(frameScheduler)
animator.start()
}
override fun onPause() {
super.onPause()
choreographer.removeFrameCallback(frameScheduler)
animator.cancel()
}
override fun onDestroy() {
super.onDestroy()
// Stop the animation and any pending frame
choreographer.removeFrameCallback(frameScheduler)
animator.cancel();
// Always detach the surface before destroying the engine
uiHelper.detach()
// Cleanup all resources
engine.destroyEntity(light)
// Destroy all 1000 entities and material instances
for (i in 0 until NUM_CUBES) {
engine.destroyEntity(renderables[i])
materialInstances[i]?.let { engine.destroyMaterialInstance(it) }
}
engine.destroyRenderer(renderer)
engine.destroyVertexBuffer(vertexBuffer)
engine.destroyIndexBuffer(indexBuffer)
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
for (entity in renderables) {
entityManager.destroy(entity)
}
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly
engine.destroy()
}
inner class FrameCallback : Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
// Schedule the next frame
choreographer.postFrameCallback(this)
// This check guarantees that we have a swap chain
if (uiHelper.isReadyToRender) {
// If beginFrame() returns false you should skip the frame
// This means you are sending frames too quickly to the GPU
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
renderer.render(view)
renderer.endFrame()
}
}
}
}
inner class SurfaceCallback : UiHelper.RendererCallback {
override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) }
swapChain = engine.createSwapChain(surface)
displayHelper.attach(renderer, surfaceView.display)
}
override fun onDetachedFromSurface() {
displayHelper.detach()
swapChain?.let {
engine.destroySwapChain(it)
// Required to ensure we don't return before Filament is done executing the
// destroySwapChain command, otherwise Android might destroy the Surface
// too early
engine.flushAndWait()
swapChain = null
}
}
override fun onResized(width: Int, height: Int) {
val aspect = width.toDouble() / height.toDouble()
camera.setProjection(45.0, aspect, 0.1, 100.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
}
}
private fun readUncompressedAsset(assetName: String): ByteBuffer {
assets.openFd(assetName).use { fd ->
val input = fd.createInputStream()
val dst = ByteBuffer.allocate(fd.length.toInt())
val src = Channels.newChannel(input)
src.read(dst)
src.close()
return dst.apply { rewind() }
}
}
}

View File

@@ -0,0 +1,53 @@
// Simple lit material that defines 3 parameters:
// - baseColor
// - roughness
// - metallic
//
// These parameters can be used by the application to change the appearance of the material.
//
// This source material must be compiled to a binary material using the matc tool.
// The command used to compile this material is:
// matc -p mobile -a opengl -o app/src/main/assets/lit.filamat app/src/materials/lit.mat
//
// See build.gradle for an example of how to compile materials automatically
// Please refer to the documentation for more information about matc and the materials system.
material {
name : lit,
// Dynamic lighting is enabled on this material
shadingModel : lit,
// We don't need to declare a "requires" array, lit materials
// always requires the "tangents" vertex attribute (the normal
// is required for lighting, tangent/bitangent for normal mapping
// and anisotropy)
// List of parameters exposed by this material
parameters : [
// The color must be passed in linear space, not sRGB
{
type : float3,
name : baseColor
},
{
type : float,
name : roughness
},
{
type : float,
name : metallic
}
],
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
// Nothing fancy here, we simply copy the parameters
material.baseColor.rgb = materialParams.baseColor;
material.roughness = materialParams.roughness;
material.metallic = materialParams.metallic;
}
}

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z"/>
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Material Instance Stress</string>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,12 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build
/captures
/src/main/assets
.externalNativeBuild

View File

@@ -0,0 +1,53 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
}
clean.doFirst {
delete "src/main/assets"
}
android {
namespace 'com.google.android.filament.texturetarget'
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.texturetarget"
minSdkVersion 26
targetSdkVersion versions.targetSdk
}
// NOTE: This is a workaround required because the AGP task collectReleaseDependencies
// is not configuration-cache friendly yet; this is only useful for Play publication
dependenciesInfo {
includeInApk = false
}
// We use the .filamat extension for materials compiled with matc
// Telling aapt to not compress them allows to load them efficiently
aaptOptions {
noCompress 'filamat', 'ktx'
}
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
}
dependencies {
implementation deps.kotlin
implementation project(':filament-android')
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:exported="true"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,429 @@
/*
* Copyright (C) 2024 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.
*/
package com.google.android.filament.texturetarget
import android.animation.ValueAnimator
import android.app.Activity
import android.hardware.HardwareBuffer
import android.opengl.Matrix
import android.os.Bundle
import android.view.Choreographer
import android.view.Surface
import android.view.SurfaceView
import android.view.animation.LinearInterpolator
import com.google.android.filament.*
import com.google.android.filament.RenderableManager.PrimitiveType
import com.google.android.filament.VertexBuffer.AttributeType
import com.google.android.filament.VertexBuffer.VertexAttribute
import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.Channels
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
class MainActivity : Activity() {
companion object {
init {
Filament.init()
}
}
private lateinit var surfaceView: SurfaceView
private lateinit var uiHelper: UiHelper
private lateinit var displayHelper: DisplayHelper
private lateinit var choreographer: Choreographer
private lateinit var engine: Engine
private lateinit var renderer: Renderer
private lateinit var scene: Scene
private lateinit var view: View
private lateinit var camera: Camera
private lateinit var triangleMaterial: Material
private lateinit var texturedMaterial: Material
private lateinit var triangleVertexBuffer: VertexBuffer
private lateinit var triangleIndexBuffer: IndexBuffer
private lateinit var quadVertexBuffer: VertexBuffer
private lateinit var quadIndexBuffer: IndexBuffer
@Entity private var triangleRenderable = 0
@Entity private var quadRenderable = 0
private var swapChain: SwapChain? = null
private val frameScheduler = FrameCallback()
private val animator = ValueAnimator.ofFloat(0.0f, 360.0f)
private var hardwareBuffer: HardwareBuffer? = null
private var texture: Texture? = null
private var renderTarget: RenderTarget? = null
private lateinit var offscreenView: View
private lateinit var offscreenCamera: Camera
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surfaceView = SurfaceView(this)
setContentView(surfaceView)
choreographer = Choreographer.getInstance()
displayHelper = DisplayHelper(this)
setupSurfaceView()
setupFilament()
setupView()
setupScene()
}
private fun setupSurfaceView() {
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
uiHelper.renderCallback = SurfaceCallback()
uiHelper.attachTo(surfaceView)
}
private fun setupFilament() {
engine = Engine.create()
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera(engine.entityManager.create())
offscreenView = engine.createView()
offscreenCamera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
scene.skybox = Skybox.Builder()
.priority(0)
.color(0.0f, 0.0f, 1.0f, 1.0f).build(engine)
// This is the view that will be drawn on screen.
view.camera = camera
view.scene = scene
view.isPostProcessingEnabled = false
// This is the view that will be rendered off-screen.
offscreenView.camera = offscreenCamera
offscreenView.scene = scene
offscreenView.isPostProcessingEnabled = false
}
private fun setupScene() {
loadMaterials()
createTriangleMesh()
createQuadMesh()
// layer 1: skybox
// layer 2: triangle
// layer 3: quad
triangleMaterial.defaultInstance.cullingMode = Material.CullingMode.NONE;
texturedMaterial.defaultInstance.cullingMode = Material.CullingMode.NONE;
// The triangle is a regular renderable.
triangleRenderable = EntityManager.get().create()
RenderableManager.Builder(1)
.geometry(0, PrimitiveType.TRIANGLES, triangleVertexBuffer, triangleIndexBuffer, 0, 3)
.material(0, triangleMaterial.defaultInstance)
.culling(false)
.castShadows(false)
.receiveShadows(false)
.layerMask(7, 2)
.build(engine, triangleRenderable)
// The quad is a regular renderable.
quadRenderable = EntityManager.get().create()
RenderableManager.Builder(1)
.geometry(0, PrimitiveType.TRIANGLES, quadVertexBuffer, quadIndexBuffer, 0, 6)
.material(0, texturedMaterial.defaultInstance)
.culling(false)
.castShadows(false)
.receiveShadows(false)
.layerMask(7, 4)
.build(engine, quadRenderable)
// We only want to render the triangle in the offscreen view.
offscreenView.setVisibleLayers(7, 3) // render skybox + triangle
// We only want to render the quad in the on-screen view.
view.setVisibleLayers(7, 4) // render quad only
scene.addEntity(triangleRenderable)
scene.addEntity(quadRenderable)
startAnimation()
}
private fun loadMaterials() {
readUncompressedAsset("materials/baked_color.filamat").let {
triangleMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
}
readUncompressedAsset("materials/textured.filamat").let {
texturedMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
}
}
private fun createTriangleMesh() {
val intSize = 4
val floatSize = 4
val shortSize = 2
val vertexSize = 3 * floatSize + intSize
data class Vertex(val x: Float, val y: Float, val z: Float, val color: Int)
fun ByteBuffer.put(v: Vertex): ByteBuffer {
putFloat(v.x)
putFloat(v.y)
putFloat(v.z)
putInt(v.color)
return this
}
val vertexCount = 3
val a1 = PI * 2.0 / 3.0
val a2 = PI * 4.0 / 3.0
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
.order(ByteOrder.nativeOrder())
.put(Vertex(1.0f, 0.0f, 0.0f, 0xffff0000.toInt()))
.put(Vertex(cos(a1).toFloat(), sin(a1).toFloat(), 0.0f, 0xff00ff00.toInt()))
.put(Vertex(cos(a2).toFloat(), sin(a2).toFloat(), 0.0f, 0xff0000ff.toInt()))
.flip()
triangleVertexBuffer = VertexBuffer.Builder()
.bufferCount(1)
.vertexCount(vertexCount)
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, vertexSize)
.attribute(VertexAttribute.COLOR, 0, AttributeType.UBYTE4, 3 * floatSize, vertexSize)
.normalized(VertexAttribute.COLOR)
.build(engine)
triangleVertexBuffer.setBufferAt(engine, 0, vertexData)
val indexData = ByteBuffer.allocate(vertexCount * shortSize)
.order(ByteOrder.nativeOrder())
.putShort(0)
.putShort(1)
.putShort(2)
.flip()
triangleIndexBuffer = IndexBuffer.Builder()
.indexCount(3)
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
.build(engine)
triangleIndexBuffer.setBuffer(engine, indexData)
}
private fun createQuadMesh() {
val floatSize = 4
val shortSize = 2
val vertexSize = (2 * floatSize) + (2 * floatSize) // position + UV
data class Vertex(val x: Float, val y: Float, val u: Float, val v: Float)
fun ByteBuffer.put(v: Vertex): ByteBuffer {
putFloat(v.x)
putFloat(v.y)
putFloat(v.u)
putFloat(v.v)
return this
}
val vertexCount = 4
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
.order(ByteOrder.nativeOrder())
.put(Vertex(-1.0f, -1.0f, 0.0f, 0.0f))
.put(Vertex( 1.0f, -1.0f, 1.0f, 0.0f))
.put(Vertex( 1.0f, 1.0f, 1.0f, 1.0f))
.put(Vertex(-1.0f, 1.0f, 0.0f, 1.0f))
.flip()
quadVertexBuffer = VertexBuffer.Builder()
.bufferCount(1)
.vertexCount(vertexCount)
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, vertexSize)
.attribute(VertexAttribute.UV0, 0, AttributeType.FLOAT2, 2 * floatSize, vertexSize)
.build(engine)
quadVertexBuffer.setBufferAt(engine, 0, vertexData)
val indexData = ByteBuffer.allocate(6 * shortSize)
.order(ByteOrder.nativeOrder())
.putShort(0).putShort(1).putShort(2)
.putShort(0).putShort(2).putShort(3)
.flip()
quadIndexBuffer = IndexBuffer.Builder()
.indexCount(6)
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
.build(engine)
quadIndexBuffer.setBuffer(engine, indexData)
}
private fun startAnimation() {
animator.interpolator = LinearInterpolator()
animator.duration = 4000
animator.repeatMode = ValueAnimator.RESTART
animator.repeatCount = ValueAnimator.INFINITE
animator.addUpdateListener { a ->
val transformMatrix = FloatArray(16)
Matrix.setRotateM(transformMatrix, 0, -(a.animatedValue as Float), 0.0f, 0.0f, 1.0f)
val tcm = engine.transformManager
tcm.setTransform(tcm.getInstance(triangleRenderable), transformMatrix)
}
animator.start()
}
override fun onResume() {
super.onResume()
choreographer.postFrameCallback(frameScheduler)
animator.start()
}
override fun onPause() {
super.onPause()
choreographer.removeFrameCallback(frameScheduler)
animator.cancel()
}
override fun onDestroy() {
super.onDestroy()
choreographer.removeFrameCallback(frameScheduler)
animator.cancel()
uiHelper.detach()
// Destroy all renderables.
scene.remove(triangleRenderable)
scene.remove(quadRenderable)
// Destroy all resources.
engine.destroyEntity(triangleRenderable)
engine.destroyEntity(quadRenderable)
engine.destroyRenderer(renderer)
engine.destroyVertexBuffer(triangleVertexBuffer)
engine.destroyIndexBuffer(triangleIndexBuffer)
engine.destroyVertexBuffer(quadVertexBuffer)
engine.destroyIndexBuffer(quadIndexBuffer)
engine.destroyMaterial(triangleMaterial)
engine.destroyMaterial(texturedMaterial)
engine.destroyView(view)
engine.destroyView(offscreenView)
engine.destroyScene(scene)
engine.destroyCameraComponent(camera.entity)
engine.destroyCameraComponent(offscreenCamera.entity)
renderTarget?.let { engine.destroyRenderTarget(it) }
texture?.let { engine.destroyTexture(it) }
hardwareBuffer?.close()
val entityManager = EntityManager.get()
entityManager.destroy(triangleRenderable)
entityManager.destroy(quadRenderable)
entityManager.destroy(camera.entity)
entityManager.destroy(offscreenCamera.entity)
engine.destroy()
}
inner class FrameCallback : Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
choreographer.postFrameCallback(this)
if (uiHelper.isReadyToRender) {
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
// Render the triangle to the texture.
renderer.render(offscreenView)
// Render the quad to the screen.
renderer.render(view)
renderer.endFrame()
}
}
}
}
inner class SurfaceCallback : UiHelper.RendererCallback {
override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) }
swapChain = engine.createSwapChain(surface, uiHelper.swapChainFlags)
displayHelper.attach(renderer, surfaceView.display)
}
override fun onDetachedFromSurface() {
displayHelper.detach()
swapChain?.let {
engine.destroySwapChain(it)
engine.flushAndWait()
swapChain = null
}
}
override fun onResized(width: Int, height: Int) {
// On-screen camera
val zoom = 1.0
val aspect = width.toDouble() / height.toDouble()
camera.setProjection(Camera.Projection.ORTHO, -aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
view.viewport = Viewport(0, 0, width, height)
// Off-screen camera
val offscreenZoom = 1.5
offscreenCamera.setProjection(Camera.Projection.ORTHO,
-aspect * offscreenZoom, aspect * offscreenZoom,
-offscreenZoom, offscreenZoom, 0.0, 10.0)
offscreenView.viewport = Viewport(0, 0, width, height)
// If we have a render target, destroy it.
renderTarget?.let { engine.destroyRenderTarget(it) }
texture?.let { engine.destroyTexture(it) }
hardwareBuffer?.close()
// Create a new render target.
hardwareBuffer = HardwareBuffer.create(width, height,
HardwareBuffer.RGBA_8888, 1,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT)
texture = Texture.Builder()
.width(width)
.height(height)
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
.sampler(Texture.Sampler.SAMPLER_EXTERNAL)
.format(Texture.InternalFormat.RGBA8)
.external()
.build(engine)
texture!!.setExternalImage(engine, hardwareBuffer!!)
renderTarget = RenderTarget.Builder()
.texture(RenderTarget.AttachmentPoint.COLOR, texture!!)
.build(engine)
offscreenView.renderTarget = renderTarget
// Set the texture on the quad material.
texturedMaterial.defaultInstance.setParameter("texture", texture!!,
TextureSampler(TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR,
TextureSampler.WrapMode.CLAMP_TO_EDGE))
FilamentHelper.synchronizePendingFrames(engine)
}
}
private fun readUncompressedAsset(assetName: String): ByteBuffer {
assets.openFd(assetName).use { fd ->
val input = fd.createInputStream()
val dst = ByteBuffer.allocate(fd.length.toInt())
val src = Channels.newChannel(input)
src.read(dst)
src.close()
return dst.apply { rewind() }
}
}
}

View File

@@ -0,0 +1,18 @@
material {
name : baked_color,
shadingModel : unlit,
requires : [
color
]
}
fragment {
void material(inout MaterialInputs material) {
// You must always call the prepareMaterial() function
prepareMaterial(material);
// We set the material's color to the color interpolated from
// the model's vertices
material.baseColor = getColor();
}
}

View File

@@ -0,0 +1,20 @@
material {
name : textured,
shadingModel : unlit,
parameters : [
{
type : samplerExternal,
name : texture
}
],
requires: [
uv0
]
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = texture(materialParams_texture, getUV0());
}
}

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z"/>
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8"/>
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Texture Target</string>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -12,10 +12,12 @@ include ':samples:sample-image-based-lighting'
include ':samples:sample-lit-cube'
include ':samples:sample-live-wallpaper'
include ':samples:sample-material-builder'
include ':samples:sample-material-instance-stress'
include ':samples:sample-multi-view'
include ':samples:sample-page-curl'
include ':samples:sample-stream-test'
include ':samples:sample-texture-view'
include ':samples:sample-texture-target'
include ':samples:sample-textured-object'
include ':samples:sample-transparent-view'

View File

@@ -77,6 +77,10 @@ function print_help {
echo " meant for building the samples."
echo " -P"
echo " Enable perfetto traces on Android. Disabled by default on the Release build, enabled otherwise."
echo " -y build_type"
echo " Build the filament dependent tools (matc, resgen) separately from the project. This will set"
echo " the tools as prebuilts that filament target will then use to build. The built_type option"
echo " (debug|release) is meant to indicate the type of build of the resulting prebuilts."
echo ""
echo "Build types:"
echo " release"
@@ -154,7 +158,7 @@ function print_fgviewer_help {
}
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g | cut -f 1 -d ".")}
FILAMENT_NDK_VERSION=$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g | cut -f 1 -d ".")
# Internal variables
ISSUE_CLEAN=false
@@ -217,6 +221,11 @@ OSMESA_OPTION=""
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
ISSUE_SPLIT_BUILD=false
SPLIT_BUILD_TYPE=""
PREBUILT_TOOLS_DIR=""
IMPORT_EXECUTABLES_DIR_OPTION="-DIMPORT_EXECUTABLES_DIR=out"
BUILD_GENERATOR=Ninja
BUILD_COMMAND=ninja
BUILD_CUSTOM_TARGETS=
@@ -242,6 +251,37 @@ function build_clean_aggressive {
git clean -qfX android
}
function build_tools_for_split_build {
local build_type_arg=$1
local lc_build_type=$(echo "${build_type_arg}" | tr '[:upper:]' '[:lower:]')
PREBUILT_TOOLS_DIR="out/prebuilt-tools-${lc_build_type}"
echo "Building tools for split build (${lc_build_type}) in ${PREBUILT_TOOLS_DIR}..."
mkdir -p "${PREBUILT_TOOLS_DIR}"
pushd "${PREBUILT_TOOLS_DIR}" > /dev/null
local lc_name=$(echo "${UNAME}" | tr '[:upper:]' '[:lower:]')
local architectures=""
if [[ "${lc_name}" == "darwin" ]]; then
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
architectures="-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64"
fi
fi
cmake \
-G "${BUILD_GENERATOR}" \
-DFILAMENT_EXPORT_PREBUILT_EXECUTABLES_DIR=${PREBUILT_TOOLS_DIR} \
-DCMAKE_BUILD_TYPE="${build_type_arg}" \
${WEBGPU_OPTION} \
${architectures} \
../..
${BUILD_COMMAND} ${WEB_HOST_TOOLS}
popd > /dev/null
}
function build_desktop_target {
local lc_target=$(echo "$1" | tr '[:upper:]' '[:lower:]')
local build_targets=$2
@@ -265,7 +305,7 @@ function build_desktop_target {
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
-G "${BUILD_GENERATOR}" \
-DIMPORT_EXECUTABLES_DIR=out \
${IMPORT_EXECUTABLES_DIR_OPTION} \
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
${EGL_ON_LINUX_OPTION} \
@@ -331,7 +371,7 @@ function build_webgl_with_target {
source "${EMSDK}/emsdk_env.sh"
cmake \
-G "${BUILD_GENERATOR}" \
-DIMPORT_EXECUTABLES_DIR=out \
${IMPORT_EXECUTABLES_DIR_OPTION} \
-DCMAKE_TOOLCHAIN_FILE="${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake" \
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../webgl-${lc_target}/filament" \
@@ -404,7 +444,7 @@ function build_android_target {
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
-G "${BUILD_GENERATOR}" \
-DIMPORT_EXECUTABLES_DIR=out \
${IMPORT_EXECUTABLES_DIR_OPTION} \
-DCMAKE_BUILD_TYPE="$1" \
-DFILAMENT_NDK_VERSION="${FILAMENT_NDK_VERSION}" \
-DCMAKE_INSTALL_PREFIX="../android-${lc_target}/filament" \
@@ -516,11 +556,14 @@ function build_android {
archive_android "Release"
fi
local root_dir=$(pwd)
pushd android > /dev/null
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${WEBGPU_ANDROID_GRADLE_OPTION} \
@@ -533,6 +576,7 @@ function build_android {
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${WEBGPU_ANDROID_GRADLE_OPTION} \
:filamat-android:assembleDebug
@@ -541,6 +585,7 @@ function build_android {
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:samples:${sample}:assembleDebug
@@ -573,6 +618,7 @@ function build_android {
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${WEBGPU_ANDROID_GRADLE_OPTION} \
@@ -585,6 +631,7 @@ function build_android {
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${WEBGPU_ANDROID_GRADLE_OPTION} \
:filamat-android:assembleRelease
@@ -593,6 +640,7 @@ function build_android {
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:samples:${sample}:assembleRelease
@@ -638,7 +686,7 @@ function build_ios_target {
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
-G "${BUILD_GENERATOR}" \
-DIMPORT_EXECUTABLES_DIR=out \
${IMPORT_EXECUTABLES_DIR_OPTION} \
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../ios-${lc_target}/filament" \
-DIOS_ARCH="${arch}" \
@@ -810,7 +858,7 @@ function check_debug_release_build {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
case ${opt} in
h)
print_help
@@ -979,6 +1027,20 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
;;
X) OSMESA_OPTION="-DFILAMENT_OSMESA_PATH=${OPTARG}"
;;
y)
ISSUE_SPLIT_BUILD=true
SPLIT_BUILD_TYPE=${OPTARG}
case $(echo "${SPLIT_BUILD_TYPE}" | tr '[:upper:]' '[:lower:]') in
debug|release)
;;
*)
echo "Unknown build type for -y: ${SPLIT_BUILD_TYPE}"
echo "Build type must be one of [debug|release]"
echo ""
exit 1
;;
esac
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo ""
@@ -1013,6 +1075,13 @@ done
validate_build_command
if [[ "${ISSUE_SPLIT_BUILD}" == "true" ]]; then
# Capitalize first letter of SPLIT_BUILD_TYPE
SPLIT_BUILD_TYPE_CAPITALIZED="$(echo ${SPLIT_BUILD_TYPE:0:1} | tr '[:lower:]' '[:upper:]')${SPLIT_BUILD_TYPE:1}"
build_tools_for_split_build "${SPLIT_BUILD_TYPE_CAPITALIZED}"
IMPORT_EXECUTABLES_DIR_OPTION="-DFILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR=${PREBUILT_TOOLS_DIR}"
fi
if [[ "${ISSUE_CLEAN}" == "true" ]]; then
build_clean
fi

View File

@@ -18,8 +18,8 @@ if [[ "$GITHUB_WORKFLOW" ]]; then
fi
fi
# Unless explicitly specified, NDK version will be set to match exactly the required one
FILAMENT_NDK_VERSION=${GITHUB_NDK_VERSION:-27.0.11718014}
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
FILAMENT_NDK_VERSION=$(cat `dirname $0`/../common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g)
(! grep "${FILAMENT_NDK_VERSION}" `dirname $0`/../../android/build.gradle > /dev/null) &&
echo "Mismatch of NDK versions: want ${FILAMENT_NDK_VERSION} and not found in android/build.gradle" &&

View File

@@ -1,6 +1,5 @@
libs/viewer/test_settings
filament/test/test_filament --gtest_filter=-FilamentTest.FroxelData:FilamentExposureWithEngineTest.SetExposure:FilamentExposureWithEngineTest.ComputeEV100:RenderingTest.*
filament/test/test_material_parser
libs/math/test_math
libs/image/test_image compare libs/image/tests/reference/
libs/utils/test_utils

View File

@@ -3,7 +3,7 @@ GITHUB_CMAKE_VERSION=3.22.1
GITHUB_NINJA_VERSION=1.10.2
GITHUB_MESA_VERSION=24.2.1
GITHUB_LLVM_VERSION=16
GITHUB_NDK_VERSION=27.0.11718014
GITHUB_NDK_VERSION=29.0.14206865
GITHUB_EMSDK_VERSION=3.1.60
GITHUB_VULKANSDK_VERSION=1.4.321.0
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f

View File

@@ -75,7 +75,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# C_FLAGS += -Wl,-pie
# CXX_FLAGS += -lstdc++
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -mcpu=cortex-a57" CACHE STRING "Toolchain CFLAGS")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -march=armv8-a -mtune=cortex-a78" CACHE STRING "Toolchain CFLAGS")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING "Toolchain CXXFLAGS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")

View File

@@ -87,7 +87,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# for hardfp: CFLAGS must have -mhard-float
# LDFLAGS must have -Wl,--no-warn-mismatch
#
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -march=armv7-a -mcpu=cortex-a15 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE" CACHE STRING "Toolchain CFLAGS")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE" CACHE STRING "Toolchain CFLAGS")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING "Toolchain CXXFLAGS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -march=armv7-a -Wl,--no-warn-mismatch -L${TOOLCHAIN}/arm-linux-androideabi/lib/armv7-a -static-libstdc++ -fPIE -pie" CACHE STRING "Toolchain LDFLAGS")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -march=armv7-a -Wl,--no-warn-mismatch -L${TOOLCHAIN}/arm-linux-androideabi/lib/armv7-a -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")

View File

@@ -165,8 +165,8 @@ Portal</a>.</p>
<p>To publish under the <code>com.google.android</code> namespace, you'll also need to email
<code>central-support@sonatype.com</code> with your account information to request access.</p>
<p>Then, generate a user token through the Sonatype website. Navigate to
<a href="https://central.sonatype.com/account">https://central.sonatype.com/account</a> and select <strong>Generate
User Token</strong>.</p>
<a href="https://central.sonatype.com/usertoken">https://central.sonatype.com/usertoken</a>
and select <strong>Generate User Token</strong>.</p>
<p>Finally, add the generated token credentials to <code>~/.gradle/gradle.properties</code>. (Note: these are
different from the credentials used to log into your Sonatype account):</p>
<pre><code class="language-gradle"># Generated Sonatype token

View File

@@ -180,7 +180,7 @@ rm -r Vulkan-Headers-1.3.232 v1.3.232.zip
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dup/filamat.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../dup/fgviewer.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -194,7 +194,7 @@ rm -r Vulkan-Headers-1.3.232 v1.3.232.zip
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dup/filamat.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../dup/fgviewer.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>

View File

@@ -200,6 +200,12 @@ inside the Filament source tree.</p>
force a clean build by adding the <code>-c</code> flag in that case.</p>
<p>To install the libraries and executables in <code>out/debug/</code> and <code>out/release/</code>, add the <code>-i</code> flag.
The script offers more features described by executing <code>build.sh -h</code>.</p>
<p>For more specialized options, please also consider the following pages:</p>
<ul>
<li><code>-d</code>: <a href="https://google.github.io/filament/dup/matdbg.html"><code>matdbg</code></a></li>
<li><code>-t</code>: <a href="https://google.github.io/filament/dup/fgviewer.html"><code>fgviewer</code></a></li>
<li><code>-b</code> and <code>-y</code>: <a href="https://google.github.io/filament/notes/asan_ubsan.html">ASAN/UBSAN builds</a></li>
</ul>
<h3 id="filament-specific-cmake-options"><a class="header" href="#filament-specific-cmake-options">Filament-specific CMake Options</a></h3>
<p>The following CMake options are boolean options specific to Filament:</p>
<ul>
@@ -434,7 +440,7 @@ to create a quick localhost server:</p>
<p>Alternatively, if you have node installed you can use the
<a href="https://www.npmjs.com/package/live-server">live-server</a> package, which automatically refreshes the
web page when it detects a change.</p>
<p>Each sample app has its own handwritten html file. Additionally the server folder contains assets
<p>Each sample app has its own handwritten html file. Additionally, the server folder contains assets
such as meshes, textures, and materials.</p>
<h2 id="running-the-native-samples"><a class="header" href="#running-the-native-samples">Running the native samples</a></h2>
<p>The <code>samples/</code> directory contains several examples of how to use Filament with SDL2.</p>

View File

@@ -179,7 +179,7 @@ Google code style and is derived from the Java code style, but not quite.</p>
<li>class access modifiers are not indented</li>
<li>last line of <code>.cpp</code> or <code>.h</code> file must be an empty line</li>
</ul>
<pre><code>for (int i = 0; i &lt; max; i++) {
<pre><code class="language-c++">for (int i = 0; i &lt; max; i++) {
}
class Foo {
@@ -227,11 +227,23 @@ src/data.inc
<li><code>public</code> class attributes <em>are not</em> prefixed</li>
<li>class attributes and methods are lower camelcase</li>
</ul>
<pre><code>extern int gGlobalWarming;
<pre><code class="language-c++">extern int gGlobalWarming;
class FooBar {
public:
void methodName();
FooBar(int attributeName, int sizeInBytes)
: mAttributeName(attributeName),
sizeInBytes(sizeInBytes) {}
void reallyLongMethodNameWithLotsOfArguments(bool argument1,
int someSecondArgument, int bestArgument) {
std::pair&lt;bool, int&gt; pair = {
argument1,
argument2,
};
// etc
}
int sizeInBytes;
private:
int mAttributeName;
@@ -248,7 +260,7 @@ private:
<li>always include the copyright notice at the top of every file</li>
<li>make sure the date is correct</li>
</ul>
<pre><code>/*
<pre><code class="language-c++">/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -293,7 +305,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
</li>
</ul>
<p><em>Sorting the headers is important to help catching missing <code>#include</code> directives.</em></p>
<pre><code>/*
<pre><code class="language-c++">/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -336,7 +348,7 @@ from other string types.</li>
<ul>
<li>Use <code>auto</code> only when the type appears on the same line or with iterators and lambdas.</li>
</ul>
<pre><code>auto foo = new Foo();
<pre><code class="language-c++">auto foo = new Foo();
for (auto&amp; i : collection) { }
</code></pre>

345
docs/dup/fgviewer.html Normal file
View File

@@ -0,0 +1,345 @@
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>fgviewer - Filament</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div style="display:flex;align-items:center;justify-content:center">
<img class="flogo" src="../images/filament_logo_small.png"></img>
</div>
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
<!--
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
-->
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Filament</h1>
<div class="right-buttons">
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="fgviewer"><a class="header" href="#fgviewer">fgviewer</a></h1>
<ol>
<li><a href="#capabilities">Capabilities</a></li>
<li><a href="#setup-for-desktop">Setup for Desktop</a></li>
<li><a href="#setup-for-android">Setup for Android</a></li>
<li><a href="#debugger-usage">Debugger Usage</a></li>
<li><a href="#architecture-overview">Architecture Overview</a></li>
<li><a href="#c-server">C++ Server</a></li>
<li><a href="#javascript-client">JavaScript Client</a></li>
<li><a href="#http-requests">HTTP Requests</a></li>
<li><a href="#wish-list">Wish List</a></li>
</ol>
<h2 id="capabilities"><a class="header" href="#capabilities">Capabilities</a></h2>
<p>fgviewer is a library and web application for real-time visualization of the frame graph in Filament.
It displays active passes and resource usage, providing insights into the rendering pipeline.</p>
<h2 id="setup-for-desktop"><a class="header" href="#setup-for-desktop">Setup for Desktop</a></h2>
<p>When using the easy build script, include the <code>-t</code> argument. For example:</p>
<pre><code>./build.sh -ft debug gltf_viewer
</code></pre>
<p>The <code>t</code> enables a CMake option called <code>FILAMENT_ENABLE_FGVIEWER</code> and the <code>f</code> ensures that CMake gets
re-run so that the option is honored.</p>
<p>Next, set an environment variable as follows. In Windows, use <code>set</code> instead of <code>export</code>.</p>
<pre><code>export FILAMENT_FGVIEWER_PORT=8050
</code></pre>
<p>Next, launch any app that links against a debug build of a Filament and point your web browser to
http://localhost:8050. Skip ahead to <strong>Debugger Usage</strong>.</p>
<h2 id="setup-for-android"><a class="header" href="#setup-for-android">Setup for Android</a></h2>
<p>Rebuild Filament for Android after enabling a CMake option called <code>FILAMENT_ENABLE_FGVIEWER</code>. Note that
CMake is invoked from several places for Android (both gradle and our easy build script), so one
pragmatic and reliable way of doing this is to simply hack <code>CMakeLists.txt</code> and
<code>filament-android/CMakeLists.txt</code> by unconditionally setting <code>FILAMENT_ENABLE_FGVIEWER</code> to <code>ON</code>.</p>
<p>After rebuilding Filament with the option enabled, ensure that internet permissions are enabled in
your app by adding the following into your manifest as a child of the <code>&lt;manifest&gt;</code> element.</p>
<pre><code>&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
</code></pre>
<p>Now launch your app as usual. The Filament Engine sets up a server that is hardcoded to listen to
port <code>8085</code>. Next, you will need to forward your device's TCP port <code>8085</code> to your host port of choice.
For example, to forward the fgviewer server on your device to port <code>8085</code> on your host machine, do the
following:</p>
<pre><code>adb forward tcp:8085 tcp:8085
</code></pre>
<p>This lets you go to http://localhost:8085 in Chrome on your host machine.</p>
<h2 id="debugger-usage"><a class="header" href="#debugger-usage">Debugger Usage</a></h2>
<p>After opening the fgviewer page in your browser, you can see the active views are on the left panel.
Then you can select any of them to see the active passes and resources for that view.</p>
<p align="center">
<img width="600px" src=https://github.com/user-attachments/assets/2d31767f-fc25-4f17-8c14-528fe5c6b698>
</p>
<h2 id="architecture-overview"><a class="header" href="#architecture-overview">Architecture Overview</a></h2>
<p align="center">
<img width="450" src=https://github.com/user-attachments/assets/537ebb89-6ad0-4b93-bbeb-207d4fe9ec5a>
</p>
<p>The fgviewer library has two parts: a C++ server and a JavaScript client. The C++ server is
responsible for instancing a <a href="https://github.com/civetweb/civetweb">civetweb</a> context that handles HTTP requests. The
JavaScript client is a small web app that contains a view into an in-browser database of framegraphs.</p>
<p>When a new connection is established, the client asks the server for a list of framegraphs
in order to populate its in-browser database. If the connection is lost (e.g. if the app crashes),
then the database stays intact and the web app is still functional.</p>
<h2 id="c-server"><a class="header" href="#c-server">C++ Server</a></h2>
<p>The civetweb server is wrapped by our <code>DebugServer</code> class, which provides a public interface consisting of
a few methods invoked by the Filament engine.</p>
<p>Since each view corresponds to a frame graph, the engine should notify <code>DebugServer</code> of any changes to the views
on the engine side.</p>
<ul>
<li><strong>createView</strong> Notifies the debugger that a new view has been created.</li>
<li><strong>updateView</strong> Notifies the debugger of updates to an existing view.</li>
<li><strong>destroyView</strong> Notifies the debugger that a view is being removed.</li>
</ul>
<h2 id="javascript-client"><a class="header" href="#javascript-client">JavaScript Client</a></h2>
<p>The web app is built using LitElement, a lightweight library for creating Web Components. Our goal is to keep the code simple and modern, avoiding frameworks like React or Angular.</p>
<p>The app presents a view over a pseudo-database, which is essentially a global variable holding a dictionary that maps frame graph ids to objects following the JSON structure described below.</p>
<h2 id="http-requests"><a class="header" href="#http-requests">HTTP requests</a></h2>
<p>The server responds to the following GET requests by returning a JSON blob. The <code>{id}</code> in these
requests is a concept specific to fgviewer (not Filament) which is an 8-digit hex string for identifying frame graphs.</p>
<hr />
<p><code>/api/framegraphs</code></p>
<p>Returns an array containing all framegraphs in an app. Example:</p>
<pre><code class="language-json">[{
"fgid": "00000000",
"viewName": "Main View",
"passes": [{
"name": "shadow pass",
"reads": [],
"writes": ["0"]
}],
"resources": [{
"id": "0",
"name": "shadowmap",
"properties": [{"resolution": "256x256"}, {"is_subresource": "false"}]
}]
},
{
"fgid": "00000001",
"viewName": "UI view",
...
}]
</code></pre>
<hr />
<p><code>/api/framegraph?fg={id}</code></p>
<p>Returns a specific framegraph info. Example:</p>
<pre><code class="language-json">{
"fgid": "00000000",
"viewName": "Main View",
"passes": [{
"name": "shadow pass",
"reads": [],
"writes": ["0"]
}],
"resources": [{
"id": "0",
"name": "shadowmap",
"properties": [{"resolution": "256x256"}, {"is_subresource": "false"}]
}]
}
</code></pre>
<hr />
<p><code>/api/status</code></p>
<p>Returns one of the below:</p>
<ul>
<li><code>0</code>: first time connected</li>
<li><code>1</code>: no-op</li>
<li><code>{fgid}</code>: the corresponding frame graph has an update
<ul>
<li>Then the web view can request for the actual info using the previous api</li>
</ul>
</li>
</ul>
<p>If the request gets timeout, the web page show disconnected to the user.</p>
<hr />
<h2 id="wish-list"><a class="header" href="#wish-list">Wish List</a></h2>
<ul>
<li>Display the texture contents on the webview</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../dup/bluevk.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dup/filamat.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../dup/bluevk.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dup/filamat.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>

View File

@@ -336,7 +336,7 @@ void material(inout MaterialInputs material) {
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../dup/bluevk.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../dup/fgviewer.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
@@ -350,7 +350,7 @@ void material(inout MaterialInputs material) {
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../dup/bluevk.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../dup/fgviewer.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

View File

@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.65.0'
implementation 'com.google.android.filament:filament-android:1.68.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.65.0'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.68.0'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>

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