Compare commits

..

41 Commits

Author SHA1 Message Date
Mathias Agopian
547f1f7e32 utils: Secure EntityManager and hide implementation details
Move the `mGens` array and `isAlive()` implementation from `EntityManager`
to `EntityManagerImpl` to hide implementation details and maintain a clean
public header. Make `isAlive()` strictly thread-safe by acquiring the
`mFreeListLock`.

isAlive() was relying on undefined behavior, and the comment about
the memory barrier being provided by the lock was misleading (wrong)
because the lock only provided the "release", but isAlive() didn't
have an "acquire". 

Better safe than sorry, we now have to acquire the lock to test isAlive().
2026-05-01 11:32:59 -07:00
dependabot[bot]
fd0a0c4781 build(deps): bump uuid (#9927)
Bumps the npm_and_yarn group with 1 update in the /build/common/upload-release-assets directory: [uuid](https://github.com/uuidjs/uuid).


Removes `uuid`

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 22:35:17 +00:00
Powei Feng
8812a35cbd webgpu: Clean up spec constants and fix validation for unused attributes (#9933)
- WebGPUProgram.cpp: Remove legacy replaceSpecConstants string injection
  since WebGPU handles specialization constants natively.
- WebGPUVertexBufferInfo.cpp: Pad unused vertex attributes safely into
  slot 0 using 4-byte formats to satisfy WebGPU stride validation.
- CodeGenerator.cpp: Remove legacy fallback generating 'const' structs
  for specialization constants.
- ShaderGenerator.cpp: Unset unused skinning/morphing attributes
  to prevent WebGPU validation crashes.
- dawn/tnt/CMakeLists.txt: Fix JNI linker error by dropping missing
  Tint AST reader libraries and adding tint_utils_system.

This commit fixes combination use of ubershader and skinning.
2026-04-30 19:08:25 +00:00
Filament Bot
35d7b819e1 [automated] Updating /docs due to commit 9b2959d
Full commit hash is 9b2959d3a4

DOCS_ALLOW_DIRECT_EDITS
2026-04-30 18:30:04 +00:00
Powei Feng
9b2959d3a4 web: fix redball and fl0 examples (#9942)
- Remove conditional forgotten by #9897
   Fixes cube_fl0 example
 - Add byte array view methods that are no longer exported by
   default in emscripten 5.0.4 (#9921)
   Fixes redball tutorial
2026-04-30 17:58:16 +00:00
Èric Bitriá Ribes
7309a05ac3 feat: iOS simulator (arm64) support (#9893) 2026-04-29 16:20:11 -07:00
Filament Bot
2132e5cda5 [automated] Updating /docs due to commit 96b8015
Full commit hash is 96b8015fb4

DOCS_ALLOW_DIRECT_EDITS
2026-04-29 22:46:17 +00:00
Powei Feng
96b8015fb4 web: rename WEBGL to WASM for cmake (#9941)
This is a more accurate name because it specifies the platform and
not the graphics API.
2026-04-29 22:21:25 +00:00
Mathias Agopian
9c27bfa3e1 utils: Improve StructureOfArrays (#9936)
- Added `copyRange()` to `StructureOfArrays` to efficiently copy a range
  of elements from another SoA of the same type. It uses `std::copy_n`
  which leverages `memcpy` for trivially copyable types.
- Added `operator[]` to `StructureOfArrays` returning `IteratorValueRef`.
- Added `operator=` for `Structure` (tuple) to `IteratorValueRef` to
  allow direct assignment: `soa[i] = tuple`.
- Added unit tests for these new methods in `test_StructureOfArrays.cpp`.
2026-04-29 09:06:26 -07:00
Filament Bot
25a12b47c9 [automated] Updating /docs due to commit c481025
Full commit hash is c48102504e

DOCS_ALLOW_DIRECT_EDITS
2026-04-29 06:44:13 +00:00
Powei Feng
052e95eb2f mesa: update mesa version and ensure linux build (#9938)
- Update mesa version to 25.0.3 so that it builds with clang-17.
 - Make sure that abseil checks do not block compilation (this
   was due to unknown incompatiblity that appeared when trying to
   build abseil on linux and clang-17).
2026-04-29 04:36:54 +00:00
Sungun Park
c48102504e Release Filament 1.71.2 2026-04-28 21:07:12 -07:00
Ben Doherty
d12be26b13 Implement shared contexts for Mesa platform (#9937) 2026-04-28 11:46:28 -06:00
Ben Doherty
3aa129240e Metal: implement asynchronous resource loading (#9930) 2026-04-27 14:18:07 -06:00
Mathias Agopian
3f58c3b57d Implement batch callback system for scene cache incremental updates. (#9935)
* Implement batch callback system for scene cache incremental updates.

This change adds a batch callback mechanism to track changes in component
managers and the entity manager, avoiding full cache rebuilds in the
future scene cache implementation.

1. SingleInstanceComponentManager:
- Added SingleInstanceComponentManagerBase to handle callbacks without
  template bloat.
- Implemented batch delivery using Slice<const Entity> and a fixed-size
  array of 16 for dirty entities to avoid heap allocations.
- Added compile-time option for sorted insertion (default to linear).

2. Manager Integration:
- RenderableManager: Added notifications to setters.
- LightManager: Added notifications to setters
- TransformManager: Handled transactions by deferring notifications
  until commit, and supported hierarchical updates in children.

3. EntityManager:
- Added a new batching callback API for entity destruction.
- Used std::function for callbacks to allow thread-safe copying of the
  callback list outside the lock.
- Simple accumulation in loop and flush when full, no bypass.

4. Tests:
- Added formal unit tests for all managers and entity manager callbacks.
2026-04-24 17:07:44 -07:00
Filament Bot
40aab3896c [automated] Updating /docs due to commit f7fd6a9
Full commit hash is f7fd6a9eab

DOCS_ALLOW_DIRECT_EDITS
2026-04-23 21:48:45 +00:00
Powei Feng
65f7939513 renderdiff: fix python < 3.10 compatibility in update_golden.py
RDIFF_ACCEPT_NEW_GOLDENS
2026-04-23 14:37:16 -07:00
Mathias Agopian
f7fd6a9eab Implement grid-based world origin snapping in View (#9917)
* Implement grid-based world origin snapping in View

Implement a grid-based world origin snapping system in View to avoid
per-frame transform updates in the future. This will allow to
improve CPU performance and to enable future caching of acceleration
structures like BVH.

The feature is protected by the 'view.enable_grid_based_world_origin'
feature flag. The grid size can be set
manually via View::setGridSize or calculated automatically as 10%
of the camera's far plane distance.

A 50% hysteresis ratio is applied to prevent rapid origin flipping
near grid edges.

Exposed the new API to Java and JavaScript bindings and added
unit tests in filament_test.cpp.

BUGS=[504726278]

* Refine grid-based world origin snapping implementation

Refine the grid-based world origin snapping in View with several
improvements:

1. Support Orthographic Projections:
   Calculate automatic grid size using projection matrix elements,
   working for both perspective and ortho without assuming positive
   near plane.

2. Stable Automatic Grid Size:
   Only update effective grid size when a position snap occurs.
   This prevents instability when frustum scale changes smoothly.

3. Immediate Manual Override:
   Force an immediate snap when user manually changes grid size.

Added test cases for ortho and auto-grid size in filament_test.cpp.
2026-04-23 14:19:44 -07:00
Romain Guy
004b410f41 Fix macOS build with clang 21 (#9928) 2026-04-23 14:00:04 -07:00
Powei Feng
10702e2d07 webgpu: implement push constants with immediates (#9932)
- Add test for skinning for gl, vk, and webgpu

RDIFF_ACCEPT_NEW_GOLDENS
2026-04-23 20:22:08 +00:00
Powei Feng
e45e9c40fe github: display original commit title for status workflows
GitHub Actions displays the workflow name instead of the commit title
when a workflow is triggered by `workflow_run`. This makes it difficult
to identify the commit associated with a status workflow run in the UI.

Added the `run-name` attribute to all `status-*.yml` files, dynamically
setting it to the `display_title` of the original workflow run. This
restores visibility of the commit message or PR title in the Actions UI.
2026-04-23 12:43:48 -07:00
Filament Bot
d00691c727 [automated] Updating /docs due to commit d16ebaa
Full commit hash is d16ebaa94f

DOCS_ALLOW_DIRECT_EDITS
2026-04-23 18:45:37 +00:00
Powei Feng
d16ebaa94f github: restore platform-specific status badges in README (#9931)
Consolidating the CI workflows into a single postsubmit.yml broke the
individual platform status badges in the README, as GitHub Actions
only supports status badges at the workflow level, not the job level.

Added shadow workflows (e.g., status-android.yml) that trigger on
the completion of the main "Postsubmit CI" workflow. These scripts
query the GitHub Actions API to determine the success or failure of
their respective job (e.g., build-android) and reflect that status.
Updated the README to point to these new workflow badges.
2026-04-23 18:17:28 +00:00
Filament Bot
7a1f155d71 [automated] Updating /docs due to commit f9e56a1
Full commit hash is f9e56a11d1

DOCS_ALLOW_DIRECT_EDITS
2026-04-23 17:20:43 +00:00
Mathias Agopian
f9e56a11d1 feat: Make C++ exceptions and RTTI configurable (#9913)
Introduced the FILAMENT_ENABLE_EXCEPTIONS (default ON) and
FILAMENT_ENABLE_RTTI (default OFF) CMake options to control these
features globally. This replaces previous hardcoded, platform-specific
overrides.

Added a -E flag to build.sh to easily disable exceptions during
build configuration.

Removed hardcoded -fno-exceptions and -fno-rtti from
android/build.gradle to allow CMake to control these flags, but kept
-fno-rtti enabled by default for the Java/Android build as requested.

Documented in CMakeLists.txt and BUILDING.md that the JNI library
(Android/Java build) requires exceptions to be enabled.

Enabled RTTI specifically for the assimp target in
third_party/libassimp/tnt/CMakeLists.txt to fix compilation errors
caused by its use of dynamic_cast.

SIZEGUARD_BYPASS
2026-04-23 09:52:26 -07:00
Doris Wu
fd2684513e Fix some issues for MaterialCache (#9922)
Updated MaterialKey comparison to check values instead of pointers
Defer the termination of MaterialCache until after mMaterials is cleaned up to avoid a double-free issue
BUGS=[499843464]
2026-04-23 09:49:59 -07:00
Powei Feng
3734dc1930 fgviewer: do not assume fgviewer is present in framegraph (#9924)
Even with FILAMENT_ENABLE_FGVIEWER defined, we cannot assume
that fgviewer has been set. For example, fgviewer can be null when
we enable the define for tests, but fgviewer did not initialize
due to the server port being undefined.
2026-04-23 09:48:21 -07:00
Powei Feng
bbc3ddea33 webgpu: update dawn to chromium/7792 (#9916)
Includes the following updates to Filament and Dawn to support the new version:
- CMake Configuration: Enabled OBJC/OBJCXX and set C++ standard to 20 for
  Apple targets to support Dawn's Metal backend.
- WebGPU Backend API: Replaced `wgpu::ShaderModuleWGSLDescriptor` with
  `wgpu::ShaderSourceWGSL`, updated compilation info callbacks to use
  `wgpu::CompilationInfoRequestStatus`, and removed deprecated
  `wgpu::TextureFormat::External`.
- Tint Integration (`GLSLPostProcessor.cpp`): Migrated to `ReadIR` and
  `WgslFromIR`. Enabled `allow_non_uniform_derivatives` and
  `disable_unreachable_code_warning` to bypass strict uniformity analysis on
  UBOs, and allowlisted `gl_ClipDistance` for stereoscopic materials.
- Dawn Patches: Manually re-applied and updated
  `remove-vk-macos-restriction.patch` to account for upstream refactoring in
  `BackendVk.cpp`.
- AppleClang 17 RTTI Workaround: Added
  `tint-texture-gather-unwrap-pointer.patch` to conditionally bypass an
  AppleClang 17 optimizer bug causing RTTI dynamic cast failures in Tint
  (`TINT_ASSERT(tex_ty)`).
  Turns out this workaround is necessary for linux clang as well.
2026-04-22 22:24:25 +00:00
Jorge Garcia Galicia
6d5f1cf691 Stencil support for VK backend (#9888)
In order to support stencil op in VK we need to:

1)Configure corresponding pipeline/render pass
2)Configure attachment/FB

Previous PR (#9716) covers 1)
This PR covers 2)

This PR also makes the the following tests pass on VK

BasicStencilBufferTest.StencilBuffer
BasicStencilBufferTest.DepthAndStencilBuffer
2026-04-22 13:40:55 -07:00
Filament Bot
594d36423a [automated] Updating /docs due to commit f4a079f
Full commit hash is f4a079f663

DOCS_ALLOW_DIRECT_EDITS
2026-04-22 18:21:46 +00:00
Mathias Agopian
f4a079f663 backend: Propagate backend thread exceptions to the main thread. (#9903)
* Filament Error Handling Remediation and noexcept Cleanup

- Replaced assert_invariant with FILAMENT_CHECK_PRECONDITION in
  Renderer::beginFrame for caller bugs.
- Removed noexcept from Camera::setCustomProjection to allow precondition
  checks to throw.
- Removed noexcept from Texture and InstanceBuffer methods using precondition
  checks.
- Documented silent clamping in View::setBloomOptions.
- Clarified comment in FrameGraphResources regarding preconditions.
- Refined MaterialInstance::commit to split texture loop into check and update
  passes, preventing partial state changes on precondition failure.

* backend: Propagate backend thread exceptions to the main thread.

Introduce a mechanism to catch exceptions thrown on the backend thread and
rethrow them on the main thread. This prevents deadlocks and allows the
application to handle fatal backend failures gracefully.

- Consolidate synchronization primitives in DriverBase.
- Add mHasUnrecoverableError flag to interrupt blocked fence waits.
- Optimize waitForFence to avoid extra atomic reads in common paths.
- Propagate FenceStatus::ERROR across all backends.
- CommandBufferQueue now stores a std::exception_ptr when the backend fails.
- The backend enters a "zombie" state on failure, skipping further command
  execution but allowing clean shutdown.
- Public APIs in Renderer and Engine now check for stored exceptions and
  rethrow them, documented with @throws.
- Guarded by __EXCEPTIONS to ensure no overhead when exceptions are disabled.
- Add unit test for fence interruption and document new APIs.

BUGS=[407545700]

* feat: harden backend exceptions and add hasUnrecoverableFailure API

- Update Renderer::beginFrame() and Renderer::shouldRenderFrame() to
  return false early if an unrecoverable backend exception has been
  delivered to the main thread.
- Document the new return behavior for beginFrame() and
  shouldRenderFrame() in Renderer.h.
- Add Engine::hasUnrecoverableFailure() to the public API to allow
  apps to check for fatal errors without relying on exceptions.
- Implement hasUnrecoverableFailure() in FEngine by delegating to
  CommandBufferQueue.
- Expose Engine::hasUnrecoverableFailure() to Java bindings
  (Engine.java and JNI).
- Expose Engine::hasUnrecoverableFailure() to JavaScript bindings
  (jsbindings.cpp).

* java: propagate C++ Panics & exceptions to JAVA
2026-04-22 10:56:09 -07:00
Ben Doherty
fa987f225d Add missing output precision to custom surface output (#9923) 2026-04-22 13:21:10 -04:00
Filament Bot
c63c8e1741 [automated] Updating /docs due to commit 05dde7e
Full commit hash is 05dde7e2cf

DOCS_ALLOW_DIRECT_EDITS
2026-04-22 16:45:54 +00:00
Powei Feng
05dde7e2cf Update emsdk to 5.0.4 (#9921)
- Bumped GITHUB_EMSDK_VERSION to 5.0.4 in build scripts and docs.
- Fixed a compilation error in web/filament-js/jsbindings.cpp where stricter
  pointer binding rules in Emscripten 5.0.4 caused a build failure when
  returning a raw pointer wrapped in `emscripten::val`. Changed the lambda
  to return the raw pointer directly, leveraging Embind's `allow_raw_pointers()`.
2026-04-22 09:18:24 -07:00
Filament Bot
dea71a278c [automated] Updating /docs due to commit b6a7226
Full commit hash is b6a7226213

DOCS_ALLOW_DIRECT_EDITS
2026-04-22 00:10:17 +00:00
Powei Feng
b6a7226213 Bump clang dep version from 16 to 17 (#9919)
The latest version of third_party/dawn requires clang 17.
2026-04-21 23:40:55 +00:00
Powei Feng
2ae4dc4c62 fgviewer: visualize intermediate buffers (#9862)
* Intermediate Buffer Visualization: Enabled live monitoring of internal
  `FrameGraph` render targets directly in the `fgviewer` web UI.
* HTTP Polling Architecture: Switched from WebSocket binary pushes to native
  `<img>` polling (`/api/image`)
* Robust Resource Tracking: Replaced string-based lookups with
  `(ViewId, ResourceId)` composite keys to prevent cross-view collisions and
  ensure accurate reads.
* Format Post-Processing: Extracted readback conversions (HDR tonemapping,
  depth normalization, MSAA downsampling, single-channel expansion) into
  `DebugServer`.
* UI Polish: Added a live-updating full-screen image modal and explicitly
  filtered internal debug passes from the Graphviz/JSON exports to prevent
  DOM thrashing.
* WIP: Currently Unsupported:
  * GL backend: failed with:
      OpenGL framebuffer error 0x8cd6 (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) in "readTexture" at line 4198
  * Mipmaps & Subresources: Reading specific mip levels or array layers is
    explicitly skipped.
  * Shadowmaps: Variance Shadow Maps (VSM) will physically evaluate to `0.0`
    and appear completely empty/black in scenes without active shadow
    casters (due to inverted-Z).
  * Stencil: Resolving and reading stencil buffer data is not supported by
    the backend.
* WIP: Untested outside of MacOS+metal/vk
2026-04-21 20:30:45 +00:00
Filament Bot
d3475e6dff [automated] Updating /docs due to commit f82085f
Full commit hash is f82085f676

DOCS_ALLOW_DIRECT_EDITS
2026-04-21 19:47:05 +00:00
Powei Feng
f82085f676 Release Filament 1.71.1 2026-04-21 12:19:43 -07:00
Filament Bot
695c2f82ea [automated] Updating /docs due to commit c55ee9f
Full commit hash is c55ee9faae

DOCS_ALLOW_DIRECT_EDITS
2026-04-21 18:25:14 +00:00
Powei Feng
c55ee9faae sizeguard: add tag to bypass test (#9743) 2026-04-21 17:58:05 +00:00
258 changed files with 7113 additions and 2413 deletions

View File

@@ -26,7 +26,7 @@ jobs:
cd build/web && printf "y" | ./build.sh release
- name: Deploy to npm
run: |
cd out/cmake-webgl-release/web/filament-js
cd out/cmake-wasm-release/web/filament-js
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -31,6 +31,8 @@ jobs:
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- name: Select Xcode 16.2
run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh continuous

View File

@@ -150,13 +150,20 @@ jobs:
pushd .
cd build/android && printf "y" | ./build.sh presubmit-with-archive arm64-v8a
popd
- id: get_commit_msg
uses: ./.github/actions/get-commit-msg
- name: Check artifact sizes
run: |
python3 test/sizeguard/dump_artifact_size.py out/*.aar > current_size.json
BYPASS_ARG=""
if python3 test/sizeguard/check_bypass.py ${{ steps.get_commit_msg.outputs.hash }}; then
BYPASS_ARG="--bypass"
fi
python3 test/sizeguard/check_size.py current_size.json \
--target-branch origin/main \
--threshold 20480 \
--artifacts filament-android-release.aar/jni/arm64-v8a/libfilament-jni.so
--artifacts filament-android-release.aar/jni/arm64-v8a/libfilament-jni.so \
$BYPASS_ARG
build-ios:
name: build-iOS
@@ -177,6 +184,8 @@ jobs:
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- name: Select Xcode 16.2
run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh presubmit

View File

@@ -286,6 +286,8 @@ jobs:
with:
ref: ${{ steps.git_ref.outputs.ref }}
- uses: ./.github/actions/mac-prereq
- name: Select Xcode 16.2
run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
- name: Run build script
env:
TAG: ${{ steps.git_ref.outputs.tag }}

27
.github/workflows/status-android.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Android
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-android');
if (job && job.conclusion !== 'success') {
core.setFailed(`Android build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-android not found in the workflow run.`);
}

27
.github/workflows/status-ios.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: iOS
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-ios');
if (job && job.conclusion !== 'success') {
core.setFailed(`iOS build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-ios not found in the workflow run.`);
}

27
.github/workflows/status-linux.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Linux
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-linux');
if (job && job.conclusion !== 'success') {
core.setFailed(`Linux build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-linux not found in the workflow run.`);
}

27
.github/workflows/status-macos.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: macOS
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-mac');
if (job && job.conclusion !== 'success') {
core.setFailed(`macOS build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-mac not found in the workflow run.`);
}

27
.github/workflows/status-web.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Web
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-web');
if (job && job.conclusion !== 'success') {
core.setFailed(`Web build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-web not found in the workflow run.`);
}

27
.github/workflows/status-windows.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Windows
run-name: ${{ github.event.workflow_run.display_title }}
on:
workflow_run:
workflows: ["Postsubmit CI"]
types: [completed]
jobs:
status:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }}
});
const job = jobs.find(j => j.name === 'build-windows');
if (job && job.conclusion !== 'success') {
core.setFailed(`Windows build failed: ${job.conclusion}`);
} else if (!job) {
core.warning(`Job build-windows not found in the workflow run.`);
}

View File

@@ -79,6 +79,10 @@ The following CMake options are boolean options specific to Filament:
- `FILAMENT_INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `FILAMENT_USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
- `FILAMENT_SKIP_SAMPLES`: Don't build sample apps
- `FILAMENT_ENABLE_EXCEPTIONS`: Enable C++ exceptions (default: ON, OFF for iOS). Required for JNI bindings.
- `FILAMENT_ENABLE_RTTI`: Enable C++ RTTI (default: OFF).
Note: If you intend to use the JNI library (Android/Java build), you need to have `FILAMENT_ENABLE_EXCEPTIONS` enabled. If you are using Filament on Android as a pure native library and want to save space, you can disable it (e.g., using `./build.sh -E`).
To turn an option on or off:
@@ -408,7 +412,7 @@ same version that our continuous builds use.
```shell
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.60.zip > emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/5.0.4.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest

View File

@@ -20,9 +20,12 @@ endif()
# Project declaration
# ==================================================================================================
set(EXTRA_LANGS)
if (APPLE)
# This is only needed for the webgpu on MacOS build.
if (APPLE AND NOT IOS)
set(EXTRA_LANGS OBJC OBJCXX)
endif()
project(TNT C CXX ${EXTRA_LANGS})
# ==================================================================================================
@@ -30,6 +33,20 @@ project(TNT C CXX ${EXTRA_LANGS})
# ==================================================================================================
option(FILAMENT_USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" OFF)
# Note: If you intend to use the JNI library (Android/Java build), you need to have
# exceptions enabled (the default). If you are using Filament on Android as a pure
# native library and want to save space, you can disable them.
# We disable exceptions on iOS by default. This fixes an availability error we see when using
# std::visit and std::get, which are not supported on iOS 11.0 when exceptions are enabled.
if (IOS)
set(FILAMENT_ENABLE_EXCEPTIONS_DEFAULT OFF)
else()
set(FILAMENT_ENABLE_EXCEPTIONS_DEFAULT ON)
endif()
option(FILAMENT_ENABLE_EXCEPTIONS "Enable C++ exceptions" ${FILAMENT_ENABLE_EXCEPTIONS_DEFAULT})
option(FILAMENT_ENABLE_RTTI "Enable C++ RTTI" OFF)
option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF)
@@ -104,6 +121,15 @@ set(FILAMENT_OSMESA_PATH "" CACHE STRING
# Enable exceptions by default in spirv-cross.
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF)
if (NOT FILAMENT_ENABLE_EXCEPTIONS)
add_compile_options(-fno-exceptions)
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON)
endif()
if (NOT FILAMENT_ENABLE_RTTI)
add_compile_options(-fno-rtti)
endif()
# ==================================================================================================
# CMake policies
# ==================================================================================================
@@ -151,7 +177,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# ==================================================================================================
# OS specific
# ==================================================================================================
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL)
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WASM)
set(LINUX TRUE)
else()
# since cmake 3.25 LINUX is automatically set based on CMAKE_SYSTEM_NAME, which the android
@@ -192,7 +218,7 @@ if (LINUX)
endif()
endif()
if (ANDROID OR WEBGL OR IOS OR FILAMENT_LINUX_IS_MOBILE)
if (ANDROID OR WASM OR IOS OR FILAMENT_LINUX_IS_MOBILE)
set(IS_MOBILE_TARGET TRUE)
endif()
@@ -200,7 +226,7 @@ if (ANDROID)
add_definitions(-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
endif()
if (NOT ANDROID AND NOT WEBGL AND NOT IOS AND NOT FILAMENT_LINUX_IS_MOBILE)
if (NOT ANDROID AND NOT WASM AND NOT IOS AND NOT FILAMENT_LINUX_IS_MOBILE)
set(IS_HOST_PLATFORM TRUE)
endif()
@@ -341,8 +367,14 @@ endif()
# ==================================================================================================
# General compiler flags
# ==================================================================================================
set(CMAKE_OBJCXX_STANDARD 20)
set(CMAKE_OBJCXX_STANDARD_REQUIRED ON)
# This is only needed for the webgpu on MacOS build.
# Don't enable for iOS because we need to support ios min target 11.0
if (APPLE AND NOT IOS)
set(CMAKE_OBJCXX_STANDARD 20)
set(CMAKE_OBJCXX_STANDARD_REQUIRED ON)
endif()
set(CXX_STANDARD "-std=c++20")
if (WIN32)
set(CXX_STANDARD "/std:c++20")
@@ -359,8 +391,8 @@ else()
endif()
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nullability-extension")
set(CMAKE_OBJCXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
set(CMAKE_OBJCXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
if (FILAMENT_USE_EXTERNAL_GLES3)
@@ -407,8 +439,7 @@ if (ANDROID)
endif()
if (CYGWIN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
if (MSVC)
@@ -442,33 +473,20 @@ if (NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
endif()
# On Android RELEASE builds, we disable exceptions and RTTI to save some space (about 75 KiB
# saved by -fno-exception and 10 KiB saved by -fno-rtti).
if (ANDROID OR IOS OR WEBGL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-rtti")
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON)
if (ANDROID OR WEBGL)
# Omitting unwind info prevents the generation of readable stack traces in crash reports on iOS
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-unwind-tables -fno-asynchronous-unwind-tables")
endif()
if (ANDROID OR WASM)
# On Android and WebGL RELEASE builds, we omit unwind info to save space.
# (We keep unwind info on iOS to allow readable stack traces in crash reports.)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-unwind-tables -fno-asynchronous-unwind-tables")
endif()
# Turn off exceptions on iOS debug as well. This fixes an availability error we see when using
# std::visit, which is not supported on iOS 11.0 when exceptions are enabled.
if (IOS)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-exceptions")
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON)
endif()
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
# With WebGL, we disable RTTI because we pass emscripten::val back and forth
# between C++ and JavaScript in order to efficiently access typed arrays, which are unbound.
# NOTE: This is not documented in emscripten so we should consider a different approach.
if (WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-rtti")
if (WASM)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
if (WEBGL_PTHREADS)
if (WASM_PTHREADS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
@@ -485,7 +503,7 @@ if (ANDROID)
# keep STL debug infos (mimics what the NDK does)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-limit-debug-info")
endif()
if (NOT MSVC AND NOT WEBGL)
if (NOT MSVC AND NOT WASM)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
@@ -504,7 +522,7 @@ endif()
# Linker flags
# ==================================================================================================
# Strip unused sections
if (NOT WEBGL)
if (NOT WASM)
set(GC_SECTIONS "-Wl,--gc-sections")
endif()
@@ -538,7 +556,7 @@ endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS} ${NO_EXEC_STACK}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GC_SECTIONS} ${B_SYMBOLIC_FUNCTIONS} ${BINARY_ALIGNMENT}")
if (WEBGL_PTHREADS)
if (WASM_PTHREADS)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread")
endif()
@@ -568,7 +586,7 @@ endif()
# By default, build with Vulkan support on desktop platforms, although clients must request to use
# it at run time.
if (WIN32 OR WEBGL OR IOS)
if (WIN32 OR WASM OR IOS)
option(FILAMENT_SUPPORTS_VULKAN "Include the Vulkan backend" OFF)
else()
option(FILAMENT_SUPPORTS_VULKAN "Include the Vulkan backend" ON)
@@ -586,7 +604,7 @@ if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
endif()
# Build with Metal support on non-WebGL Apple platforms.
if (APPLE AND NOT WEBGL)
if (APPLE AND NOT WASM)
option(FILAMENT_SUPPORTS_METAL "Include the Metal backend" ON)
else()
option(FILAMENT_SUPPORTS_METAL "Include the Metal backend" OFF)
@@ -596,7 +614,7 @@ if (FILAMENT_SUPPORTS_METAL)
endif()
# Building filamat increases build times and isn't required for web, so turn it off by default.
if (NOT WEBGL)
if (NOT WASM)
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" ON)
else()
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
@@ -666,7 +684,6 @@ if (FILAMENT_SUPPORTS_METAL)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal)
endif()
# With WebGPU, push constants are not supported. Skinning uses them.
# WebGPU has a proposal to add push constants at https://github.com/gpuweb/gpuweb/blob/main/proposals/push-constants.md
# With WebGPU, Tint does not support ClipDistance which is used in Stereo. Mentioned in comment
# https://github.com/google/dawn/blob/855d17b08abdf02f9142bf5a8f14d0ea088810a4/src/tint/lang/spirv/reader/ast_parser/function.cc#L4434
@@ -674,11 +691,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=stereo)
endif()
# Disable ESSL 1.0 code generation.
if (NOT FILAMENT_ENABLE_FEATURE_LEVEL_0)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -1)
endif()
# Enable debug info (preserves names in SPIR-V)
if (FILAMENT_ENABLE_MATDBG)
set(MATC_OPT_FLAGS ${MATC_OPT_FLAGS} -d)
@@ -715,6 +727,9 @@ string(TOLOWER "${DIST_ARCH}" DIST_ARCH)
string(REPLACE "amd64" "x86_64" DIST_ARCH "${DIST_ARCH}")
if (NOT DIST_DIR)
set(DIST_DIR "${DIST_ARCH}")
if (PLATFORM_NAME)
set(DIST_DIR "${DIST_DIR}-${PLATFORM_NAME}")
endif()
endif()
# ==================================================================================================
@@ -823,7 +838,7 @@ if (FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR)
set(IMPORT_EXECUTABLES_DIR ${FILAMENT_IMPORT_PREBUILT_EXECUTABLES_DIR})
endif()
if (WEBGL)
if (WASM)
set(IMPORT_EXECUTABLES ${FILAMENT}/${IMPORT_EXECUTABLES_DIR}/ImportExecutables-Release.cmake)
else()
if (FILAMENT_EXPORT_PREBUILT_EXECUTABLES OR FILAMENT_IMPORT_PREBUILT_EXECUTABLES)
@@ -858,7 +873,7 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
set(RESGEN_HEADER "${ARCHIVE_DIR}/${ARCHIVE_NAME}.h" PARENT_SCOPE)
# Visual Studio makes it difficult to use assembly without using MASM. MASM doesn't support
# the equivalent of .incbin, so on Windows we'll just tell resgen to output a C file.
if (WEBGL OR WIN32 OR ANDROID_ON_WINDOWS)
if (WASM OR WIN32 OR ANDROID_ON_WINDOWS)
set(RESGEN_OUTPUTS "${OUTPUTS};${ARCHIVE_DIR}/${ARCHIVE_NAME}.c" PARENT_SCOPE)
set(RESGEN_FLAGS -qcx ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}.c" PARENT_SCOPE)
@@ -963,7 +978,7 @@ add_subdirectory(${FILAMENT}/filament)
set(FILAMENT_SAMPLES_BINARY_DIR ${PROJECT_BINARY_DIR}/samples)
if (WEBGL)
if (WASM)
add_subdirectory(web/filament-js)
add_subdirectory(web/examples)
endif()

View File

@@ -6,3 +6,6 @@
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- iOS: add Apple silicon (`arm64`) iOS Simulator support. The sample Xcode projects now require Xcode 16+ (CI is pinned to Xcode 16.2).
- WEBGL_PTHREADS renamed to WASM_PTHREADS in CMakeLists.txt

View File

@@ -1,14 +1,14 @@
# Filament
[![Android Build Status](https://github.com/google/filament/workflows/Android/badge.svg)](https://github.com/google/filament/actions?query=workflow%3AAndroid)
[![iOS Build Status](https://github.com/google/filament/workflows/iOS/badge.svg)](https://github.com/google/filament/actions?query=workflow%3AiOS)
[![Linux Build Status](https://github.com/google/filament/workflows/Linux/badge.svg)](https://github.com/google/filament/actions?query=workflow%3ALinux)
[![macOS Build Status](https://github.com/google/filament/workflows/macOS/badge.svg)](https://github.com/google/filament/actions?query=workflow%3AmacOS)
[![Windows Build Status](https://github.com/google/filament/workflows/Windows/badge.svg)](https://github.com/google/filament/actions?query=workflow%3AWindows)
[![Web Build Status](https://github.com/google/filament/workflows/Web/badge.svg)](https://github.com/google/filament/actions?query=workflow%3AWeb)
[![Android Build Status](https://github.com/google/filament/actions/workflows/status-android.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-android.yml)
[![iOS Build Status](https://github.com/google/filament/actions/workflows/status-ios.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-ios.yml)
[![Linux Build Status](https://github.com/google/filament/actions/workflows/status-linux.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-linux.yml)
[![macOS Build Status](https://github.com/google/filament/actions/workflows/status-macos.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-macos.yml)
[![Windows Build Status](https://github.com/google/filament/actions/workflows/status-windows.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-windows.yml)
[![Web Build Status](https://github.com/google/filament/actions/workflows/status-web.yml/badge.svg)](https://github.com/google/filament/actions/workflows/status-web.yml)
Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows,
and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
and WASM. It is designed to be as small as possible and as efficient as possible on Android.
## Download
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.71.0'
implementation 'com.google.android.filament:filament-android:1.71.2'
}
```
@@ -50,7 +50,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.71.0'
pod 'Filament', '~> 1.71.2'
```
## Documentation

View File

@@ -7,6 +7,13 @@ 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.71.3
- Metal: add support for asynchronous resource loading
## v1.71.2
## v1.71.1

View File

@@ -145,7 +145,6 @@ buildscript {
ext.cppFlags = [
"-std=c++17",
"-fno-stack-protector",
"-fno-exceptions",
"-fno-unwind-tables",
"-fno-asynchronous-unwind-tables",
"-fno-rtti",

View File

@@ -75,6 +75,17 @@ void JniCallback::postToJavaAndDestroy(JniCallback* callback) {
delete callback;
}
void JniCallback::destroy(JniCallback* callback) {
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
env->DeleteGlobalRef(callback->mHandler);
env->DeleteGlobalRef(callback->mCallback);
#ifdef __ANDROID__
env->DeleteGlobalRef(callback->mCallbackUtils.handlerClass);
#endif
env->DeleteGlobalRef(callback->mCallbackUtils.executorClass);
delete callback;
}
// -----------------------------------------------------------------------------------------------
JniBufferCallback* JniBufferCallback::make(filament::Engine*,

View File

@@ -48,6 +48,9 @@ struct JniCallback : private filament::backend::CallbackHandler {
// execute the callback on the java thread and destroy ourselves
static void postToJavaAndDestroy(JniCallback* callback);
// destroy ourselves without executing the callback
static void destroy(JniCallback* callback);
// CallbackHandler interface.
void post(void* user, Callback callback) override;

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JniUtils.h"
namespace filament {
namespace android {
#ifdef __EXCEPTIONS
UTILS_NOINLINE void wrapJniHelper(JNIEnv* env, void (*invoker)(void*), void* userData) {
try {
invoker(userData);
} catch (const utils::PreconditionPanic& e) {
jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(exClass, e.what());
} catch (const utils::PostconditionPanic& e) {
jclass exClass = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exClass, e.what());
} catch (const std::exception& e) {
jclass exClass = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exClass, e.what());
}
}
UTILS_NOINLINE void wrapJniBackendHelper(JNIEnv* env, void (*invoker)(void*), void* userData) {
try {
invoker(userData);
} catch (const std::exception& e) {
jclass exClass = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exClass, e.what());
}
}
#endif
} // namespace android
} // namespace filament

123
android/common/JniUtils.h Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ANDROID_COMMON_JNIUTILS_H
#define TNT_ANDROID_COMMON_JNIUTILS_H
#include <jni.h>
#include <exception>
#include <type_traits>
#include <utils/Panic.h>
#include <utils/compiler.h>
namespace filament {
namespace android {
#ifdef __EXCEPTIONS
// Non-templated helpers implemented in JniUtils.cpp
void wrapJniHelper(JNIEnv* env, void (*invoker)(void*), void* userData);
void wrapJniBackendHelper(JNIEnv* env, void (*invoker)(void*), void* userData);
// For JNI methods that return a value
template<typename R, typename F>
R wrapJni(JNIEnv* env, F const& f) {
if constexpr (std::is_void_v<R>) {
auto invoker = [](void* data) {
auto& f_ref = *reinterpret_cast<const F*>(data);
f_ref();
};
wrapJniHelper(env, invoker, (void*)&f);
} else {
struct Context {
const F& f;
R result;
};
Context ctx{ f, R{} };
auto invoker = [](void* data) {
auto& context = *reinterpret_cast<Context*>(data);
context.result = context.f();
};
wrapJniHelper(env, invoker, &ctx);
return ctx.result;
}
}
// Overload for JNI methods that return void
template<typename F>
inline void wrapJni(JNIEnv* env, F const& f) {
wrapJni<void, F>(env, f);
}
// For JNI methods that can return backend errors (mapped to java.lang.Error)
template<typename R, typename F>
R wrapJniBackend(JNIEnv* env, F const& f) {
if constexpr (std::is_void_v<R>) {
auto invoker = [](void* data) {
auto& f_ref = *reinterpret_cast<const F*>(data);
f_ref();
};
wrapJniBackendHelper(env, invoker, (void*)&f);
} else {
struct Context {
const F& f;
R result;
};
Context ctx{ f, R{} };
auto invoker = [](void* data) {
auto& context = *reinterpret_cast<Context*>(data);
context.result = context.f();
};
wrapJniBackendHelper(env, invoker, &ctx);
return ctx.result;
}
}
template<typename F>
inline void wrapJniBackend(JNIEnv* env, F const& f) {
wrapJniBackend<void, F>(env, f);
}
#else
// For JNI methods that return a value
template<typename R, typename F>
R wrapJni(JNIEnv* env, F const& f) {
return f();
}
// Overload for JNI methods that return void
template<typename F>
inline void wrapJni(JNIEnv* env, F const& f) {
f();
}
template<typename R, typename F>
R wrapJniBackend(JNIEnv* env, F const& f) {
return f();
}
template<typename F>
inline void wrapJniBackend(JNIEnv* env, F const& f) {
f();
}
#endif
} // namespace android
} // namespace filament
#endif // TNT_ANDROID_COMMON_JNIUTILS_H

View File

@@ -126,6 +126,7 @@ add_library(filament-jni SHARED
# Common utils
../common/CallbackUtils.cpp
../common/NioUtils.cpp
../common/JniUtils.cpp
)
target_include_directories(filament-jni PRIVATE

View File

@@ -16,7 +16,6 @@
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
@@ -26,6 +25,7 @@
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <common/JniUtils.h>
using namespace filament;
using namespace backend;
@@ -63,7 +63,9 @@ Java_com_google_android_filament_BufferObject_nBuilderBuild(JNIEnv *env, jclass
jlong nativeBuilder, jlong nativeEngine) {
BufferObject::Builder* builder = (BufferObject::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -81,20 +83,22 @@ Java_com_google_android_filament_BufferObject_nSetBuffer(JNIEnv *env, jclass typ
BufferObject *bufferObject = (BufferObject *) nativeBufferObject;
Engine *engine = (Engine *) nativeEngine;
AutoBuffer nioBuffer(env, buffer, count);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
return filament::android::wrapJni<int>(env, [=]() {
AutoBuffer nioBuffer(env, buffer, count);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
bufferObject->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
bufferObject->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
return 0;
return 0;
});
}

View File

@@ -17,6 +17,7 @@
#include <jni.h>
#include <filament/Camera.h>
#include <common/JniUtils.h>
#include <utils/Entity.h>
@@ -24,21 +25,26 @@
#include <math/mat4.h>
using namespace filament;
using namespace filament::android;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetProjection(JNIEnv*, jclass, jlong nativeCamera,
Java_com_google_android_filament_Camera_nSetProjection(JNIEnv* env, jclass, jlong nativeCamera,
jint projection, jdouble left, jdouble right, jdouble bottom, jdouble top, jdouble near,
jdouble far) {
Camera *camera = (Camera *) nativeCamera;
camera->setProjection((Camera::Projection) projection, left, right, bottom, top, near, far);
wrapJni(env, [=]() {
camera->setProjection((Camera::Projection) projection, left, right, bottom, top, near, far);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetProjectionFov(JNIEnv*, jclass ,
Java_com_google_android_filament_Camera_nSetProjectionFov(JNIEnv* env, jclass ,
jlong nativeCamera, jdouble fovInDegrees, jdouble aspect, jdouble near, jdouble far,
jint fov) {
Camera *camera = (Camera *) nativeCamera;
camera->setProjection(fovInDegrees, aspect, near, far, (Camera::Fov) fov);
wrapJni(env, [=]() {
camera->setProjection(fovInDegrees, aspect, near, far, (Camera::Fov) fov);
});
}
extern "C" JNIEXPORT jdouble JNICALL
@@ -49,10 +55,12 @@ Java_com_google_android_filament_Camera_nGetFieldOfViewInDegrees(JNIEnv*, jclass
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetLensProjection(JNIEnv*, jclass,
Java_com_google_android_filament_Camera_nSetLensProjection(JNIEnv* env, jclass,
jlong nativeCamera, jdouble focalLength, jdouble aspect, jdouble near, jdouble far) {
Camera *camera = (Camera *) nativeCamera;
camera->setLensProjection(focalLength, aspect, near, far);
wrapJni(env, [=]() {
camera->setLensProjection(focalLength, aspect, near, far);
});
}
extern "C" JNIEXPORT void JNICALL
@@ -62,10 +70,12 @@ Java_com_google_android_filament_Camera_nSetCustomProjection(JNIEnv *env, jclass
Camera *camera = (Camera *) nativeCamera;
jdouble *inProjection = env->GetDoubleArrayElements(inProjection_, NULL);
jdouble *inProjectionForCulling = env->GetDoubleArrayElements(inProjectionForCulling_, NULL);
camera->setCustomProjection(
*reinterpret_cast<const filament::math::mat4 *>(inProjection),
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
near, far);
wrapJni(env, [=]() {
camera->setCustomProjection(
*reinterpret_cast<const filament::math::mat4 *>(inProjection),
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
near, far);
});
env->ReleaseDoubleArrayElements(inProjection_, inProjection, JNI_ABORT);
env->ReleaseDoubleArrayElements(inProjectionForCulling_, inProjectionForCulling, JNI_ABORT);
}
@@ -77,10 +87,12 @@ Java_com_google_android_filament_Camera_nSetCustomEyeProjection(JNIEnv *env, jcl
Camera *camera = (Camera *) nativeCamera;
jdouble *inProjection = env->GetDoubleArrayElements(inProjection_, NULL);
jdouble *inProjectionForCulling = env->GetDoubleArrayElements(inProjectionForCulling_, NULL);
camera->setCustomEyeProjection(
reinterpret_cast<const filament::math::mat4 *>(inProjection), (size_t) count,
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
near, far);
wrapJni(env, [=]() {
camera->setCustomEyeProjection(
reinterpret_cast<const filament::math::mat4 *>(inProjection), (size_t) count,
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
near, far);
});
env->ReleaseDoubleArrayElements(inProjection_, inProjection, JNI_ABORT);
env->ReleaseDoubleArrayElements(inProjectionForCulling_, inProjectionForCulling, JNI_ABORT);
}
@@ -154,7 +166,9 @@ Java_com_google_android_filament_Camera_nSetEyeModelMatrix(JNIEnv *env, jclass,
jlong nativeCamera, jint eyeId, jdoubleArray model_) {
Camera* camera = (Camera *) nativeCamera;
jdouble *model = env->GetDoubleArrayElements(model_, NULL);
camera->setEyeModelMatrix((uint8_t)eyeId, *reinterpret_cast<const filament::math::mat4*>(model));
wrapJni(env, [=]() {
camera->setEyeModelMatrix((uint8_t)eyeId, *reinterpret_cast<const filament::math::mat4 *>(model));
});
env->ReleaseDoubleArrayElements(model_, model, JNI_ABORT);
}

View File

@@ -21,6 +21,7 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <common/JniUtils.h>
using namespace filament;
using namespace math;
@@ -37,10 +38,12 @@ Java_com_google_android_filament_ColorGrading_nDestroyBuilder(JNIEnv*, jclass, j
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_ColorGrading_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder, jlong nativeEngine) {
Java_com_google_android_filament_ColorGrading_nBuilderBuild(JNIEnv* env, jclass, jlong nativeBuilder, jlong nativeEngine) {
ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -16,6 +16,8 @@
#include <jni.h>
#include <exception>
#include <filament/Camera.h>
#include <filament/Engine.h>
#include <filament/MorphTargetBuffer.h>
@@ -28,14 +30,18 @@
#include <filament/View.h>
#include "common/CallbackUtils.h"
#include "common/JniUtils.h"
using namespace filament;
using namespace utils;
using namespace filament::android;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyEngine(JNIEnv*, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
Engine::destroy(&engine);
Java_com_google_android_filament_Engine_nDestroyEngine(JNIEnv *env, jclass, jlong nativeEngine) {
wrapJni(env, [=]() {
Engine* engine = (Engine*) nativeEngine;
Engine::destroy(&engine);
});
}
// SwapChain
@@ -77,11 +83,13 @@ Java_com_google_android_filament_Engine_nCreateSwapChainFromRawPointer(JNIEnv*,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroySwapChain(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroySwapChain(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeSwapChain) {
Engine* engine = (Engine*) nativeEngine;
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
return engine->destroy(swapChain);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(swapChain);
});
}
// View
@@ -94,11 +102,13 @@ Java_com_google_android_filament_Engine_nCreateView(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyView(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyView(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeView) {
Engine* engine = (Engine*) nativeEngine;
View* view = (View*) nativeView;
return engine->destroy(view);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(view);
});
}
// Renderer
@@ -111,11 +121,13 @@ Java_com_google_android_filament_Engine_nCreateRenderer(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyRenderer(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyRenderer(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeRenderer) {
Engine* engine = (Engine*) nativeEngine;
Renderer* renderer = (Renderer*) nativeRenderer;
return engine->destroy(renderer);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(renderer);
});
}
// Camera
@@ -137,11 +149,13 @@ Java_com_google_android_filament_Engine_nGetCameraComponent(JNIEnv*, jclass,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyCameraComponent(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyCameraComponent(JNIEnv *env, jclass,
jlong nativeEngine, jint entity_) {
Engine* engine = (Engine*) nativeEngine;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
engine->destroyCameraComponent(entity);
wrapJni(env, [=]() {
Engine* engine = (Engine*) nativeEngine;
Entity entity = *reinterpret_cast<const Entity*>(&entity_);
engine->destroyCameraComponent(entity);
});
}
// Scene
@@ -154,11 +168,13 @@ Java_com_google_android_filament_Engine_nCreateScene(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyScene(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyScene(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeScene) {
Engine* engine = (Engine*) nativeEngine;
Scene* scene = (Scene*) nativeScene;
return engine->destroy(scene);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(scene);
});
}
// Fence
@@ -171,119 +187,147 @@ Java_com_google_android_filament_Engine_nCreateFence(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyFence(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyFence(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeFence) {
Engine* engine = (Engine*) nativeEngine;
Fence* fence = (Fence*) nativeFence;
return engine->destroy(fence);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(fence);
});
}
// Stream
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyStream(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyStream(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeStream) {
Engine* engine = (Engine*) nativeEngine;
Stream* stream = (Stream*) nativeStream;
return engine->destroy(stream);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(stream);
});
}
// Others...
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyIndexBuffer(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyIndexBuffer(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeIndexBuffer) {
Engine* engine = (Engine*) nativeEngine;
IndexBuffer* indexBuffer = (IndexBuffer*) nativeIndexBuffer;
return engine->destroy(indexBuffer);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(indexBuffer);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyVertexBuffer(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyVertexBuffer(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeVertexBuffer) {
Engine* engine = (Engine*) nativeEngine;
VertexBuffer* vertexBuffer = (VertexBuffer*) nativeVertexBuffer;
return engine->destroy(vertexBuffer);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(vertexBuffer);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroySkinningBuffer(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroySkinningBuffer(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeSkinningBuffer) {
Engine* engine = (Engine*) nativeEngine;
SkinningBuffer* skinningBuffer = (SkinningBuffer*) nativeSkinningBuffer;
return engine->destroy(skinningBuffer);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(skinningBuffer);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyMorphTargetBuffer(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyMorphTargetBuffer(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeMorphTargetBuffer) {
Engine* engine = (Engine*) nativeEngine;
MorphTargetBuffer* mtb = (MorphTargetBuffer*) nativeMorphTargetBuffer;
return engine->destroy(mtb);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(mtb);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyIndirectLight(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyIndirectLight(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeIndirectLight) {
Engine* engine = (Engine*) nativeEngine;
IndirectLight* indirectLight = (IndirectLight*) nativeIndirectLight;
return engine->destroy(indirectLight);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(indirectLight);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyMaterial(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyMaterial(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeMaterial) {
Engine* engine = (Engine*) nativeEngine;
Material* material = (Material*) nativeMaterial;
return engine->destroy(material);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(material);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyMaterialInstance(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyMaterialInstance(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeMaterialInstance) {
Engine* engine = (Engine*) nativeEngine;
MaterialInstance* materialInstance = (MaterialInstance*) nativeMaterialInstance;
return engine->destroy(materialInstance);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(materialInstance);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroySkybox(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroySkybox(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeSkybox) {
Engine* engine = (Engine*) nativeEngine;
Skybox* skybox = (Skybox*) nativeSkybox;
return engine->destroy(skybox);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(skybox);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyColorGrading(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyColorGrading(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeColorGrading) {
Engine* engine = (Engine*) nativeEngine;
ColorGrading* colorGrading = (ColorGrading*) nativeColorGrading;
return engine->destroy(colorGrading);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(colorGrading);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyTexture(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyTexture(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeTexture) {
Engine* engine = (Engine*) nativeEngine;
Texture* texture = (Texture*) nativeTexture;
return engine->destroy(texture);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(texture);
});
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nDestroyRenderTarget(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyRenderTarget(JNIEnv *env, jclass,
jlong nativeEngine, jlong nativeTarget) {
Engine* engine = (Engine*) nativeEngine;
RenderTarget* target = (RenderTarget*) nativeTarget;
return engine->destroy(target);
return wrapJni<jboolean>(env, [=]() {
return engine->destroy(target);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv *env, jclass,
jlong nativeEngine, jint entity_) {
Engine* engine = (Engine*) nativeEngine;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
engine->destroy(entity);
wrapJni(env, [=]() {
Engine* engine = (Engine*) nativeEngine;
Entity entity = *reinterpret_cast<const Entity*>(&entity_);
engine->destroy(entity);
});
}
@@ -415,17 +459,21 @@ Java_com_google_android_filament_Engine_nIsValidSwapChain(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv *env, jclass,
jlong nativeEngine, jlong timeout) {
Engine* engine = (Engine*) nativeEngine;
return engine->flushAndWait((uint64_t)timeout);
return wrapJni<jboolean>(env, [=]() {
return engine->flushAndWait((uint64_t)timeout);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nFlush(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nFlush(JNIEnv *env, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
engine->flush();
wrapJni(env, [=]() {
engine->flush();
});
}
extern "C" JNIEXPORT jboolean JNICALL
@@ -436,21 +484,32 @@ Java_com_google_android_filament_Engine_nIsPaused(JNIEnv*, jclass,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nCompile(JNIEnv* env, jclass,
Java_com_google_android_filament_Engine_nCompile(JNIEnv *env, jclass,
jlong nativeEngine, jint priority, jlong nativeMaterial, jlong nativeView,
jint shadowReceiver, jint skinning, jobject handler, jobject runnable) {
Engine* engine = (Engine*) nativeEngine;
Material* material = (Material*) nativeMaterial;
View* view = (View*) nativeView;
JniCallback* jniCallback = JniCallback::make(env, handler, runnable);
engine->compile(
(backend::CompilerPriorityQueue) priority,
material, view,
(utils::tribool::value_t) shadowReceiver,
(utils::tribool::value_t) skinning,
jniCallback->getHandler(), [jniCallback](Material*){
JniCallback::postToJavaAndDestroy(jniCallback);
});
wrapJni(env, [=]() {
#if defined(__EXCEPTIONS)
try {
#endif
engine->compile(
(backend::CompilerPriorityQueue) priority,
material, view,
(utils::tribool::value_t) shadowReceiver,
(utils::tribool::value_t) skinning,
jniCallback->getHandler(), [jniCallback](Material*){
JniCallback::postToJavaAndDestroy(jniCallback);
});
#if defined(__EXCEPTIONS)
} catch (...) {
JniCallback::destroy(jniCallback);
throw;
}
#endif
});
}
extern "C" JNIEXPORT void JNICALL
@@ -511,6 +570,12 @@ Java_com_google_android_filament_Engine_nIsAutomaticInstancingEnabled(JNIEnv*, j
return (jboolean)engine->isAutomaticInstancingEnabled();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nHasUnrecoverableFailure(JNIEnv*, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jboolean)engine->hasUnrecoverableFailure();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nGetMaxStereoscopicEyes(JNIEnv*, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
@@ -526,10 +591,12 @@ Java_com_google_android_filament_Engine_nGetSupportedFeatureLevel(JNIEnv *, jcla
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Engine_nSetActiveFeatureLevel(JNIEnv *, jclass,
Java_com_google_android_filament_Engine_nSetActiveFeatureLevel(JNIEnv *env, jclass,
jlong nativeEngine, jint ordinal) {
Engine* engine = (Engine*) nativeEngine;
return (jint)engine->setActiveFeatureLevel((Engine::FeatureLevel)ordinal);
return wrapJni<jint>(env, [=]() {
return (jint)engine->setActiveFeatureLevel((Engine::FeatureLevel)ordinal);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -651,9 +718,11 @@ Java_com_google_android_filament_Engine_nSetBuilderFeature(JNIEnv *env, jclass c
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder) {
Java_com_google_android_filament_Engine_nBuilderBuild(JNIEnv *env, jclass, jlong nativeBuilder) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
return (jlong) builder->build();
return wrapJniBackend<jlong>(env, [=]() {
return (jlong) builder->build();
});
}
extern "C"

View File

@@ -17,6 +17,7 @@
#include <jni.h>
#include <filament/Fence.h>
#include <common/JniUtils.h>
using namespace filament;
@@ -24,13 +25,17 @@ extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Fence_nWait(JNIEnv *env, jclass type, jlong nativeFence, jint mode,
jlong timeoutNanoSeconds) {
Fence *fence = (Fence *) nativeFence;
return (jint) fence->wait((Fence::Mode) mode, (uint64_t) timeoutNanoSeconds);
return filament::android::wrapJniBackend<jint>(env, [=]() {
return (jint) fence->wait((Fence::Mode) mode, (uint64_t) timeoutNanoSeconds);
});
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Fence_nWaitAndDestroy(JNIEnv *env, jclass type, jlong nativeFence,
jint mode) {
Fence *fence = (Fence *) nativeFence;
return (jint) Fence::waitAndDestroy(fence, (Fence::Mode) mode);
return filament::android::wrapJniBackend<jint>(env, [=]() {
return (jint) Fence::waitAndDestroy(fence, (Fence::Mode) mode);
});
}

View File

@@ -16,11 +16,11 @@
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
#include <filament/IndexBuffer.h>
#include <common/JniUtils.h>
#include <backend/BufferDescriptor.h>
@@ -29,6 +29,7 @@
using namespace filament;
using namespace backend;
using namespace filament::android;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_IndexBuffer_nCreateBuilder(JNIEnv *env, jclass type) {
@@ -63,7 +64,9 @@ Java_com_google_android_filament_IndexBuffer_nBuilderBuild(JNIEnv *env, jclass t
jlong nativeBuilder, jlong nativeEngine) {
IndexBuffer::Builder* builder = (IndexBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -94,7 +97,9 @@ Java_com_google_android_filament_IndexBuffer_nSetBuffer(JNIEnv *env, jclass type
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
indexBuffer->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
wrapJni(env, [&]() {
indexBuffer->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
});
return 0;
}

View File

@@ -21,6 +21,7 @@
#include <common/NioUtils.h>
#include <common/CallbackUtils.h>
#include <math/mat4.h>
#include <common/JniUtils.h>
using namespace filament;
@@ -37,11 +38,13 @@ Java_com_google_android_filament_IndirectLight_nDestroyBuilder(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_IndirectLight_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_IndirectLight_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine) {
IndirectLight::Builder* builder = (IndirectLight::Builder*) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -17,6 +17,7 @@
#include <jni.h>
#include <filament/LightManager.h>
#include <common/JniUtils.h>
#include <utils/Entity.h>
@@ -24,6 +25,7 @@
using namespace filament;
using namespace utils;
using namespace filament::android;
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_LightManager_nGetComponentCount(JNIEnv*, jclass,
@@ -210,11 +212,13 @@ Java_com_google_android_filament_LightManager_nBuilderLightChannel(JNIEnv*, jcla
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_LightManager_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_LightManager_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine, jint entity) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return jboolean(builder->build(*engine, (Entity &) entity) == LightManager::Builder::Success);
return wrapJni<jboolean>(env, [=]() {
return jboolean(builder->build(*engine, (Entity &) entity) == LightManager::Builder::Success);
});
}
// ------------------------------------------------------------------------------------------------
@@ -223,7 +227,9 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nComputeUniformSplits(JNIEnv* env, jclass,
jfloatArray splitPositions, jint cascades) {
jfloat *nativeSplits = env->GetFloatArrayElements(splitPositions, NULL);
LightManager::ShadowCascades::computeUniformSplits(nativeSplits, (uint8_t) cascades);
wrapJni(env, [=]() {
LightManager::ShadowCascades::computeUniformSplits(nativeSplits, (uint8_t) cascades);
});
env->ReleaseFloatArrayElements(splitPositions, nativeSplits, 0);
}
@@ -231,7 +237,9 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nComputeLogSplits(JNIEnv* env, jclass,
jfloatArray splitPositions, jint cascades, jfloat near, jfloat far) {
jfloat *nativeSplits = env->GetFloatArrayElements(splitPositions, NULL);
LightManager::ShadowCascades::computeLogSplits(nativeSplits, (uint8_t) cascades, near, far);
wrapJni(env, [=]() {
LightManager::ShadowCascades::computeLogSplits(nativeSplits, (uint8_t) cascades, near, far);
});
env->ReleaseFloatArrayElements(splitPositions, nativeSplits, 0);
}
@@ -239,7 +247,9 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nComputePracticalSplits(JNIEnv* env, jclass,
jfloatArray splitPositions, jint cascades, jfloat near, jfloat far, jfloat lambda) {
jfloat *nativeSplits = env->GetFloatArrayElements(splitPositions, NULL);
LightManager::ShadowCascades::computePracticalSplits(nativeSplits, (uint8_t) cascades, near, far, lambda);
wrapJni(env, [=]() {
LightManager::ShadowCascades::computePracticalSplits(nativeSplits, (uint8_t) cascades, near, far, lambda);
});
env->ReleaseFloatArrayElements(splitPositions, nativeSplits, 0);
}

View File

@@ -20,25 +20,28 @@
#include "common/NioUtils.h"
#include "common/CallbackUtils.h"
#include <common/JniUtils.h>
using namespace filament;
using namespace filament::android;
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, jint uboBatchingMode) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, buffer_, size);
auto builder = Material::Builder();
if (shBandCount) {
builder.sphericalHarmonicsBandCount(shBandCount);
}
builder.shadowSamplingQuality((Material::Builder::ShadowSamplingQuality)shadowQuality);
builder.uboBatching((Material::UboBatchingMode)uboBatchingMode);
Material* material = builder
.package(buffer.getData(), buffer.getSize())
.build(*engine);
return (jlong) material;
return wrapJni<jlong>(env, [=]() {
AutoBuffer buffer(env, buffer_, size);
auto builder = Material::Builder();
if (shBandCount) {
builder.sphericalHarmonicsBandCount(shBandCount);
}
builder.shadowSamplingQuality((Material::Builder::ShadowSamplingQuality)shadowQuality);
builder.uboBatching((Material::UboBatchingMode)uboBatchingMode);
Material* material = builder
.package(buffer.getData(), buffer.getSize())
.build(*engine);
return (jlong) material;
});
}
extern "C" JNIEXPORT jlong JNICALL

View File

@@ -25,9 +25,11 @@
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <common/JniUtils.h>
using namespace filament;
using namespace filament::math;
using namespace filament::android;
enum BooleanElement {
BOOL,
@@ -56,7 +58,9 @@ template<typename T>
static void setParameter(JNIEnv* env, jlong nativeMaterialInstance, jstring name_, T v) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
const char *name = env->GetStringUTFChars(name_, 0);
instance->setParameter(name, v);
wrapJni(env, [=]() {
instance->setParameter(name, v);
});
env->ReleaseStringUTFChars(name_, name);
}
@@ -160,20 +164,22 @@ Java_com_google_android_filament_MaterialInstance_nSetBooleanParameterArray(JNIE
// NOTE: In C++, bool has an implementation-defined size. Here we assume
// it has the same size as jboolean, which is 1 byte.
switch ((BooleanElement) element) {
case BOOL:
instance->setParameter(name, ((const bool*) v) + offset, count);
break;
case BOOL2:
instance->setParameter(name, ((const bool2*) v) + offset, count);
break;
case BOOL3:
instance->setParameter(name, ((const bool3*) v) + offset, count);
break;
case BOOL4:
instance->setParameter(name, ((const bool4*) v) + offset, count);
break;
}
wrapJni(env, [=]() {
switch ((BooleanElement) element) {
case BOOL:
instance->setParameter(name, ((const bool*) v) + offset, count);
break;
case BOOL2:
instance->setParameter(name, ((const bool2*) v) + offset, count);
break;
case BOOL3:
instance->setParameter(name, ((const bool3*) v) + offset, count);
break;
case BOOL4:
instance->setParameter(name, ((const bool4*) v) + offset, count);
break;
}
});
env->ReleaseBooleanArrayElements(v_, v, 0);
@@ -190,20 +196,22 @@ Java_com_google_android_filament_MaterialInstance_nSetIntParameterArray(JNIEnv *
const char* name = env->GetStringUTFChars(name_, 0);
jint* v = env->GetIntArrayElements(v_, NULL);
switch ((IntElement) element) {
case INT:
instance->setParameter(name, ((const int32_t*) v) + offset, count);
break;
case INT2:
instance->setParameter(name, ((const int2*) v) + offset, count);
break;
case INT3:
instance->setParameter(name, ((const int3*) v) + offset, count);
break;
case INT4:
instance->setParameter(name, ((const int4*) v) + offset, count);
break;
}
wrapJni(env, [=]() {
switch ((IntElement) element) {
case INT:
instance->setParameter(name, ((const int32_t*) v) + offset, count);
break;
case INT2:
instance->setParameter(name, ((const int2*) v) + offset, count);
break;
case INT3:
instance->setParameter(name, ((const int3*) v) + offset, count);
break;
case INT4:
instance->setParameter(name, ((const int4*) v) + offset, count);
break;
}
});
env->ReleaseIntArrayElements(v_, v, JNI_ABORT);
@@ -220,26 +228,28 @@ Java_com_google_android_filament_MaterialInstance_nSetFloatParameterArray(JNIEnv
const char* name = env->GetStringUTFChars(name_, 0);
jfloat* v = env->GetFloatArrayElements(v_, NULL);
switch ((FloatElement) element) {
case FLOAT:
instance->setParameter(name, ((const float*) v) + offset, count);
break;
case FLOAT2:
instance->setParameter(name, ((const float2*) v) + offset, count);
break;
case FLOAT3:
instance->setParameter(name, ((const float3*) v) + offset, count);
break;
case FLOAT4:
instance->setParameter(name, ((const float4*) v) + offset, count);
break;
case MAT3:
instance->setParameter(name, ((const mat3f*) v) + offset, count);
break;
case MAT4:
instance->setParameter(name, ((const mat4f*) v) + offset, count);
break;
}
wrapJni(env, [=]() {
switch ((FloatElement) element) {
case FLOAT:
instance->setParameter(name, ((const float*) v) + offset, count);
break;
case FLOAT2:
instance->setParameter(name, ((const float2*) v) + offset, count);
break;
case FLOAT3:
instance->setParameter(name, ((const float3*) v) + offset, count);
break;
case FLOAT4:
instance->setParameter(name, ((const float4*) v) + offset, count);
break;
case MAT3:
instance->setParameter(name, ((const mat3f*) v) + offset, count);
break;
case MAT4:
instance->setParameter(name, ((const mat4f*) v) + offset, count);
break;
}
});
env->ReleaseFloatArrayElements(v_, v, 0);
@@ -260,7 +270,9 @@ Java_com_google_android_filament_MaterialInstance_nSetParameterTexture(
Texture* texture = (Texture*) nativeTexture;
const char *name = env->GetStringUTFChars(name_, 0);
instance->setParameter(name, texture, JniUtils::from_long(sampler_));
wrapJni(env, [=]() {
instance->setParameter(name, texture, JniUtils::from_long(sampler_));
});
env->ReleaseStringUTFChars(name_, name);
}

View File

@@ -16,7 +16,6 @@
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
@@ -24,6 +23,7 @@
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <common/JniUtils.h>
using namespace filament;
using namespace backend;
@@ -81,11 +81,13 @@ extern "C" JNIEXPORT void JNICALL
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_MorphTargetBuffer_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine) {
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
// ------------------------------------------------------------------------------------------------
@@ -97,11 +99,13 @@ Java_com_google_android_filament_MorphTargetBuffer_nSetPositionsAt(JNIEnv* env,
jint targetIndex, jfloatArray positions, jint count) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
Engine *engine = (Engine *) nativeEngine;
jfloat* data = env->GetFloatArrayElements(positions, NULL);
morphTargetBuffer->setPositionsAt(*engine, targetIndex,
(math::float4*) data, size_t(count));
env->ReleaseFloatArrayElements(positions, data, JNI_ABORT);
return 0;
return filament::android::wrapJni<jint>(env, [=]() {
jfloat* data = env->GetFloatArrayElements(positions, NULL);
morphTargetBuffer->setPositionsAt(*engine, targetIndex,
(math::float4*) data, size_t(count));
env->ReleaseFloatArrayElements(positions, data, JNI_ABORT);
return 0;
});
}
extern "C"
@@ -111,11 +115,13 @@ Java_com_google_android_filament_MorphTargetBuffer_nSetTangentsAt(JNIEnv* env, j
jint targetIndex, jshortArray tangents, jint count) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
Engine *engine = (Engine *) nativeEngine;
jshort* data = env->GetShortArrayElements(tangents, NULL);
morphTargetBuffer->setTangentsAt(*engine, targetIndex,
(math::short4*) data, size_t(count));
env->ReleaseShortArrayElements(tangents, data, JNI_ABORT);
return 0;
return filament::android::wrapJni<jint>(env, [=]() {
jshort* data = env->GetShortArrayElements(tangents, NULL);
morphTargetBuffer->setTangentsAt(*engine, targetIndex,
(math::short4*) data, size_t(count));
env->ReleaseShortArrayElements(tangents, data, JNI_ABORT);
return 0;
});
}
extern "C"

View File

@@ -21,6 +21,7 @@
#include <string.h>
#include <filament/RenderTarget.h>
#include <common/JniUtils.h>
using namespace filament;
using namespace backend;
@@ -72,7 +73,9 @@ Java_com_google_android_filament_RenderTarget_nBuilderBuild(JNIEnv *env, jclass
jlong nativeBuilder, jlong nativeEngine) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT jint JNICALL

View File

@@ -18,6 +18,7 @@
#include <filament/RenderableManager.h>
#include <filament/MaterialInstance.h>
#include <common/JniUtils.h>
#include <utils/Entity.h>
@@ -25,6 +26,7 @@
using namespace filament;
using namespace utils;
using namespace filament::android;
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_RenderableManager_nHasComponent(JNIEnv*, jclass,
@@ -63,11 +65,13 @@ Java_com_google_android_filament_RenderableManager_nDestroyBuilder(JNIEnv*, jcla
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_RenderableManager_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine, jint entity) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return jboolean(builder->build(*engine, (Entity &) entity) == RenderableManager::Builder::Success);
return wrapJni<jboolean>(env, [=]() {
return jboolean(builder->build(*engine, (Entity &) entity) == RenderableManager::Builder::Success);
});
}
extern "C" JNIEXPORT void JNICALL
@@ -276,11 +280,13 @@ Java_com_google_android_filament_RenderableManager_nBuilderInstances(JNIEnv*, jc
// ------------------------------------------------------------------------------------------------
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetSkinningBuffer(JNIEnv*, jclass,
Java_com_google_android_filament_RenderableManager_nSetSkinningBuffer(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint i, jlong nativeSkinningBuffer, jint count, jint offset) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
SkinningBuffer *sb = (SkinningBuffer *) nativeSkinningBuffer;
rm->setSkinningBuffer(i, sb, count, offset);
wrapJni(env, [=]() {
rm->setSkinningBuffer(i, sb, count, offset);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -295,9 +301,12 @@ Java_com_google_android_filament_RenderableManager_nSetBonesAsMatrices(JNIEnv* e
// BufferOverflowException
return -1;
}
rm->setBones((RenderableManager::Instance)i,
static_cast<filament::math::mat4f const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
jint result = 0;
wrapJni(env, [=]() {
rm->setBones((RenderableManager::Instance)i,
static_cast<filament::math::mat4f const *>(data), (size_t)boneCount, (size_t)offset);
});
return result;
}
extern "C" JNIEXPORT jint JNICALL
@@ -312,9 +321,12 @@ Java_com_google_android_filament_RenderableManager_nSetBonesAsQuaternions(JNIEnv
// BufferOverflowException
return -1;
}
rm->setBones((RenderableManager::Instance)i,
static_cast<RenderableManager::Bone const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
jint result = 0;
wrapJni(env, [=]() {
rm->setBones((RenderableManager::Instance)i,
static_cast<RenderableManager::Bone const *>(data), (size_t)boneCount, (size_t)offset);
});
return result;
}
extern "C" JNIEXPORT void JNICALL
@@ -323,17 +335,21 @@ Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env,
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
jfloat* vec = env->GetFloatArrayElements(weights, NULL);
jsize count = env->GetArrayLength(weights);
rm->setMorphWeights((RenderableManager::Instance)instance, vec, count, offset);
wrapJni(env, [=]() {
rm->setMorphWeights((RenderableManager::Instance)instance, vec, count, offset);
});
env->ReleaseFloatArrayElements(weights, vec, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferOffsetAt(JNIEnv*,
Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferOffsetAt(JNIEnv* env,
jclass, jlong nativeRenderableManager, jint i, int level, jint primitiveIndex,
jlong, jint offset) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->setMorphTargetBufferOffsetAt((RenderableManager::Instance) i, (uint8_t) level,
(size_t) primitiveIndex, (size_t) offset);
wrapJni(env, [=]() {
rm->setMorphTargetBufferOffsetAt((RenderableManager::Instance) i, (uint8_t) level,
(size_t) primitiveIndex, (size_t) offset);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -344,12 +360,14 @@ Java_com_google_android_filament_RenderableManager_nGetMorphTargetCount(JNIEnv*
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetAxisAlignedBoundingBox(JNIEnv*,
Java_com_google_android_filament_RenderableManager_nSetAxisAlignedBoundingBox(JNIEnv* env,
jclass, jlong nativeRenderableManager, jint i, jfloat cx, jfloat cy, jfloat cz,
jfloat ex, jfloat ey, jfloat ez) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->setAxisAlignedBoundingBox((RenderableManager::Instance) i, {{cx, cy, cz},
{ex, ey, ez}});
wrapJni(env, [=]() {
rm->setAxisAlignedBoundingBox((RenderableManager::Instance) i, {{cx, cy, cz},
{ex, ey, ez}});
});
}
extern "C" JNIEXPORT void JNICALL
@@ -486,19 +504,23 @@ Java_com_google_android_filament_RenderableManager_nGetInstanceCount(JNIEnv*, jc
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv*, jclass,
Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint i, jint primitiveIndex, jlong nativeMaterialInstance) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
const MaterialInstance *materialInstance = (const MaterialInstance *) nativeMaterialInstance;
rm->setMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex,
materialInstance);
wrapJni(env, [=]() {
rm->setMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex,
materialInstance);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nClearMaterialInstanceAt(JNIEnv*, jclass,
Java_com_google_android_filament_RenderableManager_nClearMaterialInstanceAt(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->clearMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
wrapJni(env, [=]() {
rm->clearMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
});
}
extern "C" JNIEXPORT jlong JNICALL

View File

@@ -22,18 +22,24 @@
#include <filament/Viewport.h>
#include <backend/PixelBufferDescriptor.h>
#include <exception>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include "common/JniUtils.h"
using namespace filament;
using namespace backend;
using namespace filament::android;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSkipFrame(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nSkipFrame(JNIEnv *env, jclass, jlong nativeRenderer,
jlong vsyncSteadyClockTimeNano) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->skipFrame(uint64_t(vsyncSteadyClockTimeNano));
wrapJni(env, [=]() {
renderer->skipFrame(uint64_t(vsyncSteadyClockTimeNano));
});
}
extern "C" JNIEXPORT jboolean JNICALL
@@ -43,37 +49,45 @@ Java_com_google_android_filament_Renderer_nShouldRenderFrame(JNIEnv *, jclass, j
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Renderer_nBeginFrame(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nBeginFrame(JNIEnv *env, jclass, jlong nativeRenderer,
jlong nativeSwapChain, jlong frameTimeNanos) {
Renderer *renderer = (Renderer *) nativeRenderer;
SwapChain *swapChain = (SwapChain *) nativeSwapChain;
return (jboolean) renderer->beginFrame(swapChain, uint64_t(frameTimeNanos));
return wrapJniBackend<jboolean>(env, [=]() {
return (jboolean) renderer->beginFrame(swapChain, uint64_t(frameTimeNanos));
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nEndFrame(JNIEnv *, jclass, jlong nativeRenderer) {
Java_com_google_android_filament_Renderer_nEndFrame(JNIEnv *env, jclass, jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->endFrame();
wrapJniBackend(env, [=]() {
renderer->endFrame();
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nRender(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nRender(JNIEnv *env, jclass, jlong nativeRenderer,
jlong nativeView) {
Renderer *renderer = (Renderer *) nativeRenderer;
View *view = (View *) nativeView;
renderer->render(view);
wrapJniBackend(env, [=]() {
renderer->render(view);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nRenderStandaloneView(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nRenderStandaloneView(JNIEnv *env, jclass, jlong nativeRenderer,
jlong nativeView) {
Renderer *renderer = (Renderer *) nativeRenderer;
View *view = (View *) nativeView;
renderer->renderStandaloneView(view);
wrapJni(env, [=]() {
renderer->renderStandaloneView(view);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nCopyFrame(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nCopyFrame(JNIEnv *env, jclass, jlong nativeRenderer,
jlong nativeDstSwapChain,
jint dstLeft, jint dstBottom, jint dstWidth, jint dstHeight,
jint srcLeft, jint srcBottom, jint srcWidth, jint srcHeight,
@@ -82,7 +96,9 @@ Java_com_google_android_filament_Renderer_nCopyFrame(JNIEnv *, jclass, jlong nat
SwapChain *dstSwapChain = (SwapChain *) nativeDstSwapChain;
const filament::Viewport dstViewport {dstLeft, dstBottom, (uint32_t) dstWidth, (uint32_t) dstHeight};
const filament::Viewport srcViewport {srcLeft, srcBottom, (uint32_t) srcWidth, (uint32_t) srcHeight};
renderer->copyFrame(dstSwapChain, dstViewport, srcViewport, (uint32_t) flags);
wrapJni(env, [=]() {
renderer->copyFrame(dstSwapChain, dstViewport, srcViewport, (uint32_t) flags);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -114,10 +130,11 @@ Java_com_google_android_filament_Renderer_nReadPixels(JNIEnv *env, jclass,
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
renderer->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
return wrapJni<jint>(env, [&]() {
renderer->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -150,23 +167,28 @@ Java_com_google_android_filament_Renderer_nReadPixelsEx(JNIEnv *env, jclass,
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
renderer->readPixels(renderTarget,
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
return wrapJni<jint>(env, [&]() {
renderer->readPixels(renderTarget,
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
});
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Renderer_nGetUserTime(JNIEnv*, jclass, jlong nativeRenderer) {
Java_com_google_android_filament_Renderer_nGetUserTime(JNIEnv *env, jclass, jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;
return renderer->getUserTime();
return wrapJni<jdouble>(env, [=]() {
return renderer->getUserTime();
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nResetUserTime(JNIEnv*, jclass, jlong nativeRenderer) {
Java_com_google_android_filament_Renderer_nResetUserTime(JNIEnv *env, jclass, jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->resetUserTime();
wrapJni(env, [=]() {
renderer->resetUserTime();
});
}
extern "C" JNIEXPORT void JNICALL
@@ -186,20 +208,24 @@ Java_com_google_android_filament_Renderer_nSetFrameRateOptions(JNIEnv*, jclass,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSetClearOptions(JNIEnv *, jclass ,
Java_com_google_android_filament_Renderer_nSetClearOptions(JNIEnv *env, jclass ,
jlong nativeRenderer, jfloat r, jfloat g, jfloat b, jfloat a,
jboolean clear, jboolean discard) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->setClearOptions({ .clearColor = {r, g, b, a},
.clear = (bool) clear,
.discard = (bool) discard});
wrapJni(env, [=]() {
renderer->setClearOptions({ .clearColor = {r, g, b, a},
.clear = (bool) clear,
.discard = (bool) discard});
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSetPresentationTime(JNIEnv *, jclass ,
Java_com_google_android_filament_Renderer_nSetPresentationTime(JNIEnv *env, jclass ,
jlong nativeRenderer, jlong monotonicClockNanos) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->setPresentationTime(monotonicClockNanos);
wrapJni(env, [=]() {
renderer->setPresentationTime(monotonicClockNanos);
});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -19,9 +19,11 @@
#include <filament/Scene.h>
#include <utils/Entity.h>
#include <common/JniUtils.h>
using namespace filament;
using namespace utils;
using namespace filament::android;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nSetSkybox(JNIEnv *env, jclass type, jlong nativeScene,
@@ -43,15 +45,20 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nAddEntity(JNIEnv *env, jclass type, jlong nativeScene,
jint entity) {
Scene* scene = (Scene*) nativeScene;
scene->addEntity((Entity&) entity);
wrapJni(env, [=]() {
scene->addEntity((Entity&) entity);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nAddEntities(JNIEnv *env, jclass type, jlong nativeScene,
jintArray entities) {
Scene* scene = (Scene*) nativeScene;
jsize length = env->GetArrayLength(entities);
Entity* nativeEntities = (Entity*) env->GetIntArrayElements(entities, nullptr);
scene->addEntities(nativeEntities, env->GetArrayLength(entities));
wrapJni(env, [=]() {
scene->addEntities(nativeEntities, length);
});
env->ReleaseIntArrayElements(entities, (jint*) nativeEntities, JNI_ABORT);
}
@@ -59,15 +66,20 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nRemove(JNIEnv *env, jclass type, jlong nativeScene,
jint entity) {
Scene* scene = (Scene*) nativeScene;
scene->remove((Entity&) entity);
wrapJni(env, [=]() {
scene->remove((Entity&) entity);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nRemoveEntities(JNIEnv *env, jclass type, jlong nativeScene,
jintArray entities) {
Scene* scene = (Scene*) nativeScene;
jsize length = env->GetArrayLength(entities);
Entity* nativeEntities = (Entity*) env->GetIntArrayElements(entities, nullptr);
scene->removeEntities(nativeEntities, env->GetArrayLength(entities));
wrapJni(env, [=]() {
scene->removeEntities(nativeEntities, length);
});
env->ReleaseIntArrayElements(entities, (jint*) nativeEntities, JNI_ABORT);
}

View File

@@ -16,7 +16,6 @@
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
@@ -24,6 +23,7 @@
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <common/JniUtils.h>
using namespace filament;
using namespace backend;
@@ -60,11 +60,13 @@ Java_com_google_android_filament_SkinningBuffer_nBuilderInitialize(JNIEnv*, jcla
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_SkinningBuffer_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_SkinningBuffer_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine) {
SkinningBuffer::Builder* builder = (SkinningBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
// ------------------------------------------------------------------------------------------------
@@ -76,16 +78,18 @@ Java_com_google_android_filament_SkinningBuffer_nSetBonesAsMatrices(JNIEnv* env,
jint offset) {
SkinningBuffer *skinningBuffer = (SkinningBuffer *) nativeSkinningBuffer;
Engine *engine = (Engine *) nativeEngine;
AutoBuffer nioBuffer(env, matrices, boneCount * 16);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
skinningBuffer->setBones(*engine,
static_cast<filament::math::mat4f const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
return filament::android::wrapJni<jint>(env, [=]() {
AutoBuffer nioBuffer(env, matrices, boneCount * 16);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
skinningBuffer->setBones(*engine,
static_cast<filament::math::mat4f const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
});
}
extern "C"
@@ -95,16 +99,18 @@ Java_com_google_android_filament_SkinningBuffer_nSetBonesAsQuaternions(JNIEnv* e
jint boneCount, jint offset) {
SkinningBuffer *skinningBuffer = (SkinningBuffer *) nativeSkinningBuffer;
Engine *engine = (Engine *) nativeEngine;
AutoBuffer nioBuffer(env, quaternions, boneCount * 8);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
skinningBuffer->setBones(*engine,
static_cast<RenderableManager::Bone const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
return filament::android::wrapJni<jint>(env, [=]() {
AutoBuffer nioBuffer(env, quaternions, boneCount * 8);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
skinningBuffer->setBones(*engine,
static_cast<RenderableManager::Bone const *>(data), (size_t)boneCount, (size_t)offset);
return 0;
});
}
extern "C"

View File

@@ -19,6 +19,7 @@
#include <filament/Skybox.h>
#include <math/vec4.h>
#include <common/JniUtils.h>
using namespace filament;
@@ -76,7 +77,9 @@ Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type,
jlong nativeSkyBoxBuilder, jlong nativeEngine) {
Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -23,6 +23,7 @@
#include "common/NioUtils.h"
#include "common/CallbackUtils.h"
#include <common/JniUtils.h>
#ifdef __ANDROID__
@@ -113,11 +114,13 @@ Java_com_google_android_filament_Stream_nBuilderHeight(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Stream_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_Stream_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeStreamBuilder, jlong nativeEngine) {
StreamBuilder* builder = (StreamBuilder*) nativeStreamBuilder;
Engine* engine = (Engine*) nativeEngine;
return (jlong) builder->builder()->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->builder()->build(*engine);
});
}
extern "C" JNIEXPORT jint JNICALL

View File

@@ -21,6 +21,7 @@
#include "common/NioUtils.h"
#include <algorithm>
#include <common/JniUtils.h>
using namespace filament;
using namespace filament::geometry;
@@ -125,7 +126,9 @@ extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_SurfaceOrientation_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder) {
auto wrapper = (JniWrapper *) nativeBuilder;
return (jlong) wrapper->builder->build();
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) wrapper->builder->build();
});
}
extern "C" JNIEXPORT jint JNICALL

View File

@@ -20,6 +20,7 @@
#include <filament/SwapChain.h>
#include "common/CallbackUtils.h"
#include <common/JniUtils.h>
using namespace filament;
@@ -58,11 +59,13 @@ Java_com_google_android_filament_SwapChain_nSetFrameScheduledCallback(JNIEnv* en
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);
});
filament::android::wrapJni<void>(env, [=]() {
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

View File

@@ -17,7 +17,6 @@
#include <jni.h>
#include <algorithm>
#include <functional>
#ifdef __ANDROID__
#include <android/bitmap.h>
@@ -38,12 +37,14 @@
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <common/JniUtils.h>
#include "private/backend/VirtualMachineEnv.h"
using namespace filament;
using namespace backend;
using namespace filament::android;
static size_t getTextureDataSize(const Texture *texture,
size_t level, Texture::Format format, Texture::Type type,
@@ -273,12 +274,13 @@ Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
(uint32_t) width, (uint32_t) height, (uint32_t) depth,
std::move(desc));
return 0;
return wrapJni<jint>(env, [&]() {
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
(uint32_t) width, (uint32_t) height, (uint32_t) depth,
std::move(desc));
return 0;
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -307,12 +309,13 @@ Java_com_google_android_filament_Texture_nSetImage3DCompressed(JNIEnv *env, jcla
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
(uint32_t) width, (uint32_t) height, (uint32_t) depth,
std::move(desc));
return 0;
return wrapJni<jint>(env, [&]() {
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
(uint32_t) width, (uint32_t) height, (uint32_t) depth,
std::move(desc));
return 0;
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -346,12 +349,13 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
return wrapJni<jint>(env, [&]() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
#pragma clang diagnostic pop
return 0;
return 0;
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -384,20 +388,23 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
return wrapJni<jint>(env, [&]() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
#pragma clang diagnostic pop
return 0;
return 0;
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nSetExternalImage(JNIEnv*, jclass, jlong nativeTexture,
Java_com_google_android_filament_Texture_nSetExternalImage(JNIEnv* env, jclass, jlong nativeTexture,
jlong nativeEngine, jlong eglImage) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
texture->setExternalImage(*engine, (void*)eglImage);
wrapJni(env, [=]() {
texture->setExternalImage(*engine, (void*)eglImage);
});
}
extern "C"
@@ -418,33 +425,35 @@ Java_com_google_android_filament_Texture_nSetExternalImageByAHB(JNIEnv *env, jcl
return JNI_FALSE;
}
if (engine->getBackend() == Backend::OPENGL) {
// CAVEAT: we assume that Backend::OPENGL on Android implies PlatformEGLAndroid.
return wrapJni<jboolean>(env, [=]() {
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;
}
if (!dynamic_cast<PlatformEGLAndroid*>(platform)) {
return JNI_FALSE;
}
#endif
auto* eglPlatform = (PlatformEGLAndroid*) platform;
auto ref = eglPlatform->createExternalImage(nativeBuffer, false);
texture->setExternalImage(*engine, ref);
}
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.
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;
}
if (!dynamic_cast<VulkanPlatformAndroid*>(platform)) {
return JNI_FALSE;
}
#endif
auto* vulkanPlatform = (VulkanPlatformAndroid*) platform;
auto ref = vulkanPlatform->createExternalImage(nativeBuffer, false);
texture->setExternalImage(*engine, ref);
}
auto* vulkanPlatform = (VulkanPlatformAndroid*) platform;
auto ref = vulkanPlatform->createExternalImage(nativeBuffer, false);
texture->setExternalImage(*engine, ref);
}
#endif // FILAMENT_SUPPORTS_VULKAN
// success!
return JNI_TRUE;
// success!
return JNI_TRUE;
});
#else
// other platforms could come here
return JNI_FALSE;
@@ -452,20 +461,24 @@ Java_com_google_android_filament_Texture_nSetExternalImageByAHB(JNIEnv *env, jcl
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nSetExternalStream(JNIEnv*, jclass,
Java_com_google_android_filament_Texture_nSetExternalStream(JNIEnv* env, jclass,
jlong nativeTexture, jlong nativeEngine, jlong nativeStream) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
Stream *stream = (Stream *) nativeStream;
texture->setExternalStream(*engine, stream);
wrapJni(env, [=]() {
texture->setExternalStream(*engine, stream);
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nGenerateMipmaps(JNIEnv*, jclass,
Java_com_google_android_filament_Texture_nGenerateMipmaps(JNIEnv* env, jclass,
jlong nativeTexture, jlong nativeEngine) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
texture->generateMipmaps(*engine);
wrapJni(env, [=]() {
texture->generateMipmaps(*engine);
});
}
extern "C"
@@ -515,9 +528,10 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
options.sampleCount = sampleCount;
options.mirror = mirror;
filament::generatePrefilterMipmap(texture, *engine, std::move(desc), faceOffsets, &options);
return 0;
return wrapJni<jint>(env, [&]() {
filament::generatePrefilterMipmap(texture, *engine, std::move(desc), faceOffsets, &options);
return 0;
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -640,10 +654,12 @@ Java_com_google_android_filament_android_TextureHelper_nSetBitmap(JNIEnv* env, j
autoBitmap->getType(format),
&AutoBitmap::invokeNoCallback, autoBitmap);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height,
std::move(desc));
filament::android::wrapJni(env, [&]() {
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height,
std::move(desc));
});
}
extern "C"
@@ -663,10 +679,12 @@ Java_com_google_android_filament_android_TextureHelper_nSetBitmapWithCallback(JN
autoBitmap->getType(format),
autoBitmap->getHandler(), &AutoBitmap::invoke, autoBitmap);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height,
std::move(desc));
filament::android::wrapJni(env, [&]() {
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height,
std::move(desc));
});
}
#endif

View File

@@ -22,9 +22,11 @@
#include <utils/Entity.h>
#include <math/mat4.h>
#include <common/JniUtils.h>
using namespace utils;
using namespace filament;
using namespace filament::android;
static_assert(sizeof(jint) == sizeof(Entity), "jint and Entity are not compatible!!");
@@ -45,12 +47,14 @@ Java_com_google_android_filament_TransformManager_nGetInstance(JNIEnv*, jclass,
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TransformManager_nCreate(JNIEnv*, jclass,
Java_com_google_android_filament_TransformManager_nCreate(JNIEnv* env, jclass,
jlong nativeTransformManager, jint entity_) {
TransformManager* tm = (TransformManager*) nativeTransformManager;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
tm->create(entity);
return tm->getInstance(entity);
return wrapJni<jint>(env, [=]() {
Entity entity = *reinterpret_cast<const Entity*>(&entity_);
tm->create(entity);
return tm->getInstance(entity);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -58,16 +62,18 @@ Java_com_google_android_filament_TransformManager_nCreateArray(JNIEnv* env,
jclass, jlong nativeTransformManager, jint entity_, jint parent,
jfloatArray localTransform_) {
TransformManager* tm = (TransformManager*) nativeTransformManager;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
if (localTransform_) {
jfloat *localTransform = env->GetFloatArrayElements(localTransform_, NULL);
tm->create(entity, (TransformManager::Instance) parent,
*reinterpret_cast<const filament::math::mat4f *>(localTransform));
env->ReleaseFloatArrayElements(localTransform_, localTransform, JNI_ABORT);
} else {
tm->create(entity, (TransformManager::Instance) parent);
}
return tm->getInstance(entity);
return wrapJni<jint>(env, [=]() {
Entity entity = *reinterpret_cast<const Entity*>(&entity_);
if (localTransform_) {
jfloat *localTransform = env->GetFloatArrayElements(localTransform_, NULL);
tm->create(entity, (TransformManager::Instance) parent,
*reinterpret_cast<const filament::math::mat4f *>(localTransform));
env->ReleaseFloatArrayElements(localTransform_, localTransform, JNI_ABORT);
} else {
tm->create(entity, (TransformManager::Instance) parent);
}
return tm->getInstance(entity);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -75,16 +81,18 @@ Java_com_google_android_filament_TransformManager_nCreateArrayFp64(JNIEnv* env,
jclass, jlong nativeTransformManager, jint entity_, jint parent,
jdoubleArray localTransform_) {
TransformManager* tm = (TransformManager*) nativeTransformManager;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
if (localTransform_) {
jdouble *localTransform = env->GetDoubleArrayElements(localTransform_, NULL);
tm->create(entity, (TransformManager::Instance) parent,
*reinterpret_cast<const filament::math::mat4 *>(localTransform));
env->ReleaseDoubleArrayElements(localTransform_, localTransform, JNI_ABORT);
} else {
tm->create(entity, (TransformManager::Instance) parent);
}
return tm->getInstance(entity);
return wrapJni<jint>(env, [=]() {
Entity entity = *reinterpret_cast<const Entity*>(&entity_);
if (localTransform_) {
jdouble *localTransform = env->GetDoubleArrayElements(localTransform_, NULL);
tm->create(entity, (TransformManager::Instance) parent,
*reinterpret_cast<const filament::math::mat4 *>(localTransform));
env->ReleaseDoubleArrayElements(localTransform_, localTransform, JNI_ABORT);
} else {
tm->create(entity, (TransformManager::Instance) parent);
}
return tm->getInstance(entity);
});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -26,6 +26,7 @@
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <common/JniUtils.h>
using namespace filament;
using namespace filament::math;
@@ -82,11 +83,13 @@ Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv*, jclass
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv*, jclass,
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder, jlong nativeEngine) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
return filament::android::wrapJni<jlong>(env, [=]() {
return (jlong) builder->build(*engine);
});
}
extern "C" JNIEXPORT jint JNICALL
@@ -104,30 +107,34 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass,
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
Engine *engine = (Engine *) nativeEngine;
AutoBuffer nioBuffer(env, buffer, count);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
return filament::android::wrapJni<jint>(env, [=]() {
AutoBuffer nioBuffer(env, buffer, count);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
vertexBuffer->setBufferAt(*engine, (uint8_t) bufferIndex, std::move(desc),
(uint32_t) destOffsetInBytes);
vertexBuffer->setBufferAt(*engine, (uint8_t) bufferIndex, std::move(desc),
(uint32_t) destOffsetInBytes);
return 0;
return 0;
});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv*, jclass,
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv* env, jclass,
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex, jlong nativeBufferObject) {
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
Engine *engine = (Engine *) nativeEngine;
BufferObject *bufferObject = (BufferObject *) nativeBufferObject;
vertexBuffer->setBufferObjectAt(*engine, (uint8_t) bufferIndex, bufferObject);
filament::android::wrapJni(env, [=]() {
vertexBuffer->setBufferObjectAt(*engine, (uint8_t) bufferIndex, bufferObject);
});
}

View File

@@ -21,10 +21,12 @@
#include <filament/Viewport.h>
#include "common/CallbackUtils.h"
#include <common/JniUtils.h>
#include "private/backend/VirtualMachineEnv.h"
using namespace filament;
using namespace filament::android;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetName(JNIEnv* env, jclass, jlong nativeView, jstring name_) {
@@ -35,10 +37,12 @@ Java_com_google_android_filament_View_nSetName(JNIEnv* env, jclass, jlong native
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetScene(JNIEnv*, jclass, jlong nativeView, jlong nativeScene) {
Java_com_google_android_filament_View_nSetScene(JNIEnv* env, jclass, jlong nativeView, jlong nativeScene) {
View* view = (View*) nativeView;
Scene* scene = (Scene*) nativeScene;
view->setScene(scene);
wrapJni(env, [=]() {
view->setScene(scene);
});
}
extern "C" JNIEXPORT void JNICALL
@@ -153,6 +157,24 @@ Java_com_google_android_filament_View_nSetDynamicResolutionOptions(JNIEnv*, jcla
view->setDynamicResolutionOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetGridSize(JNIEnv*, jclass, jlong nativeView, jdouble size) {
View* view = (View*) nativeView;
view->setGridSize(size);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_View_nGetGridSize(JNIEnv*, jclass, jlong nativeView) {
View* view = (View*) nativeView;
return view->getGridSize();
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_View_nGetEffectiveGridSize(JNIEnv*, jclass, jlong nativeView) {
View* view = (View*) nativeView;
return view->getEffectiveGridSize();
}
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);
@@ -549,21 +571,27 @@ Java_com_google_android_filament_View_nSetGuardBandOptions(JNIEnv *, jclass,
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetMaterialGlobal(JNIEnv * , jclass, jlong nativeView,
Java_com_google_android_filament_View_nSetMaterialGlobal(JNIEnv *env, jclass, jlong nativeView,
jint index, jfloat x, jfloat y, jfloat z, jfloat w) {
View *view = (View *) nativeView;
view->setMaterialGlobal((uint32_t)index, { x, y, z, w });
wrapJni(env, [=]() {
view->setMaterialGlobal((uint32_t)index, { x, y, z, w });
});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nGetMaterialGlobal(JNIEnv *env, jclass clazz,
jlong nativeView, jint index, jfloatArray out_) {
jfloat* out = env->GetFloatArrayElements(out_, nullptr);
View *view = (View *) nativeView;
auto result = view->getMaterialGlobal(index);
std::copy_n(result.v, 4, out);
env->ReleaseFloatArrayElements(out_, out, 0);
wrapJni(env, [=]() {
auto result = view->getMaterialGlobal(index);
jfloat* out = env->GetFloatArrayElements(out_, nullptr);
if (out) {
std::copy_n(result.v, 4, out);
env->ReleaseFloatArrayElements(out_, out, 0);
}
});
}
extern "C"

View File

@@ -91,6 +91,8 @@ public class BufferObject {
* @return the newly created <code>BufferObject</code> object
*
* @exception IllegalStateException if the BufferObject could not be created
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*
* @see #setBuffer
*/

View File

@@ -321,8 +321,7 @@ public class Engine {
* be initialized, for instance if it doesn't support the right version of OpenGL or
* OpenGL ES.
*
* @exception IllegalStateException can be thrown if there isn't enough memory to
* allocate the command buffer.
* @throws Error if there isn't enough memory to allocate the command buffer.
*/
public Engine build() {
long nativeEngine = nBuilderBuild(mNativeBuilder);
@@ -729,6 +728,8 @@ public class Engine {
*
* @return the active feature level.
*
* @throws RuntimeException if the feature level cannot be set.
*
* @see Builder#featureLevel
* @see #getSupportedFeatureLevel
* @see #getActiveFeatureLevel
@@ -775,6 +776,15 @@ public class Engine {
return nIsAutomaticInstancingEnabled(getNativeObject());
}
/**
* Returns whether the engine has encountered an unrecoverable failure.
*
* @return true if an unrecoverable failure has occurred, false otherwise.
*/
public boolean hasUnrecoverableFailure() {
return nHasUnrecoverableFailure(getNativeObject());
}
/**
* Retrieves the configuration settings of this {@link Engine}.
*
@@ -1261,9 +1271,10 @@ public class Engine {
* Destroys a {@link Material} and frees all its associated resources.
* <p>
* All {@link MaterialInstance} of the specified {@link Material} must be destroyed before
* destroying it; if some {@link MaterialInstance} remain, this method fails silently.
* destroying it.
*
* @param material the {@link Material} to destroy
* @throws RuntimeException if some MaterialInstances remain.
*/
public void destroyMaterial(@NonNull Material material) {
assertDestroy(nDestroyMaterial(getNativeObject(), material.getNativeObject()));
@@ -1580,6 +1591,7 @@ public class Engine {
private static native long nGetEntityManager(long nativeEngine);
private static native void nSetAutomaticInstancingEnabled(long nativeEngine, boolean enable);
private static native boolean nIsAutomaticInstancingEnabled(long nativeEngine);
private static native boolean nHasUnrecoverableFailure(long nativeEngine);
private static native long nGetMaxStereoscopicEyes(long nativeEngine);
private static native int nGetSupportedFeatureLevel(long nativeEngine);
private static native int nSetActiveFeatureLevel(long nativeEngine, int ordinal);

View File

@@ -38,7 +38,17 @@ public class Fence {
}
/**
* Client-side wait on the Fence.
*
* Blocks the current thread until the Fence signals.
*
* @param mode Whether the command stream is flushed before waiting or not.
* @param timeoutNanoSeconds Wait time out in nanoseconds. Using a timeout of 0 is a way to query the state of the fence.
* A timeout value of WAIT_FOR_EVER is used to disable the timeout.
* @return FenceStatus::CONDITION_SATISFIED on success,
* FenceStatus::TIMEOUT_EXPIRED if the time out expired or
* FenceStatus::ERROR in other cases.
* @throws Error if the backend thread encountered an unrecoverable error.
*/
public FenceStatus wait(@NonNull Mode mode, long timeoutNanoSeconds) {
int nativeResult = nWait(getNativeObject(), mode.ordinal(), timeoutNanoSeconds);
@@ -55,6 +65,15 @@ public class Fence {
}
}
/**
* Client-side wait on a Fence and destroy the Fence.
*
* @param fence Fence object to wait on.
* @param mode Whether the command stream is flushed before waiting or not.
* @return FenceStatus::CONDITION_SATISFIED on success,
* FenceStatus::ERROR otherwise.
* @throws Error if the backend thread encountered an unrecoverable error.
*/
public static FenceStatus waitAndDestroy(@NonNull Fence fence, @NonNull Mode mode) {
int nativeResult = nWaitAndDestroy(fence.getNativeObject(), mode.ordinal());
switch (nativeResult) {

View File

@@ -99,6 +99,7 @@ public class IndexBuffer {
* @return the newly created <code>IndexBuffer</code> object
*
* @exception IllegalStateException if the IndexBuffer could not be created
* @throws RuntimeException if a runtime error occurred, such as running out of memory or other resources, or if a parameter to a builder function was invalid.
*
* @see #setBuffer
*/

View File

@@ -316,6 +316,8 @@ public class IndirectLight {
* @return A newly created <code>IndirectLight</code>
*
* @exception IllegalStateException if a parameter to a builder function was invalid.
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*/
@NonNull
public IndirectLight build(@NonNull Engine engine) {

View File

@@ -781,6 +781,7 @@ public class LightManager {
*
* @param engine Reference to the {@link Engine} to associate this light with.
* @param entity Entity to add the light component to.
* @throws RuntimeException if a runtime error occurred, such as running out of memory or other resources, or if a parameter to a builder function was invalid.
*/
public void build(@NonNull Engine engine, @Entity int entity) {
if (!nBuilderBuild(mNativeBuilder, engine.getNativeObject(), entity)) {

View File

@@ -476,6 +476,7 @@ public class Material {
* @return the newly created object
*
* @exception IllegalStateException if the material could not be created
* @throws RuntimeException if a parameter to a builder function was invalid.
*/
@NonNull
public Material build(@NonNull Engine engine) {

View File

@@ -156,6 +156,7 @@ public class MaterialInstance {
*
* @param name the name of the material parameter
* @param x the value of the material parameter
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, boolean x) {
nSetParameterBool(getNativeObject(), name, x);
@@ -166,6 +167,7 @@ public class MaterialInstance {
*
* @param name the name of the material parameter
* @param x the value of the material parameter
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, float x) {
nSetParameterFloat(getNativeObject(), name, x);
@@ -176,6 +178,7 @@ public class MaterialInstance {
*
* @param name the name of the material parameter
* @param x the value of the material parameter
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, int x) {
nSetParameterInt(getNativeObject(), name, x);
@@ -187,6 +190,7 @@ public class MaterialInstance {
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, boolean x, boolean y) {
nSetParameterBool2(getNativeObject(), name, x, y);
@@ -198,6 +202,7 @@ public class MaterialInstance {
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, float x, float y) {
nSetParameterFloat2(getNativeObject(), name, x, y);
@@ -209,6 +214,7 @@ public class MaterialInstance {
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, int x, int y) {
nSetParameterInt2(getNativeObject(), name, x, y);
@@ -221,6 +227,7 @@ public class MaterialInstance {
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, boolean x, boolean y, boolean z) {
nSetParameterBool3(getNativeObject(), name, x, y, z);
@@ -233,6 +240,7 @@ public class MaterialInstance {
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, float x, float y, float z) {
nSetParameterFloat3(getNativeObject(), name, x, y, z);
@@ -245,6 +253,7 @@ public class MaterialInstance {
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, int x, int y, int z) {
nSetParameterInt3(getNativeObject(), name, x, y, z);
@@ -258,6 +267,7 @@ public class MaterialInstance {
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, boolean x, boolean y, boolean z, boolean w) {
nSetParameterBool4(getNativeObject(), name, x, y, z, w);
@@ -271,6 +281,7 @@ public class MaterialInstance {
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, float x, float y, float z, float w) {
nSetParameterFloat4(getNativeObject(), name, x, y, z, w);
@@ -284,6 +295,7 @@ public class MaterialInstance {
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, int x, int y, int z, int w) {
nSetParameterInt4(getNativeObject(), name, x, y, z, w);
@@ -299,6 +311,7 @@ public class MaterialInstance {
* @param name The name of the material texture parameter
* @param texture The texture to set as parameter
* @param sampler The sampler to be used with this texture
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name,
@NonNull Texture texture, @NonNull TextureSampler sampler) {
@@ -320,6 +333,7 @@ public class MaterialInstance {
* instance.setParameter("param", MaterialInstance.BooleanElement.BOOL4, a, 0, 4);
* }</pre>
* </p>
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name,
@NonNull BooleanElement type, @NonNull boolean[] v,
@@ -342,6 +356,7 @@ public class MaterialInstance {
* instance.setParameter("param", MaterialInstance.IntElement.INT4, a, 0, 4);
* }</pre>
* </p>
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name,
@NonNull IntElement type, @NonNull int[] v,
@@ -364,6 +379,7 @@ public class MaterialInstance {
* material.setDefaultParameter("param", MaterialInstance.FloatElement.FLOAT4, a, 0, 4);
* }</pre>
* </p>
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name,
@NonNull FloatElement type, @NonNull float[] v,
@@ -379,6 +395,7 @@ public class MaterialInstance {
* @param r red component
* @param g green component
* @param b blue component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, @NonNull Colors.RgbType type,
float r, float g, float b) {
@@ -395,6 +412,7 @@ public class MaterialInstance {
* @param g green component
* @param b blue component
* @param a alpha component
* @throws RuntimeException if name doesn't exist or no-op if exceptions are disabled.
*/
public void setParameter(@NonNull String name, @NonNull Colors.RgbaType type,
float r, float g, float b, float a) {

View File

@@ -112,6 +112,8 @@ public class MorphTargetBuffer {
* @return the newly created <code>MorphTargetBuffer</code> object
*
* @exception IllegalStateException if the MorphTargetBuffer could not be created
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*
* @see #setMorphTargetBufferOffsetAt
*/

View File

@@ -587,6 +587,7 @@ public class RenderableManager {
*
* @param engine reference to the <code>Engine</code> to associate this renderable with
* @param entity entity to add the renderable component to
* @throws RuntimeException if a runtime error occurred, such as running out of memory or other resources, or if a parameter to a builder function was invalid.
*/
public void build(@NonNull Engine engine, @Entity int entity) {
if (!nBuilderBuild(mNativeBuilder, engine.getNativeObject(), entity)) {

View File

@@ -269,9 +269,8 @@ public class Renderer {
/**
* Set the time at which the frame must be presented to the display.
* <p>
*
* This must be called between {@link #beginFrame} and {@link #endFrame}.
* </p>
*
* @param monotonicClockNanos The time in nanoseconds corresponding to the system monotonic
* up-time clock. The presentation time is typically set in the
@@ -354,6 +353,8 @@ public class Renderer {
* returned and produce a frame anyways, by making calls to {@link #render(View)},
* in which case {@link #endFrame} must be called.
*
* @throws Error if the backend thread encountered an unrecoverable error.
*
* @see #endFrame
* @see #render
*/
@@ -370,6 +371,8 @@ public class Renderer {
*
* <br><p>All calls to render() must happen <b>before</b> endFrame().</p>
*
* @throws Error if the backend thread encountered an unrecoverable error, or if called again after a backend exception was already thrown.
*
* @see #beginFrame
* @see #render
*/
@@ -425,6 +428,7 @@ public class Renderer {
* </ul>
*
* @param view the {@link View} to render
* @throws Error if the backend thread encountered an unrecoverable error, or if called again after a backend exception was already thrown.
* @see #beginFrame
* @see #endFrame
* @see View
@@ -454,6 +458,7 @@ public class Renderer {
* <li><code>renderStandaloneView()</code> performs potentially heavy computations and cannot be
* multi-threaded. However, internally, it is highly multi-threaded to both improve performance
* and mitigate the call's latency.</li>
* </ul>
*
* @param view the {@link View} to render. This View must have an associated {@link RenderTarget}
* @see View
@@ -519,14 +524,14 @@ public class Renderer {
* <p><code>readPixels</code> must be called within a frame, meaning after {@link #beginFrame}
* and before {@link #endFrame}. Typically, <code>readPixels</code> will be called after
* {@link #render}.</p>
* <br>
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* <p>After issuing this method, the callback associated with <code>buffer</code> will be invoked on the
* main thread, indicating that the read-back has completed. Typically, this will happen
* after multiple calls to {@link #beginFrame}, {@link #render}, {@link #endFrame}.</p>
*
* <p>It is also possible to use a {@link Fence} to wait for the read-back.</p>
*
* <p><code>readPixels</code> is intended for debugging and testing. It will impact performance significantly.</p>
*
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
@@ -604,18 +609,19 @@ public class Renderer {
*
* <p>Typically <code>readPixels</code> will be called after {@link #render} and before
* {@link #endFrame}.</p>
* <br>
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
*
* <p>After issuing this method, the callback associated with <code>buffer</code> will be invoked on the
* main thread, indicating that the read-back has completed. Typically, this will happen
* after multiple calls to {@link #beginFrame}, {@link #render}, {@link #endFrame}.</p>
*
* <p>It is also possible to use a {@link Fence} to wait for the read-back.</p>
*
* <p>OpenGL only: if issuing a <code>readPixels</code> on a {@link RenderTarget} backed by a
* {@link Texture} that had data uploaded to it via {@link Texture#setImage}, the data returned
* from <code>readPixels</code> will be y-flipped with respect to the {@link Texture#setImage}
* call.</p>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* <p><code>readPixels</code> is intended for debugging and testing. It will impact performance significantly.</p>
*
* @param renderTarget {@link RenderTarget} to read back from
* @param xoffset left offset of the sub-region to read back

View File

@@ -78,6 +78,8 @@ public class SkinningBuffer {
* @return the newly created <code>SkinningBuffer</code> object
*
* @exception IllegalStateException if the SkinningBuffer could not be created
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*
* @see #setBonesAsMatrices
* @see #setBonesAsQuaternions

View File

@@ -885,6 +885,8 @@ public class Texture {
* @return A newly created <code>Texture</code>
* @exception IllegalStateException if a parameter to a builder function was invalid.
* A mode detailed message about the error is output in the system log.
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*/
@NonNull
public Texture build(@NonNull Engine engine) {

View File

@@ -272,6 +272,8 @@ public class VertexBuffer {
* @return the newly created <code>VertexBuffer</code> object
*
* @exception IllegalStateException if the VertexBuffer could not be created
* @throws RuntimeException if a runtime error occurred, such as running out of
* memory or other resources.
*/
@NonNull
public VertexBuffer build(@NonNull Engine engine) {

View File

@@ -697,6 +697,33 @@ public class View {
options.quality.ordinal());
}
/**
* Sets the grid size for grid-based world origin snapping.
*
* @param size The size of the grid cell in world units. If set to 0 or negative,
* the grid size is automatically calculated based on the camera frustum.
*/
public void setGridSize(double size) {
nSetGridSize(getNativeObject(), size);
}
/**
* Returns the grid size used for grid-based world origin snapping.
* @return The grid size in world units. A value of 0 or negative means automatic calculation is enabled.
*/
public double getGridSize() {
return nGetGridSize(getNativeObject());
}
/**
* Returns the effective grid size used for grid-based world origin snapping.
* If grid size was set to 0 or negative, this returns the automatically calculated size.
* @return The effective grid size in world units.
*/
public double getEffectiveGridSize() {
return nGetEffectiveGridSize(getNativeObject());
}
/**
* Returns the dynamic resolution options associated with this view.
* @return value set by {@link #setDynamicResolutionOptions}.
@@ -1370,6 +1397,9 @@ 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 nSetGridSize(long nativeView, double size);
private static native double nGetGridSize(long nativeView);
private static native double nGetEffectiveGridSize(long nativeView);
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);

View File

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

131
build.sh
View File

@@ -1,7 +1,7 @@
#!/bin/bash
set -e
# Host tools required by Android, WebGL, and iOS builds
# Host tools required by Android, WASM, and iOS builds
MOBILE_HOST_TOOLS="matc resgen cmgen filamesh uberz"
WEB_HOST_TOOLS="${MOBILE_HOST_TOOLS} mipgen filamesh"
@@ -34,7 +34,7 @@ function print_help {
echo " -m"
echo " Compile with make instead of ninja."
echo " -p platform1,platform2,..."
echo " Where platformN is [desktop|android|ios|webgl|all]."
echo " Where platformN is [desktop|android|ios|wasm|all]."
echo " Platform(s) to build, defaults to desktop."
echo " Building for iOS will automatically perform a partial desktop build."
echo " -q abi1,abi2,..."
@@ -44,6 +44,8 @@ function print_help {
echo " Run all unit tests, will trigger a debug build if needed."
echo " -v"
echo " Exclude Vulkan support from the Android build."
echo " -E"
echo " Disable C++ exceptions."
echo " -W"
echo " Include WebGPU support for the target platform. (NOT functional atm)."
echo " -s"
@@ -51,8 +53,8 @@ function print_help {
echo " -e"
echo " Enable EGL on Linux support for desktop builds."
echo " -l"
echo " Build arm64/x86_64 universal libraries."
echo " For iOS, this builds universal binaries for devices and the simulator (implies -s)."
echo " Build universal libraries/frameworks."
echo " For iOS, this builds XCFrameworks for devices and the simulator (implies -s)."
echo " For macOS, this builds universal binaries for both Apple silicon and Intel-based Macs."
echo " -k sample1,sample2,..."
echo " When building for Android, also build select sample APKs."
@@ -171,7 +173,7 @@ ISSUE_RELEASE_BUILD=false
ISSUE_ANDROID_BUILD=false
ISSUE_IOS_BUILD=false
ISSUE_DESKTOP_BUILD=true
ISSUE_WEBGL_BUILD=false
ISSUE_WASM_BUILD=false
# Default: all
ABI_ARMEABI_V7A=true
@@ -275,6 +277,7 @@ function build_tools_for_split_build {
-DCMAKE_BUILD_TYPE="${build_type_arg}" \
${WEBGPU_OPTION} \
${architectures} \
${EXCEPTIONS_OPTION} \
../..
${BUILD_COMMAND} ${WEB_HOST_TOOLS}
@@ -318,6 +321,7 @@ function build_desktop_target {
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${OSMESA_OPTION} \
${EXCEPTIONS_OPTION} \
${architectures} \
../..
ln -sf "out/cmake-${lc_target}/compile_commands.json" \
@@ -352,12 +356,12 @@ function build_desktop {
fi
}
function build_webgl_with_target {
function build_wasm_with_target {
local lc_target=$(echo "$1" | tr '[:upper:]' '[:lower:]')
echo "Building WebGL ${lc_target}..."
mkdir -p "out/cmake-webgl-${lc_target}"
pushd "out/cmake-webgl-${lc_target}" > /dev/null
echo "Building WASM ${lc_target}..."
mkdir -p "out/cmake-wasm-${lc_target}"
pushd "out/cmake-wasm-${lc_target}" > /dev/null
if [[ ! "${BUILD_TARGETS}" ]]; then
BUILD_TARGETS=${BUILD_CUSTOM_TARGETS}
@@ -374,12 +378,13 @@ function build_webgl_with_target {
${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" \
-DWEBGL=1 \
-DCMAKE_INSTALL_PREFIX="../wasm-${lc_target}/filament" \
-DWASM=1 \
${WEBGPU_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${EXCEPTIONS_OPTION} \
../..
ln -sf "out/cmake-webgl-${lc_target}/compile_commands.json" \
ln -sf "out/cmake-wasm-${lc_target}/compile_commands.json" \
../../compile_commands.json
${BUILD_COMMAND} ${BUILD_TARGETS}
)
@@ -411,7 +416,7 @@ function build_webgl_with_target {
popd > /dev/null
}
function build_webgl {
function build_wasm {
# For the host tools, suppress install and always use Release.
local old_install_command=${INSTALL_COMMAND}; INSTALL_COMMAND=
local old_issue_debug_build=${ISSUE_DEBUG_BUILD}; ISSUE_DEBUG_BUILD=false
@@ -424,11 +429,11 @@ function build_webgl {
ISSUE_RELEASE_BUILD=${old_issue_release_build}
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
build_webgl_with_target "Debug"
build_wasm_with_target "Debug"
fi
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
build_webgl_with_target "Release"
build_wasm_with_target "Release"
fi
}
@@ -457,6 +462,7 @@ function build_android_target {
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${ENABLE_PERFETTO} \
${EXCEPTIONS_OPTION} \
../..
ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \
../../compile_commands.json
@@ -679,9 +685,9 @@ function build_ios_target {
local platform=$3
echo "Building iOS ${lc_target} (${arch}) for ${platform}..."
mkdir -p "out/cmake-ios-${lc_target}-${arch}"
mkdir -p "out/cmake-ios-${lc_target}-${arch}-${platform}"
pushd "out/cmake-ios-${lc_target}-${arch}" > /dev/null
pushd "out/cmake-ios-${lc_target}-${arch}-${platform}" > /dev/null
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
@@ -698,6 +704,7 @@ function build_ios_target {
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${STEREOSCOPIC_OPTION} \
${EXCEPTIONS_OPTION} \
../..
ln -sf "out/cmake-ios-${lc_target}-${arch}/compile_commands.json" \
../../compile_commands.json
@@ -739,38 +746,79 @@ function build_ios {
# only arm64 devices support OpenGL 3.0 / Metal
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
local out_dir="out/ios-debug/filament"
local lib_dir="${out_dir}/lib"
build_ios_target "Debug" "arm64" "iphoneos"
if [[ "${IOS_BUILD_SIMULATOR}" == "true" ]]; then
build_ios_target "Debug" "arm64" "iphonesimulator"
build_ios_target "Debug" "x86_64" "iphonesimulator"
# Create a universal library for the simulator
build/ios/create-universal-libs.sh \
-o "${lib_dir}/universal" \
"${lib_dir}/arm64-iphonesimulator" \
"${lib_dir}/x86_64-iphonesimulator"
fi
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
build/ios/create-universal-libs.sh \
-o out/ios-debug/filament/lib/universal \
out/ios-debug/filament/lib/arm64 \
out/ios-debug/filament/lib/x86_64
rm -rf out/ios-debug/filament/lib/arm64
rm -rf out/ios-debug/filament/lib/x86_64
# Always create XCFrameworks
local xcframework_paths=("${lib_dir}/arm64-iphoneos")
if [[ -d "${lib_dir}/universal" ]]; then
xcframework_paths+=("${lib_dir}/universal")
elif [[ -d "${lib_dir}/arm64-iphonesimulator" ]]; then
# If we built only one simulator arch but not both
xcframework_paths+=("${lib_dir}/arm64-iphonesimulator")
elif [[ -d "${lib_dir}/x86_64-iphonesimulator" ]]; then
xcframework_paths+=("${lib_dir}/x86_64-iphonesimulator")
fi
build/ios/create-xc-frameworks.sh -o "${lib_dir}" "${xcframework_paths[@]}"
rm -rf \
"${lib_dir}/arm64-iphoneos" \
"${lib_dir}/arm64-iphonesimulator" \
"${lib_dir}/x86_64-iphonesimulator" \
"${lib_dir}/universal"
archive_ios "Debug"
fi
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
local out_dir="out/ios-release/filament"
local lib_dir="${out_dir}/lib"
build_ios_target "Release" "arm64" "iphoneos"
if [[ "${IOS_BUILD_SIMULATOR}" == "true" ]]; then
build_ios_target "Release" "arm64" "iphonesimulator"
build_ios_target "Release" "x86_64" "iphonesimulator"
# Create a universal library for the simulator
build/ios/create-universal-libs.sh \
-o "${lib_dir}/universal" \
"${lib_dir}/arm64-iphonesimulator" \
"${lib_dir}/x86_64-iphonesimulator"
fi
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
build/ios/create-universal-libs.sh \
-o out/ios-release/filament/lib/universal \
out/ios-release/filament/lib/arm64 \
out/ios-release/filament/lib/x86_64
rm -rf out/ios-release/filament/lib/arm64
rm -rf out/ios-release/filament/lib/x86_64
# Always create XCFrameworks
local xcframework_paths=("${lib_dir}/arm64-iphoneos")
if [[ -d "${lib_dir}/universal" ]]; then
xcframework_paths+=("${lib_dir}/universal")
elif [[ -d "${lib_dir}/arm64-iphonesimulator" ]]; then
xcframework_paths+=("${lib_dir}/arm64-iphonesimulator")
elif [[ -d "${lib_dir}/x86_64-iphonesimulator" ]]; then
xcframework_paths+=("${lib_dir}/x86_64-iphonesimulator")
fi
build/ios/create-xc-frameworks.sh -o "${lib_dir}" "${xcframework_paths[@]}"
rm -rf \
"${lib_dir}/arm64-iphoneos" \
"${lib_dir}/arm64-iphonesimulator" \
"${lib_dir}/x86_64-iphonesimulator" \
"${lib_dir}/universal"
archive_ios "Release"
fi
}
@@ -802,7 +850,7 @@ function validate_build_command {
fi
fi
# If building a WebAssembly module, ensure we know where Emscripten lives.
if [[ "${EMSDK}" == "" ]] && [[ "${ISSUE_WEBGL_BUILD}" == "true" ]]; then
if [[ "${EMSDK}" == "" ]] && [[ "${ISSUE_WASM_BUILD}" == "true" ]]; then
echo "Error: EMSDK is not set, exiting"
exit 1
fi
@@ -828,7 +876,7 @@ function run_test {
}
function run_tests {
if [[ "${ISSUE_WEBGL_BUILD}" == "true" ]]; then
if [[ "${ISSUE_WASM_BUILD}" == "true" ]]; then
if ! echo "TypeScript $(tsc --version)" ; then
tsc --noEmit \
third_party/gl-matrix/gl-matrix.d.ts \
@@ -858,7 +906,7 @@ function check_debug_release_build {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:E" opt; do
case ${opt} in
h)
print_help
@@ -913,18 +961,18 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
ios)
ISSUE_IOS_BUILD=true
;;
webgl)
ISSUE_WEBGL_BUILD=true
wasm)
ISSUE_WASM_BUILD=true
;;
all)
ISSUE_ANDROID_BUILD=true
ISSUE_IOS_BUILD=true
ISSUE_DESKTOP_BUILD=true
ISSUE_WEBGL_BUILD=false
ISSUE_WASM_BUILD=false
;;
*)
echo "Unknown platform ${platform}"
echo "Platform must be one of [desktop|android|ios|webgl|all]"
echo "Platform must be one of [desktop|android|ios|wasm|all]"
echo ""
exit 1
;;
@@ -1009,6 +1057,9 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
P) ENABLE_PERFETTO="-DFILAMENT_ENABLE_PERFETTO=ON"
echo "Enabled perfetto"
;;
E) EXCEPTIONS_OPTION="-DFILAMENT_ENABLE_EXCEPTIONS=OFF"
echo "Disabling exceptions."
;;
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
;;
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
@@ -1102,8 +1153,8 @@ if [[ "${ISSUE_IOS_BUILD}" == "true" ]]; then
check_debug_release_build build_ios
fi
if [[ "${ISSUE_WEBGL_BUILD}" == "true" ]]; then
check_debug_release_build build_webgl
if [[ "${ISSUE_WASM_BUILD}" == "true" ]]; then
check_debug_release_build build_wasm
fi
if [[ "${RUN_TESTS}" == "true" ]]; then

View File

@@ -11,7 +11,7 @@ if [ -d "./emsdk" ]; then
fi
# Install emscripten.
EMSDK_VERSION=${GITHUB_EMSDK_VERSION-3.1.60}
EMSDK_VERSION=${GITHUB_EMSDK_VERSION-5.0.4}
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/${EMSDK_VERSION}.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
./emsdk install latest

View File

@@ -21,7 +21,7 @@ fi
OS_NAME=$(uname -s)
LLVM_VERSION=${GITHUB_LLVM_VERSION-17}
MESA_VERSION=${GITHUB_MESA_VERSION-24.2.1}
MESA_VERSION=${GITHUB_MESA_VERSION-25.0.6}
ORIG_DIR=$(pwd)
MESA_DIR=${MESA_DIR-${ORIG_DIR}/mesa}
@@ -87,7 +87,8 @@ if [[ "$OS_NAME" == "Linux" ]]; then
elif [[ "$OS_NAME" == "Darwin" ]]; then
if command -v brew > /dev/null 2>&1; then
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr \
llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence \
glslang
brew link --overwrite llvm@${LLVM_VERSION}
# For reasons unknown, this is necessary for pkg-config to find homebrew's packages
LOCAL_PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"

View File

@@ -13,12 +13,20 @@
}
},
"node_modules/@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/glob": {
@@ -38,6 +46,11 @@
"tunnel": "^0.0.6"
}
},
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@octokit/auth-token": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
@@ -257,24 +270,24 @@
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
"license": "ISC"
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
}
},
"dependencies": {
"@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1"
}
},
"@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"requires": {
"@actions/io": "^1.0.1"
}
},
"@actions/glob": {
@@ -294,6 +307,11 @@
"tunnel": "^0.0.6"
}
},
"@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"@octokit/auth-token": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
@@ -444,11 +462,6 @@
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q=="
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
}
}
}

View File

@@ -1,9 +1,9 @@
GITHUB_CLANG_VERSION=17
GITHUB_CMAKE_VERSION=3.22.1
GITHUB_NINJA_VERSION=1.10.2
GITHUB_MESA_VERSION=24.2.1
GITHUB_MESA_VERSION=25.0.6
GITHUB_LLVM_VERSION=17
GITHUB_NDK_VERSION=29.0.14206865
GITHUB_EMSDK_VERSION=3.1.60
GITHUB_EMSDK_VERSION=5.0.4
GITHUB_VULKANSDK_VERSION=1.4.321.0
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env bash
set -e
function print_help {
local SELF_NAME
SELF_NAME=$(basename "$0")
echo "$SELF_NAME. Combine multiple platform-specific libraries into XCFramework bundles."
echo ""
echo "Usage:"
echo " $SELF_NAME [options] <path>..."
echo ""
echo "Options:"
echo " -h"
echo " Print this help message."
echo " -o"
echo " Output directory to store the XCFrameworks."
echo ""
echo "Example:"
echo " $SELF_NAME -o xcframeworks/ iphoneos/ iphonesimulator/"
echo ""
}
OUTPUT_DIR=""
while getopts "ho:" opt; do
case ${opt} in
h)
print_help
exit 1
;;
o)
OUTPUT_DIR="${OPTARG}"
;;
*)
print_help
exit 1
;;
esac
done
shift $((OPTIND - 1))
PATHS=("$@")
if [[ ! "${PATHS[*]}" ]]; then
echo "One or more paths required."
print_help
exit 1
fi
if [[ ! "${OUTPUT_DIR}" ]]; then
echo "Output directory required."
print_help
exit 1
fi
mkdir -p "${OUTPUT_DIR}"
# Use the first path as the leader to find all .a files
LEADER_PATH="${PATHS[0]}"
for FILE in "${LEADER_PATH}"/*.a; do
[ -f "${FILE}" ] || continue
LIBRARY_NAME="${FILE##*/}"
FRAMEWORK_NAME="${LIBRARY_NAME%.a}.xcframework"
echo "Creating XCFramework for: ${LIBRARY_NAME}"
CMD="xcodebuild -create-xcframework"
for PLATFORM_PATH in "${PATHS[@]}"; do
LIB_PATH="${PLATFORM_PATH}/${LIBRARY_NAME}"
if [[ -f "${LIB_PATH}" ]]; then
CMD="${CMD} -library ${LIB_PATH}"
else
echo "Warning: ${LIB_PATH} does not exist, skipping this platform for ${LIBRARY_NAME}"
fi
done
CMD="${CMD} -output ${OUTPUT_DIR}/${FRAMEWORK_NAME}"
# Remove existing framework if it exists
rm -rf "${OUTPUT_DIR}/${FRAMEWORK_NAME}"
eval "${CMD}"
done

View File

@@ -8,4 +8,4 @@ set -x
source `dirname $0`/../common/build-common.sh
pushd `dirname $0`/../.. > /dev/null
./build.sh -p webgl -c $RUN_TESTS $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
./build.sh -p wasm -c $RUN_TESTS $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE

View File

@@ -163,7 +163,7 @@
<p>To build Filament, you must first install the following tools:</p>
<ul>
<li>CMake 3.22.1 (or more recent)</li>
<li>clang 16.0 (or more recent) (Required for Linux and macOS; see <a href="#windows">Windows</a> section for MSVC support)</li>
<li>clang 17.0 (or more recent) (Required for Linux and macOS; see <a href="#windows">Windows</a> section for MSVC support)</li>
<li><a href="https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages">ninja 1.10</a> (or more recent)</li>
</ul>
<p>Additional dependencies may be required for your operating system. Please refer to the appropriate
@@ -217,7 +217,10 @@ The script offers more features described by executing <code>build.sh -h</code>.
<li><code>FILAMENT_INSTALL_BACKEND_TEST</code>: Install the backend test library so it can be consumed on iOS</li>
<li><code>FILAMENT_USE_EXTERNAL_GLES3</code>: Experimental: Compile Filament against OpenGL ES 3</li>
<li><code>FILAMENT_SKIP_SAMPLES</code>: Don't build sample apps</li>
<li><code>FILAMENT_ENABLE_EXCEPTIONS</code>: Enable C++ exceptions (default: ON, OFF for iOS). Required for JNI bindings.</li>
<li><code>FILAMENT_ENABLE_RTTI</code>: Enable C++ RTTI (default: OFF).</li>
</ul>
<p>Note: If you intend to use the JNI library (Android/Java build), you need to have <code>FILAMENT_ENABLE_EXCEPTIONS</code> enabled. If you are using Filament on Android as a pure native library and want to save space, you can disable it (e.g., using <code>./build.sh -E</code>).</p>
<p>To turn an option on or off:</p>
<pre><code class="language-shell">cd &lt;cmake-build-directory&gt;
cmake . -DOPTION=ON # Replace OPTION with the option name, set to ON / OFF
@@ -226,16 +229,16 @@ cmake . -DOPTION=ON # Replace OPTION with the option name, set to ON / OFF
<h2 id="linux"><a class="header" href="#linux">Linux</a></h2>
<p>Make sure you've installed the following dependencies:</p>
<ul>
<li><code>clang-16</code> or higher</li>
<li><code>clang-17</code> or higher</li>
<li><code>libglu1-mesa-dev</code></li>
<li><code>libc++-16-dev</code> (<code>libcxx-devel</code> and <code>libcxx-static</code> on Fedora) or higher</li>
<li><code>libc++abi-16-dev</code> (<code>libcxxabi-static</code> on Fedora) or higher</li>
<li><code>libc++-17-dev</code> (<code>libcxx-devel</code> and <code>libcxx-static</code> on Fedora) or higher</li>
<li><code>libc++abi-17-dev</code> (<code>libcxxabi-static</code> on Fedora) or higher</li>
<li><code>ninja-build</code></li>
<li><code>libxi-dev</code></li>
<li><code>libxcomposite-dev</code> (<code>libXcomposite-devel</code> on Fedora)</li>
<li><code>libxxf86vm-dev</code> (<code>libXxf86vm-devel</code> on Fedora)</li>
</ul>
<pre><code class="language-shell">sudo apt install clang-16 libglu1-mesa-dev libc++-16-dev libc++abi-16-dev ninja-build libxi-dev libxcomposite-dev libxxf86vm-dev -y
<pre><code class="language-shell">sudo apt install clang-17 libglu1-mesa-dev libc++-17-dev libc++abi-17-dev ninja-build libxi-dev libxcomposite-dev libxxf86vm-dev -y
</code></pre>
<p>After dependencies have been installed, we highly recommend using the <a href="#easy-build">easy build</a>
script.</p>
@@ -249,15 +252,15 @@ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/fila
<code>cmake</code> with the following command:</p>
<pre><code class="language-shell">mkdir out/cmake-release
cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-16
# Or use a specific version of clang, for instance /usr/bin/clang-17
CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
</code></pre>
<p>You can also export the <code>CC</code> and <code>CXX</code> environment variables to always point to <code>clang</code>. Another
solution is to use <code>update-alternatives</code> to both change the default compiler, and point to a
specific version of clang:</p>
<pre><code class="language-shell">update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100
<pre><code class="language-shell">update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100
update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
</code></pre>
@@ -448,7 +451,7 @@ started, follow the instructions for building Filament on your platform (<a href
<p>Next, you need to install the Emscripten SDK. The following instructions show how to install the
same version that our continuous builds use.</p>
<pre><code class="language-shell">cd &lt;your chosen parent folder for the emscripten SDK&gt;
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.60.zip &gt; emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/5.0.4.zip &gt; emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest

View File

@@ -234,11 +234,11 @@ book.</p>
<p>The process for copying and processing these READMEs is outlined in
<a href="#introductory-doc">Introductory docs</a>.</p>
<h3 id="web-examples-and-tutorials"><a class="header" href="#web-examples-and-tutorials">Web Examples and Tutorials</a></h3>
<p>Filament provides a number of WebGL tutorials and examples in the <code>web/</code> directory. These are
compiled during the WebGL CMake build and are integrated into the documentation via
<p>Filament provides a number of web tutorials and examples in the <code>web/</code> directory. These are
compiled during the web CMake build and are integrated into the documentation via
<code>duplicates.json</code>. The process is entirely automated:</p>
<ol>
<li><code>run.py</code> maps the <code>.html</code> and <code>.md</code> WebGL outputs from the <code>out/cmake-webgl-release/...</code>
<li><code>run.py</code> maps the <code>.html</code> and <code>.md</code> web outputs from the <code>out/cmake-wasm-release/...</code>
directory into <code>docs_src/src_mdbook/src/samples/web/</code> using the instructions in <code>duplicates.json</code>.</li>
<li>While transferring <code>.html</code> to <code>.md</code>, <code>run.py</code> strips away the <code>&lt;!DOCTYPE html&gt;</code>, <code>&lt;head&gt;</code>, and
<code>&lt;html&gt;</code> tags. By retaining only the <code>&lt;style&gt;</code> and <code>&lt;body&gt;</code> elements, the HTML samples can be

View File

@@ -159,14 +159,14 @@
<div id="content" class="content">
<main>
<h1 id="filament"><a class="header" href="#filament">Filament</a></h1>
<p><a href="https://github.com/google/filament/actions?query=workflow%3AAndroid"><img src="https://github.com/google/filament/workflows/Android/badge.svg" alt="Android Build Status" /></a>
<a href="https://github.com/google/filament/actions?query=workflow%3AiOS"><img src="https://github.com/google/filament/workflows/iOS/badge.svg" alt="iOS Build Status" /></a>
<a href="https://github.com/google/filament/actions?query=workflow%3ALinux"><img src="https://github.com/google/filament/workflows/Linux/badge.svg" alt="Linux Build Status" /></a>
<a href="https://github.com/google/filament/actions?query=workflow%3AmacOS"><img src="https://github.com/google/filament/workflows/macOS/badge.svg" alt="macOS Build Status" /></a>
<a href="https://github.com/google/filament/actions?query=workflow%3AWindows"><img src="https://github.com/google/filament/workflows/Windows/badge.svg" alt="Windows Build Status" /></a>
<a href="https://github.com/google/filament/actions?query=workflow%3AWeb"><img src="https://github.com/google/filament/workflows/Web/badge.svg" alt="Web Build Status" /></a></p>
<p><a href="https://github.com/google/filament/actions/workflows/status-android.yml"><img src="https://github.com/google/filament/actions/workflows/status-android.yml/badge.svg" alt="Android Build Status" /></a>
<a href="https://github.com/google/filament/actions/workflows/status-ios.yml"><img src="https://github.com/google/filament/actions/workflows/status-ios.yml/badge.svg" alt="iOS Build Status" /></a>
<a href="https://github.com/google/filament/actions/workflows/status-linux.yml"><img src="https://github.com/google/filament/actions/workflows/status-linux.yml/badge.svg" alt="Linux Build Status" /></a>
<a href="https://github.com/google/filament/actions/workflows/status-macos.yml"><img src="https://github.com/google/filament/actions/workflows/status-macos.yml/badge.svg" alt="macOS Build Status" /></a>
<a href="https://github.com/google/filament/actions/workflows/status-windows.yml"><img src="https://github.com/google/filament/actions/workflows/status-windows.yml/badge.svg" alt="Windows Build Status" /></a>
<a href="https://github.com/google/filament/actions/workflows/status-web.yml"><img src="https://github.com/google/filament/actions/workflows/status-web.yml/badge.svg" alt="Web Build Status" /></a></p>
<p>Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows,
and WebGL. It is designed to be as small as possible and as efficient as possible on Android.</p>
and WASM. It is designed to be as small as possible and as efficient as possible on Android.</p>
<h2 id="download"><a class="header" href="#download">Download</a></h2>
<p><a href="https://github.com/google/filament/releases">Download Filament releases</a> to access stable builds.
Filament release archives contains host-side tools that are required to generate assets.</p>
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.71.0'
implementation 'com.google.android.filament:filament-android:1.71.2'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
@@ -195,7 +195,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.71.0'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.71.2'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>

View File

@@ -319,7 +319,7 @@ the run number is <code>18023632663</code>.</p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../notes/libs.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../dup/test_ci_sizeguard.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -333,7 +333,7 @@ the run number is <code>18023632663</code>.</p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../notes/libs.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../dup/test_ci_sizeguard.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

@@ -0,0 +1,240 @@
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>CI: sizeguard - 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="sizeguard"><a class="header" href="#sizeguard">Sizeguard</a></h1>
<p>This directory contains scripts used to monitor and gate the size of Filament artifacts.</p>
<h2 id="scripts"><a class="header" href="#scripts">Scripts</a></h2>
<h3 id="dump_artifact_sizepy"><a class="header" href="#dump_artifact_sizepy"><code>dump_artifact_size.py</code></a></h3>
<p>Computes the sizes of build artifacts (e.g., <code>.aar</code>, <code>.tgz</code>) and their internal contents. It outputs a JSON representation of these sizes.</p>
<p><strong>Usage:</strong></p>
<pre><code class="language-bash">python3 dump_artifact_size.py out/*.aar &gt; current_size.json
</code></pre>
<h3 id="check_sizepy"><a class="header" href="#check_sizepy"><code>check_size.py</code></a></h3>
<p>Compares a current size JSON (generated by <code>dump_artifact_size.py</code>) against historical data stored in the <code>filament-assets</code> repository. It fails if any artifact's size increase exceeds a specified threshold.</p>
<p><strong>Key Arguments:</strong></p>
<ul>
<li><code>current_json</code>: Path to the local JSON file.</li>
<li><code>--threshold</code>: Size increase threshold in bytes (default: 20KB).</li>
<li><code>--bypass</code>: If provided, the script will print the comparison but exit successfully even if thresholds are exceeded.</li>
</ul>
<h3 id="check_bypasspy"><a class="header" href="#check_bypasspy"><code>check_bypass.py</code></a></h3>
<p>A utility script that checks the commit message for a specific tag to determine if the sizeguard check should be bypassed.</p>
<p><strong>Usage:</strong></p>
<ul>
<li>Returns exit code <code>0</code> if the tag <code>SIZEGUARD_BYPASS</code> is found in the commit message.</li>
<li>Returns exit code <code>1</code> otherwise.</li>
</ul>
<h2 id="continuous-integration"><a class="header" href="#continuous-integration">Continuous Integration</a></h2>
<p>These scripts are integrated into the GitHub Actions workflows (e.g., <code>.github/workflows/presubmit.yml</code>).</p>
<p>To bypass a failing sizeguard check in a PR, add the following tag on a new line in your commit message:</p>
<pre><code>SIZEGUARD_BYPASS
</code></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../dup/test_ci_renderdiff.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="../notes/libs.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/test_ci_renderdiff.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="../notes/libs.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

@@ -165,7 +165,7 @@
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../dup/test_ci_renderdiff.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../dup/test_ci_sizeguard.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
@@ -179,7 +179,7 @@
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../dup/test_ci_renderdiff.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../dup/test_ci_sizeguard.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -81,10 +81,10 @@ The process for copying and processing these READMEs is outlined in
[Introductory docs](#introductory-doc).
### Web Examples and Tutorials
Filament provides a number of WebGL tutorials and examples in the `web/` directory. These are
compiled during the WebGL CMake build and are integrated into the documentation via
Filament provides a number of web tutorials and examples in the `web/` directory. These are
compiled during the web CMake build and are integrated into the documentation via
`duplicates.json`. The process is entirely automated:
1. `run.py` maps the `.html` and `.md` WebGL outputs from the `out/cmake-webgl-release/...`
1. `run.py` maps the `.html` and `.md` web outputs from the `out/cmake-wasm-release/...`
directory into `docs_src/src_mdbook/src/samples/web/` using the instructions in `duplicates.json`.
2. While transferring `.html` to `.md`, `run.py` strips away the `<!DOCTYPE html>`, `<head>`, and
`<html>` tags. By retaining only the `<style>` and `<body>` elements, the HTML samples can be

View File

@@ -20,7 +20,7 @@ import glob
import re
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
OUT_DIR = os.path.join(CUR_DIR, "../../out/cmake-webgl-release/web/examples/examples")
OUT_DIR = os.path.join(CUR_DIR, "../../out/cmake-wasm-release/web/examples/examples")
BOOK_DIR = os.path.join(CUR_DIR, "../src_mdbook/book")
def setup_dirs():

View File

@@ -100,46 +100,49 @@
"test/backend/README.md": {
"dest": "dup/test_ci_backend.md"
},
"test/sizeguard/README.md": {
"dest": "dup/test_ci_sizeguard.md"
},
"filament/backend/test/README.md": {
"dest": "dup/backend_test.md"
},
"out/cmake-webgl-release/web/examples/examples/triangle/triangle.md": {
"out/cmake-wasm-release/web/examples/examples/triangle/triangle.md": {
"dest": "samples/web/triangle.md"
},
"out/cmake-webgl-release/web/examples/examples/redball/redball.md": {
"out/cmake-wasm-release/web/examples/examples/redball/redball.md": {
"dest": "samples/web/redball.md"
},
"out/cmake-webgl-release/web/examples/examples/suzanne/suzanne.md": {
"out/cmake-wasm-release/web/examples/examples/suzanne/suzanne.md": {
"dest": "samples/web/suzanne.md"
},
"out/cmake-webgl-release/web/examples/examples/animation/animation.html": {
"out/cmake-wasm-release/web/examples/examples/animation/animation.html": {
"dest": "samples/web/animation.md"
},
"out/cmake-webgl-release/web/examples/examples/cube_fl0/cube_fl0.html": {
"out/cmake-wasm-release/web/examples/examples/cube_fl0/cube_fl0.html": {
"dest": "samples/web/cube_fl0.md"
},
"out/cmake-webgl-release/web/examples/examples/helmet/helmet.html": {
"out/cmake-wasm-release/web/examples/examples/helmet/helmet.html": {
"dest": "samples/web/helmet.md"
},
"out/cmake-webgl-release/web/examples/examples/morphing/morphing.html": {
"out/cmake-wasm-release/web/examples/examples/morphing/morphing.html": {
"dest": "samples/web/morphing.md"
},
"out/cmake-webgl-release/web/examples/examples/parquet/parquet.html": {
"out/cmake-wasm-release/web/examples/examples/parquet/parquet.html": {
"dest": "samples/web/parquet.md"
},
"out/cmake-webgl-release/web/examples/examples/skinning/skinning.html": {
"out/cmake-wasm-release/web/examples/examples/skinning/skinning.html": {
"dest": "samples/web/skinning.md"
},
"out/cmake-webgl-release/web/examples/examples/sky/sky.html": {
"out/cmake-wasm-release/web/examples/examples/sky/sky.html": {
"dest": "samples/web/sky.md",
"replacements": {
"<!-- mdbook: add fullscreen mode -->": "<a href=\"../../web/sky.html\">Full screen</a>"
}
},
"./out/cmake-webgl-release/web/examples/examples/sky/sky.html": {
"./out/cmake-wasm-release/web/examples/examples/sky/sky.html": {
"dest": "web/sky.html"
},
"out/cmake-webgl-release/web/examples/examples/remote/remote.html": {
"out/cmake-wasm-release/web/examples/examples/remote/remote.html": {
"dest": "remote/index.html"
}
}

View File

@@ -19,7 +19,7 @@ FILAMENT_BOT_TOKEN=$2
set -ex
function update_to_main() {
./build.sh -p webgl release
./build.sh -p wasm release
python3 docs_src/build/run.py
mkdir -p tmp
pushd .

View File

@@ -44,6 +44,7 @@
- [backend](./dup/backend_test.md)
- [CI: backend](./dup/test_ci_backend.md)
- [CI: renderdiff](./dup/test_ci_renderdiff.md)
- [CI: sizeguard](./dup/test_ci_sizeguard.md)
- [Libraries](./notes/libs.md)
- [bluegl](./dup/bluegl.md)
- [bluevk](./dup/bluevk.md)

View File

@@ -156,6 +156,7 @@ set(SRCS
src/ds/StructureDescriptorSet.cpp
src/fg/Blackboard.cpp
src/fg/DependencyGraph.cpp
src/fg/FgviewerManager.cpp
src/fg/FrameGraph.cpp
src/fg/FrameGraphPass.cpp
src/fg/FrameGraphResources.cpp
@@ -743,10 +744,10 @@ if (MSVC)
set(OPTIMIZATION_FLAGS
/fp:fast
)
elseif(WEBGL)
elseif (WASM)
# Avoid strict-vtable-pointers here, it is broken in WebAssembly.
set(OPTIMIZATION_FLAGS -fvisibility-inlines-hidden)
elseif(FILAMENT_USING_GCC)
elseif (FILAMENT_USING_GCC)
set(OPTIMIZATION_FLAGS
-ffast-math
-fno-finite-math-only

View File

@@ -124,7 +124,7 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaExternalImage.mm)
endif()
elseif (WEBGL)
elseif (WASM)
list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp)
elseif (LINUX)
if (FILAMENT_SUPPORTS_X11)
@@ -432,7 +432,7 @@ if (FILAMENT_USE_ABSEIL_LOGGING)
endif()
# Android, iOS, and WebGL do not use bluegl.
if(FILAMENT_SUPPORTS_OPENGL AND NOT IOS AND NOT ANDROID AND NOT WEBGL)
if(FILAMENT_SUPPORTS_OPENGL AND NOT IOS AND NOT ANDROID AND NOT WASM)
target_link_libraries(${TARGET} PRIVATE bluegl)
endif()
@@ -463,7 +463,7 @@ if (MSVC)
set(OPTIMIZATION_FLAGS
/fp:fast
)
elseif(WEBGL)
elseif(WASM)
# Avoid strict-vtable-pointers here, it is broken in WebAssembly.
set(OPTIMIZATION_FLAGS -fvisibility-inlines-hidden)
elseif(FILAMENT_USING_GCC)
@@ -602,6 +602,7 @@ if (FILAMENT_BUILD_TESTING)
test/test_CircularBuffer.cpp
test/test_CommandBufferQueue.cpp
test/test_Template.cpp
test/test_AsyncUploads.cpp
test/test_Platform.cpp
)
if (FILAMENT_SUPPORTS_WEBGPU)
@@ -698,7 +699,7 @@ if (FILAMENT_BUILD_TESTING)
# ==================================================================================================
# Compute tests
#
#if (NOT IOS AND NOT WEBGL)
#if (NOT IOS AND NOT WASM)
#
#add_executable(compute_test
# test/ComputeTest.cpp

View File

@@ -67,7 +67,7 @@ public:
*
* createDevice is called by the Metal backend from the backend thread.
*/
virtual void createDevice(MetalDevice& outDevice) noexcept;
void createDevice(MetalDevice& outDevice) noexcept;
/**
* Create a command submission queue on the Metal device object.
@@ -76,7 +76,7 @@ public:
*
* @param device The device which was returned from createDevice()
*/
virtual void createCommandQueue(
void createCommandQueue(
MetalDevice& device, MetalCommandQueue& outCommandQueue) noexcept;
/**

View File

@@ -31,6 +31,11 @@
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <unordered_map>
#include <thread>
#include <shared_mutex>
#include <memory>
namespace filament::backend {
/**
@@ -58,10 +63,20 @@ protected:
bool makeCurrent(ContextType type, SwapChain* drawSwapChain,
SwapChain* readSwapChain) override;
void commit(SwapChain* swapChain) noexcept override;
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
void releaseContext() noexcept override;
private:
OSMesaContext mContext;
void* mOsMesaApi = nullptr;
struct ContextInfo {
OSMesaContext context;
std::unique_ptr<uint8_t[]> buffer;
};
std::unordered_map<std::thread::id, ContextInfo> mAdditionalContexts;
mutable std::shared_mutex mAdditionalContextsLock;
};
} // namespace filament::backend

View File

@@ -23,6 +23,8 @@
#include <utils/Mutex.h>
#include <vector>
#include <exception>
#include <atomic>
#include <stddef.h>
#include <stdint.h>
@@ -75,6 +77,25 @@ public:
bool isExitRequested() const;
#ifdef __EXCEPTIONS
bool hasUnrecoverableError() const noexcept {
return mHasUnrecoverableError.load(std::memory_order_acquire);
}
void setUnrecoverableException(std::exception_ptr e) noexcept {
mBackendException = e;
mHasUnrecoverableError.store(true, std::memory_order_release);
}
void propagateBackendException() const;
bool hasExceptionBeenRethrown() const noexcept {
return mExceptionRethrown.load(std::memory_order_relaxed);
}
#else
void propagateBackendException() const noexcept {}
constexpr bool hasUnrecoverableError() const noexcept { return false; }
constexpr bool hasExceptionBeenRethrown() const noexcept { return false; }
#endif
private:
const size_t mRequiredSize;
@@ -91,6 +112,12 @@ private:
bool mPaused = false;
static constexpr uint32_t EXIT_REQUESTED = 0x31415926;
#ifdef __EXCEPTIONS
mutable std::exception_ptr mBackendException;
std::atomic<bool> mHasUnrecoverableError{false};
mutable std::atomic<bool> mExceptionRethrown{false};
#endif
};
} // namespace filament::backend

View File

@@ -75,6 +75,12 @@ public:
// thread via `purge()`.
virtual void scheduleCallback(CallbackHandler* handler, void* user, CallbackHandler::Callback callback) = 0;
/**
* Flags the driver as having encountered an unrecoverable error.
* This will interrupt all pending fence waits and prevent further waits.
*/
virtual void setUnrecoverableError() noexcept {}
virtual ShaderModel getShaderModel() const noexcept = 0;
// The shader languages used for shaders for this driver in order of preference, used to inform

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