Compare commits

..
Author SHA1 Message Date
Powei Feng 5a2b46e134 [WIP] Trying to fix issue 2025-08-14 23:48:03 -07:00
271 changed files with 12591 additions and 6086 deletions
@@ -1,23 +0,0 @@
name: 'Get and cache glTF Assets'
description: 'Downloads and caches glTF assets by calling the get-gltf-sample-assets.sh script.'
runs:
using: "composite"
steps:
- uses: ./.github/actions/dep-versions
- name: Hash models file
id: hash-models
shell: bash
run: echo "hash=$(cat test/renderdiff/tests/gltf_models.txt | md5sum | sed 's/ -//g')" >> $GITHUB_OUTPUT
- name: Cache glTF assets
id: cache-gltf
uses: actions/cache@v4
with:
path: gltf
key: gltf-assets-${{ env.GITHUB_GLTF_SAMPLE_ASSETS_COMMIT }}-${{ steps.hash-models.outputs.hash }}
- name: Download assets via script if cache not found
if: steps.cache-gltf.outputs.cache-hit != 'true'
shell: bash
run: |
echo "Cache miss for commit ${{ env.GITHUB_GLTF_SAMPLE_ASSETS_COMMIT }}. Running download script..."
xargs bash build/common/get-gltf-sample-assets.sh < test/renderdiff/tests/gltf_models.txt
+2 -3
View File
@@ -1,6 +1,5 @@
name: 'Get and cache Mesa'
description: 'Get and cache Mesa'
name: 'Get Mesa'
description: 'Caches and installs Mesa'
runs:
using: "composite"
steps:
+2 -6
View File
@@ -8,8 +8,8 @@ runs:
uses: actions/cache@v3
id: cache-vulkan-sdk
with:
path: ${{ runner.homedir }}/VulkanSDK
key: vulkansdk-${{ env.GITHUB_VULKANSDK_VERSION }}-2-${{ runner.os }}
path: vulkansdk
key: vulkansdk-${{ env.GITHUB_VULKANSDK_VERSION }}-${{ runner.os }}
- name: Download Vulkan SDK
if: steps.cache-vulkan-sdk.outputs.cache-hit != 'true'
run: |
@@ -21,8 +21,4 @@ runs:
run: |
source ${{ github.workspace }}/build/common/get-vulkan-sdk.sh
unpack_vulkan_installer
pushd .
cd ~/VulkanSDK/${GITHUB_VULKANSDK_VERSION}
sudo ./install_vulkan.py
popd
shell: bash
-2
View File
@@ -19,7 +19,5 @@ runs:
- name: Install Mac Prerequisites
shell: bash
run: |
# Install brew prereqs
brew install coreutils
# Install ninja
source ./build/common/get-ninja.sh
+180 -173
View File
@@ -9,36 +9,6 @@ on:
- main
jobs:
build-desktop-mac:
name: build-mac
runs-on: macos-14-xlarge
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- name: Run build script
run: |
cd build/mac && printf "y" | ./build.sh presubmit
- name: Test material parser
run: |
out/cmake-release/filament/test/test_material_parser
build-desktop-linux:
name: build-linux
runs-on: ubuntu-22.04-16core
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/linux-prereq
- name: Run build script
run: |
cd build/linux && printf "y" | ./build.sh presubmit
- name: Test material parser
run: |
out/cmake-release/filament/test/test_material_parser
build-windows:
name: build-windows
runs-on: windows-2022-32core
@@ -48,157 +18,194 @@ jobs:
fetch-depth: 0
- name: Run build script
run: |
build\windows\build-github.bat presubmit
build\windows\build-github.bat continuous
shell: cmd
build-android:
name: build-android
runs-on: 'ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/linux-prereq
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run build script
# Only build 1 64 bit target during presubmit to cut down build times during presubmit
# Continuous builds will build everything
run: |
cd build/android && printf "y" | ./build.sh presubmit arm64-v8a
# build-desktop-mac:
# name: build-mac
# runs-on: macos-14-xlarge
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/mac-prereq
# - name: Run build script
# run: |
# cd build/mac && printf "y" | ./build.sh presubmit
# - name: Test material parser
# run: |
# out/cmake-release/filament/test/test_material_parser
build-ios:
name: build-iOS
runs-on: macos-14-xlarge
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh presubmit
- name: Build iOS samples
run: |
cd build/ios && ./build-samples.sh presubmit
# build-desktop-linux:
# name: build-linux
# runs-on: ubuntu-22.04-16core
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/linux-prereq
# - name: Run build script
# run: |
# cd build/linux && printf "y" | ./build.sh presubmit
# - name: Test material parser
# run: |
# out/cmake-release/filament/test/test_material_parser
build-web:
name: build-web
runs-on: 'ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/linux-prereq
- uses: ./.github/actions/web-prereq
- name: Run build script
run: |
cd build/web && printf "y" | ./build.sh presubmit
# build-windows:
# name: build-windows
# runs-on: windows-2022-32core
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - name: Run build script
# run: |
# build\windows\build-github.bat presubmit
# shell: cmd
validate-docs:
name: validate-docs
runs-on: 'ubuntu-24.04-4core'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- id: get_commit_msg
uses: ./.github/actions/get-commit-msg
- name: Check for manual edits to /docs
run: |
COMMIT_ID=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
bash docs_src/build/presubmit_check.sh ${COMMIT_ID}
# build-android:
# name: build-android
# runs-on: 'ubuntu-24.04-16core'
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/linux-prereq
# - uses: actions/setup-java@v3
# with:
# distribution: 'temurin'
# java-version: '17'
# - name: Run build script
# # Only build 1 64 bit target during presubmit to cut down build times during presubmit
# # Continuous builds will build everything
# run: |
# cd build/android && printf "y" | ./build.sh presubmit arm64-v8a
test-renderdiff:
name: test-renderdiff
runs-on: macos-14-xlarge
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- uses: ./.github/actions/get-gltf-assets
- uses: ./.github/actions/get-mesa
- uses: ./.github/actions/get-vulkan-sdk
- id: get_commit_msg
uses: ./.github/actions/get-commit-msg
- name: Prerequisites
run: |
pip install tifffile numpy
# Must have at least clang-16 for a webgpu/dawn build.
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
shell: bash
- name: Render and compare
id: render_compare
run: |
ls ./gltf/Models
TEST_DIR=test/renderdiff
source ${TEST_DIR}/src/preamble.sh
start_
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 ${TEST_DIR}/src/commit_msg.py)
bash ${TEST_DIR}/generate.sh && \
python3 ${TEST_DIR}/src/golden_manager.py \
--branch=${GOLDEN_BRANCH} \
--output=${GOLDEN_OUTPUT_DIR}
# build-ios:
# name: build-iOS
# runs-on: macos-14-xlarge
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/mac-prereq
# - name: Run build script
# run: |
# cd build/ios && printf "y" | ./build.sh presubmit
# - name: Build iOS samples
# run: |
# cd build/ios && ./build-samples.sh presubmit
# Note that we need to upload the output even if comparison fails, so we undo `set -ex`
end_
# build-web:
# name: build-web
# runs-on: 'ubuntu-24.04-16core'
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/linux-prereq
# - uses: ./.github/actions/web-prereq
# - name: Run build script
# run: |
# cd build/web && printf "y" | ./build.sh presubmit
python3 ${TEST_DIR}/src/compare.py \
--src=${GOLDEN_OUTPUT_DIR} \
--dest=${RENDER_OUTPUT_DIR} \
--out=${DIFF_OUTPUT_DIR} 2>&1 | tee compare_output.txt
# validate-docs:
# name: validate-docs
# runs-on: 'ubuntu-24.04-4core'
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - id: get_commit_msg
# uses: ./.github/actions/get-commit-msg
# - name: Check for manual edits to /docs
# run: |
# COMMIT_ID=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
# bash docs_src/build/presubmit_check.sh ${COMMIT_ID}
if grep "Failed" compare_output.txt > /dev/null; then
DELIMITER="EOF_FILE_CONTENT_$(date +%s)" # Using timestamp to make it more unique
echo "err<<$DELIMITER" >> "$GITHUB_OUTPUT"
cat compare_output.txt >> "$GITHUB_OUTPUT"
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
fi
- uses: actions/upload-artifact@v4
with:
name: presubmit-renderdiff-result
path: ./out/renderdiff
- name: Compare result
run: |
ERROR_STR="${{ steps.render_compare.outputs.err }}"
if [ -n "${ERROR_STR}" ]; then
echo "${ERROR_STR}"
exit 1
fi
# test-renderdiff:
# name: test-renderdiff
# runs-on: macos-14-xlarge
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - id: get_commit_msg
# uses: ./.github/actions/get-commit-msg
# - uses: ./.github/actions/mac-prereq
# - uses: ./.github/actions/get-mesa
# - name: Prerequisites
# run: |
# pip install tifffile numpy
# shell: bash
# - name: Render and compare
# id: render_compare
# run: |
# TEST_DIR=test/renderdiff
# source ${TEST_DIR}/src/preamble.sh
# start_
# GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 ${TEST_DIR}/src/commit_msg.py)
# bash ${TEST_DIR}/generate.sh && \
# python3 ${TEST_DIR}/src/golden_manager.py \
# --branch=${GOLDEN_BRANCH} \
# --output=${GOLDEN_OUTPUT_DIR}
validate-wgsl-webgpu:
name: validate-wgsl-webgpu
runs-on: 'ubuntu-24.04-8core'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/linux-prereq
- name: Run build script
run: ./build.sh -W debug test_filamat filament
- name: Run test
run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
# # Note that we need to upload the output even if comparison fails, so we undo `set -ex`
# end_
test-code-correctness:
name: test-code-correctness
runs-on: 'macos-14-xlarge'
steps:
- uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- uses: ./.github/actions/mac-prereq
- name: Install clang-tidy and deps
run: |
pip install pyyaml
brew install llvm@${GITHUB_LLVM_VERSION}
sudo ln -s "$(brew --prefix llvm)@${GITHUB_LLVM_VERSION}/bin/clang-tidy" "/usr/local/bin/clang-tidy"
- name: Run build script
# We need to build before clang-tidy can run analysis
run: |
# This will build for all three desktop backends on mac
./build.sh -p desktop debug gltf_viewer
- name: Run test
run: bash test/code-correctness/test.sh
# python3 ${TEST_DIR}/src/compare.py \
# --src=${GOLDEN_OUTPUT_DIR} \
# --dest=${RENDER_OUTPUT_DIR} \
# --out=${DIFF_OUTPUT_DIR} 2>&1 | tee compare_output.txt
# if grep "Failed" compare_output.txt > /dev/null; then
# DELIMITER="EOF_FILE_CONTENT_$(date +%s)" # Using timestamp to make it more unique
# echo "err<<$DELIMITER" >> "$GITHUB_OUTPUT"
# cat compare_output.txt >> "$GITHUB_OUTPUT"
# echo "$DELIMITER" >> "$GITHUB_OUTPUT"
# fi
# - uses: actions/upload-artifact@v4
# with:
# name: presubmit-renderdiff-result
# path: ./out/renderdiff
# - name: Compare result
# run: |
# ERROR_STR="${{ steps.render_compare.outputs.err }}"
# if [ -n "${ERROR_STR}" ]; then
# echo "${ERROR_STR}"
# exit 1
# fi
# validate-wgsl-webgpu:
# name: validate-wgsl-webgpu
# runs-on: 'ubuntu-24.04-8core'
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/linux-prereq
# - name: Run build script
# run: ./build.sh -W debug test_filamat filament
# - name: Run test
# run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
# test-code-correctness:
# name: test-code-correctness
# runs-on: 'macos-14-xlarge'
# steps:
# - uses: actions/checkout@v4.1.6
# with:
# fetch-depth: 0
# - uses: ./.github/actions/mac-prereq
# - name: Install clang-tidy and deps
# run: |
# pip install pyyaml
# brew install llvm@${GITHUB_LLVM_VERSION}
# sudo ln -s "$(brew --prefix llvm)@${GITHUB_LLVM_VERSION}/bin/clang-tidy" "/usr/local/bin/clang-tidy"
# - name: Run build script
# # We need to build before clang-tidy can run analysis
# run: |
# # This will build for all three desktop backends on mac
# ./build.sh -p desktop debug gltf_viewer
# - name: Run test
# run: bash test/code-correctness/test.sh
+2 -10
View File
@@ -532,15 +532,6 @@ if (FILAMENT_SUPPORTS_OPENGL)
add_definitions(-DFILAMENT_SUPPORTS_OPENGL)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
option(FILAMENT_ENABLE_PERFETTO "Enable perfetto SDK on Android" OFF)
else()
option(FILAMENT_ENABLE_PERFETTO "Enable perfetto SDK on Android" ON)
endif()
if (FILAMENT_ENABLE_PERFETTO)
add_definitions(-DFILAMENT_ENABLE_PERFETTO)
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)
@@ -553,6 +544,7 @@ if (FILAMENT_SUPPORTS_VULKAN)
endif()
if (FILAMENT_SUPPORTS_WEBGPU)
message(AUTHOR_WARNING "WebGPU is in development stage and broken at this stage. Its support is very limited.")
add_definitions(-DFILAMENT_SUPPORTS_WEBGPU)
endif()
@@ -642,7 +634,7 @@ endif()
# 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
if (FILAMENT_SUPPORTS_WEBGPU)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=stereo)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=skinning,stereo)
endif()
# Disable ESSL 1.0 code generation.
+3
View File
@@ -7,3 +7,6 @@ We are chaning the way Vulkan buffers are handled. We need to switch over to a m
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- Update CMake minimum version to 3.22.1
- material: Add a material parameter to control shadow far attenuation (b/436680157)
+6 -6
View File
@@ -18,7 +18,7 @@ Filament release archives contains host-side tools that are required to generate
Make sure you always use tools from the same release as the runtime library. This is particularly
important for `matc` (material compiler).
If you'd rather build Filament yourself, please refer to our [build manual](/BUILDING.md).
If you'd rather build Filament yourself, please refer to our [build manual](BUILDING.md).
### Android
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.65.1'
implementation 'com.google.android.filament:filament-android:1.63.1'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
pod 'Filament', '~> 1.65.1'
pod 'Filament', '~> 1.63.1'
```
## Documentation
@@ -222,7 +222,7 @@ MaterialInstance* materialInstance = material->createInstance();
```
To learn more about materials and `matc`, please refer to the
[materials documentation](https://google.github.io/filament/Materials.html).
[materials documentation](./docs/Materials.md.html).
To render, simply pass the `View` to the `Renderer`:
@@ -240,7 +240,7 @@ in the `samples/` directory. These samples are all based on `libs/filamentapp/`
code that creates a native window with SDL2 and initializes the Filament engine, renderer and views.
For more information on how to prepare environment maps for image-based lighting please refer to
[BUILDING.md](/BUILDING.md#running-the-native-samples).
[BUILDING.md](https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples).
### Android
@@ -272,7 +272,7 @@ To get started you can use the textures and environment maps found respectively
refer to their respective `URL.txt` files to know more about the original authors.
Environments must be pre-processed using
[`cmgen`](/BUILDING.md#running-the-native-samples) or
[`cmgen`](https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples) or
using the `libiblprefilter` library.
## How to make contributions
-17
View File
@@ -7,23 +7,6 @@ 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.65.1
- `setFrameScheduledCallback` now works on all backends (frame presentation scheduling is still only
available on Metal). Non-Metal backends can use the callback to be notified when Filament has
finished processing a frame on the CPU.
- materials: added `getEyeFromViewMatrix()` for vertex shader [⚠️ **Recompile Materials**]
- matc: make `--workarounds=none` the default [**Recompile Materials to take effect**]
## v1.65.0
lighting: the intermediate froxel record buffer is now dynamically sized [⚠️ **New Material Version**]
## v1.64.1
- Update CMake minimum version to 3.22.1
- material: Add a material parameter to control shadow far attenuation (b/436680157)
## v1.64.0
- engine: add a `linearFog` material parameter. [⚠️ **New Material Version**]
@@ -146,7 +146,7 @@ abstract class MaterialCompiler extends TaskWithBinary {
.gradleProperty("com.google.android.filament.include-webgpu")
.forUseAtConfigurationTime().present
if (include_webgpu) {
matcArgs += ['-a', 'webgpu', '--variant-filter=stereo']
matcArgs += ['-a', 'webgpu', '--variant-filter=skinning,stereo']
}
def mat_no_opt = providers
-2
View File
@@ -1,8 +1,6 @@
cmake_minimum_required(VERSION 3.19)
project(filamat-android)
set(CMAKE_CXX_STANDARD 20)
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
+17 -19
View File
@@ -7,8 +7,6 @@ option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
set(CMAKE_CXX_STANDARD 20)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
add_library(filament STATIC IMPORTED)
@@ -132,14 +130,6 @@ add_library(filament-jni SHARED
../common/NioUtils.cpp
)
target_include_directories(filament-jni PRIVATE
..
${FILAMENT_DIR}/include
../../filament/backend/include
../../third_party/robin-map
../../third_party/perfetto
../../libs/utils/include)
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
target_link_libraries(filament-jni
PRIVATE filament-generatePrefilterMipmap
@@ -154,21 +144,29 @@ target_link_libraries(filament-jni
PRIVATE android
PRIVATE jnigraphics
PRIVATE utils
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
PRIVATE abseil # needed only when FILAMENT_USE_ABSEIL_LOGGING is defined
PRIVATE perfetto
PRIVATE abseil
PRIVATE zstd
# libgeometry is PUBLIC because gltfio uses it.
PUBLIC geometry
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_FGVIEWER},ON>:fgviewer>
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:smol-v>
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:webgpu_dawn>
$<$<STREQUAL:${FILAMENT_ENABLE_FGVIEWER},ON>:fgviewer>
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>
$<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:webgpu_dawn>
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:smol-v>
)
target_include_directories(filament-jni PRIVATE
..
${FILAMENT_DIR}/include
../../filament/backend/include
../../third_party/robin-map
../../third_party/perfetto
../../libs/utils/include)
# Force a relink when the version script is changed:
set_target_properties(filament-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
@@ -450,13 +450,6 @@ Java_com_google_android_filament_RenderableManager_nGetPrimitiveCount(JNIEnv*, j
return (jint) rm->getPrimitiveCount((RenderableManager::Instance) i);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderableManager_nGetInstanceCount(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
return (jint) rm->getInstanceCount((RenderableManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jint primitiveIndex, jlong nativeMaterialInstance) {
@@ -851,14 +851,6 @@ public class RenderableManager {
return nGetPrimitiveCount(mNativeObject, i);
}
/**
* Gets the immutable number of instances in the given renderable.
*/
@IntRange(from = 0)
public int getInstanceCount(@EntityInstance int i) {
return nGetInstanceCount(mNativeObject, i);
}
/**
* Changes the material instance binding for the given primitive.
*
@@ -1026,7 +1018,6 @@ public class RenderableManager {
private static native boolean nIsShadowReceiver(long nativeRenderableManager, int i);
private static native void nGetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float[] center, float[] halfExtent);
private static native int nGetPrimitiveCount(long nativeRenderableManager, int i);
private static native int nGetInstanceCount(long nativeRenderableManager, int i);
private static native void nSetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex, long nativeMaterialInstance);
private static native void nClearMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
private static native long nGetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
@@ -231,7 +231,7 @@ public class View {
*
* <p>
* The View does not take ownership of the Scene pointer. Before destroying a Camera, be sure
* to remove it from all associated Views. If the camera isn't set, Renderer::render() will result in a no-op.
* to remove it from all assoicated Views.
* </p>
*
* @see #getCamera
@@ -1949,18 +1949,6 @@ public class View {
* Ground Truth-base Ambient Occlusion (GTAO) options
*/
public float gtaoThicknessHeuristic = 0.004f;
/**
* Ground Truth-base Ambient Occlusion (GTAO) options
*/
public boolean gtaoUseVisibilityBitmasks = false;
/**
* Ground Truth-base Ambient Occlusion (GTAO) options
*/
public float gtaoConstThickness = 0.5f;
/**
* Ground Truth-base Ambient Occlusion (GTAO) options
*/
public boolean gtaoLinearThickness = false;
}
+11 -31
View File
@@ -1,14 +1,6 @@
cmake_minimum_required(VERSION 3.19)
project(filament-utils-android)
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
option(FILAMENT_ENABLE_FGVIEWER "Enables Frame Graph Viewer" OFF)
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
set(CMAKE_CXX_STANDARD 20)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(IMAGEIO_DIR ../../libs/imageio)
@@ -38,16 +30,7 @@ add_library(iblprefilter STATIC IMPORTED)
set_target_properties(iblprefilter PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament-iblprefilter.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
add_library(perfetto STATIC IMPORTED)
set_target_properties(perfetto PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libperfetto.a)
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
add_library(filament-utils-jni SHARED
@@ -70,25 +53,22 @@ add_library(filament-utils-jni SHARED
target_compile_definitions(filament-utils-jni PUBLIC IMAGEIO_LITE=1)
target_include_directories(filament-utils-jni PRIVATE
..
${FILAMENT_DIR}/include
..
../../filament/backend/include
${IMAGEIO_DIR}/include
../../libs/utils/include)
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.symbols)
# The ordering in the following list is important because CMake does not have dependency information.
target_link_libraries(filament-utils-jni
PRIVATE gltfio-jni
PRIVATE civetweb
PRIVATE camutils
PRIVATE iblprefilter
PRIVATE image
PRIVATE filament-jni
PRIVATE ktxreader
PRIVATE viewer
PRIVATE log
PRIVATE utils
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
gltfio-jni
civetweb
camutils
iblprefilter
image
ktxreader
viewer
)
+69 -37
View File
@@ -1,27 +1,20 @@
cmake_minimum_required(VERSION 3.19)
project(gltfio-android)
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
option(FILAMENT_ENABLE_FGVIEWER "Enables Frame Graph Viewer" OFF)
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
set(CMAKE_CXX_STANDARD 20)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(GLTFIO_DIR ../../libs/gltfio)
set(DRACO_DIR ../../third_party/draco)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../filament-android ${CMAKE_CURRENT_BINARY_DIR}/filament-android)
add_library(gltfio_core STATIC IMPORTED)
set_target_properties(gltfio_core PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
add_library(dracodec STATIC IMPORTED)
set_target_properties(dracodec PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libdracodec.a)
add_library(meshoptimizer STATIC IMPORTED)
set_target_properties(meshoptimizer PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libmeshoptimizer.a)
add_library(ktxreader STATIC IMPORTED)
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
@@ -34,6 +27,10 @@ add_library(basis_transcoder STATIC IMPORTED)
set_target_properties(basis_transcoder PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbasis_transcoder.a)
add_library(zstd STATIC IMPORTED)
set_target_properties(zstd PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libzstd.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
@@ -50,11 +47,60 @@ add_library(uberarchive STATIC IMPORTED)
set_target_properties(uberarchive PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libuberarchive.a)
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
set(GLTFIO_SRCS
${GLTFIO_DIR}/include/gltfio/Animator.h
${GLTFIO_DIR}/include/gltfio/AssetLoader.h
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
${GLTFIO_DIR}/include/gltfio/MaterialProvider.h
${GLTFIO_DIR}/include/gltfio/NodeManager.h
${GLTFIO_DIR}/include/gltfio/TrsTransformManager.h
${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
${GLTFIO_DIR}/include/gltfio/TextureProvider.h
${GLTFIO_DIR}/include/gltfio/math.h
${GLTFIO_DIR}/src/ArchiveCache.cpp
${GLTFIO_DIR}/src/ArchiveCache.h
${GLTFIO_DIR}/src/Animator.cpp
${GLTFIO_DIR}/src/AssetLoader.cpp
${GLTFIO_DIR}/src/DependencyGraph.cpp
${GLTFIO_DIR}/src/DependencyGraph.h
${GLTFIO_DIR}/src/DracoCache.cpp
${GLTFIO_DIR}/src/DracoCache.h
${GLTFIO_DIR}/src/FFilamentAsset.h
${GLTFIO_DIR}/src/FFilamentInstance.h
${GLTFIO_DIR}/src/FilamentAsset.cpp
${GLTFIO_DIR}/src/FilamentInstance.cpp
${GLTFIO_DIR}/src/FNodeManager.h
${GLTFIO_DIR}/src/FTrsTransformManager.h
${GLTFIO_DIR}/src/GltfEnums.h
${GLTFIO_DIR}/src/Ktx2Provider.cpp
${GLTFIO_DIR}/src/MaterialProvider.cpp
${GLTFIO_DIR}/src/NodeManager.cpp
${GLTFIO_DIR}/src/TrsTransformManager.cpp
${GLTFIO_DIR}/src/ResourceLoader.cpp
${GLTFIO_DIR}/src/StbProvider.cpp
${GLTFIO_DIR}/src/TangentsJob.cpp
${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/UbershaderProvider.cpp
${GLTFIO_DIR}/src/Utility.cpp
${GLTFIO_DIR}/src/Utility.h
${GLTFIO_DIR}/src/Wireframe.cpp
${GLTFIO_DIR}/src/Wireframe.h
${GLTFIO_DIR}/src/downcast.h
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.cpp
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.h
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.cpp
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.h
${GLTFIO_DIR}/src/extended/TangentsJobExtended.cpp
${GLTFIO_DIR}/src/extended/TangentsJobExtended.h
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.cpp
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.h
src/main/cpp/Animator.cpp
src/main/cpp/AssetLoader.cpp
src/main/cpp/FilamentAsset.cpp
@@ -72,38 +118,24 @@ set(GLTFIO_SRCS
set(GLTFIO_INCLUDE_DIRS
..
${FILAMENT_DIR}/include
${FILAMENT_DIR}/backend/include
../../filament/backend/include
../../libs/gltfio/include
../../third_party/zstd/lib
../../third_party/cgltf
../../third_party/meshoptimizer/src
../../third_party/robin-map
../../third_party/stb
../../third_party/perfetto
../../libs/utils/include
../../libs/ktxreader/include
)
add_library(gltfio-jni SHARED ${GLTFIO_SRCS})
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
target_include_directories(gltfio-jni PRIVATE ${GLTFIO_INCLUDE_DIRS})
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols)
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map)
target_link_libraries(gltfio-jni filament-jni utils perfetto uberzlib log stb ktxreader basis_transcoder zstd uberarchive)
target_link_libraries(gltfio-jni dracodec meshoptimizer)
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/src)
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/tnt)
# Force a relink when the version script is changed:
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols;${VERSION_SCRIPT}")
# The ordering in the following list is important because CMake does not have dependency information.
target_link_libraries(gltfio-jni
PRIVATE gltfio_core
PRIVATE ktxreader
PUBLIC filament-jni
PRIVATE stb
PRIVATE basis_transcoder
PRIVATE uberarchive
PRIVATE dracodec
PRIVATE utils
PRIVATE uberzlib
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
PRIVATE log # needed only when perfetto above is used
)
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.65.1
VERSION_NAME=1.63.1
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+1 -8
View File
@@ -75,8 +75,6 @@ function print_help {
echo " -S type"
echo " Enable stereoscopic rendering where type is one of [instanced|multiview]. This is only"
echo " meant for building the samples."
echo " -P"
echo " Enable perfetto traces on Android. Disabled by default on the Release build, enabled otherwise."
echo ""
echo "Build types:"
echo " release"
@@ -206,7 +204,6 @@ MATOPT_GRADLE_OPTION=""
ASAN_UBSAN_OPTION=""
COVERAGE_OPTION=""
ENABLE_PERFETTO=""
BACKEND_DEBUG_FLAG_OPTION=""
@@ -416,7 +413,6 @@ function build_android_target {
${WEBGPU_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${ENABLE_PERFETTO} \
../..
ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \
../../compile_commands.json
@@ -810,7 +806,7 @@ function check_debug_release_build {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:" opt; do
case ${opt} in
h)
print_help
@@ -958,9 +954,6 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
V) COVERAGE_OPTION="-DFILAMENT_ENABLE_COVERAGE=ON"
echo "Enabled coverage"
;;
P) ENABLE_PERFETTO="-DFILAMENT_ENABLE_PERFETTO=ON"
echo "Enabled perfetto"
;;
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
;;
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
-60
View File
@@ -1,60 +0,0 @@
# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#!/usr/bin/bash
set -e
GLTF_SAMPLE_ASSETS_COMMIT=${GITHUB_GLTF_SAMPLE_ASSETS_COMMIT:-d441dfdb87413ff412c620849a649d61789a470f}
COMMIT_HASH="${GLTF_SAMPLE_ASSETS_COMMIT}"
REPO_URL="https://github.com/KhronosGroup/glTF-Sample-Assets.git"
TARGET_DIR="gltf"
# The default directories to check out if none are specified
DEFAULT_SPARSE_PATHS=(
"Models/Box/"
"Models/Triangle/"
"Models/AnimatedCube/"
)
# Check if command-line arguments are provided
if [ "$#" -gt 0 ]; then
# If arguments are provided, use them as the paths
SPARSE_PATHS=()
for model_name in "$@"; do
SPARSE_PATHS+=("Models/${model_name}/")
done
echo "Downloading specified models: $@"
else
# Otherwise, use the default list
SPARSE_PATHS=("${DEFAULT_SPARSE_PATHS[@]}")
echo "No models specified, downloading default set."
fi
echo "Removing old directory..."
rm -rf "${TARGET_DIR}"
# Clone the repository using a "treeless" clone, which is highly efficient.
# --filter=tree:0: Clones only the repository structure without file content (no historical directory listings), making the initial clone very small.
# --no-checkout: Prevents automatically checking out the main branch. We will check out a specific commit later.
# --sparse: Initializes the repository for sparse checkout, allowing us to fetch only specific directories.
git clone --filter=tree:0 --no-checkout --sparse "${REPO_URL}" "${TARGET_DIR}"
cd "${TARGET_DIR}"
git sparse-checkout set "${SPARSE_PATHS[@]}"
echo "Checking out commit ${COMMIT_HASH}..."
git checkout "${COMMIT_HASH}"
echo "Successfully checked out the specified models into the '${TARGET_DIR}' directory."
-3
View File
@@ -137,9 +137,6 @@ if [[ "$OS_NAME" == "Darwin" ]]; then
# This is necessary to be able to build vk (lavapipe) on macOS. Doesn't seem like a real dependency.
sed -I '' "s/error('Vulkan drivers require dri3 for X11 support')//g" meson.build
# This is to properly link lib-xcb-present on the mac build (though we won't be drawing to any
# real hardware surface).
sed -I '' "s/dep_xcb_present = null_dep/dep_xcb_present = dependency('xcb-present')/g" meson.build
fi
# -Dosmesa=true => builds OSMesa, which is an offscreen GL context
+6 -1
View File
@@ -109,8 +109,13 @@ function install_mac() {
unzip -t vulkan_sdk.zip
fi
echo "recognized zip layout 'vulkan_sdk.zip' ${InstallVulkan}.app/Contents" >&2
${InstallVulkan}.app/Contents/MacOS/${InstallVulkan} --accept-licenses --default-answer --confirm-command install
local sdk_temp=${VULKAN_SDK_DIR}.tmp
sudo ${InstallVulkan}.app/Contents/MacOS/${InstallVulkan} --root "$sdk_temp" --accept-licenses --default-answer --confirm-command install
du -hs $sdk_temp
test -d $sdk_temp/macOS || { echo "unrecognized dmg folder layout: $sdk_temp" ; ls -l $sdk_temp ; }
cp -r $sdk_temp/macOS/* $VULKAN_SDK_DIR/
if [[ -d ${InstallVulkan}.app/Contents ]] ; then
sudo rm -rf "$sdk_temp"
rm -rf ${InstallVulkan}.app
fi
}
+1 -2
View File
@@ -5,5 +5,4 @@ GITHUB_MESA_VERSION=24.2.1
GITHUB_LLVM_VERSION=16
GITHUB_NDK_VERSION=27.0.11718014
GITHUB_EMSDK_VERSION=3.1.60
GITHUB_VULKANSDK_VERSION=1.4.321.0
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f
GITHUB_VULKANSDK_VERSION=1.4.321.0
+3 -1
View File
@@ -135,7 +135,9 @@ set build_flags=-j %NUMBER_OF_PROCESSORS%
:: cmake --build . --target sample-resources --config %config% %build_flags% || exit /b
:: cmake --build . --target suzanne-resources --config %config% %build_flags% || exit /b
cmake --build . %INSTALL% --config %config% %build_flags% -- /m || exit /b
cmake --build . --target sample-resources --config %config% %build_flags% -- /m || exit /b
:: cmake --build . %INSTALL% --config %config% %build_flags% -- /m || exit /b
@echo off
echo Disk info after building variant: %variant%
+22 -25
View File
@@ -212,7 +212,7 @@ when using textures.
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
(reflected light takes on the color of the surfaced as defined by `baseColor`).
(reflected light takes on the color of the surfaced as defined by `baseColor`).
The effect of `metallic` is shown in figure [metallicProperty] (click on the image to see a
larger version).
@@ -248,7 +248,7 @@ The effect of `roughness` on metallic surfaces is shown in figure [roughnessCond
When refraction through an object is enabled (using a `refractonType` of `thin` or `solid`), the
`roughness` property will also affect the refractions, as shown in figure
[roughnessRefractionProperty] (click on the image to see a larger version).
![Figure [roughnessRefractionProperty]: Refractive sphere with `roughness` varying from 0.0
(left) to 1.0 (right)](images/materials/refraction_roughness.png)
@@ -307,7 +307,7 @@ The sheen color controls the color appearance and strength of an optional sheen
base layer described by the properties above. The sheen layer always sits below the clear coat layer
if such a layer is present.
The sheen layer can be used to represent cloth and fabric materials. Please refer to
The sheen layer can be used to represent cloth and fabric materials. Please refer to
section [Cloth model] for more information about cloth and fabric materials.
The effect of `sheenColor` is shown in figure [materialSheenColor]
@@ -520,14 +520,14 @@ light to bend further away from the initial path.
Table [commonMatIOR] describes acceptable refractive indices for various types of materials.
Material | IOR
Material | IOR
--------------------------:|:-----------------
Air | 1.0
Water | 1.33
Common liquids | 1.33 to 1.5
Common gemstones | 1.58 to 2.33
Plastics, glass | 1.5 to 1.58
Other dielectric materials | 1.33 to 1.58
Water | 1.33
Common liquids | 1.33 to 1.5
Common gemstones | 1.58 to 2.33
Plastics, glass | 1.5 to 1.58
Other dielectric materials | 1.33 to 1.58
[Table [commonMatIOR]: Index of refraction of common materials]
The appearance of a refractive material will greatly depend on the `refractionType` and
@@ -995,10 +995,10 @@ Value
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
mobile), `low`, `medium`, `high`. The type must be one of the types described in
table [materialParamsTypes]. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
table [materialParamsTypes]. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
this will always be identity.
this will always be identity.
Type | Description
:----------------------|:---------------------------------
@@ -2476,17 +2476,14 @@ type aliases:
### Matrices
Name | Type | Description
:-----------------------------------------|:--------:|:------------------------------------
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
**getEyeFromViewMatrix()** | float4x4 | Matrix that converts from view space to eye space
**getEyeFromViewMatrix(int eyeIndex)** | float4x4 | Matrix that converts from view space to eye space for the eye referred to by eyeIndex
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
**getClipFromWorldMatrix(int eyeIndex)** | float4x4 | Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
Name | Type | Description
:-----------------------------------|:--------:|:------------------------------------
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
### Frame constants
@@ -2642,7 +2639,7 @@ standard skybox material. It produces a list of 2 parameters, named `showSun` an
respectively a boolean and a cubemap texture.
```text
$ matc --reflect parameters filament/src/materials/skybox.mat
$ matc --reflect parameters filament/src/materials/skybox.mat
{
"parameters": [
{
@@ -2658,7 +2655,7 @@ $ matc --reflect parameters filament/src/materials/skybox.mat
}
]
}
```
```
### --variant-filter
+2 -4
View File
@@ -221,8 +221,6 @@ export is an html with the output captured in a <code>&lt;pre&gt;</code> tag).</
<li>Replace css styling in the exported output as needed (so they don't interfere with the book's css.</li>
<li>Replace resource urls to refer to locations relative to the mdbook structure.</li>
</ul>
<p>Any <code>markdeep</code> doc can be placed in <code>docs_src/src_markdeep/</code> and they will be parsed to html and included
in the book as above.</p>
<h3 id="readmes"><a class="header" href="#readmes">READMEs</a></h3>
<p>Filament depends on a number of libraries, which reside in the directory <code>libs</code>. These individual
libaries often have README.md in their root to describe itself. We collect these descriptions into our
@@ -231,7 +229,7 @@ located in <code>tools</code>. Some of tools also have README.md as description.
<p>The process for copying and processing these READMEs is outlined in <a href="#introductory-doc">Introductory docs</a>.</p>
<h3 id="other-technical-notes"><a class="header" href="#other-technical-notes">Other technical notes</a></h3>
<p>These are technical documents that do not fit into a library, tool, or directory of the
Filament source tree. We collect them into the <code>docs_src/src_mdbook/src/notes</code> directory. No additional
Filament source tree. We collect them into the <code>docs_src/src/notes</code> directory. No additional
processing is needed for these documents.</p>
<h3 id="raw-source-files"><a class="header" href="#raw-source-files">Raw source files</a></h3>
<p>These are files that are not part of the <code>mdbook</code> generation, but should be included output in <code>/docs</code>
@@ -244,7 +242,7 @@ add a link in <code>SUMMARY.md</code>, and perform the steps outlined in
<a href="#how-to-create">how-to create section</a>.</p>
<p>For example, if you are adding a general technical note, then you would</p>
<ul>
<li>Place the document (file with extension <code>.md</code>) in <code>docs_src/src_mdbook/src/notes</code></li>
<li>Place the document (file with extension <code>.md</code>) in <code>docs_src/src/notes</code></li>
<li>Add a link in <a href="https://github.com/google/filament/blob/main/docs_src/src_mdbook/src/SUMMARY.md"><code>docs_src/src_mdbook/src/SUMMARY.md</code></a></li>
<li>Run the commands in the <a href="#how-to-generate">Generate</a> section</li>
</ul>
+9 -9
View File
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.64.1'
implementation 'com.google.android.filament:filament-android:1.63.1'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
@@ -196,18 +196,18 @@ 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.64.1'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.63.1'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>
<li><a href="../main/filament.html">Filament</a>, an in-depth explanation of
<li><a href="https://google.github.io/filament/Filament.html">Filament</a>, an in-depth explanation of
real-time physically based rendering, the graphics capabilities and implementation of Filament.
This document explains the math and reasoning behind most of our decisions. This document is a
good introduction to PBR for graphics programmers.</li>
<li><a href="../main/materials.html">Materials</a>, the full reference
<li><a href="https://google.github.io/filament/Materials.html">Materials</a>, the full reference
documentation for our material system. This document explains our different material models, how
to use the material compiler <code>matc</code> and how to write custom materials.</li>
<li><a href="../notes/material_properties.html">Material Properties</a>, a reference
<li><a href="https://google.github.io/filament/notes/material_properties.html">Material Properties</a>, a reference
sheet for the standard material model.</li>
</ul>
<h2 id="examples"><a class="header" href="#examples">Examples</a></h2>
@@ -395,7 +395,7 @@ by <code>matc</code>:</p>
MaterialInstance* materialInstance = material-&gt;createInstance();
</code></pre>
<p>To learn more about materials and <code>matc</code>, please refer to the
<a href="../main/materials.html">materials documentation</a>.</p>
<a href="./docs/Materials.html">materials documentation</a>.</p>
<p>To render, simply pass the <code>View</code> to the <code>Renderer</code>:</p>
<pre><code class="language-c++">// beginFrame() returns false if we need to skip a frame
if (renderer-&gt;beginFrame(swapChain)) {
@@ -408,7 +408,7 @@ if (renderer-&gt;beginFrame(swapChain)) {
in the <code>samples/</code> directory. These samples are all based on <code>libs/filamentapp/</code> which contains the
code that creates a native window with SDL2 and initializes the Filament engine, renderer and views.</p>
<p>For more information on how to prepare environment maps for image-based lighting please refer to
<a href="building.html#running-the-native-samples">BUILDING.md</a>.</p>
<a href="https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples">BUILDING.md</a>.</p>
<h3 id="android-1"><a class="header" href="#android-1">Android</a></h3>
<p>See <code>android/samples</code> for examples of how to use Filament on Android.</p>
<p>You must always first initialize Filament by calling <code>Filament.init()</code>.</p>
@@ -430,7 +430,7 @@ OpenGL ES.</p>
<code>third_party/textures</code> and <code>third_party/environments</code>. These assets are under CC0 license. Please
refer to their respective <code>URL.txt</code> files to know more about the original authors.</p>
<p>Environments must be pre-processed using
<a href="building.html#running-the-native-samples"><code>cmgen</code></a> or
<a href="https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples"><code>cmgen</code></a> or
using the <code>libiblprefilter</code> library.</p>
<h2 id="how-to-make-contributions"><a class="header" href="#how-to-make-contributions">How to make contributions</a></h2>
<p>Please read and follow the steps in <a href="contributing.html">CONTRIBUTING.md</a>. Make sure you are
@@ -513,7 +513,7 @@ and tools.</p>
<li><code>web</code>: JavaScript bindings, documentation, and samples</li>
</ul>
<h2 id="license"><a class="header" href="#license">License</a></h2>
<p>Please see <a href="https://github.com/google/filament/blob/main/LICENSE">LICENSE</a>.</p>
<p>Please see <a href="/LICENSE">LICENSE</a>.</p>
<h2 id="disclaimer"><a class="header" href="#disclaimer">Disclaimer</a></h2>
<p>This is not an officially supported Google product.</p>
+1 -1
View File
@@ -162,7 +162,7 @@
<p>This tool makes it easy to analyze the composition of Android applications that use Filament.</p>
<ul>
<li>Filament materials are shown in the treemap if <code>resgen --json</code> was used in the build.</li>
<li>The input path can be a <code>.so</code> or <code>.a</code> file, a folder, or a zip archive (apk or aar).</li>
<li>The input path can be a so file, folder, or zip archive (apk or aar).</li>
<li>If the path is a zip or folder, interactively finds the file to analyze.</li>
<li>The generated web report is a self-contained HTML file.</li>
<li>Reports the gzipped size of all Filament materials.</li>
+563 -10
View File
@@ -1,11 +1,564 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redirecting...</title>
<meta http-equiv="refresh" content="0; url=./dup/intro.html">
</head>
<body>
</body>
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Introduction - 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="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>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>
<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>
<p>Make sure you always use tools from the same release as the runtime library. This is particularly
important for <code>matc</code> (material compiler).</p>
<p>If you'd rather build Filament yourself, please refer to our <a href="building.html">build manual</a>.</p>
<h3 id="android"><a class="header" href="#android">Android</a></h3>
<p>Android projects can simply declare Filament libraries as Maven dependencies:</p>
<pre><code class="language-gradle">repositories {
// ...
mavenCentral()
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.63.1'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
<div class="table-wrapper"><table><thead><tr><th>Artifact</th><th>Description</th></tr></thead><tbody>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android/badge.svg?subject=filament-android" alt="filament-android" /></a></td><td>The Filament rendering engine itself.</td></tr>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android-debug"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android-debug/badge.svg?subject=filament-android-debug" alt="filament-android-debug" /></a></td><td>Debug version of <code>filament-android</code>.</td></tr>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android/badge.svg?subject=gltfio-android" alt="gltfio-android" /></a></td><td>A glTF 2.0 loader for Filament, depends on <code>filament-android</code>.</td></tr>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android/badge.svg?subject=filament-utils-android" alt="filament-utils-android" /></a></td><td>KTX loading, Kotlin math, and camera utilities, depends on <code>gltfio-android</code>.</td></tr>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android/badge.svg?subject=filamat-android" alt="filamat-android" /></a></td><td>A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan.</td></tr>
<tr><td><a href="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite"><img src="https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite/badge.svg?subject=filamat-android-lite" alt="filamat-android-lite" /></a></td><td>A much smaller alternative to <code>filamat-android</code> that can only generate OpenGL shaders. It does not provide validation or optimizations.</td></tr>
</tbody></table>
</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.63.1'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>
<li><a href="https://google.github.io/filament/Filament.html">Filament</a>, an in-depth explanation of
real-time physically based rendering, the graphics capabilities and implementation of Filament.
This document explains the math and reasoning behind most of our decisions. This document is a
good introduction to PBR for graphics programmers.</li>
<li><a href="https://google.github.io/filament/Materials.html">Materials</a>, the full reference
documentation for our material system. This document explains our different material models, how
to use the material compiler <code>matc</code> and how to write custom materials.</li>
<li><a href="https://google.github.io/filament/notes/material_properties.html">Material Properties</a>, a reference
sheet for the standard material model.</li>
</ul>
<h2 id="examples"><a class="header" href="#examples">Examples</a></h2>
<p><img src="../images/samples/example_bistro1.jpg" alt="Night scene" />
<img src="../images/samples/example_bistro2.jpg" alt="Night scene" />
<img src="../images/samples/example_materials1.jpg" alt="Materials" />
<img src="../images/samples/example_materials2.jpg" alt="Materials" />
<img src="../images/samples/example_helmet.jpg" alt="Helmet" />
<img src="../images/samples/example_ssr.jpg" alt="Screen-space refraction" /></p>
<h2 id="features"><a class="header" href="#features">Features</a></h2>
<h3 id="apis"><a class="header" href="#apis">APIs</a></h3>
<ul>
<li>Native C++ API for Android, iOS, Linux, macOS and Windows</li>
<li>Java/JNI API for Android</li>
<li>JavaScript API</li>
</ul>
<h3 id="backends"><a class="header" href="#backends">Backends</a></h3>
<ul>
<li>OpenGL 4.1+ for Linux, macOS and Windows</li>
<li>OpenGL ES 3.0+ for Android and iOS</li>
<li>Metal for macOS and iOS</li>
<li>Vulkan 1.0 for Android, Linux, macOS, and Windows</li>
<li>WebGL 2.0 for all platforms</li>
</ul>
<h3 id="rendering"><a class="header" href="#rendering">Rendering</a></h3>
<ul>
<li>Clustered forward renderer</li>
<li>Cook-Torrance microfacet specular BRDF</li>
<li>Lambertian diffuse BRDF</li>
<li>Custom lighting/surface shading</li>
<li>HDR/linear lighting</li>
<li>Metallic workflow</li>
<li>Clear coat</li>
<li>Anisotropic lighting</li>
<li>Approximated translucent (subsurface) materials</li>
<li>Cloth/fabric/sheen shading</li>
<li>Normal mapping &amp; ambient occlusion mapping</li>
<li>Image-based lighting</li>
<li>Physically-based camera (shutter speed, sensitivity and aperture)</li>
<li>Physical light units</li>
<li>Point lights, spot lights, and directional light</li>
<li>Specular anti-aliasing</li>
<li>Point, spot, and directional light shadows</li>
<li>Cascaded shadows</li>
<li>EVSM, PCSS, DPCF, or PCF shadows</li>
<li>Transparent shadows</li>
<li>Contact shadows</li>
<li>Screen-space ambient occlusion</li>
<li>Screen-space reflections</li>
<li>Screen-space refraction</li>
<li>Global fog</li>
<li>Dynamic resolution (with support for AMD FidelityFX FSR)</li>
</ul>
<h3 id="post-processing"><a class="header" href="#post-processing">Post processing</a></h3>
<ul>
<li>HDR bloom</li>
<li>Depth of field bokeh</li>
<li>Multiple tone mappers: generic (customizable), ACES, filmic, etc.</li>
<li>Color and tone management: luminance scaling, gamut mapping</li>
<li>Color grading: exposure, night adaptation, white balance, channel mixer,
shadows/mid-tones/highlights, ASC CDL, contrast, saturation, etc.</li>
<li>TAA, FXAA, MSAA</li>
<li>Screen-space lens flares</li>
</ul>
<h3 id="gltf-20"><a class="header" href="#gltf-20">glTF 2.0</a></h3>
<ul>
<li>
<p>Encodings</p>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Embeded</li>
<li><input disabled="" type="checkbox" checked=""/>
Binary</li>
</ul>
</li>
<li>
<p>Primitive Types</p>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Points</li>
<li><input disabled="" type="checkbox" checked=""/>
Lines</li>
<li><input disabled="" type="checkbox"/>
Line Loop</li>
<li><input disabled="" type="checkbox" checked=""/>
Line Strip</li>
<li><input disabled="" type="checkbox" checked=""/>
Triangles</li>
<li><input disabled="" type="checkbox" checked=""/>
Triangle Strip</li>
<li><input disabled="" type="checkbox"/>
Triangle Fan</li>
</ul>
</li>
<li>
<p>Animation</p>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Transform animation</li>
<li><input disabled="" type="checkbox" checked=""/>
Linear interpolation</li>
<li><input disabled="" type="checkbox" checked=""/>
Morph animation
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Sparse accessor</li>
</ul>
</li>
<li><input disabled="" type="checkbox" checked=""/>
Skin animation</li>
<li><input disabled="" type="checkbox" checked=""/>
Joint animation</li>
</ul>
</li>
<li>
<p>Extensions</p>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
KHR_draco_mesh_compression</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_lights_punctual</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_clearcoat</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_emissive_strength</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_ior</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_pbrSpecularGlossiness</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_sheen</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_transmission</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_unlit</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_variants</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_volume</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_materials_specular</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_mesh_quantization</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_texture_basisu</li>
<li><input disabled="" type="checkbox" checked=""/>
KHR_texture_transform</li>
<li><input disabled="" type="checkbox" checked=""/>
EXT_meshopt_compression</li>
</ul>
</li>
</ul>
<h2 id="rendering-with-filament"><a class="header" href="#rendering-with-filament">Rendering with Filament</a></h2>
<h3 id="native-linux-macos-and-windows"><a class="header" href="#native-linux-macos-and-windows">Native Linux, macOS and Windows</a></h3>
<p>You must create an <code>Engine</code>, a <code>Renderer</code> and a <code>SwapChain</code>. The <code>SwapChain</code> is created from a
native window pointer (an <code>NSView</code> on macOS or a <code>HWND</code> on Windows for instance):</p>
<pre><code class="language-c++">Engine* engine = Engine::create();
SwapChain* swapChain = engine-&gt;createSwapChain(nativeWindow);
Renderer* renderer = engine-&gt;createRenderer();
</code></pre>
<p>To render a frame you must then create a <code>View</code>, a <code>Scene</code> and a <code>Camera</code>:</p>
<pre><code class="language-c++">Camera* camera = engine-&gt;createCamera(EntityManager::get().create());
View* view = engine-&gt;createView();
Scene* scene = engine-&gt;createScene();
view-&gt;setCamera(camera);
view-&gt;setScene(scene);
</code></pre>
<p>Renderables are added to the scene:</p>
<pre><code class="language-c++">Entity renderable = EntityManager::get().create();
// build a quad
RenderableManager::Builder(1)
.boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }})
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 6)
.culling(false)
.build(*engine, renderable);
scene-&gt;addEntity(renderable);
</code></pre>
<p>The material instance is obtained from a material, itself loaded from a binary blob generated
by <code>matc</code>:</p>
<pre><code class="language-c++">Material* material = Material::Builder()
.package((void*) BAKED_MATERIAL_PACKAGE, sizeof(BAKED_MATERIAL_PACKAGE))
.build(*engine);
MaterialInstance* materialInstance = material-&gt;createInstance();
</code></pre>
<p>To learn more about materials and <code>matc</code>, please refer to the
<a href="./docs/Materials.html">materials documentation</a>.</p>
<p>To render, simply pass the <code>View</code> to the <code>Renderer</code>:</p>
<pre><code class="language-c++">// beginFrame() returns false if we need to skip a frame
if (renderer-&gt;beginFrame(swapChain)) {
// for each View
renderer-&gt;render(view);
renderer-&gt;endFrame();
}
</code></pre>
<p>For complete examples of Linux, macOS and Windows Filament applications, look at the source files
in the <code>samples/</code> directory. These samples are all based on <code>libs/filamentapp/</code> which contains the
code that creates a native window with SDL2 and initializes the Filament engine, renderer and views.</p>
<p>For more information on how to prepare environment maps for image-based lighting please refer to
<a href="https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples">BUILDING.md</a>.</p>
<h3 id="android-1"><a class="header" href="#android-1">Android</a></h3>
<p>See <code>android/samples</code> for examples of how to use Filament on Android.</p>
<p>You must always first initialize Filament by calling <code>Filament.init()</code>.</p>
<p>Rendering with Filament on Android is similar to rendering from native code (the APIs are largely
the same across languages). You can render into a <code>Surface</code> by passing a <code>Surface</code> to the
<code>createSwapChain</code> method. This allows you to render to a <code>SurfaceTexture</code>, a <code>TextureView</code> or
a <code>SurfaceView</code>. To make things easier we provide an Android specific API called <code>UiHelper</code> in the
package <code>com.google.android.filament.android</code>. All you need to do is set a render callback on the
helper and attach your <code>SurfaceView</code> or <code>TextureView</code> to it. You are still responsible for
creating the swap chain in the <code>onNativeWindowChanged()</code> callback.</p>
<h3 id="ios-1"><a class="header" href="#ios-1">iOS</a></h3>
<p>Filament is supported on iOS 11.0 and above. See <code>ios/samples</code> for examples of using Filament on
iOS.</p>
<p>Filament on iOS is largely the same as native rendering with C++. A <code>CAEAGLLayer</code> or <code>CAMetalLayer</code>
is passed to the <code>createSwapChain</code> method. Filament for iOS supports both Metal (preferred) and
OpenGL ES.</p>
<h2 id="assets"><a class="header" href="#assets">Assets</a></h2>
<p>To get started you can use the textures and environment maps found respectively in
<code>third_party/textures</code> and <code>third_party/environments</code>. These assets are under CC0 license. Please
refer to their respective <code>URL.txt</code> files to know more about the original authors.</p>
<p>Environments must be pre-processed using
<a href="https://github.com/google/filament/blob/main/BUILDING.md#running-the-native-samples"><code>cmgen</code></a> or
using the <code>libiblprefilter</code> library.</p>
<h2 id="how-to-make-contributions"><a class="header" href="#how-to-make-contributions">How to make contributions</a></h2>
<p>Please read and follow the steps in <a href="contributing.html">CONTRIBUTING.md</a>. Make sure you are
familiar with the <a href="code_style.html">code style</a>.</p>
<h2 id="directory-structure"><a class="header" href="#directory-structure">Directory structure</a></h2>
<p>This repository not only contains the core Filament engine, but also its supporting libraries
and tools.</p>
<ul>
<li><code>android</code>: Android libraries and projects
<ul>
<li><code>filamat-android</code>: Filament material generation library (AAR) for Android</li>
<li><code>filament-android</code>: Filament library (AAR) for Android</li>
<li><code>filament-utils-android</code>: Extra utilities (KTX loader, math types, etc.)</li>
<li><code>gltfio-android</code>: Filament glTF loading library (AAR) for Android</li>
<li><code>samples</code>: Android-specific Filament samples</li>
</ul>
</li>
<li><code>art</code>: Source for various artworks (logos, PDF manuals, etc.)</li>
<li><code>assets</code>: 3D assets to use with sample applications</li>
<li><code>build</code>: CMake build scripts</li>
<li><code>docs</code>: Documentation
<ul>
<li><code>math</code>: Mathematica notebooks used to explore BRDFs, equations, etc.</li>
</ul>
</li>
<li><code>filament</code>: Filament rendering engine (minimal dependencies)
<ul>
<li><code>backend</code>: Rendering backends/drivers (Vulkan, Metal, OpenGL/ES)</li>
</ul>
</li>
<li><code>ide</code>: Configuration files for IDEs (CLion, etc.)</li>
<li><code>ios</code>: Sample projects for iOS</li>
<li><code>libs</code>: Libraries
<ul>
<li><code>bluegl</code>: OpenGL bindings for macOS, Linux and Windows</li>
<li><code>bluevk</code>: Vulkan bindings for macOS, Linux, Windows and Android</li>
<li><code>camutils</code>: Camera manipulation utilities</li>
<li><code>filabridge</code>: Library shared by the Filament engine and host tools</li>
<li><code>filaflat</code>: Serialization/deserialization library used for materials</li>
<li><code>filagui</code>: Helper library for <a href="https://github.com/ocornut/imgui">Dear ImGui</a></li>
<li><code>filamat</code>: Material generation library</li>
<li><code>filamentapp</code>: SDL2 skeleton to build sample apps</li>
<li><code>filameshio</code>: Tiny filamesh parsing library (see also <code>tools/filamesh</code>)</li>
<li><code>geometry</code>: Mesh-related utilities</li>
<li><code>gltfio</code>: Loader for glTF 2.0</li>
<li><code>ibl</code>: IBL generation tools</li>
<li><code>image</code>: Image filtering and simple transforms</li>
<li><code>imageio</code>: Image file reading / writing, only intended for internal use</li>
<li><code>matdbg</code>: DebugServer for inspecting shaders at run-time (debug builds only)</li>
<li><code>math</code>: Math library</li>
<li><code>mathio</code>: Math types support for output streams</li>
<li><code>utils</code>: Utility library (threads, memory, data structures, etc.)</li>
<li><code>viewer</code>: glTF viewer library (requires gltfio)</li>
</ul>
</li>
<li><code>samples</code>: Sample desktop applications</li>
<li><code>shaders</code>: Shaders used by <code>filamat</code> and <code>matc</code></li>
<li><code>third_party</code>: External libraries and assets
<ul>
<li><code>environments</code>: Environment maps under CC0 license that can be used with <code>cmgen</code></li>
<li><code>models</code>: Models under permissive licenses</li>
<li><code>textures</code>: Textures under CC0 license</li>
</ul>
</li>
<li><code>tools</code>: Host tools
<ul>
<li><code>cmgen</code>: Image-based lighting asset generator</li>
<li><code>filamesh</code>: Mesh converter</li>
<li><code>glslminifier</code>: Minifies GLSL source code</li>
<li><code>matc</code>: Material compiler</li>
<li><code>filament-matp</code>: Material parser</li>
<li><code>matinfo</code> Displays information about materials compiled with <code>matc</code></li>
<li><code>mipgen</code> Generates a series of miplevels from a source image</li>
<li><code>normal-blending</code>: Tool to blend normal maps</li>
<li><code>resgen</code> Aggregates binary blobs into embeddable resources</li>
<li><code>roughness-prefilter</code>: Pre-filters a roughness map from a normal map to reduce aliasing</li>
<li><code>specular-color</code>: Computes the specular color of conductors based on spectral data</li>
</ul>
</li>
<li><code>web</code>: JavaScript bindings, documentation, and samples</li>
</ul>
<h2 id="license"><a class="header" href="#license">License</a></h2>
<p>Please see <a href="/LICENSE">LICENSE</a>.</p>
<h2 id="disclaimer"><a class="header" href="#disclaimer">Disclaimer</a></h2>
<p>This is not an officially supported Google product.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="next prefetch" href="dup/building.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="next prefetch" href="dup/building.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>
+4 -4
View File
@@ -178,9 +178,9 @@ content:counter(h1) "."counter(h2) "."counter(h3) "."counter(h4) "."counter(h5)
counter-increment: h6;margin-right:10px}
</style><style>.hljs{display:block;overflow-x:auto;padding:0.5em;background:#fff;color:#000;-webkit-text-size-adjust:none}.hljs-comment{color:#006a00}.hljs-keyword{color:#02E}.hljs-literal,.nginx .hljs-title{color:#aa0d91}.method,.hljs-list .hljs-title,.hljs-tag .hljs-title,.setting .hljs-value,.hljs-winutils,.tex .hljs-command,.http .hljs-title,.hljs-request,.hljs-status,.hljs-name{color:#008}.hljs-envvar,.tex .hljs-special{color:#660}.hljs-string{color:#c41a16}.hljs-tag .hljs-value,.hljs-cdata,.hljs-filter .hljs-argument,.hljs-attr_selector,.apache .hljs-cbracket,.hljs-date,.hljs-regexp{color:#080}.hljs-sub .hljs-identifier,.hljs-pi,.hljs-tag,.hljs-tag .hljs-keyword,.hljs-decorator,.ini .hljs-title,.hljs-shebang,.hljs-prompt,.hljs-hexcolor,.hljs-rule .hljs-value,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-number,.css .hljs-function,.hljs-function .hljs-title,.coffeescript .hljs-attribute{color:#A0C}.hljs-function .hljs-title{font-weight:bold;color:#000}.hljs-class .hljs-title,.smalltalk .hljs-class,.hljs-type,.hljs-typename,.hljs-tag .hljs-attribute,.hljs-doctype,.hljs-class .hljs-id,.hljs-built_in,.setting,.hljs-params,.clojure .hljs-attribute{color:#5c2699}.hljs-variable{color:#3f6e74}.css .hljs-tag,.hljs-rule .hljs-property,.hljs-pseudo,.hljs-subst{color:#000}.css .hljs-class,.css .hljs-id{color:#9b703f}.hljs-value .hljs-important{color:#ff7700;font-weight:bold}.hljs-rule .hljs-keyword{color:#c5af75}.hljs-annotation,.apache .hljs-sqbracket,.nginx .hljs-built_in{color:#9b859d}.hljs-preprocessor,.hljs-preprocessor *,.hljs-pragma{color:#643820}.tex .hljs-formula{background-color:#eee;font-style:italic}.diff .hljs-header,.hljs-chunk{color:#808080;font-weight:bold}.diff .hljs-change{background-color:#bccff9}.hljs-addition{background-color:#baeeba}.hljs-deletion{background-color:#ffc8bd}.hljs-comment .hljs-doctag{font-weight:bold}.method .hljs-id{color:#000}</style><style>div.title { padding-top: 40px; } div.afterTitles { height: 15px; }</style><meta charset="utf-8"></p>
<style>img { max-width: 100%; }</style>
<p><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{,\mathrm{#1}}$$
<script type="text/x-mathjax-config">MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });</script><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{\,\mathrm{#1}}$$
</span>
<span class="md"><p><title>Physically Based Rendering in Filament</title><div class="title"> Physically Based Rendering in Filament </div></p>
<span class="md"><p><title>Physically Based Rendering in Filament</title><div class="title"> Physically Based Rendering in Filament </div>
<div class="afterTitles"></div>
</p><p>
</p>
@@ -2060,7 +2060,7 @@ In practice only 4 or 9 coefficients (i.e.: 2 or 3 bands) are enough for \(\cosT
In practice we pre-convolve \(\Lt\) with \(\cosTheta\) and pre-scale these coefficients by the basis scaling factors \(K_l^m\) so that the reconstruction code is as simple as possible in the shader:
</p><a class="target" name="listing_irradiancesh">&nbsp;</a><pre class="listing tilde"><code><span class="line"></span>vec3 irradianceSH(vec3 n) {
<span class="line"></span> // uniform vec3 sphericalHarmonics<span class="hljs-selector-attr">[9]</span>
<span class="line"></span> // We can <span class="hljs-selector-tag">use</span> only the first <span class="hljs-number">2</span> bands for better performance
<span class="line"></span> // We can use only the first <span class="hljs-number">2</span> bands for better performance
<span class="line"></span> return
<span class="line"></span> sphericalHarmonics<span class="hljs-selector-attr">[0]</span>
<span class="line"></span> + sphericalHarmonics<span class="hljs-selector-attr">[1]</span> * (n<span class="hljs-selector-class">.y</span>)
@@ -4395,7 +4395,7 @@ For Fast Realistic Image Display. <em class="asterisk">SIGGRAPH '00 Proceedings
</div><div class="bib">[<a class="target" name="citation-schlick94">&nbsp;</a><b>Schlick94</b>] Christophe Schlick. 1994. An Inexpensive BRDF Model for Physically-Based Rendering. <em class="asterisk">Computer Graphics Forum</em>, 13 (3), 233–246.
</div><div class="bib">[<a class="target" name="citation-walter07">&nbsp;</a><b>Walter07</b>] Bruce Walter et al. 2007. Microfacet Models for Refraction through Rough Surfaces. <em class="asterisk">Proceedings of the Eurographics Symposium on Rendering</em>.
</div>
</sample></float></sample></float></float></p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep&nbsp;1.18&nbsp;&nbsp;</a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">&#x2712;</div></div><script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
</sample></float></sample></float></float></p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep&nbsp;1.18&nbsp;&nbsp;</a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">&#x2712;</div></div><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
+2 -2
View File
@@ -160,8 +160,8 @@
<main>
<h1 id="core-concepts"><a class="header" href="#core-concepts">Core Concepts</a></h1>
<ul>
<li><a href="filament.html">Filament</a> - High-level designs; Filament's PBR/math assumptions; implementation details.</li>
<li><a href="materials.html">Materials</a> - A guide to Filament's material definition.</li>
<li><a href="main/filament.html">Filament</a> - High-level designs; Filament's PBR/math assumptions; implementation details.</li>
<li><a href="main/materials.html">Materials</a> - A guide to Filament's material definition.</li>
</ul>
</main>
+9 -12
View File
@@ -178,9 +178,9 @@ content:counter(h1) "."counter(h2) "."counter(h3) "."counter(h4) "."counter(h5)
counter-increment: h6;margin-right:10px}
</style><style>.hljs{display:block;overflow-x:auto;padding:0.5em;background:#fff;color:#000;-webkit-text-size-adjust:none}.hljs-comment{color:#006a00}.hljs-keyword{color:#02E}.hljs-literal,.nginx .hljs-title{color:#aa0d91}.method,.hljs-list .hljs-title,.hljs-tag .hljs-title,.setting .hljs-value,.hljs-winutils,.tex .hljs-command,.http .hljs-title,.hljs-request,.hljs-status,.hljs-name{color:#008}.hljs-envvar,.tex .hljs-special{color:#660}.hljs-string{color:#c41a16}.hljs-tag .hljs-value,.hljs-cdata,.hljs-filter .hljs-argument,.hljs-attr_selector,.apache .hljs-cbracket,.hljs-date,.hljs-regexp{color:#080}.hljs-sub .hljs-identifier,.hljs-pi,.hljs-tag,.hljs-tag .hljs-keyword,.hljs-decorator,.ini .hljs-title,.hljs-shebang,.hljs-prompt,.hljs-hexcolor,.hljs-rule .hljs-value,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-number,.css .hljs-function,.hljs-function .hljs-title,.coffeescript .hljs-attribute{color:#A0C}.hljs-function .hljs-title{font-weight:bold;color:#000}.hljs-class .hljs-title,.smalltalk .hljs-class,.hljs-type,.hljs-typename,.hljs-tag .hljs-attribute,.hljs-doctype,.hljs-class .hljs-id,.hljs-built_in,.setting,.hljs-params,.clojure .hljs-attribute{color:#5c2699}.hljs-variable{color:#3f6e74}.css .hljs-tag,.hljs-rule .hljs-property,.hljs-pseudo,.hljs-subst{color:#000}.css .hljs-class,.css .hljs-id{color:#9b703f}.hljs-value .hljs-important{color:#ff7700;font-weight:bold}.hljs-rule .hljs-keyword{color:#c5af75}.hljs-annotation,.apache .hljs-sqbracket,.nginx .hljs-built_in{color:#9b859d}.hljs-preprocessor,.hljs-preprocessor *,.hljs-pragma{color:#643820}.tex .hljs-formula{background-color:#eee;font-style:italic}.diff .hljs-header,.hljs-chunk{color:#808080;font-weight:bold}.diff .hljs-change{background-color:#bccff9}.hljs-addition{background-color:#baeeba}.hljs-deletion{background-color:#ffc8bd}.hljs-comment .hljs-doctag{font-weight:bold}.method .hljs-id{color:#000}</style><style>div.title { padding-top: 40px; } div.afterTitles { height: 15px; }</style><meta charset="utf-8"></p>
<style>img { max-width: 100%; }</style>
<p><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{,\mathrm{#1}}$$
<script type="text/x-mathjax-config">MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });</script><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{\,\mathrm{#1}}$$
</span>
<span class="md"><p><title>Filament Materials Guide</title><div class="title"> Filament Materials Guide </div></p>
<span class="md"><p><title>Filament Materials Guide</title><div class="title"> Filament Materials Guide </div>
<div class="afterTitles"></div>
</p><p>
</p>
@@ -504,7 +504,7 @@ when using textures.</p>
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
(reflected light takes on the color of the surfaced as defined by <code>baseColor</code>).
(reflected light takes on the color of the surfaced as defined by <code>baseColor</code>).
</p><p>
The effect of <code>metallic</code> is shown in <a href="#figure_metallicproperty" target="_self">figure&nbsp;1</a> (click on the image to see a
larger version).
@@ -597,7 +597,7 @@ indices.
base layer described by the properties above. The sheen layer always sits below the clear coat layer
if such a layer is present.</p>
</p><p>
The sheen layer can be used to represent cloth and fabric materials. Please refer to
The sheen layer can be used to represent cloth and fabric materials. Please refer to
section <a href="#toc3.3" target="_self">3.3</a> for more information about cloth and fabric materials.
</p><p>
The effect of <code>sheenColor</code> is shown in <a href="#figure_materialsheencolor" target="_self">figure&nbsp;7</a>
@@ -1220,10 +1220,10 @@ non-shader data.</p>
name must be a valid GLSL identifier. Entries have an optional <code>precision</code>, which can be
one of <code>default</code> (best precision for the platform, typically <code>high</code> on desktop, <code>medium</code> on
mobile), <code>low</code>, <code>medium</code>, <code>high</code>. The type must be one of the types described in
<a href="#table_materialparamstypes" target="_self">table&nbsp;14</a>. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
<a href="#table_materialparamstypes" target="_self">table&nbsp;14</a>. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
this will always be identity.
this will always be identity.
</p></dd></dl><div class='table'>
<a class="target" name="table_materialparamstypes">&nbsp;</a><table class="table longtable"><tr><th style="text-align:left"> Type </th><th style="text-align:left"> Description </th></tr>
<tr><td style="text-align:left"> bool </td><td style="text-align:left"> Single boolean </td></tr>
@@ -2361,10 +2361,7 @@ type aliases:</p>
<tr><td style="text-align:left"> <strong class="asterisk">getWorldFromViewMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from view/eye space to world space </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromViewMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from view/eye space to clip (NDC) space </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getViewFromClipMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from clip (NDC) space to view/eye space </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getEyeFromViewMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from view space to eye space </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getEyeFromViewMatrix(int eyeIndex)</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from view space to eye space for the eye referred to by eyeIndex </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromWorldMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from world to clip (NDC) space </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromWorldMatrix(int eyeIndex)</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getWorldFromClipMatrix()</strong> </td><td style="text-align:center"> float4&times;4 </td><td style="text-align:left"> Matrix that converts from clip (NDC) space to world space </td></tr>
</table></div>
</p>
@@ -2504,7 +2501,7 @@ a good compromise between runtime performance and size.</p>
metadata in JSON format. The example below prints out the list of parameters defined in Filament's
standard skybox material. It produces a list of 2 parameters, named <code>showSun</code> and <code>skybox</code>,
respectively a boolean and a cubemap texture.</p>
</p><pre class="listing backtick"><code><span class="line"></span>$ matc --reflect parameters filament/src/materials/skybox.mat
</p><pre class="listing backtick"><code><span class="line"></span>$ matc --reflect parameters filament/src/materials/skybox.mat
<span class="line"></span>{
<span class="line"></span> &quot;parameters&quot;: [
<span class="line"></span> {
@@ -2603,7 +2600,7 @@ Finally if <code>variantFilter</code> contains the <code>fog</code> filter, an e
</p><p>
Be aware that <code>external</code> samplers account for 2 regular samplers.</div>
</p><p>
</p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep&nbsp;1.18&nbsp;&nbsp;</a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">&#x2712;</div></div><script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
</p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep&nbsp;1.18&nbsp;&nbsp;</a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">&#x2712;</div></div><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
+2 -2
View File
@@ -250,7 +250,7 @@ execution profile data.</p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../notes/performance_analysis.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../notes/framegraph.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -264,7 +264,7 @@ execution profile data.</p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../notes/performance_analysis.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="../notes/framegraph.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
+2 -2
View File
@@ -331,7 +331,7 @@ nodes</li>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../notes/performance_analysis.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../notes/coverage.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
@@ -345,7 +345,7 @@ nodes</li>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../notes/performance_analysis.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="../notes/coverage.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
-352
View File
@@ -1,352 +0,0 @@
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Performance analysis - 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="performance-analysis"><a class="header" href="#performance-analysis">Performance Analysis</a></h1>
<h2 id="android"><a class="header" href="#android">Android</a></h2>
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
<ul>
<li>Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi.</li>
</ul>
<hr />
<h4 id="profiling"><a class="header" href="#profiling">Profiling</a></h4>
<ol>
<li>
<p>Before profiling the application or analyzing the performance in a consistent way, ideally
the <strong>GPU frequency on the target hardware should get locked</strong>. In order to do this, you need to do the following:</p>
<ol>
<li>Ensure your device is OEM unlocked. If your phone is carrier-locked, you may need
to wait a period, such as 60 or 90 days after activation to be eligible for unlocking.
Some phones don't support this at all. You will need to enable developer options
(e.g. Settings &gt; About Phone and tap the Build number 7 times). You need to go to
Settings &gt; System &gt; Developer options and toggle on "OEM unlocking".</li>
<li>Next, you need to unlock the phone. You will need to install Android SDK Platform
Tools on you computer, enable "USB debugging" in your phone's Settings &gt; System &gt; Developer options.</li>
<li>Connect the phone to the computer via a USB cable and run from the command line:
<pre><code class="language-shell">adb reboot bootloader
# once the phone is in bootloader mode, run the following to begin the unlocking
# process:
fastboot flashing unlock
</code></pre>
A warning will appear on your phone's screen. Use the volume buttons to navigate and
the power button to select the "Unlock the bootloader" option. The phone will perform
a factory data reset and reboot with an unlocked bootloader.</li>
<li>You would need to flash an image to the phone with root permissions, such as a *-userdebug or *-eng
build. One way to do this is with the <a href="https://flash.android.com/">Android Flash Tool</a>. Connect the
tool to your device and find a build to flash ending in <code>-userdebug</code> or <code>-eng</code>. Once you have that
selected run <code>Install build</code>.</li>
<li>Shell into your device as root and configure the gpu frequency to be locked, e.g.:
<pre><code class="language-shell">adb shell
su
# navigate to the system GPU directory. this varies on different phones. One phone might have
# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with "mali" instead
# of "kgsl". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali
cd /sys/devices/platform/1f000000.mali
# get the current available GPU governors and frequencies.
# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but
# the system at the time of writing this had available_governors and available_frequences
cat available_governors
cat available_frequencies
# depending on the governors, you may want to set it prioritize performance over other things like
# battery. Some systems allow you to do this with something like (although, for the device used at the
# time of writing this did not have an equivalent option):
echo performance &gt; gpu_governor
# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you
# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:
echo 940000 &gt; hint_min_freq
echo 940000 &gt; hint_max_freq
# you can typically verify the GPU is running at that frequency consistently by running something like
# the following a few times over time, which should show the frequency you want to lock the device to:
cat cur_freq
</code></pre>
</li>
<li>You may need to re-apply the <code>hint_min_freq</code> just before starting the profiling trace and check before and after
that the frequency remained at the value expected. Some systems may adjust the frequency on you, but you
may want to ensure the frequency remains the same through the analysis.</li>
<li>The GPU frequency settings should be undone after restarting the device, but after you have done your app profiling,
you can revert the state of the device, such as the OS build image, back to the way you had it
initially, as needed.</li>
</ol>
</li>
<li>
<p>Build a release build of Filament with the applicable backend(s) enabled
<em>(+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from
building a release build with no flags)</em> <em>(debug builds for this are useless)</em></p>
<pre><code class="language-shell"># the following command assumes you are in the root filament directory
# and ANDROID_HOME is exported (and possibly also CC and CXX on linux as needed)
#
# NOTE: to build with WebGPU support you need to explicitly include the -W flag
# (it doesn't get compiled in by default), e.g.:
# ./build.sh -W -p android,desktop -i release
#
# Note that you can speed this up a bit (and reduce disk space usage) by limiting the target to just
# the ABI you plan on testing with the -q flag, e.g. -q arm64-v8a. If you do this, you
# will need to update the android/gradle.properties file to specify the ABI(s) you are targeting
# with the com.google.android.filament.abis property.
# Thus, a build command that would target BOTH Vulkan AND WebGPU AND only target the ARM64 ABI would look something
# like:
# ./build.sh -W -q arm64-v8a -p android,desktop -i release
./build.sh -p android,desktop -i release
</code></pre>
</li>
<li>
<p>Connect your Android device to your computer via a USB cord with USB debugging enabled and configure
the system property to default to the desired backend, e.g.
<em>(to determine how these numbers map to the backends, see the <code>enum class Backend</code>
definition in <a href="../../../../filament/backend/include/backend/DriverEnums.h">filament/filament/backend/include/backend/DriverEnums.h</a>)</em>:</p>
<pre><code class="language-shell"># to set the backend to Vulkan:
adb shell setprop debug.filament.backend 2
# to set the backend to WebGPU:
adb shell setprop debug.filament.backend 4
# to view the current property:
adb shell getprop debug.filament.backend
</code></pre>
</li>
<li>
<p>Build and run a sample, e.g. sample-gltf-viewer, on your Android device
<em>(<a href="https://developer.android.com/studio">Android Studio</a> recommended)</em>.</p>
</li>
<li>
<p>Run <a href="https://developer.android.com/agi">AGI</a> and follow instructions to profile the app/system
with trace capture(s). See https://developer.android.com/agi/start for more details to
get started.</p>
<ul>
<li>We typically only run "Capture System Profiler trace" <em>(not necessarily "Capture Frame Profiler trace")</em></li>
<li>When configuring the trace:
<ul>
<li>For both the WebGPU and Vulkan backends configure the profiler for the Vulkan API
<em>(since WebGPU should be using Vulkan under the hood as well)</em></li>
<li>Running for ~1 seconds should suffice</li>
<li>Hit the "Configure" button in Trace objects, select "Switch to advanced mode" and add:
<pre><code>data_sources {
config {
name: "track_event"
track_event_config {
disabled_categories: "*"
enabled_categories: "filament/filament"
enabled_categories: "filament/jobsystem"
enabled_categories: "filament/gltfio"
}
}
}
</code></pre>
</li>
</ul>
</li>
<li>One you open the trace, zoom into a series of frames to get a sense of generally how long they typically take
<em>(use <code>W</code>, <code>S</code>, <code>A</code> and <code>D</code> keys and mouse wheel for navigation)</em> and find a representative one.
We are most interested in the performance of the
<code>FEngine::loop</code> thread, how long it takes, overlap in activities/processes/commands, reduction in queue submissions,
etc. Similarly, we can view GPU timeline as it relates to that. We want to see overlapping
shader invocations and non-interrupted fragment shader runs.</li>
</ul>
</li>
</ol>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../notes/coverage.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/framegraph.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="../notes/coverage.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/framegraph.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>
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -5
View File
@@ -65,9 +65,6 @@ We describe step 1 in detail for the sake of record:
- Replace css styling in the exported output as needed (so they don't interfere with the book's css.
- Replace resource urls to refer to locations relative to the mdbook structure.
Any `markdeep` doc can be placed in `docs_src/src_markdeep/` and they will be parsed to html and included
in the book as above.
### READMEs
Filament depends on a number of libraries, which reside in the directory `libs`. These individual
libaries often have README.md in their root to describe itself. We collect these descriptions into our
@@ -78,7 +75,7 @@ The process for copying and processing these READMEs is outlined in [Introductor
### Other technical notes
These are technical documents that do not fit into a library, tool, or directory of the
Filament source tree. We collect them into the `docs_src/src_mdbook/src/notes` directory. No additional
Filament source tree. We collect them into the `docs_src/src/notes` directory. No additional
processing is needed for these documents.
### Raw source files
@@ -93,7 +90,7 @@ add a link in `SUMMARY.md`, and perform the steps outlined in
[how-to create section](#how-to-create).
For example, if you are adding a general technical note, then you would
- Place the document (file with extension `.md`) in `docs_src/src_mdbook/src/notes`
- Place the document (file with extension `.md`) in `docs_src/src/notes`
- Add a link in [`docs_src/src_mdbook/src/SUMMARY.md`]
- Run the commands in the [Generate](#how-to-generate) section
+1 -6
View File
@@ -2,14 +2,9 @@
"README.md": {
"dest": "dup/intro.md",
"link_transforms": {
"/BUILDING.md#running-the-native-samples": "building.md#running-the-native-samples",
"/BUILDING.md": "building.md",
"BUILDING.md": "building.md",
"/CONTRIBUTING.md": "contributing.md",
"/CODE_STYLE.md": "code_style.md",
"/LICENSE": "https://github.com/google/filament/blob/main/LICENSE",
"https://google.github.io/filament/Filament.html": "../main/filament.md",
"https://google.github.io/filament/Materials.html": "../main/materials.md",
"https://google.github.io/filament/notes/material_properties.html": "../notes/material_properties.md",
"docs/images/samples": "../images/samples"
}
},
+22 -25
View File
@@ -212,7 +212,7 @@ when using textures.
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
(reflected light takes on the color of the surfaced as defined by `baseColor`).
(reflected light takes on the color of the surfaced as defined by `baseColor`).
The effect of `metallic` is shown in figure [metallicProperty] (click on the image to see a
larger version).
@@ -248,7 +248,7 @@ The effect of `roughness` on metallic surfaces is shown in figure [roughnessCond
When refraction through an object is enabled (using a `refractonType` of `thin` or `solid`), the
`roughness` property will also affect the refractions, as shown in figure
[roughnessRefractionProperty] (click on the image to see a larger version).
![Figure [roughnessRefractionProperty]: Refractive sphere with `roughness` varying from 0.0
(left) to 1.0 (right)](images/materials/refraction_roughness.png)
@@ -307,7 +307,7 @@ The sheen color controls the color appearance and strength of an optional sheen
base layer described by the properties above. The sheen layer always sits below the clear coat layer
if such a layer is present.
The sheen layer can be used to represent cloth and fabric materials. Please refer to
The sheen layer can be used to represent cloth and fabric materials. Please refer to
section [Cloth model] for more information about cloth and fabric materials.
The effect of `sheenColor` is shown in figure [materialSheenColor]
@@ -520,14 +520,14 @@ light to bend further away from the initial path.
Table [commonMatIOR] describes acceptable refractive indices for various types of materials.
Material | IOR
Material | IOR
--------------------------:|:-----------------
Air | 1.0
Water | 1.33
Common liquids | 1.33 to 1.5
Common gemstones | 1.58 to 2.33
Plastics, glass | 1.5 to 1.58
Other dielectric materials | 1.33 to 1.58
Water | 1.33
Common liquids | 1.33 to 1.5
Common gemstones | 1.58 to 2.33
Plastics, glass | 1.5 to 1.58
Other dielectric materials | 1.33 to 1.58
[Table [commonMatIOR]: Index of refraction of common materials]
The appearance of a refractive material will greatly depend on the `refractionType` and
@@ -995,10 +995,10 @@ Value
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
mobile), `low`, `medium`, `high`. The type must be one of the types described in
table [materialParamsTypes]. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
table [materialParamsTypes]. For Android external textures, entries also have an optional
transformName parameter to specify the name of the material parameter that will be
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
this will always be identity.
this will always be identity.
Type | Description
:----------------------|:---------------------------------
@@ -2476,17 +2476,14 @@ type aliases:
### Matrices
Name | Type | Description
:-----------------------------------------|:--------:|:------------------------------------
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
**getEyeFromViewMatrix()** | float4x4 | Matrix that converts from view space to eye space
**getEyeFromViewMatrix(int eyeIndex)** | float4x4 | Matrix that converts from view space to eye space for the eye referred to by eyeIndex
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
**getClipFromWorldMatrix(int eyeIndex)** | float4x4 | Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
Name | Type | Description
:-----------------------------------|:--------:|:------------------------------------
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
### Frame constants
@@ -2642,7 +2639,7 @@ standard skybox material. It produces a list of 2 parameters, named `showSun` an
respectively a boolean and a cubemap texture.
```text
$ matc --reflect parameters filament/src/materials/skybox.mat
$ matc --reflect parameters filament/src/materials/skybox.mat
{
"parameters": [
{
@@ -2658,7 +2655,7 @@ $ matc --reflect parameters filament/src/materials/skybox.mat
}
]
}
```
```
### --variant-filter
-1
View File
@@ -24,7 +24,6 @@
- [Running with ASAN and UBSAN](./notes/asan_ubsan.md)
- [Using Instruments on macOS](./notes/instruments.md)
- [Code coverage analysis](./notes/coverage.md)
- [Performance analysis](./notes/performance_analysis.md)
- [Framegraph](./notes/framegraph.md)
- [Libraries](./notes/libs.md)
- [bluegl](./dup/bluegl.md)
+2 -2
View File
@@ -1,5 +1,5 @@
# Core Concepts
- [Filament](filament.md) - High-level designs; Filament's PBR/math assumptions; implementation details.
- [Materials](materials.md) - A guide to Filament's material definition.
- [Filament](main/filament.md) - High-level designs; Filament's PBR/math assumptions; implementation details.
- [Materials](main/materials.md) - A guide to Filament's material definition.
@@ -1,129 +0,0 @@
# Performance Analysis
## Android
### Prerequisites
- Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi.
---
#### Profiling
1. Before profiling the application or analyzing the performance in a consistent way, ideally
the **GPU frequency on the target hardware should get locked**. In order to do this, you need to do the following:
1. Ensure your device is OEM unlocked. If your phone is carrier-locked, you may need
to wait a period, such as 60 or 90 days after activation to be eligible for unlocking.
Some phones don't support this at all. You will need to enable developer options
(e.g. Settings > About Phone and tap the Build number 7 times). You need to go to
Settings > System > Developer options and toggle on "OEM unlocking".
1. Next, you need to unlock the phone. You will need to install Android SDK Platform
Tools on you computer, enable "USB debugging" in your phone's Settings > System > Developer options.
1. Connect the phone to the computer via a USB cable and run from the command line:
```shell
adb reboot bootloader
# once the phone is in bootloader mode, run the following to begin the unlocking
# process:
fastboot flashing unlock
```
A warning will appear on your phone's screen. Use the volume buttons to navigate and
the power button to select the "Unlock the bootloader" option. The phone will perform
a factory data reset and reboot with an unlocked bootloader.
1. You would need to flash an image to the phone with root permissions, such as a *-userdebug or *-eng
build. One way to do this is with the [Android Flash Tool](https://flash.android.com/). Connect the
tool to your device and find a build to flash ending in `-userdebug` or `-eng`. Once you have that
selected run `Install build`.
1. Shell into your device as root and configure the gpu frequency to be locked, e.g.:
```shell
adb shell
su
# navigate to the system GPU directory. this varies on different phones. One phone might have
# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with "mali" instead
# of "kgsl". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali
cd /sys/devices/platform/1f000000.mali
# get the current available GPU governors and frequencies.
# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but
# the system at the time of writing this had available_governors and available_frequences
cat available_governors
cat available_frequencies
# depending on the governors, you may want to set it prioritize performance over other things like
# battery. Some systems allow you to do this with something like (although, for the device used at the
# time of writing this did not have an equivalent option):
echo performance > gpu_governor
# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you
# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:
echo 940000 > hint_min_freq
echo 940000 > hint_max_freq
# you can typically verify the GPU is running at that frequency consistently by running something like
# the following a few times over time, which should show the frequency you want to lock the device to:
cat cur_freq
```
1. You may need to re-apply the `hint_min_freq` just before starting the profiling trace and check before and after
that the frequency remained at the value expected. Some systems may adjust the frequency on you, but you
may want to ensure the frequency remains the same through the analysis.
1. The GPU frequency settings should be undone after restarting the device, but after you have done your app profiling,
you can revert the state of the device, such as the OS build image, back to the way you had it
initially, as needed.
1. Build a release build of Filament with the applicable backend(s) enabled
_(+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from
building a release build with no flags)_ _(debug builds for this are useless)_
```shell
# the following command assumes you are in the root filament directory
# and ANDROID_HOME is exported (and possibly also CC and CXX on linux as needed)
#
# NOTE: to build with WebGPU support you need to explicitly include the -W flag
# (it doesn't get compiled in by default), e.g.:
# ./build.sh -W -p android,desktop -i release
#
# Note that you can speed this up a bit (and reduce disk space usage) by limiting the target to just
# the ABI you plan on testing with the -q flag, e.g. -q arm64-v8a. If you do this, you
# will need to update the android/gradle.properties file to specify the ABI(s) you are targeting
# with the com.google.android.filament.abis property.
# Thus, a build command that would target BOTH Vulkan AND WebGPU AND only target the ARM64 ABI would look something
# like:
# ./build.sh -W -q arm64-v8a -p android,desktop -i release
./build.sh -p android,desktop -i release
```
1. Connect your Android device to your computer via a USB cord with USB debugging enabled and configure
the system property to default to the desired backend, e.g.
_(to determine how these numbers map to the backends, see the `enum class Backend`
definition in [filament/filament/backend/include/backend/DriverEnums.h](../../../../filament/backend/include/backend/DriverEnums.h))_:
```shell
# to set the backend to Vulkan:
adb shell setprop debug.filament.backend 2
# to set the backend to WebGPU:
adb shell setprop debug.filament.backend 4
# to view the current property:
adb shell getprop debug.filament.backend
```
1. Build and run a sample, e.g. sample-gltf-viewer, on your Android device
_([Android Studio](https://developer.android.com/studio) recommended)_.
1. Run [AGI](https://developer.android.com/agi) and follow instructions to profile the app/system
with trace capture(s). See https://developer.android.com/agi/start for more details to
get started.
- We typically only run "Capture System Profiler trace" _(not necessarily "Capture Frame Profiler trace")_
- When configuring the trace:
- For both the WebGPU and Vulkan backends configure the profiler for the Vulkan API
_(since WebGPU should be using Vulkan under the hood as well)_
- Running for ~1 seconds should suffice
- Hit the "Configure" button in Trace objects, select "Switch to advanced mode" and add:
```
data_sources {
config {
name: "track_event"
track_event_config {
disabled_categories: "*"
enabled_categories: "filament/filament"
enabled_categories: "filament/jobsystem"
enabled_categories: "filament/gltfio"
}
}
}
```
- One you open the trace, zoom into a series of frames to get a sense of generally how long they typically take
_(use `W`, `S`, `A` and `D` keys and mouse wheel for navigation)_ and find a representative one.
We are most interested in the performance of the
`FEngine::loop` thread, how long it takes, overlap in activities/processes/commands, reduction in queue submissions,
etc. Similarly, we can view GPU timeline as it relates to that. We want to see overlapping
shader invocations and non-interrupted fragment shader runs.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redirecting...</title>
<meta http-equiv="refresh" content="0; url=./dup/intro.html">
</head>
<body>
</body>
</html>
+4 -17
View File
@@ -258,8 +258,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
include/backend/platforms/WebGPUPlatform.h
src/webgpu/platform/WebGPUPlatform.cpp
src/webgpu/SpdMipmapGenerator/SpdMipmapGenerator.cpp
src/webgpu/utils/AsyncTaskCounter.cpp
src/webgpu/utils/AsyncTaskCounter.h
src/webgpu/utils/StringPlaceholderTemplateProcessor.cpp
src/webgpu/utils/StringPlaceholderTemplateProcessor.h
src/webgpu/WebGPUBlitter.cpp
@@ -414,7 +412,6 @@ endif()
if (APPLE AND NOT IOS)
target_link_libraries(${TARGET} PRIVATE "-framework Cocoa")
target_link_libraries(${TARGET} PRIVATE "-framework QuartzCore")
endif()
target_link_libraries(${TARGET} PUBLIC math)
@@ -494,6 +491,9 @@ else()
-Wover-aligned -Wreorder-init-list
-Werror
)
if (CMAKE_CXX_STANDARD EQUAL 20)
list(APPEND FILAMENT_WARNINGS -Wno-deprecated-this-capture)
endif()
endif()
if (APPLE)
@@ -527,7 +527,7 @@ target_link_libraries(${TARGET} PRIVATE
if (LINUX AND FILAMENT_SUPPORTS_WEBGPU)
# Unclear why this needs to be explicit while other linux libs do not, but it is necessary for
# WebGPU to build on linux.
target_link_libraries(${TARGET} PRIVATE -lxcb -lX11)
target_link_libraries(${TARGET} PRIVATE -lxcb)
endif()
# ==================================================================================================
@@ -576,11 +576,6 @@ if (APPLE OR LINUX)
test/test_CommandBufferQueue.cpp
test/test_Template.cpp
)
if (FILAMENT_SUPPORTS_WEBGPU)
list(APPEND BACKEND_TEST_SRC
test/test_WebGPUAsyncTaskCounter.cpp
test/test_WebGPUComposeSwizzle.cpp)
endif()
if (APPLE)
# Metal-specific tests
list(APPEND BACKEND_TEST_SRC
@@ -598,7 +593,6 @@ if (APPLE OR LINUX)
spirv-cross-glsl)
# Create input/output directories for test result images.
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/images/actual_images)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/images/diff_images)
file(COPY test/expected_images DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/images)
endif()
@@ -628,10 +622,6 @@ if (APPLE AND NOT IOS)
target_link_libraries(backend_test PRIVATE image imageio)
list(APPEND BACKEND_TEST_DEPS image)
endif()
if (FILAMENT_SUPPORTS_WEBGPU)
target_link_libraries(backend_test PRIVATE webgpu_dawn dawncpp_headers)
list(APPEND BACKEND_TEST_DEPS webgpu_dawn dawncpp_headers)
endif()
set(BACKEND_TEST_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libbackendtest_combined.a")
combine_static_libs(backend_test "${BACKEND_TEST_COMBINED_OUTPUT}" "${BACKEND_TEST_DEPS}")
@@ -663,9 +653,6 @@ if (LINUX)
add_executable(backend_test_linux test/linux_runner.cpp ${BACKEND_TEST_SRC})
target_link_libraries(backend_test_linux PRIVATE ${BACKEND_TEST_LIBS})
set_target_properties(backend_test_linux PROPERTIES FOLDER Tests)
if (FILAMENT_SUPPORTS_WEBGPU)
target_link_libraries(backend_test_linux PRIVATE webgpu_dawn dawncpp_headers)
endif()
endif()
# ==================================================================================================
@@ -629,18 +629,6 @@ enum class PrimitiveType : uint8_t {
TRIANGLE_STRIP = 5 //!< triangle strip
};
[[nodiscard]] constexpr bool isStripPrimitiveType(const PrimitiveType type) {
switch (type) {
case PrimitiveType::POINTS:
case PrimitiveType::LINES:
case PrimitiveType::TRIANGLES:
return false;
case PrimitiveType::LINE_STRIP:
case PrimitiveType::TRIANGLE_STRIP:
return true;
}
}
/**
* Supported uniform types
*/
+1 -1
View File
@@ -156,7 +156,7 @@ public:
* Set to `true` to forcibly disable amortized shader compilation in the backend.
* Currently only honored by the GL backend.
*/
bool disableAmortizedShaderCompile = true;
bool disableAmortizedShaderCompile = false;
/**
* Disable backend handles use-after-free checks.
@@ -27,12 +27,12 @@ namespace filament::backend {
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
* a SwapChain.
*
* Typically, Filament's backend is responsible for scheduling a frame's presentation. However,
* there are certain cases where the application might want to control when a frame is scheduled for
* Typically, Filament's backend is responsible scheduling a frame's presentation. However, there
* are certain cases where the application might want to control when a frame is scheduled for
* presentation.
*
* For example, on iOS, UIKit elements can be synchronized to 3D content by scheduling a present
* within a CATransaction:
* within a CATransation:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* void myFrameScheduledCallback(PresentCallable presentCallable, void* user) {
@@ -55,13 +55,12 @@ namespace filament::backend {
* }
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* @remark The PresentCallable mechanism for user-controlled presentation is only supported by
* Filament's Metal backend. On other backends, the FrameScheduledCallback is still invoked, but the
* PresentCallable passed to it is a no-op and calling it has no effect.
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
* backends ignore the callback (which will never be called) and proceed normally.
*
* When using the Metal backend, applications *must* call each PresentCallable they receive. Each
* PresentCallable represents a frame that is waiting to be presented, and failing to call it
* will result in a memory leak. To "cancel" the presentation of a frame, pass false to the
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
* PresentCallable, which will cancel the presentation of the frame and release associated memory.
*
* @see Renderer, SwapChain::setFrameScheduledCallback
@@ -70,7 +69,6 @@ class UTILS_PUBLIC PresentCallable {
public:
using PresentFn = void(*)(bool presentFrame, void* user);
static void noopPresent(bool, void*) {}
PresentCallable(PresentFn fn, void* user) noexcept;
~PresentCallable() noexcept = default;
@@ -19,16 +19,6 @@
#include <backend/Platform.h>
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_X11)
// Resolve the conflicts between webgpu_cpp.h and X11 defines
#undef Always
#undef Success
#undef None
#undef True
#undef False
#undef Status
#undef Bool
#endif
#include <webgpu/webgpu_cpp.h>
#include <cstdint>
@@ -40,7 +30,7 @@ namespace filament::backend {
* A Platform interface, handling the environment-specific concerns, e.g. OS, for creating a WebGPU
* driver (backend).
*/
class WebGPUPlatform : public Platform {
class WebGPUPlatform final : public Platform {
public:
WebGPUPlatform();
~WebGPUPlatform() override = default;
@@ -62,14 +52,6 @@ public:
// either returns a valid device or panics
[[nodiscard]] wgpu::Device requestDevice(wgpu::Adapter const& adapter);
struct Configuration {
wgpu::BackendType forceBackendType = wgpu::BackendType::Undefined;
};
[[nodiscard]] virtual Configuration getConfiguration() const noexcept {
return {};
}
protected:
[[nodiscard]] Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
@@ -107,10 +107,6 @@
#define DECL_DRIVER_API_R_N(R, N, ...) \
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
#define DECL_DRIVER_API_TAGGED_R_N(R, N, ...) \
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString, tag = {}), \
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString, tag))
#define DECL_DRIVER_API_SYNCHRONOUS_N(R, N, ...) \
DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
@@ -169,31 +165,35 @@ DECL_DRIVER_API_0(finish)
// reset state tracking, if the driver does any state tracking (e.g. GL)
DECL_DRIVER_API_0(resetState)
DECL_DRIVER_API_N(setDebugTag,
backend::HandleBase::HandleId, handleId,
utils::CString, tag)
/*
* Creating driver objects
* -----------------------
*/
DECL_DRIVER_API_TAGGED_R_N(backend::VertexBufferInfoHandle, createVertexBufferInfo,
DECL_DRIVER_API_R_N(backend::VertexBufferInfoHandle, createVertexBufferInfo,
uint8_t, bufferCount,
uint8_t, attributeCount,
backend::AttributeArray, attributes)
DECL_DRIVER_API_TAGGED_R_N(backend::VertexBufferHandle, createVertexBuffer,
DECL_DRIVER_API_R_N(backend::VertexBufferHandle, createVertexBuffer,
uint32_t, vertexCount,
backend::VertexBufferInfoHandle, vbih)
DECL_DRIVER_API_TAGGED_R_N(backend::IndexBufferHandle, createIndexBuffer,
DECL_DRIVER_API_R_N(backend::IndexBufferHandle, createIndexBuffer,
backend::ElementType, elementType,
uint32_t, indexCount,
backend::BufferUsage, usage)
DECL_DRIVER_API_TAGGED_R_N(backend::BufferObjectHandle, createBufferObject,
DECL_DRIVER_API_R_N(backend::BufferObjectHandle, createBufferObject,
uint32_t, byteCount,
backend::BufferObjectBinding, bindingType,
backend::BufferUsage, usage)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTexture,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTexture,
backend::SamplerType, target,
uint8_t, levels,
backend::TextureFormat, format,
@@ -203,19 +203,19 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTexture,
uint32_t, depth,
backend::TextureUsage, usage)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureView,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureView,
backend::TextureHandle, texture,
uint8_t, baseLevel,
uint8_t, levelCount)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureViewSwizzle,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
backend::TextureHandle, texture,
backend::TextureSwizzle, r,
backend::TextureSwizzle, g,
backend::TextureSwizzle, b,
backend::TextureSwizzle, a)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage2,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage2,
backend::SamplerType, target,
backend::TextureFormat, format,
uint32_t, width,
@@ -223,7 +223,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage2,
backend::TextureUsage, usage,
backend::Platform::ExternalImageHandleRef, image)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
backend::SamplerType, target,
backend::TextureFormat, format,
uint32_t, width,
@@ -231,7 +231,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage,
backend::TextureUsage, usage,
void*, image)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImagePlane,
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImagePlane,
backend::TextureFormat, format,
uint32_t, width,
uint32_t, height,
@@ -239,7 +239,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImagePla
void*, image,
uint32_t, plane)
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, importTexture,
DECL_DRIVER_API_R_N(backend::TextureHandle, importTexture,
intptr_t, id,
backend::SamplerType, target,
uint8_t, levels,
@@ -250,17 +250,17 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, importTexture,
uint32_t, depth,
backend::TextureUsage, usage)
DECL_DRIVER_API_TAGGED_R_N(backend::RenderPrimitiveHandle, createRenderPrimitive,
DECL_DRIVER_API_R_N(backend::RenderPrimitiveHandle, createRenderPrimitive,
backend::VertexBufferHandle, vbh,
backend::IndexBufferHandle, ibh,
backend::PrimitiveType, pt)
DECL_DRIVER_API_TAGGED_R_N(backend::ProgramHandle, createProgram,
DECL_DRIVER_API_R_N(backend::ProgramHandle, createProgram,
backend::Program&&, program)
DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createDefaultRenderTarget)
DECL_DRIVER_API_R_0(backend::RenderTargetHandle, createDefaultRenderTarget)
DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createRenderTarget,
DECL_DRIVER_API_R_N(backend::RenderTargetHandle, createRenderTarget,
backend::TargetBufferFlags, targetBufferFlags,
uint32_t, width,
uint32_t, height,
@@ -270,23 +270,23 @@ DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createRenderTarget,
backend::TargetBufferInfo, depth,
backend::TargetBufferInfo, stencil)
DECL_DRIVER_API_TAGGED_R_N(backend::FenceHandle, createFence)
DECL_DRIVER_API_R_0(backend::FenceHandle, createFence)
DECL_DRIVER_API_TAGGED_R_N(backend::SwapChainHandle, createSwapChain,
DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChain,
void*, nativeWindow,
uint64_t, flags)
DECL_DRIVER_API_TAGGED_R_N(backend::SwapChainHandle, createSwapChainHeadless,
DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChainHeadless,
uint32_t, width,
uint32_t, height,
uint64_t, flags)
DECL_DRIVER_API_TAGGED_R_N(backend::TimerQueryHandle, createTimerQuery)
DECL_DRIVER_API_R_0(backend::TimerQueryHandle, createTimerQuery)
DECL_DRIVER_API_TAGGED_R_N(backend::DescriptorSetLayoutHandle, createDescriptorSetLayout,
DECL_DRIVER_API_R_N(backend::DescriptorSetLayoutHandle, createDescriptorSetLayout,
backend::DescriptorSetLayout&&, info)
DECL_DRIVER_API_TAGGED_R_N(backend::DescriptorSetHandle, createDescriptorSet,
DECL_DRIVER_API_R_N(backend::DescriptorSetHandle, createDescriptorSet,
backend::DescriptorSetLayoutHandle, dslh)
DECL_DRIVER_API_N(updateDescriptorSetBuffer,
@@ -337,8 +337,8 @@ DECL_DRIVER_API_N(destroyDescriptorSet, backend::DescriptorSetHandle, ds
*/
DECL_DRIVER_API_SYNCHRONOUS_0(void, terminate)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream, utils::CString, tag)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamAcquired, utils::CString, tag)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream)
DECL_DRIVER_API_SYNCHRONOUS_0(backend::StreamHandle, createStreamAcquired)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, const math::mat3f&, transform, backend::CallbackHandler*, handler, backend::StreamCallback, cb, void*, userData)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setStreamDimensions, backend::StreamHandle, stream, uint32_t, width, uint32_t, height)
DECL_DRIVER_API_SYNCHRONOUS_N(int64_t, getStreamTimestamp, backend::StreamHandle, stream)
@@ -249,9 +249,8 @@ public:
}
void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
if (tag.empty()) {
return;
}
// TODO: for now, only pool handles check for use-after-free, so we only keep tags for
// those
uint32_t key = id;
if (UTILS_LIKELY(isPoolHandle(id))) {
// Truncate the age to get the debug tag
-24
View File
@@ -38,11 +38,6 @@
#include <stdlib.h>
#include <string.h>
#if defined(WIN32)
# include <windows.h> // for VirtualAlloc, VirtualProtect, VirtualFree
# include <utils/unwindows.h>
#endif
using namespace utils;
namespace filament::backend {
@@ -139,21 +134,6 @@ void* CircularBuffer::alloc(size_t size) {
mprotect(guard, BLOCK_SIZE, PROT_NONE);
}
return data;
#elif defined(WIN32)
size_t const BLOCK_SIZE = getBlockSize();
// On Windows, use VirtualAlloc instead of malloc to allocate virtual memory.
// This allows us to set page protection by VirtualProtect.
void* data = VirtualAlloc(nullptr, size * 2 + BLOCK_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
FILAMENT_CHECK_POSTCONDITION(data != nullptr)
<< "couldn't allocate " << (size * 2 / 1024)
<< " KiB of virtual address space for the command buffer";
// guard page at the end
void* guard = (void*)(uintptr_t(data) + size * 2);
DWORD oldProtect = 0;
BOOL ok = VirtualProtect(guard, BLOCK_SIZE, PAGE_NOACCESS, &oldProtect);
FILAMENT_CHECK_POSTCONDITION(ok) << "VirtualProtect failed to set guard page";
return data;
#else
return ::malloc(2 * size);
#endif
@@ -170,10 +150,6 @@ void CircularBuffer::dealloc() noexcept {
mAshmemFd = -1;
}
}
#elif defined(WIN32)
if (mData) {
VirtualFree(mData, 0, MEM_RELEASE);
}
#else
::free(mData);
#endif
+10 -12
View File
@@ -57,7 +57,7 @@ static void printParameterPack(io::ostream& out, const FIRST& first, const REMAI
printParameterPack(out, rest...);
}
static UTILS_NOINLINE UTILS_UNUSED std::string_view extractMethodName(std::string_view command) noexcept {
static UTILS_NOINLINE UTILS_UNUSED std::string extractMethodName(std::string& command) noexcept {
constexpr const char startPattern[] = "::Command<&filament::backend::Driver::";
auto pos = command.rfind(startPattern);
auto end = command.rfind('(');
@@ -97,13 +97,11 @@ void CommandStream::execute(void* buffer) {
}
}
Driver& UTILS_RESTRICT driver = mDriver;
CommandBase* UTILS_RESTRICT base = static_cast<CommandBase*>(buffer);
mDriver.execute([&driver, base] {
auto& d = driver;
auto p = base;
while (UTILS_LIKELY(p)) {
p = p->execute(d);
mDriver.execute([this, buffer]() {
Driver& UTILS_RESTRICT driver = mDriver;
CommandBase* UTILS_RESTRICT base = static_cast<CommandBase*>(buffer);
while (UTILS_LIKELY(base)) {
base = base->execute(driver);
}
});
@@ -133,9 +131,9 @@ template<std::size_t... I>
void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log(std::index_sequence<I...>) noexcept {
#if DEBUG_COMMAND_STREAM
static_assert(UTILS_HAS_RTTI, "DEBUG_COMMAND_STREAM can only be used with RTTI");
CString command = CallStack::demangleTypeName(typeid(Command).name());
DLOG(INFO) << extractMethodName({command.data(), command.size()}) << " : size=" << sizeof(Command);
io::sstream parameterPack;
std::string command = utils::CallStack::demangleTypeName(typeid(Command).name()).c_str();
DLOG(INFO) << extractMethodName(command) << " : size=" << sizeof(Command);
utils::io::sstream parameterPack;
printParameterPack(parameterPack, std::get<I>(mArgs)...);
DLOG(INFO) << "\t" << parameterPack.c_str();
#endif
@@ -164,7 +162,7 @@ void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log() noexcept {
// ------------------------------------------------------------------------------------------------
void CustomCommand::execute(Driver&, CommandBase* base, intptr_t* next) {
*next = align(sizeof(CustomCommand));
*next = CustomCommand::align(sizeof(CustomCommand));
static_cast<CustomCommand*>(base)->mCommand();
static_cast<CustomCommand*>(base)->~CustomCommand();
}
+6 -7
View File
@@ -21,8 +21,7 @@
#include <utils/ostream.h>
#ifndef NDEBUG
# include <utils/CString.h>
# include <string_view>
# include <string>
#endif
#include <stddef.h>
@@ -37,11 +36,11 @@ static char const * const kOurNamespace = "filament::backend::";
// removes all occurrences of "what" from "str"
UTILS_NOINLINE
static CString& removeAll(CString& str, const std::string_view what) noexcept {
static std::string& removeAll(std::string& str, const std::string& what) noexcept {
if (!what.empty()) {
const CString empty;
const std::string empty;
size_t pos = 0;
while ((pos = std::string_view{ str.data(), str.size() }.find(what, pos)) != std::string_view::npos) {
while ((pos = str.find(what, pos)) != std::string::npos) {
str.replace(pos, what.length(), empty);
}
}
@@ -50,13 +49,13 @@ static CString& removeAll(CString& str, const std::string_view what) noexcept {
template <typename T>
UTILS_NOINLINE
static io::ostream& logHandle(io::ostream& out, CString& typeName, T id) noexcept {
static io::ostream& logHandle(io::ostream& out, std::string& typeName, T id) noexcept {
return out << removeAll(typeName, kOurNamespace) << " @ " << id;
}
template <typename T>
io::ostream& operator<<(io::ostream& out, const Handle<T>& h) noexcept {
CString s{ CallStack::typeName<Handle<T>>() };
std::string s(CallStack::typeName<Handle<T>>().c_str());
return logHandle(out, s, h.getId());
}
+50 -55
View File
@@ -418,40 +418,49 @@ void MetalDriver::finish(int) {
}
void MetalDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
uint8_t attributeCount, AttributeArray attributes, utils::CString tag) {
uint8_t attributeCount, AttributeArray attributes) {
construct_handle<MetalVertexBufferInfo>(vbih, *mContext,
bufferCount, attributeCount, attributes);
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
}
void MetalDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh,
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih, utils::CString tag) {
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih) {
MetalVertexBufferInfo const* const vbi = handle_cast<const MetalVertexBufferInfo>(vbih);
construct_handle<MetalVertexBuffer>(vbh, *mContext, vertexCount, vbi->bufferCount, vbih);
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
// No actual GPU memory is allocated here, so no need to check for allocation success.
}
void MetalDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
uint32_t indexCount, BufferUsage usage, utils::CString tag) {
uint32_t indexCount, BufferUsage usage) {
auto elementSize = (uint8_t)getElementTypeSize(elementType);
auto* indexBuffer =
construct_handle<MetalIndexBuffer>(ibh, *mContext, usage, elementSize, indexCount);
auto& buffer = indexBuffer->buffer;
FILAMENT_CHECK_POSTCONDITION(buffer.wasAllocationSuccessful())
<< "Could not allocate Metal index buffer of size " << buffer.getSize()
<< ", tag=" << tag.c_str_safe();
mHandleAllocator.associateTagToHandle(ibh.getId(), std::move(tag));
// If the allocation was not successful, postpone the error message until the next tick, to give
// Filament a chance to call setDebugTag on the handle; this way we get a nicer error message.
if (UTILS_UNLIKELY(!buffer.wasAllocationSuccessful())) {
const size_t byteCount = buffer.getSize();
runAtNextTick([byteCount, this, ibh]() {
FILAMENT_CHECK_POSTCONDITION(false)
<< "Could not allocate Metal index buffer of size " << byteCount
<< ", tag=" << mHandleAllocator.getHandleTag(ibh.getId()).c_str_safe();
});
}
}
void MetalDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
BufferObjectBinding bindingType, BufferUsage usage) {
auto* bufferObject =
construct_handle<MetalBufferObject>(boh, *mContext, bindingType, usage, byteCount);
FILAMENT_CHECK_POSTCONDITION(bufferObject->getBuffer()->wasAllocationSuccessful())
<< "Could not allocate Metal buffer of size " << byteCount
<< ", tag=" << tag.c_str_safe();
mHandleAllocator.associateTagToHandle(boh.getId(), std::move(tag));
// If the allocation was not successful, postpone the error message until the next tick, to give
// Filament a chance to call setDebugTag on the handle; this way we get a nicer error message.
if (UTILS_UNLIKELY(!bufferObject->getBuffer()->wasAllocationSuccessful())) {
runAtNextTick([byteCount, this, boh]() {
FILAMENT_CHECK_POSTCONDITION(false)
<< "Could not allocate Metal buffer of size " << byteCount
<< ", tag=" << mHandleAllocator.getHandleTag(boh.getId()).c_str_safe();
});
}
}
// fixme: TextureUsage is a bitfield
@@ -486,7 +495,7 @@ inline const char* stringify(SamplerType samplerType) {
void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
uint32_t depth, TextureUsage usage, utils::CString tag) {
uint32_t depth, TextureUsage usage) {
// Clamp sample count to what the device supports.
auto& sc = mContext->sampleCountLookup;
samples = sc[std::min(MAX_SAMPLE_COUNT, samples)];
@@ -498,60 +507,55 @@ void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8
"createTextureR(th = %d, target = %s, levels = %d, format = ?, samples = %d, width = "
"%d, height = %d, depth = %d, usage = %s)\n",
th.getId(), stringify(target), levels, samples, width, height, depth, stringify(usage));
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
void MetalDriver::createTextureViewR(
Handle<HwTexture> th, Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
MetalTexture const* src = handle_cast<MetalTexture>(srch);
mContext->textures.insert(
construct_handle<MetalTexture>(th, *mContext, src, baseLevel, levelCount));
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
backend::TextureSwizzle a, utils::CString tag) {
backend::TextureSwizzle a) {
MetalTexture const* src = handle_cast<MetalTexture>(srch);
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
backend::SamplerType target,
backend::TextureFormat format,
uint32_t width, uint32_t height, backend::TextureUsage usage,
Platform::ExternalImageHandleRef image, utils::CString tag) {
Platform::ExternalImageHandleRef image) {
// FIXME: implement createTextureExternalImage2R
}
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* image, utils::CString tag) {
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
backend::SamplerType target,
backend::TextureFormat format,
uint32_t width, uint32_t height, backend::TextureUsage usage, void* image) {
mContext->textures.insert(construct_handle<MetalTexture>(
th, *mContext, format, width, height, usage, (CVPixelBufferRef)image));
// This release matches the retain call in setupExternalImage. The MetalTexture will have
// retained the buffer by now.
CVPixelBufferRelease((CVPixelBufferRef)image);
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* image, uint32_t plane, utils::CString tag) {
void* image, uint32_t plane) {
mContext->textures.insert(construct_handle<MetalTexture>(
th, *mContext, format, width, height, usage, (CVPixelBufferRef)image, plane));
// This release matches the retain call in setupExternalImage. The MetalTexture will have
// retained the buffer by now.
CVPixelBufferRelease((CVPixelBufferRef)image);
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
uint32_t depth, TextureUsage usage, utils::CString tag) {
uint32_t depth, TextureUsage usage) {
id<MTLTexture> metalTexture = (id<MTLTexture>) CFBridgingRelease((void*) i);
FILAMENT_CHECK_PRECONDITION(metalTexture.width == width)
<< "Imported id<MTLTexture> width (" << metalTexture.width
@@ -568,36 +572,32 @@ void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
<< ") != Filament texture type (" << filamentMetalType << ")";
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext,
target, levels, format, samples, width, height, depth, usage, metalTexture));
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void MetalDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
PrimitiveType pt, utils::CString tag) {
PrimitiveType pt) {
construct_handle<MetalRenderPrimitive>(rph);
MetalDriver::setRenderPrimitiveBuffer(rph, pt, vbh, ibh);
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
}
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program, utils::CString tag) {
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program) {
#if FILAMENT_METAL_DEBUG_LOG
auto handleId = rph.getId();
DEBUG_LOG("createProgramR(rph = %d, program = ", handleId);
DLOG(INFO) << program;
#endif
construct_handle<MetalProgram>(rph, *mContext, std::move(program));
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
}
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString tag) {
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int dummy) {
construct_handle<MetalRenderTarget>(rth, mContext);
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
}
void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
uint8_t samples, uint8_t layerCount, MRT color,
TargetBufferInfo depth, TargetBufferInfo stencil, utils::CString tag) {
TargetBufferInfo depth, TargetBufferInfo stencil) {
FILAMENT_CHECK_PRECONDITION(!isInRenderPass(mContext))
<< "createRenderTarget must be called outside of a render pass.";
// Clamp sample count to what the device supports.
@@ -640,18 +640,14 @@ void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
construct_handle<MetalRenderTarget>(rth, mContext, width, height, samples,
colorAttachments, depthAttachment, stencilAttachment);
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
}
void MetalDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
void MetalDriver::createFenceR(Handle<HwFence> fh, int dummy) {
auto* fence = handle_cast<MetalFence>(fh);
fence->encode();
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
}
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
utils::CString tag) {
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) nativeWindow;
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, pixelBuffer, flags);
@@ -662,18 +658,15 @@ void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
auto* metalLayer = (__bridge CAMetalLayer*) nativeWindow;
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, metalLayer, flags);
}
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
}
void MetalDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
uint32_t width, uint32_t height, uint64_t flags, utils::CString tag) {
uint32_t width, uint32_t height, uint64_t flags) {
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, width, height, flags);
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
}
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
// nothing to do, timer query was constructed in createTimerQueryS
mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag));
}
UTILS_UNUSED
@@ -710,7 +703,7 @@ const char* toString(DescriptorFlags flags) {
}
void MetalDriver::createDescriptorSetLayoutR(
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info, utils::CString tag) {
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info) {
#if FILAMENT_METAL_DEBUG_LOG == 1
const char* labelStr = "";
std::visit([&labelStr](auto&& arg) {
@@ -731,15 +724,13 @@ void MetalDriver::createDescriptorSetLayoutR(
DEBUG_LOG("})\n");
#endif
construct_handle<MetalDescriptorSetLayout>(dslh, std::move(info));
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
}
void MetalDriver::createDescriptorSetR(
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh) {
DEBUG_LOG("createDescriptorSetR(dsh = %d, dslh = %d)\n", dsh.getId(), dslh.getId());
MetalDescriptorSetLayout* layout = handle_cast<MetalDescriptorSetLayout>(dslh);
construct_handle<MetalDescriptorSet>(dsh, layout);
mHandleAllocator.associateTagToHandle(dsh.getId(), std::move(tag));
}
Handle<HwVertexBufferInfo> MetalDriver::createVertexBufferInfoS() noexcept {
@@ -978,11 +969,11 @@ ShaderLanguage MetalDriver::getShaderLanguage() const noexcept {
return ShaderLanguage::MSL;
}
Handle<HwStream> MetalDriver::createStreamNative(void* stream, utils::CString tag) {
Handle<HwStream> MetalDriver::createStreamNative(void* stream) {
return {};
}
Handle<HwStream> MetalDriver::createStreamAcquired(utils::CString tag) {
Handle<HwStream> MetalDriver::createStreamAcquired() {
return {};
}
@@ -2144,6 +2135,10 @@ void MetalDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
void MetalDriver::resetState(int) {
}
void MetalDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
}
void MetalDriver::runAtNextTick(const std::function<void()>& fn) noexcept {
mTickOps.push_back(fn);
}
@@ -118,10 +118,6 @@ MetalSwapChain::MetalSwapChain(
layerDrawableMutex(std::make_shared<std::mutex>()),
type(SwapChainType::CAMETALLAYER) {
FILAMENT_CHECK_PRECONDITION([nativeWindow isKindOfClass:[CAMetalLayer class]])
<< "nativeWindow pointer of class "
<< [NSStringFromClass([nativeWindow class]) UTF8String] << " is not a CAMetalLayer";
if (!(flags & SwapChain::CONFIG_TRANSPARENT) && !nativeWindow.opaque) {
LOG(WARNING) << "Warning: Filament SwapChain has no CONFIG_TRANSPARENT flag, but the "
"CAMetaLayer("
+5 -2
View File
@@ -125,11 +125,11 @@ void NoopDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> tqh) {
void NoopDriver::destroyDescriptorSet(Handle<HwDescriptorSet> tqh) {
}
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream, utils::CString tag) {
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream) {
return {};
}
Handle<HwStream> NoopDriver::createStreamAcquired(utils::CString tag) {
Handle<HwStream> NoopDriver::createStreamAcquired() {
return {};
}
@@ -415,4 +415,7 @@ void NoopDriver::bindDescriptorSet(
backend::DescriptorSetOffsetArray&& offsets) {
}
void NoopDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
}
} // namespace filament
+34 -73
View File
@@ -639,29 +639,24 @@ void OpenGLDriver::createVertexBufferInfoR(
Handle<HwVertexBufferInfo> vbih,
uint8_t bufferCount,
uint8_t attributeCount,
AttributeArray attributes,
utils::CString tag) {
AttributeArray attributes) {
DEBUG_MARKER()
construct<GLVertexBufferInfo>(vbih, bufferCount, attributeCount, attributes);
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
}
void OpenGLDriver::createVertexBufferR(
Handle<HwVertexBuffer> vbh,
uint32_t vertexCount,
Handle<HwVertexBufferInfo> vbih,
utils::CString tag) {
Handle<HwVertexBufferInfo> vbih) {
DEBUG_MARKER()
construct<GLVertexBuffer>(vbh, vertexCount, vbih);
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
}
void OpenGLDriver::createIndexBufferR(
Handle<HwIndexBuffer> ibh,
ElementType elementType,
uint32_t indexCount,
BufferUsage usage,
utils::CString tag) {
BufferUsage usage) {
DEBUG_MARKER()
auto& gl = mContext;
@@ -673,11 +668,10 @@ void OpenGLDriver::createIndexBufferR(
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, nullptr, getBufferUsage(usage));
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(ibh.getId(), std::move(tag));
}
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
uint32_t byteCount, BufferObjectBinding bindingType, BufferUsage usage) {
DEBUG_MARKER()
assert_invariant(byteCount > 0);
@@ -699,12 +693,11 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byte
}
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(boh.getId(), std::move(tag));
}
void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
PrimitiveType pt, utils::CString tag) {
PrimitiveType pt) {
DEBUG_MARKER()
auto& gl = mContext;
@@ -737,10 +730,9 @@ void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
}
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::CString tag) {
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
DEBUG_MARKER()
@@ -768,7 +760,6 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils
construct<OpenGLProgram>(ph, *this, std::move(program));
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(ph.getId(), std::move(tag));
}
UTILS_NOINLINE
@@ -873,7 +864,7 @@ void OpenGLDriver::textureStorage(GLTexture* t,
void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage, utils::CString tag) {
TextureUsage usage) {
DEBUG_MARKER()
GLenum internalFormat = getInternalFormat(format);
@@ -962,11 +953,10 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
}
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
DEBUG_MARKER()
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
@@ -1009,12 +999,10 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
ref->count++;
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a,
utils::CString tag) {
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
DEBUG_MARKER()
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
@@ -1074,12 +1062,11 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
ref->count++;
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
Platform::ExternalImageHandleRef image, utils::CString tag) {
Platform::ExternalImageHandleRef image) {
DEBUG_MARKER()
usage |= TextureUsage::SAMPLEABLE;
@@ -1126,12 +1113,10 @@ void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerTyp
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
}
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image,
utils::CString tag) {
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
DEBUG_MARKER()
usage |= TextureUsage::SAMPLEABLE;
@@ -1177,18 +1162,17 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
}
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
void* image, uint32_t plane, utils::CString tag) {
void* image, uint32_t plane) {
// not relevant for the OpenGL backend
}
void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage, utils::CString tag) {
uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage) {
DEBUG_MARKER()
auto& gl = mContext;
@@ -1241,7 +1225,6 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
}
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
}
void OpenGLDriver::updateVertexArrayObject(GLRenderPrimitive* rp, GLVertexBuffer const* vb) {
@@ -1643,7 +1626,7 @@ void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32
}
void OpenGLDriver::createDefaultRenderTargetR(
Handle<HwRenderTarget> rth, utils::CString tag) {
Handle<HwRenderTarget> rth, int) {
DEBUG_MARKER()
construct<GLRenderTarget>(rth, 0, 0); // FIXME: we don't know the width/height
@@ -1654,7 +1637,6 @@ void OpenGLDriver::createDefaultRenderTargetR(
rt->gl.samples = 1;
// FIXME: these flags should reflect the actual attachments present
rt->targets = TargetBufferFlags::COLOR0 | TargetBufferFlags::DEPTH;
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
}
void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
@@ -1665,8 +1647,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
uint8_t layerCount,
MRT color,
TargetBufferInfo depth,
TargetBufferInfo stencil,
utils::CString tag) {
TargetBufferInfo stencil) {
DEBUG_MARKER()
GLRenderTarget* rt = construct<GLRenderTarget>(rth, width, height);
@@ -1779,10 +1760,9 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
assert_invariant(tmin == tmax);
CHECK_GL_ERROR()
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
}
void OpenGLDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
void OpenGLDriver::createFenceR(Handle<HwFence> fh, int) {
DEBUG_MARKER()
GLFence* f = handle_cast<GLFence*>(fh);
@@ -1804,11 +1784,9 @@ void OpenGLDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
});
}
#endif
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
}
void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
utils::CString tag) {
void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
DEBUG_MARKER()
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
@@ -1825,12 +1803,10 @@ void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
sc->rec709 = ((flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) &&
!mPlatform.isSRGBSwapChainSupported());
}
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
}
void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
uint32_t width, uint32_t height, uint64_t flags, utils::CString tag) {
uint32_t width, uint32_t height, uint64_t flags) {
DEBUG_MARKER()
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
@@ -1848,30 +1824,25 @@ void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
sc->rec709 = (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE &&
!mPlatform.isSRGBSwapChainSupported());
}
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
}
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
DEBUG_MARKER()
GLTimerQuery* tq = handle_cast<GLTimerQuery*>(tqh);
mContext.createTimerQuery(tq);
mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag));
}
void OpenGLDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
DescriptorSetLayout&& info, utils::CString tag) {
DescriptorSetLayout&& info) {
DEBUG_MARKER()
construct<GLDescriptorSetLayout>(dslh, std::move(info));
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
}
void OpenGLDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
Handle<HwDescriptorSetLayout> dslh) {
DEBUG_MARKER()
GLDescriptorSetLayout const* dsl = handle_cast<GLDescriptorSetLayout*>(dslh);
construct<GLDescriptorSet>(dsh, mContext, dslh, dsl);
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
}
// ------------------------------------------------------------------------------------------------
@@ -1977,7 +1948,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
if (UTILS_UNLIKELY(t->hwStream)) {
detachStream(t);
}
if (UTILS_UNLIKELY(t->externalTexture)) {
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
mPlatform.destroyExternalImageTexture(t->externalTexture);
} else {
glDeleteTextures(1, &t->gl.id);
@@ -2117,17 +2088,13 @@ void OpenGLDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
// These are called on the application's thread
// ------------------------------------------------------------------------------------------------
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream, utils::CString tag) {
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream) {
Platform::Stream* stream = mPlatform.createStream(nativeStream);
auto handle = initHandle<GLStream>(stream);
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
return handle;
return initHandle<GLStream>(stream);
}
Handle<HwStream> OpenGLDriver::createStreamAcquired(utils::CString tag) {
auto handle = initHandle<GLStream>();
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
return handle;
Handle<HwStream> OpenGLDriver::createStreamAcquired() {
return initHandle<GLStream>();
}
// Stashes an acquired external image and a release callback. The image is not bound to OpenGL until
@@ -2547,20 +2514,13 @@ size_t OpenGLDriver::getMaxArrayTextureLayers() {
// Swap chains
// ------------------------------------------------------------------------------------------------
void OpenGLDriver::commit(Handle<HwSwapChain> sch) {
DEBUG_MARKER()
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
mPlatform.commit(sc->swapChain);
auto& fs = sc->frameScheduled;
if (fs.callback) {
scheduleCallback(fs.handler, [callback = std::move(fs.callback)]() {
PresentCallable noop = PresentCallable(PresentCallable::noopPresent, nullptr);
callback(noop);
});
}
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
if (UTILS_UNLIKELY(!mFrameCompleteOps.empty())) {
whenGpuCommandsComplete([ops = std::move(mFrameCompleteOps)]() {
@@ -2626,6 +2586,10 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
// Updating driver objects
// ------------------------------------------------------------------------------------------------
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, CString tag) {
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
}
void OpenGLDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh,
uint32_t index, Handle<HwBufferObject> boh) {
DEBUG_MARKER()
@@ -3753,12 +3717,9 @@ void OpenGLDriver::beginFrame(
}
}
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
FrameScheduledCallback&& callback, uint64_t /*flags*/) {
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain>, CallbackHandler*,
FrameScheduledCallback&& /*callback*/, uint64_t /*flags*/) {
DEBUG_MARKER()
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
sc->frameScheduled.handler = handler;
sc->frameScheduled.callback = std::move(callback);
}
void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain>,
@@ -28,7 +28,6 @@
#include "ShaderCompilerService.h"
#include <backend/AcquiredImage.h>
#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/PipelineState.h>
@@ -100,10 +99,6 @@ public:
struct GLSwapChain : public HwSwapChain {
using HwSwapChain::HwSwapChain;
bool rec709 = false;
struct {
CallbackHandler* handler = nullptr;
FrameScheduledCallback callback;
} frameScheduled;
};
struct GLVertexBufferInfo : public HwVertexBufferInfo {
@@ -46,6 +46,7 @@
#include <cctype>
#include <mutex>
#include <memory>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
@@ -66,9 +67,9 @@ constexpr uint32_t MAX_NUM_SYNCHRONOUS_PROGRAMS_PER_FRAME = 1;
// ------------------------------------------------------------------------------------------------
static CString to_string(bool const b) { return CString{ b ? "true" : "false" }; }
static CString to_string(int const i) { return utils::to_string(i); }
static CString to_string(float const f) { return "float(" + utils::to_string(f) + ")"; }
static std::string to_string(bool const b) { return b ? "true" : "false"; }
static std::string to_string(int const i) { return std::to_string(i); }
static std::string to_string(float const f) { return "float(" + std::to_string(f) + ")"; }
static void logCompilationError(ShaderStage shaderType, const char* name, GLuint shaderId,
Program::ShaderBlob const& sourceCode) noexcept;
@@ -695,14 +696,14 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
bool multiview, program_token_t const& token) noexcept {
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
auto const appendSpecConstantString = +[](CString& s, Program::SpecializationConstant const& sc) {
s += "#define SPIRV_CROSS_CONSTANT_ID_" + utils::to_string(sc.id) + ' ';
auto const appendSpecConstantString = +[](std::string& s, Program::SpecializationConstant const& sc) {
s += "#define SPIRV_CROSS_CONSTANT_ID_" + std::to_string(sc.id) + ' ';
s += std::visit([](auto&& arg) { return to_string(arg); }, sc.value);
s += '\n';
return s;
};
CString specializationConstantString;
std::string specializationConstantString;
int32_t numViews = 2;
for (auto const& sc: specializationConstants) {
appendSpecConstantString(specializationConstantString, sc);
@@ -765,10 +766,8 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
}
std::array<std::string_view, 5> sources = {
version, prolog,
{ specializationConstantString.data(), specializationConstantString.size() },
packingFunctions,
{ body.data(), body.size() - 1 } // null-terminated
version, prolog, specializationConstantString, packingFunctions,
{ body.data(), body.size() - 1 }// null-terminated
};
// Some of the sources may be zero-length. Remove them as to avoid passing lengths of
@@ -967,18 +966,16 @@ UTILS_NOINLINE
sourceCode.size() };
size_t lc = 1;
size_t start = 0;
CString line;
std::string line;
while (true) {
size_t const end = shader.find('\n', start);
if (end == std::string_view::npos) {
auto sv = shader.substr(start);
line = { sv.data(), sv.size() };
if (end == std::string::npos) {
line = shader.substr(start);
} else {
auto sv = shader.substr(start, end - start);
line = { sv.data(), sv.size() };
line = shader.substr(start, end - start);
}
LOG(ERROR) << lc++ << ": " << line.c_str();
if (end == std::string_view::npos) {
if (end == std::string::npos) {
break;
}
start = end + 1;
+12 -18
View File
@@ -24,7 +24,6 @@
#include "VulkanConstants.h"
#include "VulkanContext.h"
#include <utils/CString.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <utils/debug.h>
@@ -58,26 +57,26 @@ VkCommandBuffer createCommandBuffer(VkDevice device, VkCommandPool pool) {
} // anonymous namespace
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
void VulkanGroupMarkers::push(CString const& marker, Timestamp start) noexcept {
void VulkanGroupMarkers::push(std::string const& marker, Timestamp start) noexcept {
mMarkers.push_back({marker,
start.time_since_epoch().count() > 0.0
? start
: std::chrono::high_resolution_clock::now()});
}
std::pair<CString, Timestamp> VulkanGroupMarkers::pop() noexcept {
std::pair<std::string, Timestamp> VulkanGroupMarkers::pop() noexcept {
auto ret = mMarkers.back();
mMarkers.pop_back();
return ret;
}
std::pair<CString, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
std::pair<std::string, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
auto ret = mMarkers.front();
mMarkers.pop_front();
return ret;
}
std::pair<CString, Timestamp> const& VulkanGroupMarkers::top() const {
std::pair<std::string, Timestamp> const& VulkanGroupMarkers::top() const {
assert_invariant(!empty());
return mMarkers.back();
}
@@ -212,9 +211,7 @@ VkSemaphore VulkanCommandBuffer::submit() {
FVK_LOGI << "Submitting cmdbuffer=" << mBuffer
<< " wait=(";
for (size_t s = 0, count = mWaitSemaphores.size(); s < count; ++s) {
FVK_LOGI << "\tsemaphore=" << mWaitSemaphores[s] << "|stage="
<< mWaitSemaphoreStages[s]
<< (s < mWaitSemaphores.size() - 1 ? "\n" : "");
FVK_LOGI << mWaitSemaphores[s] << " ";
}
FVK_LOGI << ") "
<< " signal=" << mSubmission
@@ -354,7 +351,7 @@ void CommandBufferPool::waitFor(VkSemaphore previousAction, VkPipelineStageFlags
}
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
CString CommandBufferPool::topMarker() const {
std::string CommandBufferPool::topMarker() const {
if (!mGroupMarkers || mGroupMarkers->empty()) {
return "";
}
@@ -365,11 +362,11 @@ void CommandBufferPool::pushMarker(char const* marker, VulkanGroupMarkers::Times
if (!mGroupMarkers) {
mGroupMarkers = std::make_unique<VulkanGroupMarkers>();
}
mGroupMarkers->push(CString{ marker }, timestamp);
mGroupMarkers->push(marker, timestamp);
getRecording().pushMarker(marker);
}
std::pair<CString, VulkanGroupMarkers::Timestamp> CommandBufferPool::popMarker() {
std::pair<std::string, VulkanGroupMarkers::Timestamp> CommandBufferPool::popMarker() {
assert_invariant(mGroupMarkers && !mGroupMarkers->empty());
auto ret = mGroupMarkers->pop();
@@ -437,13 +434,10 @@ bool VulkanCommands::flush() {
}
if (lastSubmit != VK_NULL_HANDLE) {
// Note that the stage we're waiting on is the fragment shader stage. This assumes
// that the subsequent command buffer will only depend on
// 1) fragment output of the previous command buffer
// 2) reading/writing of buffers (i.e. UBO) of the previous command buffer
// Restricting the wait stages will allow for vertex work to proceed (more overlapping
// that the subsequent command buffer will only dependent on the fragment output of the
// previous buffer, allowing for vertex work to proceed (more overlapping
// vertex/fragment work).
pool->waitFor(lastSubmit,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT);
pool->waitFor(lastSubmit, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
lastSubmit = VK_NULL_HANDLE;
}
dependency = pool->flush();
@@ -529,7 +523,7 @@ void VulkanCommands::insertEventMarker(char const* str, uint32_t len) {
}
}
CString VulkanCommands::getTopGroupMarker() const {
std::string VulkanCommands::getTopGroupMarker() const {
if (mProtectedPool) {
return mProtectedPool->topMarker();
}
+9 -9
View File
@@ -28,7 +28,6 @@
#include "vulkan/utils/StaticVector.h"
#include <utils/Condition.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Mutex.h>
@@ -36,6 +35,7 @@
#include <chrono>
#include <list>
#include <string>
#include <utility>
namespace filament::backend {
@@ -47,14 +47,14 @@ class VulkanGroupMarkers {
public:
using Timestamp = std::chrono::time_point<std::chrono::high_resolution_clock>;
void push(utils::CString const& marker, Timestamp start = {}) noexcept;
std::pair<utils::CString, Timestamp> pop() noexcept;
std::pair<utils::CString, Timestamp> pop_bottom() noexcept;
std::pair<utils::CString, Timestamp> const& top() const;
void push(std::string const& marker, Timestamp start = {}) noexcept;
std::pair<std::string, Timestamp> pop() noexcept;
std::pair<std::string, Timestamp> pop_bottom() noexcept;
std::pair<std::string, Timestamp> const& top() const;
bool empty() const noexcept;
private:
std::list<std::pair<utils::CString, Timestamp>> mMarkers;
std::list<std::pair<std::string, Timestamp>> mMarkers;
};
#endif // FVK_DEBUG_GROUP_MARKERS
@@ -148,9 +148,9 @@ struct CommandBufferPool {
void waitFor(VkSemaphore previousAction, VkPipelineStageFlags waitStage);
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
utils::CString topMarker() const;
std::string topMarker() const;
void pushMarker(char const* marker, VulkanGroupMarkers::Timestamp timestamp);
std::pair<utils::CString, VulkanGroupMarkers::Timestamp> popMarker();
std::pair<std::string, VulkanGroupMarkers::Timestamp> popMarker();
void insertEvent(char const* marker);
#endif
@@ -249,7 +249,7 @@ public:
void pushGroupMarker(char const* str, VulkanGroupMarkers::Timestamp timestamp = {});
void popGroupMarker();
void insertEventMarker(char const* string, uint32_t len);
utils::CString getTopGroupMarker() const;
std::string getTopGroupMarker() const;
#endif
private:
+35 -68
View File
@@ -416,8 +416,6 @@ void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
void VulkanDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
FrameScheduledCallback&& callback, uint64_t flags) {
auto swapChain = resource_ptr<VulkanSwapChain>::cast(&mResourceManager, sch);
swapChain->setFrameScheduledCallback(handler, std::move(callback));
}
void VulkanDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
@@ -454,7 +452,7 @@ void VulkanDriver::updateDescriptorSetTexture(
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
if (UTILS_UNLIKELY(mExternalImageManager.isExternallySampledTexture(texture))) {
if (mExternalImageManager.isExternallySampledTexture(texture)) {
mExternalImageManager.bindExternallySampledTexture(set, binding, texture, params);
mAppState.hasBoundExternalImages = true;
} else {
@@ -483,13 +481,12 @@ void VulkanDriver::finish(int dummy) {
void VulkanDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
PrimitiveType pt, utils::CString tag) {
PrimitiveType pt) {
FVK_SYSTRACE_SCOPE();
auto vb = resource_ptr<VulkanVertexBuffer>::cast(&mResourceManager, vbh);
auto ib = resource_ptr<VulkanIndexBuffer>::cast(&mResourceManager, ibh);
auto ptr = resource_ptr<VulkanRenderPrimitive>::make(&mResourceManager, rph, pt, vb, ib);
ptr.inc();
mResourceManager.associateHandle(rph.getId(), std::move(tag));
}
void VulkanDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
@@ -502,12 +499,11 @@ void VulkanDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
}
void VulkanDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
uint8_t attributeCount, AttributeArray attributes, utils::CString tag) {
uint8_t attributeCount, AttributeArray attributes) {
FVK_SYSTRACE_SCOPE();
auto vbi = resource_ptr<VulkanVertexBufferInfo>::make(&mResourceManager, vbih, bufferCount,
attributeCount, attributes);
vbi.inc();
mResourceManager.associateHandle(vbih.getId(), std::move(tag));
}
void VulkanDriver::destroyVertexBufferInfo(Handle<HwVertexBufferInfo> vbih) {
@@ -520,13 +516,12 @@ void VulkanDriver::destroyVertexBufferInfo(Handle<HwVertexBufferInfo> vbih) {
}
void VulkanDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh, uint32_t vertexCount,
Handle<HwVertexBufferInfo> vbih, utils::CString tag) {
Handle<HwVertexBufferInfo> vbih) {
FVK_SYSTRACE_SCOPE();
auto vbi = resource_ptr<VulkanVertexBufferInfo>::cast(&mResourceManager, vbih);
auto vb = resource_ptr<VulkanVertexBuffer>::make(&mResourceManager, vbh, mContext, mStagePool,
vertexCount, vbi);
vb.inc();
mResourceManager.associateHandle(vbh.getId(), std::move(tag));
}
void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
@@ -539,13 +534,12 @@ void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
}
void VulkanDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
uint32_t indexCount, BufferUsage usage, utils::CString tag) {
uint32_t indexCount, BufferUsage usage) {
FVK_SYSTRACE_SCOPE();
auto elementSize = (uint8_t) getElementTypeSize(elementType);
auto ib = resource_ptr<VulkanIndexBuffer>::make(&mResourceManager, ibh, mContext, mAllocator,
mStagePool, mBufferCache, elementSize, indexCount);
ib.inc();
mResourceManager.associateHandle(ibh.getId(), std::move(tag));
}
void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
@@ -558,12 +552,11 @@ void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
}
void VulkanDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
BufferObjectBinding bindingType, BufferUsage usage) {
FVK_SYSTRACE_SCOPE();
auto bo = resource_ptr<VulkanBufferObject>::make(&mResourceManager, boh, mContext, mAllocator,
mStagePool, mBufferCache, byteCount, bindingType);
bo.inc();
mResourceManager.associateHandle(boh.getId(), std::move(tag));
}
void VulkanDriver::destroyBufferObject(Handle<HwBufferObject> boh) {
@@ -577,7 +570,7 @@ void VulkanDriver::destroyBufferObject(Handle<HwBufferObject> boh) {
void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage, utils::CString tag) {
TextureUsage usage) {
FVK_SYSTRACE_SCOPE();
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mResourceManager, &mCommands,
@@ -590,34 +583,31 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
texture->transitionLayout(&commandsBuf, primaryViewRange, defaultLayout);
texture.inc();
mResourceManager.associateHandle(th.getId(), std::move(tag));
}
void VulkanDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
uint8_t baseLevel, uint8_t levelCount) {
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, baseLevel,
levelCount);
texture.inc();
mResourceManager.associateHandle(th.getId(), std::move(tag));
}
void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
backend::TextureSwizzle a, utils::CString tag) {
TextureSwizzle const swizzleArray[] = { r, g, b, a };
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
texture.inc();
mResourceManager.associateHandle(th.getId(), std::move(tag));
backend::TextureSwizzle a) {
TextureSwizzle const swizzleArray[] = {r, g, b, a};
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
texture.inc();
}
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::SamplerType target,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
Platform::ExternalImageHandleRef externalImage, utils::CString tag) {
Platform::ExternalImageHandleRef externalImage) {
FVK_SYSTRACE_SCOPE();
auto metadata = mPlatform->extractExternalImageMetadata(externalImage);
@@ -663,12 +653,11 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
}
texture.inc();
mResourceManager.associateHandle(th.getId(), std::move(tag));
}
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* externalImage, utils::CString tag) {
void* externalImage) {
FVK_SYSTRACE_SCOPE();
assert_invariant(false && "Not supported in Vulkan backend");
// not supported in this backend
@@ -676,17 +665,16 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* image, uint32_t plane, utils::CString tag) {
void* image, uint32_t plane) {
assert_invariant(false && "Not supported in Vulkan backend");
}
void VulkanDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage, utils::CString tag) {
TextureUsage usage) {
// not supported in this backend
assert_invariant(false && "Not supported in Vulkan backend");
mResourceManager.associateHandle(th.getId(), std::move(tag));
}
void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
@@ -699,12 +687,11 @@ void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
mExternalImageManager.removeExternallySampledTexture(texture);
}
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::CString tag) {
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
FVK_SYSTRACE_SCOPE();
auto vprogram = resource_ptr<VulkanProgram>::make(&mResourceManager, ph, mPlatform->getDevice(),
program);
vprogram.inc();
mResourceManager.associateHandle(ph.getId(), std::move(tag));
}
void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
@@ -715,20 +702,18 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
vprogram.dec();
}
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString tag) {
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
assert_invariant(mDefaultRenderTarget); // Default render target should already exist.
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth,
std::move(std::move(*mDefaultRenderTarget.get())));
mDefaultRenderTarget = renderTarget;
mResourceManager.associateHandle(rth.getId(), std::move(tag));
}
void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
TargetBufferFlags targets, uint32_t width, uint32_t height, uint8_t samples,
uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil,
utils::CString tag) {
uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil) {
FVK_SYSTRACE_SCOPE();
@@ -789,8 +774,6 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
mPlatform->getPhysicalDevice(), mContext, &mResourceManager, mAllocator, &mCommands,
width, height, samples, colorTargets, depthStencil, mStagePool, layerCount);
rt.inc();
mResourceManager.associateHandle(rth.getId(), std::move(tag));
}
void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
@@ -807,7 +790,7 @@ void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
}
}
void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
void VulkanDriver::createFenceR(Handle<HwFence> fh, int) {
VulkanCommandBuffer* cmdbuf;
if (mCurrentRenderPass.commandBuffer) {
cmdbuf = mCurrentRenderPass.commandBuffer;
@@ -819,11 +802,9 @@ void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
// buffer.
auto fence = resource_ptr<VulkanFence>::cast(&mResourceManager, fh);
fence->fence = cmdbuf->getFenceStatus();
mResourceManager.associateHandle(fh.getId(), std::move(tag));
}
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
utils::CString tag) {
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
FVK_SYSTRACE_SCOPE();
// Running gc() to guard against an edge case where the old swapchains need to have been
// destroyed before the new swapchain can be created. Otherwise, we would fail
@@ -842,11 +823,10 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
auto swapChain = resource_ptr<VulkanSwapChain>::make(&mResourceManager, sch, mPlatform,
mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nativeWindow, flags);
swapChain.inc();
mResourceManager.associateHandle(sch.getId(), std::move(tag));
}
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
uint32_t height, uint64_t flags, utils::CString tag) {
uint32_t height, uint64_t flags) {
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
@@ -856,24 +836,21 @@ void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nullptr, flags,
VkExtent2D{width, height});
swapChain.inc();
mResourceManager.associateHandle(sch.getId(), std::move(tag));
}
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
// nothing to do, timer query was constructed in createTimerQueryS
mResourceManager.associateHandle(tqh.getId(), std::move(tag));
}
void VulkanDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
backend::DescriptorSetLayout&& info, utils::CString tag) {
backend::DescriptorSetLayout&& info) {
FVK_SYSTRACE_SCOPE();
auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info));
layout.inc();
mResourceManager.associateHandle(dslh.getId(), std::move(tag));
}
void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
Handle<HwDescriptorSetLayout> dslh) {
FVK_SYSTRACE_SCOPE();
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout =
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
@@ -883,8 +860,6 @@ void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
if (layout->hasExternalSamplers()) {
mAppState.hasExternalSamplerLayouts = true;
}
mResourceManager.associateHandle(dsh.getId(), std::move(tag));
}
Handle<HwVertexBufferInfo> VulkanDriver::createVertexBufferInfoS() noexcept {
@@ -1015,11 +990,11 @@ void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
}
}
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream, utils::CString tag) {
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream) {
return {};
}
Handle<HwStream> VulkanDriver::createStreamAcquired(utils::CString tag) {
Handle<HwStream> VulkanDriver::createStreamAcquired() {
return {};
}
@@ -1632,7 +1607,7 @@ void VulkanDriver::commit(Handle<HwSwapChain> sch) {
auto swapChain = resource_ptr<VulkanSwapChain>::cast(&mResourceManager, sch);
// Present the backbuffer after the most recent command buffer submission has finished.
swapChain->present(*this);
swapChain->present();
}
void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
@@ -1964,18 +1939,6 @@ void VulkanDriver::bindDescriptorSet(
if (dsh) {
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
mDescriptorSetCache.bind(setIndex, set, std::move(offsets));
if (mAppState.hasExternalSamplers()) {
auto const& bindInDrawBundle = mPipelineState.bindInDraw.second;
// The set index being bound has already been bound or will be bound. If it's already
// been bound and this set has external samplers, we do the doBindindraw block in
// draw2() again. Because this set might potentially cause a new pipelineLayout
// (therefore pipeline) to be bound.
if (bindInDrawBundle.descriptorSetMask[setIndex] &&
mExternalImageManager.hasExternalSampler(set)) {
mPipelineState.bindInDraw.first = true;
}
}
} else {
mDescriptorSetCache.unbind(setIndex);
}
@@ -2104,6 +2067,10 @@ void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, cons
void VulkanDriver::resetState(int) {
}
void VulkanDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
mResourceManager.associateHandle(handleId, std::move(tag));
}
void VulkanDriver::endCommandRecording() {
mCommands.flush();
mPipelineCache.resetBoundPipeline();
@@ -121,7 +121,7 @@ fvkutils::DescriptorSetMask VulkanExternalImageManager::prepareBindSets(LayoutAr
}
bool VulkanExternalImageManager::hasExternalSampler(
fvkmemory::resource_ptr<VulkanDescriptorSet> set) const {
fvkmemory::resource_ptr<VulkanDescriptorSet> set) {
auto itr = std::find_if(mSetBindings.begin(), mSetBindings.end(),
[&](SetBindingInfo const& info) { return info.set == set; });
return itr != mSetBindings.end();
@@ -191,11 +191,9 @@ void VulkanExternalImageManager::updateSetAndLayout(
VkDescriptorSet const srcSet = oldSet != VK_NULL_HANDLE ? oldSet : set->getVkSet();
copySet(mPlatform->getDevice(), srcSet, newSet, copyBindings);
set->setExternalSamplerVkSet(newSet,
[&descriptorSetCache = mDescriptorSetCache, layoutCount = layout->count, newLayout,
newSet](VulkanDescriptorSet*) {
descriptorSetCache->manualRecycle(layoutCount, newLayout, newSet);
});
set->setExternalSamplerVkSet(newSet, [&](VulkanDescriptorSet*) {
mDescriptorSetCache->manualRecycle(layout->count, newLayout, newSet);
});
if (oldLayout != newLayout) {
layout->setExternalSamplerVkLayout(newLayout);
}
@@ -86,9 +86,9 @@ public:
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
};
bool hasExternalSampler(fvkmemory::resource_ptr<VulkanDescriptorSet> set) const;
private:
bool hasExternalSampler(fvkmemory::resource_ptr<VulkanDescriptorSet> set);
void updateSetAndLayout(fvkmemory::resource_ptr<VulkanDescriptorSet> set,
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
@@ -32,7 +32,6 @@
#include <utils/compiler.h> // UTILS_FALLTHROUGH
#include <utils/Panic.h> // ASSERT_POSTCONDITION
#include <utils/CString.h>
using namespace bluevk;
@@ -286,7 +285,7 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
<< " error=" << static_cast<int32_t>(result);
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
utils::CString name{ builder.getName().c_str(), builder.getName().size() };
std::string name{ builder.getName().c_str(), builder.getName().size() };
switch (static_cast<ShaderStage>(i)) {
case ShaderStage::VERTEX:
name += "_vs";
+1 -6
View File
@@ -308,10 +308,7 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
// Creates a special "default" render target (i.e. associated with the swap chain)
explicit VulkanRenderTarget();
VulkanRenderTarget(VulkanRenderTarget&& target)
: HwRenderTarget(0, 0),
mOffscreen(false),
mProtected(false) {
VulkanRenderTarget(VulkanRenderTarget&& target) {
swap(std::move(target));
}
@@ -368,8 +365,6 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
private:
void swap(VulkanRenderTarget&& target) {
std::swap(width, target.width);
std::swap(height, target.height);
std::swap(mOffscreen, target.mOffscreen);
std::swap(mProtected, target.mProtected);
std::swap(mInfo, target.mInfo);
@@ -46,13 +46,17 @@ fvkmemory::resource_ptr<VulkanTimerQuery> VulkanQueryManager::getNextQuery(
return {};
}
bool found = false;
std::pair<uint32_t, uint32_t> queryIndices;
size_t const firstUnused = unused.firstSetBit();
{
unused.forEachSetBit([&](size_t index) {
if (found) {
return;
}
std::unique_lock<utils::Mutex> lock(mMutex);
mUsed.set(firstUnused);
queryIndices = { firstUnused * 2, firstUnused * 2 + 1 };
}
mUsed.set(index);
found = true;
queryIndices = std::make_pair(index * 2, index * 2 + 1);
});
return fvkmemory::resource_ptr<VulkanTimerQuery>::construct(resourceManager, queryIndices.first,
queryIndices.second);
}
@@ -93,7 +93,7 @@ void VulkanSwapChain::update() {
mLayerCount = bundle.layerCount;
}
void VulkanSwapChain::present(DriverBase& driver) {
void VulkanSwapChain::present() {
if (!mHeadless && mTransitionSwapChainImageLayoutForPresent) {
VulkanCommandBuffer& commands = mCommands->get();
VkImageSubresourceRange const subresources{
@@ -120,14 +120,6 @@ void VulkanSwapChain::present(DriverBase& driver) {
// We presented the last acquired buffer.
mAcquired = false;
mIsFirstRenderPass = true;
if (frameScheduled.callback) {
driver.scheduleCallback(frameScheduled.handler,
[callback = std::move(frameScheduled.callback)]() {
PresentCallable noop = PresentCallable(PresentCallable::noopPresent, nullptr);
callback(noop);
});
}
}
void VulkanSwapChain::acquire(bool& resized) {
+1 -14
View File
@@ -47,7 +47,7 @@ struct VulkanSwapChain : public HwSwapChain, fvkmemory::Resource {
~VulkanSwapChain();
void present(DriverBase& driver);
void present();
// Acquire a new image from the swapchain. If the image is not available it would wait until it
// is.
@@ -79,13 +79,6 @@ struct VulkanSwapChain : public HwSwapChain, fvkmemory::Resource {
inline bool isProtected() noexcept {
return mPlatform->isProtected(swapChain);
}
inline void setFrameScheduledCallback(CallbackHandler* handler,
FrameScheduledCallback&& callback) noexcept {
frameScheduled.handler = handler;
frameScheduled.callback = std::move(callback);
}
private:
static constexpr int IMAGE_READY_SEMAPHORE_COUNT = FVK_MAX_COMMAND_BUFFERS;
@@ -101,12 +94,6 @@ private:
bool const mFlushAndWaitOnResize;
bool const mTransitionSwapChainImageLayoutForPresent;
// These fields store a callback to notify the client that Filament is commiting a frame.
struct {
CallbackHandler* handler = nullptr;
FrameScheduledCallback callback;
} frameScheduled;
// We create VulkanTextures based on VkImages. VulkanTexture has facilities for doing layout
// transitions, which are useful here.
utils::FixedCapacityVector<fvkmemory::resource_ptr<VulkanTexture>> mColors;
@@ -106,7 +106,7 @@ VkComponentMapping composeSwizzle(VkComponentMapping const& prev, VkComponentMap
return { vals[0], vals[1], vals[2], vals[3] };
};
// We make sure all identities are mapped into respective channels so that actual channel
// We make sure all all identities are mapped into respective channels so that actual channel
// mapping will be passed onto the output.
VkComponentMapping const prevExplicit = identityToChannel(prev);
VkComponentMapping const nextExplicit = identityToChannel(next);
@@ -95,7 +95,7 @@ ResourceType getTypeEnum() noexcept {
return ResourceType::UNDEFINED_TYPE;
}
std::string_view getTypeStr(ResourceType type) {
std::string getTypeStr(ResourceType type) {
switch (type) {
case ResourceType::BUFFER_OBJECT:
return "BufferObject";
@@ -58,7 +58,7 @@ enum class ResourceType : uint8_t {
template<typename D>
ResourceType getTypeEnum() noexcept;
std::string_view getTypeStr(ResourceType type);
std::string getTypeStr(ResourceType type);
inline bool isThreadSafeType(ResourceType type) {
return type == ResourceType::FENCE || type == ResourceType::TIMER_QUERY;
File diff suppressed because it is too large Load Diff
+24 -50
View File
@@ -58,10 +58,10 @@ namespace {
areCopyCompatible(sourceFormat, destinationFormat) &&
(sourceExtent.width == destinationExtent.width) &&
(sourceExtent.height == destinationExtent.height) &&
((sourceOrigin.x % sourceBlockSize.width) == 0) &&
((sourceOrigin.y % sourceBlockSize.height) == 0) &&
((destinationOrigin.x % destinationBlockSize.width) == 0) &&
((destinationOrigin.y % destinationBlockSize.height) == 0);
((sourceOrigin.x & sourceBlockSize.width) == 0) &&
((sourceOrigin.y & sourceBlockSize.height) == 0) &&
((destinationOrigin.x & destinationBlockSize.width) == 0) &&
((destinationOrigin.y & destinationBlockSize.height) == 0);
}
struct BlitFragmentShaderArgs final {
@@ -206,20 +206,9 @@ constexpr std::string_view FRAGMENT_SHADER_SNIPPET_2D_INPUT_TEMPLATE{ R"(
} // namespace
// It can perform a direct memory copy if the formats are compatible and no scaling or format
// conversion is needed. Otherwise, it uses a render pass with a custom shader to perform
// the blit. This allows for scaling, format conversion, and resolving multisampled textures.
// The blitter caches pipelines, layouts, and shaders to avoid recompilation.
WebGPUBlitter::WebGPUBlitter(wgpu::Device const& device)
: mDevice{ device } {}
// Performs a blit operation from a source to a destination texture.
// This function first checks if a direct texture-to-texture copy can be performed.
// A direct copy is possible if the source and destination textures have the same sample count,
// compatible formats, and the copy extents match. If a direct copy is not possible, this
// function falls back to a render pass-based blit. The render pass uses a shader to read from
// the source texture and write to the destination texture, allowing for format conversion,
// scaling, and MSAA resolves.
void WebGPUBlitter::blit(wgpu::Queue const& queue, wgpu::CommandEncoder const& commandEncoder,
BlitArgs const& args) {
// current assumptions/simplifications made in this implementation:
@@ -278,20 +267,22 @@ void WebGPUBlitter::blit(wgpu::Queue const& queue, wgpu::CommandEncoder const& c
args.destination.texture.GetUsage() & wgpu::TextureUsage::CopyDst)
<< "destination texture usage doesn't have wgpu::TextureUsage::CopyDst";
copyByteByByte(commandEncoder, args);
copy(commandEncoder, args);
return;
}
// need to do a render pass blit...
FILAMENT_CHECK_PRECONDITION(args.destination.texture.GetSampleCount() == 1)
<< "Blitting does not currently support writing to multisampled output textures.";
FILAMENT_CHECK_PRECONDITION(args.source.texture.GetUsage() & wgpu::TextureUsage::TextureBinding)
<< "Source texture usage doesn't have wgpu::TextureUsage::TextureBinding";
<< "source texture usage doesn't have wgpu::TextureUsage::TextureBinding";
FILAMENT_CHECK_PRECONDITION(
args.destination.texture.GetUsage() & wgpu::TextureUsage::RenderAttachment)
<< "Destination texture usage doesn't have wgpu::TextureUsage::RenderAttachment";
<< "destination texture usage doesn't have wgpu::TextureUsage::RenderAttachment";
// create input/output texture views...
const wgpu::TextureViewDimension sourceDimension{ args.source.texture.GetDimension() ==
wgpu::TextureDimension::e3D
? wgpu::TextureViewDimension::e3D
@@ -336,6 +327,7 @@ void WebGPUBlitter::blit(wgpu::Queue const& queue, wgpu::CommandEncoder const& c
<< destinationViewDescriptor.baseArrayLayer << " and mip level "
<< destinationViewDescriptor.baseMipLevel << " for render pass blit?";
// create uniform buffer (for shader args)...
const BlitFragmentShaderArgs blitFragmentShaderArgs{
.depthPlane = args.source.layerOrDepth,
.scale = { static_cast<float>(args.source.extent.width) / args.destination.extent.width,
@@ -446,7 +438,7 @@ void WebGPUBlitter::blit(wgpu::Queue const& queue, wgpu::CommandEncoder const& c
const wgpu::RenderPassEncoder renderPassEncoder{ commandEncoder.BeginRenderPass(
&renderPassDescriptor) };
FILAMENT_CHECK_POSTCONDITION(renderPassEncoder)
<< "Failed to create render pass encoder for blit.";
<< "Failed to create render pass encoder for blit?";
renderPassEncoder.SetPipeline(getOrCreateRenderPipeline(args.filter, sourceDimension,
args.source.texture.GetSampleCount(), depthSource,
args.destination.texture.GetFormat()));
@@ -456,7 +448,7 @@ void WebGPUBlitter::blit(wgpu::Queue const& queue, wgpu::CommandEncoder const& c
renderPassEncoder.End();
}
void WebGPUBlitter::copyByteByByte(wgpu::CommandEncoder const& commandEncoder, BlitArgs const& args) {
void WebGPUBlitter::copy(wgpu::CommandEncoder const& commandEncoder, BlitArgs const& args) {
const wgpu::TexelCopyTextureInfo sourceCopyInfo{
.texture = args.source.texture,
.mipLevel = args.source.mipLevel,
@@ -513,7 +505,7 @@ void WebGPUBlitter::createSampler(const SamplerMagFilter filter) {
.maxAnisotropy = 1, // should not matter, just being consistently defined
};
const wgpu::Sampler sampler{ mDevice.CreateSampler(&descriptor) };
FILAMENT_CHECK_POSTCONDITION(sampler) << "Failed to create blit sampler.";
FILAMENT_CHECK_POSTCONDITION(sampler) << "Failed to create blit sampler?";
switch (filter) {
case SamplerMagFilter::NEAREST:
mNearestSampler = sampler;
@@ -524,8 +516,6 @@ void WebGPUBlitter::createSampler(const SamplerMagFilter filter) {
}
}
// Caches and returns a render pipeline for a given blit configuration.
// If a pipeline for the given configuration does not exist, it creates and caches one.
wgpu::RenderPipeline const& WebGPUBlitter::getOrCreateRenderPipeline(
const SamplerMagFilter filterType, const wgpu::TextureViewDimension sourceDimension,
const uint32_t sourceSampleCount, const bool depthSource,
@@ -539,9 +529,6 @@ wgpu::RenderPipeline const& WebGPUBlitter::getOrCreateRenderPipeline(
return mRenderPipelines[key];
}
// Creates a render pipeline for a blit operation.
// The pipeline is configured with the appropriate vertex and fragment shaders,
// pipeline layout, and render target state based on the blit parameters.
wgpu::RenderPipeline WebGPUBlitter::createRenderPipeline(const SamplerMagFilter filterType,
const wgpu::TextureViewDimension sourceDimension, const uint32_t sourceSampleCount,
const bool depthSource, const wgpu::TextureFormat destinationTextureFormat) {
@@ -593,7 +580,7 @@ wgpu::RenderPipeline WebGPUBlitter::createRenderPipeline(const SamplerMagFilter
.fragment = &fragmentState,
};
const wgpu::RenderPipeline pipeline{ mDevice.CreateRenderPipeline(&pipelineDescriptor) };
FILAMENT_CHECK_POSTCONDITION(pipeline) << "Failed to create pipeline for render pass blit.";
FILAMENT_CHECK_POSTCONDITION(pipeline) << "Failed to create pipeline for render pass blit?";
return pipeline;
}
@@ -608,8 +595,6 @@ size_t WebGPUBlitter::hashRenderPipelineKey(const SamplerMagFilter filterType,
return seed;
}
// Caches and returns a pipeline layout for a given blit configuration.
// If a layout for the given configuration does not exist, it creates and caches one.
wgpu::PipelineLayout const& WebGPUBlitter::getOrCreatePipelineLayout(
const SamplerMagFilter filterType, const wgpu::TextureViewDimension sourceDimension,
const bool multisampledSource, const bool depthSource) {
@@ -622,8 +607,6 @@ wgpu::PipelineLayout const& WebGPUBlitter::getOrCreatePipelineLayout(
return mPipelineLayouts[key];
}
// Creates a pipeline layout for a blit operation.
// The layout defines the bind group layouts used by the blit pipeline.
wgpu::PipelineLayout WebGPUBlitter::createPipelineLayout(const SamplerMagFilter filterType,
const wgpu::TextureViewDimension sourceDimension, const bool multisampledSource,
const bool depthSource) {
@@ -636,7 +619,7 @@ wgpu::PipelineLayout WebGPUBlitter::createPipelineLayout(const SamplerMagFilter
const wgpu::PipelineLayout pipelineLayout{ mDevice.CreatePipelineLayout(
&pipelineLayoutDescriptor) };
FILAMENT_CHECK_POSTCONDITION(pipelineLayout)
<< "Failed to create pipeline layout for render pass blit.";
<< "Failed to create pipeline layout for render pass blit?";
return pipelineLayout;
}
@@ -650,8 +633,6 @@ size_t WebGPUBlitter::hashPipelineLayoutKey(const SamplerMagFilter filterType,
return seed;
}
// Caches and returns a bind group layout for a given blit configuration.
// If a layout for the given configuration does not exist, it creates and caches one.
wgpu::BindGroupLayout const& WebGPUBlitter::getOrCreateTextureBindGroupLayout(
const SamplerMagFilter filterType, const wgpu::TextureViewDimension sourceDimension,
const bool multisampledSource, const bool depthSource) {
@@ -664,9 +645,6 @@ wgpu::BindGroupLayout const& WebGPUBlitter::getOrCreateTextureBindGroupLayout(
return mTextureBindGroupLayouts[key];
}
// Creates a bind group layout for the blit operation's texture resources.
// This layout specifies the bindings for the source texture, a uniform buffer with blit parameters,
// and optionally a sampler.
wgpu::BindGroupLayout WebGPUBlitter::createTextureBindGroupLayout(const SamplerMagFilter filterType,
const wgpu::TextureViewDimension sourceDimension, const bool multisampledSource,
const bool depthSource) {
@@ -677,11 +655,11 @@ wgpu::BindGroupLayout WebGPUBlitter::createTextureBindGroupLayout(const SamplerM
.texture = {
.sampleType = depthSource
? wgpu::TextureSampleType::Depth
: (multisampledSource
? wgpu::TextureSampleType::UnfilterableFloat
: wgpu::TextureSampleType::Float), // only F32 scalar sample
// type supported for now
// (aside from depth)
: wgpu::TextureSampleType::Float, // only F32 scalar sample
// type supported for now
// (aside from depth)
// see assumptions listed
// in blit function
.viewDimension = sourceDimension,
.multisampled = multisampledSource,
},
@@ -715,7 +693,7 @@ wgpu::BindGroupLayout WebGPUBlitter::createTextureBindGroupLayout(const SamplerM
const wgpu::BindGroupLayout textureBindGroupLayout{ mDevice.CreateBindGroupLayout(
&textureBindGroupLayoutDescriptor) };
FILAMENT_CHECK_POSTCONDITION(textureBindGroupLayout)
<< "Failed to create texture bind group layout for render pass blit.";
<< "Failed to create texture bind group layout for render pass blit?";
return textureBindGroupLayout;
}
@@ -729,8 +707,6 @@ size_t WebGPUBlitter::hashTextureBindGroupLayoutKey(const SamplerMagFilter filte
return seed;
}
// Caches and returns a shader module for a given blit configuration.
// If a shader module for the given configuration does not exist, it creates and caches one.
wgpu::ShaderModule const& WebGPUBlitter::getOrCreateShaderModule(
const wgpu::TextureViewDimension sourceDimension, const bool multisampledSource,
const bool depthSource, const bool depthDestination) {
@@ -743,9 +719,6 @@ wgpu::ShaderModule const& WebGPUBlitter::getOrCreateShaderModule(
return mShaderModules[key];
}
// Creates a shader module containing the vertex and fragment shaders for the blit operation.
// The shader source is generated from a template, with placeholders filled in based on the
// blit configuration (e.g., texture type, sample count).
wgpu::ShaderModule WebGPUBlitter::createShaderModule(
const wgpu::TextureViewDimension sourceDimension, const bool multisampledSource,
const bool depthSource, const bool depthDestination) {
@@ -757,8 +730,9 @@ wgpu::ShaderModule WebGPUBlitter::createShaderModule(
textureType = "texture_depth_2d";
}
} else {
// non-depth
if (multisampledSource) {
textureType = "texture_multisampled_2d<f32>";
textureType = "texture_multisampled_2d";
} else {
if (sourceDimension == wgpu::TextureViewDimension::e3D) {
textureType = "texture_3d<f32>";
@@ -811,7 +785,7 @@ wgpu::ShaderModule WebGPUBlitter::createShaderModule(
};
const wgpu::ShaderModule shaderModule{ mDevice.CreateShaderModule(&shaderModuleDescriptor) };
FILAMENT_CHECK_POSTCONDITION(shaderModule)
<< "Failed to create shader module for render pass blit.";
<< "Failed to create shader module for render pass blit?";
return shaderModule;
}
+1 -17
View File
@@ -26,17 +26,6 @@
namespace filament::backend {
/**
* A blit essentially writes pixels to a region of one texture given a region of another texture.
* Such a process can be a byte-by-byte copy when possible, while other scenarios involve various
* transformations, such as pixel format conversion, image scaling, filtering/sampling
* (such as down sampling), or even multi-sample resolves. Some blits can be faster than others,
* depending on what is needed; for example, a byte-by-byte copy is generally faster than other
* operations.
*
* This class is responsible for performing blits throughout the lifecycle of its owner/caller,
* e.g. the WebGPU backend/driver, where it can leverage state to optimize such blit calls over time.
*/
class WebGPUBlitter final {
public:
struct BlitArgs final {
@@ -69,15 +58,10 @@ private:
/**
* ONLY should be called if canDoDirectCopy(...) is true (see it in WebGPUBlitter.cpp)
*/
void copyByteByByte(wgpu::CommandEncoder const&, BlitArgs const&);
void copy(wgpu::CommandEncoder const&, BlitArgs const&);
void createSampler(SamplerMagFilter);
// The following methods are used to create and cache WebGPU objects.
// The pattern is to have a `getOrCreate...` method that looks up the object in a cache,
// and if it's not found, it calls a `create...` method to create it and then stores it in the
// cache. A `hash...` method is used to generate a key for the cache.
[[nodiscard]] wgpu::RenderPipeline const& getOrCreateRenderPipeline(SamplerMagFilter,
wgpu::TextureViewDimension sourceDimension, uint32_t sourceSampleCount,
bool depthSource, wgpu::TextureFormat destinationTextureFormat);
@@ -33,9 +33,6 @@ namespace filament::backend {
namespace {
// Creates a wgpu::Buffer, ensuring its size is a multiple of FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS.
// WebGPU's WriteBuffer requires the write size to be a multiple of 4. By ensuring the buffer
// size is also a multiple of 4, we simplify the update logic.
[[nodiscard]] wgpu::Buffer createBuffer(wgpu::Device const& device, const wgpu::BufferUsage usage,
uint32_t size, const char* const label) {
// Write size must be divisible by WEBGPU_BUFFER_SIZE_MODULUS (e.g. 4).
@@ -58,11 +55,6 @@ WebGPUBufferBase::WebGPUBufferBase(wgpu::Device const& device, const wgpu::Buffe
const uint32_t size, char const* const label)
: mBuffer{ createBuffer(device, usage, size, label) } {}
// Updates the GPU buffer with data from a BufferDescriptor.
// WebGPU requires that the size of the data written to a buffer is a multiple of 4.
// This function handles cases where the buffer descriptor's size is not a multiple of 4
// by writing the bulk of the data first, and then copying the remaining bytes into a
// padded temporary chunk which is then written to the buffer.
void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
const uint32_t byteOffset, wgpu::Queue const& queue) {
FILAMENT_CHECK_PRECONDITION(bufferDescriptor.buffer)
@@ -28,10 +28,6 @@ namespace filament::backend {
class BufferDescriptor;
/**
* A base class for WebGPU buffer objects, providing common functionality for creating and
* updating GPU buffers.
*/
class WebGPUBufferBase /* intended to be extended */ {
public:
/**
@@ -50,8 +46,7 @@ protected:
private:
const wgpu::Buffer mBuffer;
// WebGPU requires that the source buffer of a writeBuffer call has a size that is a multiple
// of 4. This member is used to pad the data if the source size is not a multiple of 4.
// FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS (e.g. 4) bytes to hold any extra chunk we need.
std::array<uint8_t, FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS> mRemainderChunk{};
};
@@ -40,8 +40,6 @@ namespace {
} // namespace
// The usage flags are determined by the binding type, and always include CopyDst to allow for
// updating the buffer.
WebGPUBufferObject::WebGPUBufferObject(wgpu::Device const& device,
const BufferObjectBinding bindingType, const uint32_t byteCount)
: HwBufferObject{ byteCount },
@@ -31,12 +31,6 @@ namespace filament::backend {
enum class BufferObjectBinding : uint8_t;
/**
* A WebGPU-specific implementation of BufferObject.
* A BufferObject is a GPU buffer that can be used for a variety of purposes, such as storing
* uniform data, vertex attributes, or pixel data. The specific usage is determined by the
* BufferObjectBinding.
*/
class WebGPUBufferObject final : public HwBufferObject, public WebGPUBufferBase {
public:
WebGPUBufferObject(wgpu::Device const&, BufferObjectBinding, uint32_t byteCount);
+3 -52
View File
@@ -21,7 +21,6 @@
#include <cstdint>
// WebGPU requires that the source buffer of a writeBuffer call has a size that is a multiple of 4.
constexpr size_t FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS = 4;
// FWGPU is short for Filament WebGPU
@@ -49,16 +48,8 @@ constexpr size_t FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS = 4;
// textures, samplers, and buffers,...), which would otherwise spam the logs.
#define FWGPU_DEBUG_BIND_GROUPS 0x00000020
// Enables Android systrace
#define FWGPU_DEBUG_SYSTRACE 0x00000040
// Enable a minimal set of traces to assess the performance of the backend.
// All other debug features must be disabled.
#define FWGPU_DEBUG_PROFILING 0x00000080
// Useful default combinations
#define FWGPU_DEBUG_EVERYTHING (0xFFFFFFFF & ~FWGPU_DEBUG_PROFILING)
#define FWGPU_DEBUG_PERFORMANCE FWGPU_DEBUG_SYSTRACE
#define FWGPU_DEBUG_EVERYTHING 0xFFFFFFFF
#if defined(FILAMENT_BACKEND_DEBUG_FLAG)
#define FWGPU_DEBUG_FORWARDED_FLAG (FILAMENT_BACKEND_DEBUG_FLAG & FWGPU_DEBUG_EVERYTHING)
@@ -67,53 +58,13 @@ constexpr size_t FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS = 4;
#endif
#ifndef NDEBUG
#define FWGPU_DEBUG_FLAGS (FWGPU_DEBUG_PERFORMANCE | FWGPU_DEBUG_FORWARDED_FLAG)
#define FWGPU_DEBUG_FLAGS FWGPU_DEBUG_FORWARDED_FLAG
#else
#define FWGPU_DEBUG_FLAGS FWGPU_DEBUG_SYSTRACE
#endif
// Override the debug flags if we are forcing profiling mode
#if defined(FILAMENT_FORCE_PROFILING_MODE)
#undef FWGPU_DEBUG_FLAGS
#define FWGPU_DEBUG_FLAGS (FWGPU_DEBUG_PROFILING)
#define FWGPU_DEBUG_FLAGS 0
#endif
#define FWGPU_ENABLED(flags) (((FWGPU_DEBUG_FLAGS) & (flags)) == (flags))
#if FWGPU_ENABLED(FWGPU_DEBUG_PROFILING) && FWGPU_DEBUG_FLAGS != FWGPU_DEBUG_PROFILING
#error PROFILING is exclusive; all other debug features must be disabled.
#endif
#if FWGPU_DEBUG_FLAGS == FWGPU_DEBUG_PROFILING
#ifndef NDEBUG
#error PROFILING is meaningless in DEBUG mode.
#endif
#define FWGPU_SYSTRACE_CONTEXT()
#define FWGPU_SYSTRACE_START(marker)
#define FWGPU_SYSTRACE_END()
#define FWGPU_SYSTRACE_SCOPE()
#define FWGPU_PROFILE_MARKER(marker) PROFILE_SCOPE(marker)
#elif FWGPU_ENABLED(FWGPU_DEBUG_SYSTRACE)
#include <private/utils/Tracing.h>
#define FWGPU_SYSTRACE_CONTEXT() FILAMENT_TRACING_CONTEXT(FILAMENT_TRACING_CATEGORY_FILAMENT)
#define FWGPU_SYSTRACE_START(marker) FILAMENT_TRACING_NAME_BEGIN(FILAMENT_TRACING_CATEGORY_FILAMENT, marker)
#define FWGPU_SYSTRACE_END() FILAMENT_TRACING_NAME_END(FILAMENT_TRACING_CATEGORY_FILAMENT)
#define FWGPU_SYSTRACE_SCOPE() FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT)
#define FWGPU_PROFILE_MARKER(marker) FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT)
#else
#define FWGPU_SYSTRACE_CONTEXT()
#define FWGPU_SYSTRACE_START(marker)
#define FWGPU_SYSTRACE_END()
#define FWGPU_SYSTRACE_SCOPE()
#define FWGPU_PROFILE_MARKER(marker)
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_FORCE_LOG_TO_I)
#define FWGPU_LOGI LOG(INFO)
#define FWGPU_LOGD FWGPU_LOGI
@@ -42,9 +42,6 @@ constexpr uint8_t INVALID_INDEX = MAX_DESCRIPTOR_COUNT + 1;
} // namespace
// The constructor initializes the descriptor set based on a given layout.
// It pre-allocates space for the bind group entries and sets up a mapping from binding index
// to the internal entry array index. This prepares the object to be populated with resources.
WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries)
: mLayout{ layout },
@@ -55,10 +52,11 @@ WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
for (size_t i = 0; i < bindGroupEntries.size(); ++i) {
mEntries[i].binding = bindGroupEntries[i].binding;
}
// Create a mapping from binding index to entry index for efficient lookup.
// Establish the size of entries based on the layout. This should be reliable and efficient.
assert_invariant(INVALID_INDEX > mEntryIndexByBinding.size());
std::fill(mEntryIndexByBinding.begin(), mEntryIndexByBinding.end(), INVALID_INDEX);
for (size_t i = 0; i < mEntryIndexByBinding.size(); i++) {
mEntryIndexByBinding[i] = INVALID_INDEX;
}
for (size_t index = 0; index < mEntries.size(); index++) {
wgpu::BindGroupEntry const& entry = mEntries[index];
assert_invariant(entry.binding < mEntryIndexByBinding.size());
@@ -68,20 +66,19 @@ WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
void WebGPUDescriptorSet::addEntry(const unsigned int index, wgpu::BindGroupEntry&& entry) {
if (mBindGroup) {
// The bind group has already been created, so we can't add new entries.
// Filament guarantees that the descriptor set will not be modified after it has been locked.
// We will keep getting hits from future updates, but shouldn't do anything
// Filament guarantees this won't change after things have locked.
return;
}
// TODO: Putting some level of trust that Filament is not going to reuse indexes or go past the
// layout index for efficiency. Add guards if wrong.
FILAMENT_CHECK_POSTCONDITION(index < mEntryIndexByBinding.size())
<< "impossible/invalid index for a descriptor/binding (out of range or >= "
<< "impossible/invalid index for a descriptor/binding (our of range or >= "
"MAX_DESCRIPTOR_COUNT) "
<< index;
uint8_t entryIndex = mEntryIndexByBinding[index];
FILAMENT_CHECK_POSTCONDITION(entryIndex != INVALID_INDEX && entryIndex < mEntries.size())
<< "Invalid binding index: " << index;
<< "Invalid binding " << index;
entry.binding = index;
mEntries[entryIndex] = std::move(entry);
}
@@ -97,9 +94,8 @@ wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn(wgpu::Device const& device) {
.entries = mEntries.data()
};
mBindGroup = device.CreateBindGroup(&descriptor);
FILAMENT_CHECK_POSTCONDITION(mBindGroup) << "Failed to create bind group.";
// Once the bind group is created, we can release the resources used to create it.
FILAMENT_CHECK_POSTCONDITION(mBindGroup) << "Failed to create bind group?";
// once we have created the bind group itself we should no longer need any other state
#if FWGPU_ENABLED(FWGPU_DEBUG_BIND_GROUPS)
FWGPU_LOGD << "WebGPUDescriptorSet (lockAndReturn):";
FWGPU_LOGD << " wgpu::BindGroupLayout handle: " << mLayout.Get();
@@ -32,46 +32,23 @@
namespace filament::backend {
/**
* A WebGPU-specific implementation of DescriptorSet.
* This class manages a collection of resource bindings (e.g., textures, buffers) that are used by
* a shader. It corresponds to a `wgpu::BindGroup` in WebGPU. The actual `wgpu::BindGroup` is
* created lazily when `lockAndReturn` is called, at which point the descriptor set becomes
* immutable.
*/
class WebGPUDescriptorSet final : public HwDescriptorSet {
public:
WebGPUDescriptorSet(wgpu::BindGroupLayout const&,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const&);
~WebGPUDescriptorSet();
/**
* Adds or updates a resource binding in the descriptor set.
* This method is called to populate the descriptor set with buffers, textures, and samplers.
* It is only valid to call this before the descriptor set is locked (i.e., before
* `lockAndReturn` is called).
*/
void addEntry(unsigned int index, wgpu::BindGroupEntry&& entry);
/**
* Finalizes the descriptor set by creating the wgpu::BindGroup. After this call, the
* descriptor set is considered "locked" and cannot be modified further.
*/
[[nodiscard]] wgpu::BindGroup lockAndReturn(wgpu::Device const&);
/**
* @return true if the descriptor set has been locked (i.e., the wgpu::BindGroup has been
* created).
*/
[[nodiscard]] bool getIsLocked() const { return mBindGroup != nullptr; }
[[nodiscard]] size_t getEntitiesWithDynamicOffsetsCount() const {
return mEntriesWithDynamicOffsetsCount;
}
/**
* May be nullptr. Use lockAndReturn to create the bind group when appropriate
*/
// May be nullptr. Use lockAndReturn to create the bind group when appropriate
[[nodiscard]] wgpu::BindGroup const& getBindGroup() const { return mBindGroup; }
#if FWGPU_ENABLED(FWGPU_DEBUG_BIND_GROUPS)
@@ -83,7 +60,6 @@ private:
std::array<uint8_t, MAX_DESCRIPTOR_COUNT> mEntryIndexByBinding{};
std::vector<wgpu::BindGroupEntry> mEntries;
const size_t mEntriesWithDynamicOffsetsCount;
// This is created lazily when lockAndReturn is called.
wgpu::BindGroup mBindGroup = nullptr;
};
@@ -40,9 +40,7 @@ namespace filament::backend {
namespace {
/**
* Converts Filament shader stage flags to the corresponding WebGPU shader stage bitmask.
*/
// Convert Filament Shader Stage Flags bitmask to webgpu equivalent
[[nodiscard]] wgpu::ShaderStage filamentStageToWGPUStage(const ShaderStageFlags fFlags) {
wgpu::ShaderStage retStages = wgpu::ShaderStage::None;
if (any(ShaderStageFlags::VERTEX & fFlags)) {
@@ -72,6 +70,10 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
baseLabel = temp->c_str();
}
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value.
static int layoutNum = 0;
const unsigned int samplerCount =
std::count_if(layout.bindings.begin(), layout.bindings.end(), [](auto& fEntry) {
return DescriptorSetLayoutBinding::isSampler(fEntry.type);
@@ -85,11 +87,6 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
auto& wEntry = wEntries.emplace_back();
auto& entryInfo = mBindGroupEntries.emplace_back();
wEntry.visibility = filamentStageToWGPUStage(fEntry.stageFlags);
// In WebGPU, textures and samplers are separate bindings.
// We map the Filament binding index to two WebGPU binding indices:
// - texture: binding * 2
// - sampler: binding * 2 + 1
wEntry.binding = fEntry.binding * 2;
entryInfo.binding = wEntry.binding;
@@ -181,13 +178,11 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
} else if (isCubeArrayTypeDescriptor(fEntry.type)) {
wEntry.texture.viewDimension = wgpu::TextureViewDimension::CubeArray;
}
// fEntry.count is unused currently
}
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value.
static int layoutNum = 0;
std::string label = "layout_" + baseLabel + "_" + std::to_string(++layoutNum) ;
std::string label = "layout_" + baseLabel + std::to_string(++layoutNum) ;
const wgpu::BindGroupLayoutDescriptor layoutDescriptor{
.label{label.c_str()},
.label{label.c_str()}, // Use .c_str() if label needs to be const char*
.entryCount = wEntries.size(),
.entries = wEntries.data()
};
@@ -27,11 +27,6 @@
namespace filament::backend {
/**
* A WebGPU implementation of the HwDescriptorSetLayout.
* This class defines the layout of a descriptor set, which specifies the types and arrangement
* of resources that can be bound to a pipeline.
*/
class WebGPUDescriptorSetLayout final : public HwDescriptorSetLayout {
public:
struct BindGroupEntryInfo final {
File diff suppressed because it is too large Load Diff
+3 -10
View File
@@ -24,7 +24,6 @@
#include "webgpu/WebGPUPipelineCache.h"
#include "webgpu/WebGPUPipelineLayoutCache.h"
#include "webgpu/WebGPURenderPassMipmapGenerator.h"
#include "webgpu/utils/AsyncTaskCounter.h"
#include <backend/platforms/WebGPUPlatform.h>
#include "DriverBase.h"
@@ -48,12 +47,8 @@
namespace filament::backend {
class WebGPUSwapChain;
/**
* Implements the private backend driver API for WebGPU specifically (that API is essentially
* expressed in private/backend/DriverAPI.inc)
*
* It manages all the WebGPU resources necessary to accomplish this.
* WebGPU backend (driver) implementation
*/
class WebGPUDriver final : public DriverBase {
public:
@@ -68,10 +63,9 @@ private:
[[nodiscard]] ShaderLanguage getShaderLanguage() const noexcept final;
[[nodiscard]] wgpu::Sampler makeSampler(SamplerParams const& params);
[[nodiscard]] static wgpu::AddressMode fWrapModeToWAddressMode(const filament::backend::SamplerWrapMode& fUsage);
void setDebugTag(HandleBase::HandleId handleId, utils::CString tag);
// The platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
// handled in the WebGPUPlatform.
// the platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
// handled in the WebGPUPlatform
WebGPUPlatform& mPlatform;
wgpu::Adapter mAdapter = nullptr;
wgpu::Device mDevice = nullptr;
@@ -92,7 +86,6 @@ private:
spd::MipmapGenerator mSpdComputePassMipmapGenerator;
WebGPUMsaaTextureResolver mMsaaTextureResolver{};
WebGPUBlitter mBlitter;
webgpuutils::AsyncTaskCounter mReadPixelMapsCounter{};
struct DescriptorSetBindingInfo{
wgpu::BindGroup bindGroup;
+3 -2
View File
@@ -28,11 +28,12 @@ namespace filament::backend {
FenceStatus WebGPUFence::getStatus() { return mStatus.load(); }
void WebGPUFence::addMarkerToQueueState(wgpu::Queue const& queue) {
// The lambda function is called when the work is done. It updates the fence status based on the
// result of the work.
queue.OnSubmittedWorkDone(
wgpu::CallbackMode::AllowSpontaneous,
[this](const wgpu::QueueWorkDoneStatus status, wgpu::StringView message) {
// Note: The 'message' parameter is required by the function signature
// but can be ignored if not needed.
switch (status) {
case wgpu::QueueWorkDoneStatus::Success:
mStatus.store(FenceStatus::CONDITION_SATISFIED);
@@ -28,11 +28,6 @@ class Queue;
namespace filament::backend {
/**
* A WebGPU-specific implementation of the HwFence.
* This class is used to synchronize the CPU and GPU. It allows the CPU to know when the GPU has
* finished a set of commands.
*/
class WebGPUFence final : public HwFence {
public:
[[nodiscard]] FenceStatus getStatus();
@@ -40,9 +35,6 @@ public:
void addMarkerToQueueState(wgpu::Queue const&);
private:
// The current status of the fence.
// This is atomic because it can be updated by a WebGPU callback thread and read from the main
// thread.
std::atomic<FenceStatus> mStatus{ FenceStatus::TIMEOUT_EXPIRED };
};
@@ -30,10 +30,6 @@ enum class IndexFormat : uint32_t;
namespace filament::backend {
/**
* A WebGPU implementation of the HwIndexBuffer.
* This class represents a GPU buffer that stores indices for indexed drawing.
*/
class WebGPUIndexBuffer final : public HwIndexBuffer, public WebGPUBufferBase {
public:
WebGPUIndexBuffer(wgpu::Device const&, uint8_t elementSize, uint32_t indexCount);
@@ -48,8 +48,8 @@ void resolveColorTextures(wgpu::CommandEncoder const& commandEncoder,
const wgpu::RenderPassEncoder renderPassEncoder{ commandEncoder.BeginRenderPass(
&renderPassDescriptor) };
FILAMENT_CHECK_POSTCONDITION(renderPassEncoder)
<< "Failed to create wgpu::RenderPassEncoder for MSAA resolve.";
renderPassEncoder.End(); // The resolve is implicit in the pass.
<< "Failed to create wgpu::RenderPassEncoder for WebGPUDriver::resolve";
renderPassEncoder.End(); // only the implicit resolve is happening in the pass
}
} // namespace
@@ -59,29 +59,30 @@ void WebGPUMsaaTextureResolver::resolve(ResolveRequest const& request) {
ResolveRequest::TextureInfo const& destination{ request.destination };
FILAMENT_CHECK_PRECONDITION(destination.texture.GetWidth() == source.texture.GetWidth() &&
destination.texture.GetHeight() == source.texture.GetHeight())
<< "Invalid resolve: source and destination sizes don't match.";
<< "invalid resolve: source and destination sizes don't match";
FILAMENT_CHECK_PRECONDITION(
source.texture.GetSampleCount() > 1 && destination.texture.GetSampleCount() == 1)
<< "Invalid resolve: source.samples=" << source.texture.GetSampleCount()
<< "invalid resolve: source.samples=" << source.texture.GetSampleCount()
<< ", destination.samples=" << destination.texture.GetSampleCount();
FILAMENT_CHECK_PRECONDITION(source.texture.GetFormat() == destination.texture.GetFormat())
<< "Source and destination texture format don't match.";
<< "source and destination texture format don't match";
const wgpu::TextureFormat format{ source.texture.GetFormat() };
FILAMENT_CHECK_PRECONDITION(!hasDepth(format)) << "Can't resolve depth formats.";
FILAMENT_CHECK_PRECONDITION(!hasStencil(format)) << "Can't resolve stencil formats.";
FILAMENT_CHECK_PRECONDITION(!hasDepth(format)) << "can't resolve depth formats";
FILAMENT_CHECK_PRECONDITION(!hasStencil(format)) << "can't resolve stencil formats";
FILAMENT_CHECK_PRECONDITION(source.texture.GetUsage() & wgpu::TextureUsage::RenderAttachment)
<< "Source texture usage doesn't have wgpu::TextureUsage::RenderAttachment.";
<< "source texture usage doesn't have wgpu::TextureUsage::RenderAttachment";
FILAMENT_CHECK_PRECONDITION(
destination.texture.GetUsage() & wgpu::TextureUsage::RenderAttachment)
<< "Destination texture usage doesn't have wgpu::TextureUsage::RenderAttachment.";
<< "destination texture usage doesn't have wgpu::TextureUsage::RenderAttachment";
FILAMENT_CHECK_PRECONDITION(destination.texture.GetUsage() & wgpu::TextureUsage::TextureBinding)
<< "Destination texture usage doesn't have wgpu::TextureUsage::TextureBinding.";
<< "destination texture usage doesn't have wgpu::TextureUsage::TextureBinding";
const wgpu::TextureViewDescriptor sourceTextureViewDescriptor{
.label = "resolve_source_texture_view",
@@ -115,7 +116,7 @@ void WebGPUMsaaTextureResolver::resolve(ResolveRequest const& request) {
<< "Failed to create wgpu::TextureView destinationTextureView.";
if (hasDepth(format)) {
PANIC_PRECONDITION("Depth resolve not yet implemented.");
PANIC_PRECONDITION("DEPTH RESOLVE NOT IMPLEMENTED YET");
} else {
resolveColorTextures(request.commandEncoder, sourceTextureView, destinationTextureView);
}
@@ -31,10 +31,6 @@ namespace filament::backend {
class WebGPUTexture;
/**
* A utility class for resolving multisampled textures in WebGPU.
* This is necessary because WebGPU does not have an implicit resolve step like other APIs.
*/
class WebGPUMsaaTextureResolver final {
public:
struct ResolveRequest final {
@@ -51,9 +47,6 @@ public:
TextureInfo destination;
};
/**
* Resolves a multisampled texture into a single-sampled texture.
*/
void resolve(ResolveRequest const&);
};
@@ -54,7 +54,7 @@ namespace {
case CullingMode::FRONT: return wgpu::CullMode::Front;
case CullingMode::BACK: return wgpu::CullMode::Back;
case CullingMode::FRONT_AND_BACK:
// WebGPU does not support culling both front and back faces simultaneously.
// no WegGPU equivalent of front and back
FILAMENT_CHECK_POSTCONDITION(false)
<< "WebGPU does not support CullingMode::FRONT_AND_BACK";
return wgpu::CullMode::Undefined;
@@ -220,7 +220,7 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
const bool requestedDepth{ any(request.targetRenderFlags & TargetBufferFlags::DEPTH) };
const bool requestedStencil{ any(request.targetRenderFlags & TargetBufferFlags::STENCIL) };
const bool depthOrStencilRequested{ requestedDepth || requestedStencil };
// depth/stencil...
if (depthOrStencilRequested) {
FILAMENT_CHECK_PRECONDITION(request.depthStencilFormat != wgpu::TextureFormat::Undefined)
<< "Depth or Stencil requested for pipeline, but depthStencilFormat is "
@@ -293,11 +293,10 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
},
.primitive = {
.topology = toWebGPU(request.primitiveType),
// TODO This won't always be the case for the primitives bound. But this particular field
// in the pipeline struct is only meant for restarting the strip, which we don't need so far.
.stripIndexFormat =
isStripPrimitiveType(request.primitiveType)? wgpu::IndexFormat::Uint16 :
wgpu::IndexFormat::Undefined,
// TODO should we assume some constant format here or is there a way to get
// this from PipelineState somehow or elsewhere?
// Perhaps, cache/assert format from index buffers as they are requested?
.stripIndexFormat = wgpu::IndexFormat::Undefined,
.frontFace = request.rasterState.inverseFrontFaces ? wgpu::FrontFace::CW : wgpu::FrontFace::CCW,
.cullMode = toWebGPU(request.rasterState.culling),
// TODO no depth clamp in WebGPU supported directly. unclippedDepth is close, so we are
@@ -313,11 +312,6 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
},
.fragment = nullptr // will add below if fragment module is included
};
FILAMENT_CHECK_POSTCONDITION(!isStripPrimitiveType(request.primitiveType) ||
pipelineDescriptor.primitive.stripIndexFormat != wgpu::IndexFormat::Undefined)
<< "If the topology is a strip format, e.g. TriangleStrip, the stripIndexFormat cannot "
"be Undefined.";
wgpu::FragmentState fragmentState = {};
const wgpu::BlendState blendState {
.color = {
@@ -371,7 +365,6 @@ bool WebGPUPipelineCache::RenderPipelineKeyEqual::operator()(RenderPipelineKey c
}
void WebGPUPipelineCache::removeExpiredPipelines() {
FWGPU_SYSTRACE_SCOPE();
using Iterator = decltype(mRenderPipelines)::const_iterator;
for (Iterator iterator{ mRenderPipelines.begin() }; iterator != mRenderPipelines.end();) {
RenderPipelineCacheEntry const& entry{ iterator.value() };
@@ -34,11 +34,6 @@
namespace filament::backend {
/**
* A cache for WebGPU render pipelines.
* This class is responsible for creating and caching wgpu::RenderPipeline objects to avoid
* expensive pipeline creation at runtime.
*/
class WebGPUPipelineCache final {
public:
struct RenderPipelineRequest final {
@@ -68,9 +63,6 @@ public:
[[nodiscard]] wgpu::RenderPipeline const& getOrCreateRenderPipeline(
RenderPipelineRequest const&);
/**
* Should be called at the end of each frame to perform cache maintenance.
*/
void onFrameEnd();
private:
@@ -161,7 +153,7 @@ private:
// render targets... //
uint8_t multisampleCount{ 0 }; // 1 : 313
uint8_t colorFormatCount{ 0 }; // 1 : 314
uint8_t padding[5]{ 0 }; // 5 : 315
uint8_t padding[5]{ 0 }; // 5 : 319
TargetBufferFlags targetRenderFlags{ TargetBufferFlags::NONE }; // 4 : 320
wgpu::TextureFormat depthStencilFormat { wgpu::TextureFormat::Undefined }; // 4 : 324
wgpu::TextureFormat colorFormats[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]{ //
@@ -77,27 +77,26 @@ wgpu::PipelineLayout WebGPUPipelineLayoutCache::createPipelineLayout(
};
const wgpu::PipelineLayout layout{ mDevice.CreatePipelineLayout(&descriptor) };
FILAMENT_CHECK_POSTCONDITION(layout)
<< "Failed to create pipeline layout " << descriptor.label << ".";
<< "Failed to create pipeline layout " << descriptor.label << "?";
return layout;
}
bool WebGPUPipelineLayoutCache::PipelineLayoutKeyEqual::operator()(PipelineLayoutKey const& key1,
PipelineLayoutKey const& key2) const {
// Compare the raw bytes of the keys for equality.
return 0 == memcmp(reinterpret_cast<void const*>(&key1), reinterpret_cast<void const*>(&key2),
sizeof(key1));
}
void WebGPUPipelineLayoutCache::removeExpiredPipelineLayouts() {
FWGPU_SYSTRACE_SCOPE();
using Iterator = decltype(mPipelineLayouts)::const_iterator;
for (Iterator iterator{ mPipelineLayouts.begin() }; iterator != mPipelineLayouts.end();) {
PipelineLayoutCacheEntry const& entry{ iterator.value() };
if (mFrameCount > (entry.lastUsedFrameCount +
FILAMENT_WEBGPU_PIPELINE_LAYOUT_EXPIRATION_IN_FRAME_COUNT)) {
// The pipeline layout has not been used recently, so we can remove it from the cache.
// pipeline layout expired...
iterator = mPipelineLayouts.erase(iterator);
} else {
// pipeline layout not yet expired...
++iterator;
}
}
@@ -31,11 +31,6 @@
namespace filament::backend {
/**
* A cache for WebGPU pipeline layouts.
* This class is responsible for creating and caching wgpu::PipelineLayout objects to avoid
* expensive pipeline layout creation at runtime.
*/
class WebGPUPipelineLayoutCache final {
public:
struct PipelineLayoutRequest final {
@@ -50,16 +45,9 @@ public:
WebGPUPipelineLayoutCache& operator=(WebGPUPipelineLayoutCache const&) = delete;
WebGPUPipelineLayoutCache& operator=(WebGPUPipelineLayoutCache const&&) = delete;
/**
* Retrieves a pipeline layout from the cache or creates a new one if it doesn't exist.
* @return A constant reference to the cached or newly created pipeline layout.
*/
[[nodiscard]] wgpu::PipelineLayout const& getOrCreatePipelineLayout(
PipelineLayoutRequest const&);
/**
* Should be called at the end of each frame to perform cache maintenance.
*/
void onFrameEnd();
private:
@@ -71,10 +59,10 @@ private:
* instances, single bytes for booleans etc.), trivial copying and comparison (byte by byte),
* and a word-aligned structure with a size in bytes as a multiple of 4 (for murmer hash).
*/
struct PipelineLayoutKey final {
WGPUBindGroupLayout bindGroupLayoutHandles[MAX_DESCRIPTOR_SET_COUNT]{ nullptr }; // 32 :0
uint8_t bindGroupLayoutCount{ 0 }; // 1 :32
uint8_t padding[7]{ 0 }; // 7 :33
struct PipelineLayoutKey final { // size : offset (need multiples of 4 bytes for hashing)
WGPUBindGroupLayout bindGroupLayoutHandles[MAX_DESCRIPTOR_SET_COUNT]{ nullptr }; // 32 : 0
uint8_t bindGroupLayoutCount{ 0 }; // 1 : 32
uint8_t padding[7]{ 0 }; // 7 : 33
};
static_assert(sizeof(PipelineLayoutKey) == 40,
"PipelineLayoutKey must not have implicit padding.");
@@ -89,7 +89,7 @@ namespace {
std::string_view(sourceData + posAfterId, posEndOfStatement - posAfterId);
size_t posOfEqual = statementSegment.find('=');
if (posOfEqual == std::string::npos) {
// Not an assignment, so we don't need to replace it.
// not an assignment statement, so stream to the end of the statement and continue...
processedShaderSource << std::string_view(sourceData + pos,
posEndOfStatement + 1 - pos);
pos = posEndOfStatement + 1;
@@ -122,7 +122,10 @@ namespace {
}
const auto newValueItr = specConstants.find(static_cast<uint32_t>(constantId));
if (newValueItr == specConstants.end()) {
// The constant is not being overridden, so keep the default value.
// not going to override the constant,
// as the specConstants parameter doesn't specify it. So, we will keep the default
// already in the source text
// (stream to the end of the statement)...
processedShaderSource << std::string_view(sourceData + pos,
posEndOfStatement + 1 - pos);
pos = posEndOfStatement + 1;
@@ -171,7 +174,7 @@ namespace {
utils::FixedCapacityVector<uint8_t> const& sourceBytes =
shaderSource[static_cast<size_t>(stage)];
if (sourceBytes.empty()) {
return nullptr; // No shader source to compile.
return nullptr;// nothing to compile/create, the shader was not provided
}
std::stringstream labelStream;
labelStream << programName << " " << filamentShaderStageToString(stage) << " shader";
@@ -189,8 +192,7 @@ namespace {
};
const wgpu::ShaderModule shaderModule = device.CreateShaderModule(&descriptor);
const wgpu::Instance instance = device.GetAdapter().GetInstance();
// Synchronously compile the shader module.
// synchronously creates the shader module...
const wgpu::WaitStatus waitResult = instance.WaitAny(
shaderModule.GetCompilationInfo(wgpu::CallbackMode::WaitAnyOnly,
[&descriptor](auto const& status,
@@ -280,7 +282,7 @@ WebGPUProgram::WebGPUProgram(wgpu::Device const& device, Program const& program)
: HwProgram{ program.getName() } {
std::unordered_map<uint32_t, std::variant<int32_t, float, bool>> specConstants;
toMap(program.getSpecializationConstants(), specConstants);
// TODO: Consider creating/compiling these shaders in parallel.
// TODO consider creating/compiling these shaders in parallel
vertexShaderModule = createShaderModule(device, program, ShaderStage::VERTEX, specConstants);
fragmentShaderModule =
createShaderModule(device, program, ShaderStage::FRAGMENT, specConstants);
@@ -25,10 +25,6 @@ namespace filament::backend {
class Program;
/**
* A WebGPU implementation of the HwProgram.
* This class holds the compiled shader modules for a given program.
*/
class WebGPUProgram final : public HwProgram {
public:
WebGPUProgram(wgpu::Device const&, Program const&);

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