Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a2b46e134 |
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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) {
|
||||
|
||||
-9
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -221,8 +221,6 @@ export is an html with the output captured in a <code><pre></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
@@ -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', '~> 1.64.1'
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 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->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->beginFrame(swapChain)) {
|
||||
@@ -408,7 +408,7 @@ if (renderer->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>
|
||||
|
||||
|
||||
@@ -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
@@ -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', '~> 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 & 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->createSwapChain(nativeWindow);
|
||||
Renderer* renderer = engine->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->createCamera(EntityManager::get().create());
|
||||
View* view = engine->createView();
|
||||
Scene* scene = engine->createScene();
|
||||
|
||||
view->setCamera(camera);
|
||||
view->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->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->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->beginFrame(swapChain)) {
|
||||
// for each View
|
||||
renderer->render(view);
|
||||
renderer->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>
|
||||
|
||||
@@ -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"> </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"> </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"> </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 1.18 </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);">✒</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 1.18 </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);">✒</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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 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 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 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 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"> </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×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×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×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×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×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×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×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×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> "parameters": [
|
||||
<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 1.18 </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);">✒</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 1.18 </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);">✒</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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 > About Phone and tap the Build number 7 times). You need to go to
|
||||
Settings > System > 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 > System > 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 > 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
|
||||
</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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+2
-5
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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("
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user