Compare commits

..
127 changed files with 1623 additions and 3791 deletions
+1 -1
View File
@@ -3,5 +3,5 @@ runs:
using: "composite"
steps:
- name: Set up dependency versions
shell: bash
shell: bash
run: cat ./build/common/versions >> $GITHUB_ENV
-16
View File
@@ -1,16 +0,0 @@
name: 'Web Preqrequisites'
runs:
using: "composite"
steps:
- uses: ./.github/actions/dep-versions
- name: Cache EMSDK
id: emsdk-cache
uses: actions/cache@v4 # Use a specific version
with:
path: emsdk
key: ${{ runner.os }}-emsdk-${{ env.GITHUB_EMSDK_VERSION }}
- name: Install Web Prerequisites
shell: bash
run: |
bash ./build/common/get-emscripten.sh
echo "EMSDK=$PWD/emsdk" >> $GITHUB_ENV
+1 -1
View File
@@ -26,4 +26,4 @@ jobs:
path: out/filament-release-darwin.tgz
- name: Check public headers
run: |
test/check-headers/test.sh out/release/filament/include
build/common/check-headers.sh out/release/filament/include
+6 -9
View File
@@ -96,7 +96,6 @@ jobs:
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
@@ -124,15 +123,13 @@ jobs:
- uses: ./.github/actions/mac-prereq
- name: Cache Mesa and deps
id: mesa-cache
uses: actions/cache@v4
uses: actions/cache@v4 # Use a specific version
with:
path: mesa
key: ${{ runner.os }}-mesa-deps-2-${{ vars.MESA_VERSION }}
- name: Prerequisites
id: prereqs
run: |
bash build/common/get-mesa.sh
pip install tifffile numpy
- name: Get Mesa
id: mesa-prereq
run: bash test/utils/get_mesa.sh
- name: Run Test
run: bash test/renderdiff/test.sh
- uses: actions/upload-artifact@v4
@@ -153,8 +150,8 @@ jobs:
- name: Run test
run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
test-code-correctness:
name: test-code-correctness
code-correcteness:
name: code-correctness
runs-on: 'macos-14-xlarge'
steps:
- uses: actions/checkout@v4.1.6
+6 -6
View File
@@ -65,9 +65,13 @@ jobs:
build-mac:
name: build-mac
runs-on: macos-14-xlarge
runs-on: ${{ matrix.os }}
if: github.event_name == 'release' || github.event.inputs.platform == 'desktop'
strategy:
matrix:
os: [macos-14-xlarge, ubuntu-22.04-32core]
steps:
- name: Decide Git ref
id: git_ref
@@ -114,7 +118,6 @@ jobs:
with:
ref: ${{ steps.git_ref.outputs.ref }}
- uses: ./.github/actions/linux-prereq
- uses: ./.github/actions/web-prereq
- name: Run build script
env:
TAG: ${{ steps.git_ref.outputs.tag }}
@@ -163,9 +166,6 @@ jobs:
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
mv out/gltfio-android-release.aar out/gltfio-${TAG}-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${TAG}-android.aar
cd out/android-release/filament
tar -czf ../../filament-${TAG}-android-native.tgz .
cd ../../..
- name: Sign sample-gltf-viewer
run: |
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
@@ -187,7 +187,7 @@ jobs:
script: |
const upload = require('./build/common/upload-release-assets');
const { TAG } = process.env;
const globber = await glob.create(['out/*.aar', 'out/*.apk', 'out/*.tgz'].join('\n'));
const globber = await glob.create(['out/*.aar', 'out/*.apk'].join('\n'));
await upload({ github, context }, await globber.glob(), TAG);
build-ios:
-1
View File
@@ -17,7 +17,6 @@ jobs:
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 continuous
-2
View File
@@ -363,8 +363,6 @@ python ./emsdk.py activate latest
source ./emsdk_env.sh
```
Alternatively, you can try running the script `build/common/get-emscripten.sh`.
After this you can invoke the [easy build](#easy-build) script as follows:
```shell
-2
View File
@@ -7,5 +7,3 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.59.5'
implementation 'com.google.android.filament:filament-android:1.59.4'
}
```
@@ -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.59.5'
pod 'Filament', '~> 1.59.4'
```
## Documentation
-5
View File
@@ -7,11 +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.60.0
- materials: remove dependence on per-view descset layout from filamat. [⚠️ **New Material Version**]
- `ColorGrading::Builder::toneMapper` now takes a `shared_ptr<ToneMapper>`
## v1.59.5
@@ -18,7 +18,6 @@
#include <filament/ColorGrading.h>
#include <filament/ToneMapper.h>
#include <memory>
#include <math/vec3.h>
#include <math/vec4.h>
@@ -68,9 +67,8 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_ColorGrading_nBuilderToneMapper(JNIEnv*, jclass,
jlong nativeBuilder, jlong toneMapper_) {
ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder;
ToneMapper* toneMapper = reinterpret_cast<ToneMapper*>(toneMapper_);
std::shared_ptr<ToneMapper> toneMapperCopy(toneMapper->clone());
builder->toneMapper(toneMapperCopy);
const ToneMapper* toneMapper = (const ToneMapper*) toneMapper_;
builder->toneMapper(toneMapper);
}
#pragma clang diagnostic push
@@ -214,9 +214,9 @@ public class ColorGrading {
*
* The default tone mapping operator is {@link ToneMapper.ACESLegacy}.
*
* The copy of the specified tone mapper is set to this builder. It is safe to delete
* the original tone mapper object while the copied one is held by the built ColorGrading
* object.
* The specified tone mapper must have a lifecycle that exceeds the lifetime of
* this builder. Since the build(Engine&) method is synchronous, it is safe to
* delete the tone mapper object after that finishes executing.
*
* @param toneMapper The tone mapping operator to apply to the HDR color buffer
*
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.59.5
VERSION_NAME=1.59.4
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+1 -1
View File
@@ -151,7 +151,7 @@ function print_fgviewer_help {
}
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | cut -f 1 -d ".")}
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/android/ndk.version | cut -f 1 -d ".")}
# Requirements
CMAKE_MAJOR=3
+28 -1
View File
@@ -1,6 +1,28 @@
#!/bin/bash
source `dirname $0`/../common/ci-check.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
set -e
set -x
@@ -8,6 +30,11 @@ set -x
UNAME=`echo $(uname)`
LC_UNAME=`echo $UNAME | tr '[:upper:]' '[:lower:]'`
# build-common.sh will generate the following variables:
# $GENERATE_ARCHIVES
# $BUILD_DEBUG
# $BUILD_RELEASE
source `dirname $0`/../common/ci-common.sh
source `dirname $0`/../common/build-common.sh
if [[ "$GITHUB_WORKFLOW" ]]; then
-15
View File
@@ -1,20 +1,5 @@
#!/bin/bash
# build-common.sh will generate the following variables:
# $GENERATE_ARCHIVES
# $BUILD_DEBUG
# $BUILD_RELEASE
# Typically a build script (build.sh) would source this script. For example,
# source `dirname $0`/../common/build-common.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
if [[ ! "$TARGET" ]]; then
if [[ "$1" ]]; then
TARGET=$1
-19
View File
@@ -1,19 +0,0 @@
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
if [[ "$GITHUB_WORKFLOW" ]]; then
echo "Running workflow $GITHUB_WORKFLOW (event: $GITHUB_EVENT_NAME, action: $GITHUB_ACTION)"
fi
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
if [[ "$GITHUB_WORKFLOW" ]]; then
echo "Running workflow $GITHUB_WORKFLOW (event: $GITHUB_EVENT_NAME, action: $GITHUB_ACTION)"
fi
-22
View File
@@ -1,22 +0,0 @@
#!/bin/bash
if [ -d "./emsdk" ]; then
echo "emsdk folder found. Assume emsdk has been installed."
cd emsdk
./emsdk activate latest
source ./emsdk_env.sh
export EMSDK="$PWD"
cd ..
exit 0
fi
# Install emscripten.
EMSDK_VERSION=${GITHUB_EMSDK_VERSION-3.1.60}
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/${EMSDK_VERSION}.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
export EMSDK="$PWD"
cd ..
+1 -2
View File
@@ -3,5 +3,4 @@ GITHUB_CMAKE_VERSION=3.19.5
GITHUB_NINJA_VERSION=1.10.2
GITHUB_MESA_VERSION=24.2.1
GITHUB_LLVM_VERSION=16
GITHUB_NDK_VERSION=27.0.11718014
GITHUB_EMSDK_VERSION=3.1.60
GITHUB_NDK_VERSION=27.0.11718014
+25 -1
View File
@@ -1,11 +1,35 @@
#!/bin/bash
source `dirname $0`/../common/ci-check.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
set -e
set -x
source `dirname $0`/../common/ci-common.sh
source `dirname $0`/../common/build-common.sh
pushd `dirname $0`/../.. > /dev/null
# If we're generating an archive for release or continuous builds, then we'll also build for the
+29 -2
View File
@@ -1,11 +1,38 @@
#!/bin/bash
source `dirname $0`/../common/ci-check.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
set -e
set -x
# build-common.sh will generate the following variables:
# $GENERATE_ARCHIVES
# $BUILD_DEBUG
# $BUILD_RELEASE
source `dirname $0`/../common/ci-common.sh
source `dirname $0`/../common/build-common.sh
pushd `dirname $0`/../.. > /dev/null
pushd `dirname $0`/../.. > /dev/null
./build.sh -c $RUN_TESTS $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
+25 -2
View File
@@ -1,11 +1,34 @@
#!/bin/bash
source `dirname $0`/../common/ci-check.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
set -e
set -x
source `dirname $0`/../common/ci-common.sh
source `dirname $0`/../common/build-common.sh
pushd `dirname $0`/../.. > /dev/null
pushd `dirname $0`/../.. > /dev/null
./build.sh -c $RUN_TESTS $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
+25 -1
View File
@@ -1,10 +1,34 @@
#!/bin/bash
source `dirname $0`/../common/ci-check.sh
# Usage: the first argument selects the build type:
# - release, to build release only
# - debug, to build debug only
# - continuous, to build release and debug
# - presubmit, for presubmit builds
#
# The default is release
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
read -r -p "Do you wish to proceed (y/n)? " choice
case "${choice}" in
y|Y)
echo "Build will proceed..."
;;
n|N)
exit 0
;;
*)
exit 0
;;
esac
set -e
set -x
source `dirname $0`/../common/ci-common.sh
source `dirname $0`/ci-common.sh
source `dirname $0`/../common/build-common.sh
pushd `dirname $0`/../.. > /dev/null
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
# Install emscripten.
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.60.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
export EMSDK="$PWD"
cd ..
-1
View File
@@ -18,7 +18,6 @@
- [Metal](./notes/metal_debugging.md)
- [Vulkan](./notes/vulkan_debugging.md)
- [SPIR-V](./notes/spirv_debugging.md)
- [Running with ASAN and UBSAN](./notes/asan_ubsan.md)
- [Libraries](./notes/libs.md)
- [bluegl](./dup/bluegl.md)
- [bluevk](./dup/bluevk.md)
-41
View File
@@ -1,41 +0,0 @@
# Running with ASAN/UBSAN
## Enabling
When building though build.sh, pass the `-b` flag. This sets the cmake variable
`FILAMENT_ENABLE_ASAN_UBSAN=ON` which eventually passes `"-fsanitize=address -fsanitize=undefined"`
to all compile and link operations.
If building through CMake directly, or an IDE like CLion that doesn't use build.sh, instead pass
`-DFILAMENT_ENABLE_ASAN_UBSAN=ON` to cmake in order to get the same result.
## Getting memory leak detection on Mac
Memory leak detection isn't enabled by default on MacOS. There are two issues to address, first is
using a version of clang that supports memory leak detection and second is enabling it at runtime.
The version of clang distributed by Apple (with a version like "Apple clang version 16.0.0") doesn't
currently support leak detection at all. Instead you will need to get or build a different LLVM,
such as the one distributed through homebrew and get CMake to use that instead.
Then during runtime you'll need to have the environment variable `ASAN_OPTIONS` include the option
`detect_leaks=1`. Multiple `ASAN_OPTIONS` values are concatenated with `:`.
## Getting memory leak output in CLion
### Setting variables
Under `Settings | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers` there is an
ASAN Settings field that overrides whatever other `ASAN_OPTIONS` you might set elsewhere, so you
must use that instead of setting it through your Run/Debug Configuration.
To pass `-DFILAMENT_ENABLE_ASAN_UBSAN=ON` to CMake you'll want to create a new CMake Profile and
pass it as a CMake argument.
### Avoiding losing output
CMake will consume ASAN output and display it through a separate "Sanitizers" tab. Unfortunately
certain leak detection errors that interrupt the executable seem to not show up in this tab, but are
still removed from the user-visible console output. If this is happening and you need to see the
unfiltered console output you'll need to go to `Settings | Build, Execution, Deployment | Dynamic
Analysis Tools | Sanitizers` and uncheck "Use visual representation for Sanitizer's output".
+20
View File
@@ -5,6 +5,18 @@ set(TARGET backend)
set(PUBLIC_HDR_DIR include)
set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
# ==================================================================================================
# Compilation options
# ==================================================================================================
#
set(BACKEND_SANITIZATION "" CACHE STRING "Sanitization option")
set_property(CACHE BACKEND_SANITIZATION PROPERTY STRINGS ";ASAN")
set(BACKEND_SANITIZERS)
if (BACKEND_SANITIZATION STREQUAL "ASAN")
set(BACKEND_SANITIZERS -fsanitize=address)
endif()
# ==================================================================================================
# Sources and headers
# ==================================================================================================
@@ -472,6 +484,7 @@ target_compile_options(${TARGET} PRIVATE
${OSMESA_COMPILE_FLAGS}
$<$<CONFIG:Release>:${OPTIMIZATION_FLAGS}>
$<$<AND:$<PLATFORM_ID:Darwin>,$<CONFIG:Release>>:${DARWIN_OPTIMIZATION_FLAGS}>
${BACKEND_SANITIZERS}
)
if (FILAMENT_SUPPORTS_METAL)
@@ -482,6 +495,8 @@ if (FILAMENT_SUPPORTS_WEBGPU)
target_compile_definitions(${TARGET} PRIVATE $<$<BOOL:${FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING}>:FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING>)
endif()
target_link_options(${TARGET} PRIVATE ${BACKEND_SANITIZERS})
target_link_libraries(${TARGET} PRIVATE
${OSMESA_LINKER_FLAGS}
$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>:${LINUX_LINKER_OPTIMIZATION_FLAGS}>
@@ -551,6 +566,8 @@ if (APPLE AND NOT IOS)
test/test_RenderExternalImage.cpp)
add_library(backend_test STATIC ${BACKEND_TEST_SRC})
target_link_libraries(backend_test PUBLIC ${BACKEND_TEST_LIBS})
target_compile_options(backend_test PRIVATE ${BACKEND_SANITIZERS})
target_link_options(backend_test PRIVATE ${BACKEND_SANITIZERS})
set(BACKEND_TEST_DEPS
OSDependent
@@ -589,6 +606,7 @@ if (APPLE AND NOT IOS)
# linker from removing "unused" symbols.
target_link_libraries(backend_test_mac PRIVATE -force_load backend_test)
set_target_properties(backend_test_mac PROPERTIES FOLDER Tests)
target_link_options(backend_test_mac PRIVATE ${BACKEND_SANITIZERS})
# This is needed after XCode 15.3
set_target_properties(backend_test_mac PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
@@ -598,6 +616,8 @@ endif()
if (LINUX)
add_executable(backend_test_linux test/linux_runner.cpp ${BACKEND_TEST_SRC})
target_compile_options(backend_test_linux PRIVATE ${BACKEND_SANITIZERS})
target_link_options(backend_test_linux PRIVATE ${BACKEND_SANITIZERS})
target_link_libraries(backend_test_linux PRIVATE ${BACKEND_TEST_LIBS})
set_target_properties(backend_test_linux PROPERTIES FOLDER Tests)
endif()
+35 -184
View File
@@ -30,17 +30,16 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <utils/StaticString.h>
#include <math/vec4.h>
#include <array>
#include <type_traits>
#include <variant>
#include <string_view>
#include <stddef.h>
#include <stdint.h>
#include <utils/StaticString.h>
/**
* Types and enums used by filament's driver.
@@ -160,7 +159,7 @@ enum class TimerQueryResult : int8_t {
AVAILABLE = 1, // result is available
};
constexpr std::string_view to_string(Backend const backend) noexcept {
static constexpr const char* backendToString(Backend backend) {
switch (backend) {
case Backend::NOOP:
return "Noop";
@@ -172,11 +171,9 @@ enum class TimerQueryResult : int8_t {
return "Metal";
case Backend::WEBGPU:
return "WebGPU";
case Backend::DEFAULT:
return "Default";
break;
default:
return "Unknown";
}
return "Unknown";
}
/**
@@ -193,7 +190,7 @@ enum class ShaderLanguage {
WGSL = 5,
};
constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) noexcept {
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
switch (shaderLanguage) {
case ShaderLanguage::ESSL1:
return "ESSL 1.0";
@@ -208,7 +205,6 @@ constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) noex
case ShaderLanguage::WGSL:
return "WGSL";
}
return "UNKNOWN";
}
enum class ShaderStage : uint8_t {
@@ -226,7 +222,7 @@ enum class ShaderStageFlags : uint8_t {
ALL_SHADER_STAGE_FLAGS = VERTEX | FRAGMENT | COMPUTE
};
constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
switch (type) {
case ShaderStage::VERTEX:
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::VERTEX));
@@ -237,114 +233,14 @@ enum class ShaderStageFlags : uint8_t {
}
}
enum class TextureType : uint8_t {
FLOAT,
INT,
UINT,
DEPTH,
STENCIL,
DEPTH_STENCIL
enum class DescriptorType : uint8_t {
UNIFORM_BUFFER,
SHADER_STORAGE_BUFFER,
SAMPLER,
INPUT_ATTACHMENT,
SAMPLER_EXTERNAL
};
constexpr std::string_view to_string(TextureType type) noexcept {
switch (type) {
case TextureType::FLOAT: return "FLOAT";
case TextureType::INT: return "INT";
case TextureType::UINT: return "UINT";
case TextureType::DEPTH: return "DEPTH";
case TextureType::STENCIL: return "STENCIL";
case TextureType::DEPTH_STENCIL: return "DEPTH_STENCIL";
}
return "UNKNOWN";
}
enum class DescriptorType : uint8_t {
SAMPLER_2D_FLOAT,
SAMPLER_2D_INT,
SAMPLER_2D_UINT,
SAMPLER_2D_DEPTH,
SAMPLER_2D_ARRAY_FLOAT,
SAMPLER_2D_ARRAY_INT,
SAMPLER_2D_ARRAY_UINT,
SAMPLER_2D_ARRAY_DEPTH,
SAMPLER_CUBE_FLOAT,
SAMPLER_CUBE_INT,
SAMPLER_CUBE_UINT,
SAMPLER_CUBE_DEPTH,
SAMPLER_CUBE_ARRAY_FLOAT,
SAMPLER_CUBE_ARRAY_INT,
SAMPLER_CUBE_ARRAY_UINT,
SAMPLER_CUBE_ARRAY_DEPTH,
SAMPLER_3D_FLOAT,
SAMPLER_3D_INT,
SAMPLER_3D_UINT,
SAMPLER_EXTERNAL,
UNIFORM_BUFFER,
SHADER_STORAGE_BUFFER,
INPUT_ATTACHMENT,
};
constexpr bool isDepthDescriptor(DescriptorType const type) noexcept {
switch (type) {
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
return true;
default: ;
}
return false;
}
constexpr bool isFloatDescriptor(DescriptorType const type) noexcept {
switch (type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
return true;
default: ;
}
return false;
}
constexpr std::string_view to_string(DescriptorType type) noexcept {
#define DESCRIPTOR_TYPE_CASE(TYPE) case DescriptorType::TYPE: return #TYPE;
switch (type) {
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_EXTERNAL)
DESCRIPTOR_TYPE_CASE(UNIFORM_BUFFER)
DESCRIPTOR_TYPE_CASE(SHADER_STORAGE_BUFFER)
DESCRIPTOR_TYPE_CASE(INPUT_ATTACHMENT)
}
return "UNKNOWN";
#undef DESCRIPTOR_TYPE_CASE
}
enum class DescriptorFlags : uint8_t {
NONE = 0x00,
DYNAMIC_OFFSET = 0x01
@@ -355,13 +251,6 @@ using descriptor_set_t = uint8_t;
using descriptor_binding_t = uint8_t;
struct DescriptorSetLayoutBinding {
static bool isSampler(DescriptorType type) noexcept {
return int(type) <= int(DescriptorType::SAMPLER_EXTERNAL);
}
static bool isBuffer(DescriptorType type) noexcept {
return type == DescriptorType::UNIFORM_BUFFER ||
type == DescriptorType::SHADER_STORAGE_BUFFER;
}
DescriptorType type;
ShaderStageFlags stageFlags;
descriptor_binding_t binding;
@@ -372,7 +261,7 @@ struct DescriptorSetLayoutBinding {
// no uninitialized padding bytes.
// uint8_t externalSamplerDataIndex = EXTERNAL_SAMPLER_DATA_INDEX_UNUSED;
friend bool operator==(DescriptorSetLayoutBinding const& lhs,
friend inline bool operator==(DescriptorSetLayoutBinding const& lhs,
DescriptorSetLayoutBinding const& rhs) noexcept {
return lhs.type == rhs.type &&
lhs.flags == rhs.flags &&
@@ -405,7 +294,7 @@ enum class TargetBufferFlags : uint32_t {
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
};
constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
inline constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
if (index == 0u) return TargetBufferFlags::COLOR0;
if (index == 1u) return TargetBufferFlags::COLOR1;
if (index == 2u) return TargetBufferFlags::COLOR2;
@@ -562,24 +451,6 @@ enum class SamplerType : uint8_t {
SAMPLER_CUBEMAP_ARRAY, //!< Cube map array texture (feature level 2)
};
constexpr std::string_view to_string(SamplerType const type) noexcept {
switch (type) {
case SamplerType::SAMPLER_2D:
return "SAMPLER_2D";
case SamplerType::SAMPLER_2D_ARRAY:
return "SAMPLER_2D_ARRAY";
case SamplerType::SAMPLER_CUBEMAP:
return "SAMPLER_CUBEMAP";
case SamplerType::SAMPLER_EXTERNAL:
return "SAMPLER_EXTERNAL";
case SamplerType::SAMPLER_3D:
return "SAMPLER_3D";
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return "SAMPLER_CUBEMAP_ARRAY";
}
return "Unknown";
}
//! Subpass type
enum class SubpassType : uint8_t {
SUBPASS_INPUT
@@ -593,20 +464,6 @@ enum class SamplerFormat : uint8_t {
SHADOW = 3 //!< shadow sampler (PCF)
};
constexpr std::string_view to_string(SamplerFormat const format) noexcept {
switch (format) {
case SamplerFormat::INT:
return "INT";
case SamplerFormat::UINT:
return "UINT";
case SamplerFormat::FLOAT:
return "FLOAT";
case SamplerFormat::SHADOW:
return "SHADOW";
}
return "Unknown";
}
/**
* Supported element types
*/
@@ -907,8 +764,6 @@ enum class TextureFormat : uint16_t {
SRGB_ALPHA_BPTC_UNORM, // BC7 sRGB
};
TextureType getTextureType(TextureFormat format) noexcept;
//! Bitmask describing the intended Texture Usage
enum class TextureUsage : uint16_t {
NONE = 0x0000,
@@ -936,7 +791,7 @@ enum class TextureSwizzle : uint8_t {
};
//! returns whether this format a depth format
constexpr bool isDepthFormat(TextureFormat format) noexcept {
static constexpr bool isDepthFormat(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::DEPTH32F:
case TextureFormat::DEPTH24:
@@ -949,7 +804,7 @@ enum class TextureSwizzle : uint8_t {
}
}
constexpr bool isStencilFormat(TextureFormat format) noexcept {
static constexpr bool isStencilFormat(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::STENCIL8:
case TextureFormat::DEPTH24_STENCIL8:
@@ -960,7 +815,7 @@ enum class TextureSwizzle : uint8_t {
}
}
constexpr bool isColorFormat(TextureFormat format) noexcept {
inline constexpr bool isColorFormat(TextureFormat format) noexcept {
switch (format) {
// Standard color formats
case TextureFormat::R8:
@@ -987,7 +842,7 @@ enum class TextureSwizzle : uint8_t {
return false;
}
constexpr bool isUnsignedIntFormat(TextureFormat format) {
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8UI:
case TextureFormat::R16UI:
@@ -1008,7 +863,7 @@ enum class TextureSwizzle : uint8_t {
}
}
constexpr bool isSignedIntFormat(TextureFormat format) {
static constexpr bool isSignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8I:
case TextureFormat::R16I:
@@ -1030,35 +885,35 @@ enum class TextureSwizzle : uint8_t {
}
//! returns whether this format is a compressed format
constexpr bool isCompressedFormat(TextureFormat format) noexcept {
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11;
}
//! returns whether this format is an ETC2 compressed format
constexpr bool isETC2Compression(TextureFormat format) noexcept {
static constexpr bool isETC2Compression(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11 && format <= TextureFormat::ETC2_EAC_SRGBA8;
}
//! returns whether this format is an S3TC compressed format
constexpr bool isS3TCCompression(TextureFormat format) noexcept {
static constexpr bool isS3TCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_SRGBA;
}
constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA;
}
//! returns whether this format is an RGTC compressed format
constexpr bool isRGTCCompression(TextureFormat format) noexcept {
static constexpr bool isRGTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RED_RGTC1 && format <= TextureFormat::SIGNED_RED_GREEN_RGTC2;
}
//! returns whether this format is an BPTC compressed format
constexpr bool isBPTCCompression(TextureFormat format) noexcept {
static constexpr bool isBPTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RGB_BPTC_SIGNED_FLOAT && format <= TextureFormat::SRGB_ALPHA_BPTC_UNORM;
}
constexpr bool isASTCCompression(TextureFormat format) noexcept {
static constexpr bool isASTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RGBA_ASTC_4x4 && format <= TextureFormat::SRGB8_ALPHA8_ASTC_12x12;
}
@@ -1183,19 +1038,15 @@ struct SamplerParams { // NOLINT
}
};
bool isFiltered() const noexcept {
return filterMag != SamplerMagFilter::NEAREST || filterMin != SamplerMinFilter::NEAREST;
}
private:
friend bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
return EqualTo{}(lhs, rhs);
friend inline bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
return SamplerParams::EqualTo{}(lhs, rhs);
}
friend bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
return !EqualTo{}(lhs, rhs);
friend inline bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
return !SamplerParams::EqualTo{}(lhs, rhs);
}
friend bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
return LessThan{}(lhs, rhs);
friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
return SamplerParams::LessThan{}(lhs, rhs);
}
};
@@ -1245,15 +1096,15 @@ struct SamplerYcbcrConversion {// NOLINT
};
private:
friend bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend inline bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
}
friend bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend inline bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return !SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
}
friend bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend inline bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return SamplerYcbcrConversion::LessThan{}(lhs, rhs);
}
+2 -2
View File
@@ -44,8 +44,8 @@ public:
struct Descriptor {
utils::CString name;
DescriptorType type;
descriptor_binding_t binding;
backend::DescriptorType type;
backend::descriptor_binding_t binding;
};
struct SpecializationConstant {
-139
View File
@@ -18,8 +18,6 @@
#include "DataReshaper.h"
#include <backend/DriverEnums.h>
#include <utils/CString.h>
#include <string_view>
@@ -225,143 +223,6 @@ size_t getFormatSize(TextureFormat format) noexcept {
}
}
TextureType getTextureType(TextureFormat const format) noexcept {
switch (format) {
case TextureFormat::UNUSED:
// should not happen
return TextureType::FLOAT;
case TextureFormat::R8:
case TextureFormat::R16F:
case TextureFormat::RG8:
case TextureFormat::RGB565:
case TextureFormat::RGB5_A1:
case TextureFormat::RGBA4:
case TextureFormat::R32F:
case TextureFormat::RGB8:
case TextureFormat::SRGB8:
case TextureFormat::RG16F:
case TextureFormat::R11F_G11F_B10F:
case TextureFormat::RGB9_E5:
case TextureFormat::RGBA8:
case TextureFormat::SRGB8_A8:
case TextureFormat::RGB10_A2:
case TextureFormat::RGB16F:
case TextureFormat::RG32F:
case TextureFormat::RGBA16F:
case TextureFormat::RGB32F:
case TextureFormat::RGBA32F:
return TextureType::FLOAT;
case TextureFormat::R8_SNORM:
case TextureFormat::RG8_SNORM:
case TextureFormat::RGB8_SNORM:
case TextureFormat::RGBA8_SNORM:
// SNORM are treated as float
return TextureType::FLOAT;
case TextureFormat::R8UI:
case TextureFormat::R16UI:
case TextureFormat::RG8UI:
case TextureFormat::RGB8UI:
case TextureFormat::R32UI:
case TextureFormat::RG16UI:
case TextureFormat::RGBA8UI:
case TextureFormat::RGB16UI:
case TextureFormat::RG32UI:
case TextureFormat::RGBA16UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA32UI:
return TextureType::UINT;
case TextureFormat::R8I:
case TextureFormat::R16I:
case TextureFormat::RG8I:
case TextureFormat::RGB8I:
case TextureFormat::R32I:
case TextureFormat::RG16I:
case TextureFormat::RGBA8I:
case TextureFormat::RGB16I:
case TextureFormat::RG32I:
case TextureFormat::RGBA16I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA32I:
return TextureType::INT;
case TextureFormat::DEPTH16:
case TextureFormat::DEPTH24:
case TextureFormat::DEPTH32F:
return TextureType::DEPTH;
case TextureFormat::STENCIL8:
return TextureType::STENCIL;
case TextureFormat::DEPTH24_STENCIL8:
case TextureFormat::DEPTH32F_STENCIL8:
return TextureType::DEPTH_STENCIL;
// Compressed formats ---------------------------------------------------------------------
case TextureFormat::EAC_RG11:
case TextureFormat::EAC_RG11_SIGNED:
case TextureFormat::ETC2_EAC_RGBA8:
case TextureFormat::ETC2_EAC_SRGBA8:
case TextureFormat::EAC_R11:
case TextureFormat::EAC_R11_SIGNED:
case TextureFormat::ETC2_RGB8:
case TextureFormat::ETC2_SRGB8:
case TextureFormat::ETC2_RGB8_A1:
case TextureFormat::ETC2_SRGB8_A1:
case TextureFormat::DXT1_RGB:
case TextureFormat::DXT1_RGBA:
case TextureFormat::DXT1_SRGB:
case TextureFormat::DXT1_SRGBA:
case TextureFormat::DXT3_RGBA:
case TextureFormat::DXT3_SRGBA:
case TextureFormat::DXT5_RGBA:
case TextureFormat::DXT5_SRGBA:
case TextureFormat::RED_RGTC1:
case TextureFormat::SIGNED_RED_RGTC1:
case TextureFormat::RED_GREEN_RGTC2:
case TextureFormat::SIGNED_RED_GREEN_RGTC2:
case TextureFormat::RGB_BPTC_SIGNED_FLOAT:
case TextureFormat::RGB_BPTC_UNSIGNED_FLOAT:
case TextureFormat::RGBA_BPTC_UNORM:
case TextureFormat::SRGB_ALPHA_BPTC_UNORM:
case TextureFormat::RGBA_ASTC_4x4:
case TextureFormat::RGBA_ASTC_5x4:
case TextureFormat::RGBA_ASTC_5x5:
case TextureFormat::RGBA_ASTC_6x5:
case TextureFormat::RGBA_ASTC_6x6:
case TextureFormat::RGBA_ASTC_8x5:
case TextureFormat::RGBA_ASTC_8x6:
case TextureFormat::RGBA_ASTC_8x8:
case TextureFormat::RGBA_ASTC_10x5:
case TextureFormat::RGBA_ASTC_10x6:
case TextureFormat::RGBA_ASTC_10x8:
case TextureFormat::RGBA_ASTC_10x10:
case TextureFormat::RGBA_ASTC_12x10:
case TextureFormat::RGBA_ASTC_12x12:
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
return TextureType::FLOAT;
}
return TextureType::FLOAT;
}
size_t getFormatComponentCount(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::R8:
+2 -2
View File
@@ -84,7 +84,7 @@ void CommandStream::execute(void* buffer) {
Profiler profiler;
if (SYSTRACE_TAG) {
if constexpr (SYSTRACE_TAG) {
if (UTILS_UNLIKELY(mUsePerformanceCounter)) {
// we want to remove all this when tracing is completely disabled
profiler.resetEvents(Profiler::EV_CPU_CYCLES | Profiler::EV_BPU_MISSES);
@@ -100,7 +100,7 @@ void CommandStream::execute(void* buffer) {
}
});
if (SYSTRACE_TAG) {
if constexpr (SYSTRACE_TAG) {
if (UTILS_UNLIKELY(mUsePerformanceCounter)) {
// we want to remove all this when tracing is completely disabled
profiler.stop();
+16 -2
View File
@@ -672,8 +672,22 @@ void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
// nothing to do, timer query was constructed in createTimerQueryS
}
UTILS_UNUSED
static const char* toString(ShaderStageFlags flags) {
const char* toString(DescriptorType type) {
switch (type) {
case DescriptorType::UNIFORM_BUFFER:
return "UNIFORM_BUFFER";
case DescriptorType::SHADER_STORAGE_BUFFER:
return "SHADER_STORAGE_BUFFER";
case DescriptorType::SAMPLER:
return "SAMPLER";
case DescriptorType::INPUT_ATTACHMENT:
return "INPUT_ATTACHMENT";
case DescriptorType::SAMPLER_EXTERNAL:
return "SAMPLER_EXTERNAL";
}
}
const char* toString(ShaderStageFlags flags) {
std::vector<const char*> stages;
if (any(flags & ShaderStageFlags::VERTEX)) {
stages.push_back("VERTEX");
-1
View File
@@ -185,7 +185,6 @@ inline MTLPixelFormat getMetalFormat(PixelDataFormat format, PixelDataType type)
CONVERT(RGBA_INTEGER, UINT, RGBA32Uint);
CONVERT(RGBA_INTEGER, INT, RGBA32Sint);
CONVERT(RGBA, FLOAT, RGBA32Float);
CONVERT(DEPTH_COMPONENT, FLOAT, Depth32Float);
#undef CONVERT
return MTLPixelFormatInvalid;
+2 -38
View File
@@ -1356,25 +1356,7 @@ id<MTLArgumentEncoder> MetalDescriptorSetLayout::getArgumentEncoderSlow(id<MTLDe
[arguments addObject:bufferArgument];
break;
}
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_EXTERNAL: {
MTLArgumentDescriptor* textureArgument = [MTLArgumentDescriptor argumentDescriptor];
textureArgument.index = binding.binding * 2;
@@ -1490,25 +1472,7 @@ id<MTLBuffer> MetalDescriptorSet::finalizeAndGetBuffer(MetalDriver* driver, Shad
atIndex:binding.binding * 2];
break;
}
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_EXTERNAL: {
auto found = textures.find(binding.binding);
if (found == textures.end()) {
+3 -2
View File
@@ -69,8 +69,9 @@ public:
assert_invariant(set < MAX_DESCRIPTOR_SET_COUNT);
assert_invariant(binding < MAX_DESCRIPTOR_COUNT);
assert_invariant(entry.binding < 128); // we reserve 1 bit for the type right now
mStorage[set][binding] = { uint8_t(entry.binding),
DescriptorSetLayoutBinding::isSampler(entry.type) };
mStorage[set][binding] = { (uint8_t)entry.binding,
entry.type == DescriptorType::SAMPLER ||
entry.type == DescriptorType::SAMPLER_EXTERNAL };
mActiveDescriptors[set].set(binding);
}
@@ -95,26 +95,7 @@ GLDescriptorSet::GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle ds
}
break;
}
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_EXTERNAL:
if (UTILS_UNLIKELY(gl.isES2())) {
desc.emplace<SamplerGLES2>();
+1 -19
View File
@@ -175,25 +175,7 @@ void OpenGLProgram::initializeProgramState(OpenGLContext& context, GLuint progra
}
break;
}
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_EXTERNAL: {
if (!entry.name.empty()) {
GLint const loc = glGetUniformLocation(program, entry.name.c_str());
@@ -152,12 +152,12 @@ static_assert(FVK_ENABLED(FVK_DEBUG_VALIDATION));
#elif FVK_ENABLED(FVK_DEBUG_SYSTRACE)
#include <utils/Systrace.h>
#define FVK_SYSTRACE_CONTEXT() SYSTRACE_CONTEXT()
#define FVK_SYSTRACE_START(marker) SYSTRACE_NAME_BEGIN(marker)
#define FVK_SYSTRACE_END() SYSTRACE_NAME_END()
#define FVK_SYSTRACE_SCOPE() SYSTRACE_NAME(__func__)
#define FVK_PROFILE_MARKER(marker) FVK_SYSTRACE_SCOPE()
#define FVK_SYSTRACE_SCOPE() SYSTRACE_CALL()
#define FVK_PROFILE_MARKER(marker) SYSTRACE_CALL()
#else
#define FVK_SYSTRACE_CONTEXT()
@@ -142,10 +142,6 @@ public:
return mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
inline bool isUnifiedMemoryArchitecture() const noexcept {
return mIsUnifiedMemoryArchitecture;
}
private:
VkPhysicalDeviceMemoryProperties mMemoryProperties = {};
VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = {
@@ -168,7 +164,6 @@ private:
bool mDebugUtilsSupported = false;
bool mLazilyAllocatedMemorySupported = false;
bool mProtectedMemorySupported = false;
bool mIsUnifiedMemoryArchitecture = false;
fvkutils::VkFormatList mDepthStencilFormats;
fvkutils::VkFormatList mBlittableDepthStencilFormats;
+1 -20
View File
@@ -93,26 +93,7 @@ BitmaskGroup fromBackendLayout(DescriptorSetLayout const& layout) {
case DescriptorType::SAMPLER_EXTERNAL:
fromStageFlags(binding.stageFlags, binding.binding, mask.externalSampler);
UTILS_FALLTHROUGH;
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT: {
case DescriptorType::SAMPLER: {
fromStageFlags(binding.stageFlags, binding.binding, mask.sampler);
break;
}
@@ -631,21 +631,6 @@ fvkutils::VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device)
return ret;
}
/**
* Check if the GPU has a unified memory architecture.
*/
bool hasUnifiedMemoryArchitecture(VkPhysicalDeviceMemoryProperties memoryProperties) noexcept {
// Try to identify if the platform is running on a Unified Memory Architecture by inspecting the
// memory heap flags, if they are all VK_MEMORY_HEAP_DEVICE_LOCAL_BIT it's UMA, otherwise not
// enough information to make a decision, so default to false.
for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) {
if ((memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == 0) {
return false;
}
}
return true;
}
}// anonymous namespace
using SwapChainPtr = VulkanPlatform::SwapChainPtr;
@@ -879,8 +864,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
}
context.mIsUnifiedMemoryArchitecture = hasUnifiedMemoryArchitecture(context.mMemoryProperties);
#ifdef NDEBUG
// If we are in release build, we should not have turned on debug extensions
FILAMENT_CHECK_POSTCONDITION(!context.mDebugUtilsSupported && !context.mDebugMarkersSupported)
+86 -95
View File
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <utils/Hash.h>
#include "webgpu/WebGPUDriver.h"
#include "WebGPUPipelineCreation.h"
@@ -469,7 +469,7 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
mDevice, flags);
assert_invariant(mSwapChain);
WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(mDevice,
mSwapChain->getColorFormat(), mSwapChain->getDepthFormat());
mSwapChain->getColorFormat());
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
"background components have been instantiated/selected, such as surface/screen, "
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
@@ -591,7 +591,7 @@ void WebGPUDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
Handle<HwDescriptorSetLayout> dslh) {
auto layout = handleCast<WebGPUDescriptorSetLayout>(dslh);
constructHandle<WebGPUDescriptorSet>(dsh, layout->getLayout(), layout->getBindGroupEntries(), layout->label);
constructHandle<WebGPUDescriptorSet>(dsh, layout->getLayout(), layout->getBindGroupEntries());
}
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
@@ -916,14 +916,6 @@ void WebGPUDriver::blit(
}
void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
// TODO Investigate implications of this hash more closely. Vulkan has a whole class
// VulkanPipelineCache to handle this, may be missing nuance
static auto pipleineStateHasher = utils::hash::MurmurHashFn<filament::backend::PipelineState>();
auto hash = pipleineStateHasher(pipelineState);
if(mPipelineMap.find(hash) != mPipelineMap.end()){
mRenderPassEncoder.SetPipeline(mPipelineMap[hash]);
return;
}
const auto* program = handleCast<WGPUProgram>(pipelineState.program);
assert_invariant(program);
assert_invariant(program->computeShaderModule == nullptr &&
@@ -960,7 +952,7 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
*vertexBufferInfo, layout, pipelineState.rasterState, pipelineState.stencilState,
pipelineState.polygonOffset, pipelineState.primitiveType, mSwapChain->getColorFormat(),
mSwapChain->getDepthFormat());
mPipelineMap[hash] = pipeline;
// TODO: uncomment once we have a valid pipeline to set
mRenderPassEncoder.SetPipeline(pipeline);
}
@@ -1069,98 +1061,97 @@ wgpu::Sampler WebGPUDriver::makeSampler(SamplerParams const& params) {
desc.addressModeU = fWrapModeToWAddressMode(params.wrapS);
desc.addressModeV = fWrapModeToWAddressMode(params.wrapR);
desc.addressModeW = fWrapModeToWAddressMode(params.wrapT);
if (params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE) {
switch (params.filterMag) {
case SamplerMagFilter::NEAREST: {
desc.magFilter = wgpu::FilterMode::Nearest;
break;
}
case SamplerMagFilter::LINEAR: {
desc.magFilter = wgpu::FilterMode::Linear;
break;
}
switch (params.filterMag) {
case SamplerMagFilter::NEAREST: {
desc.magFilter = wgpu::FilterMode::Nearest;
break;
}
switch (params.filterMin) {
case SamplerMinFilter::NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
break;
}
case SamplerMinFilter::LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
case SamplerMagFilter::LINEAR: {
desc.magFilter = wgpu::FilterMode::Linear;
break;
}
switch (params.compareFunc) {
case SamplerCompareFunc::LE: {
desc.compare = wgpu::CompareFunction::LessEqual;
break;
}
case SamplerCompareFunc::GE: {
desc.compare = wgpu::CompareFunction::GreaterEqual;
break;
}
case SamplerCompareFunc::L: {
desc.compare = wgpu::CompareFunction::Less;
break;
}
case SamplerCompareFunc::G: {
desc.compare = wgpu::CompareFunction::Greater;
break;
}
case SamplerCompareFunc::E: {
desc.compare = wgpu::CompareFunction::Equal;
break;
}
case SamplerCompareFunc::NE: {
desc.compare = wgpu::CompareFunction::NotEqual;
break;
}
case SamplerCompareFunc::A: {
desc.compare = wgpu::CompareFunction::Always;
break;
}
case SamplerCompareFunc::N: {
desc.compare = wgpu::CompareFunction::Never;
break;
}
}
switch (params.filterMin) {
case SamplerMinFilter::NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
}
switch (params.compareFunc) {
case SamplerCompareFunc::LE: {
desc.compare = wgpu::CompareFunction::LessEqual;
break;
}
case SamplerCompareFunc::GE: {
desc.compare = wgpu::CompareFunction::GreaterEqual;
break;
}
case SamplerCompareFunc::L: {
desc.compare = wgpu::CompareFunction::Less;
break;
}
case SamplerCompareFunc::G: {
desc.compare = wgpu::CompareFunction::Greater;
break;
}
case SamplerCompareFunc::E: {
desc.compare = wgpu::CompareFunction::Equal;
break;
}
case SamplerCompareFunc::NE: {
desc.compare = wgpu::CompareFunction::NotEqual;
break;
}
case SamplerCompareFunc::A: {
desc.compare = wgpu::CompareFunction::Always;
break;
}
case SamplerCompareFunc::N: {
desc.compare = wgpu::CompareFunction::Never;
break;
}
}
desc.maxAnisotropy = 1u << params.anisotropyLog2;
// Unused: WGPU lodMinClamp/lodMaxClamp
// Unused: Filament's compareMode, WGPU lodMinClamp/lodMaxClamp
return mDevice.CreateSampler(&desc);
//TODO Once we can properly map to descriptorsetlayout use the sampler.
return mDevice.CreateSampler(/*&desc*/);
}
wgpu::AddressMode WebGPUDriver::fWrapModeToWAddressMode(const SamplerWrapMode& fWrapMode) {
switch (fWrapMode) {
@@ -93,8 +93,6 @@ private:
wgpu::RenderPassEncoder mRenderPassEncoder = nullptr;
wgpu::CommandBuffer mCommandBuffer = nullptr;
WGPURenderTarget* mDefaultRenderTarget = nullptr;
tsl::robin_map<uint32_t, wgpu::RenderPipeline> mPipelineMap;
/*
* Driver interface
*/
+40 -201
View File
@@ -247,7 +247,6 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
const auto& temp = std::get_if<utils::CString>(&layout.label);
baseLabel = temp->c_str();
}
label = baseLabel;
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value.
@@ -255,7 +254,8 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
unsigned int samplerCount =
std::count_if(layout.bindings.begin(), layout.bindings.end(), [](auto& fEntry) {
return DescriptorSetLayoutBinding::isSampler(fEntry.type);
return fEntry.type == DescriptorType::SAMPLER ||
fEntry.type == DescriptorType::SAMPLER_EXTERNAL;
});
@@ -269,31 +269,12 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
wEntry.visibility = filamentStageToWGPUStage(fEntry.stageFlags);
wEntry.binding = fEntry.binding * 2;
entryInfo.binding = wEntry.binding;
wgpu::BindGroupLayoutEntry* sEntry;
switch (fEntry.type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT: {
case DescriptorType::SAMPLER_EXTERNAL:
case DescriptorType::SAMPLER: {
auto& samplerEntry = wEntries.emplace_back();
auto& samplerEntryInfo = mBindGroupEntries.emplace_back();
sEntry = &samplerEntry;
samplerEntry.binding = fEntry.binding * 2 + 1;
samplerEntryInfo.binding = samplerEntry.binding;
samplerEntryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER;
@@ -301,6 +282,15 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
// We are simply hoping that undefined and defaults suffices here.
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering; // Example default
wEntry.texture.sampleType = wgpu::TextureSampleType::Float; // Example default
// TODO: FIX! THIS IS HACK FOR HELLO-TRIANGLE!
if (baseLabel.find("Skybox") != std::string::npos ||
(baseLabel == "Filament Default Material_perView" && wEntry.binding == 22)) {
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
} else {
wEntry.texture.viewDimension =
wgpu::TextureViewDimension::e2D;// Example default
}
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW;
break;
}
case DescriptorType::UNIFORM_BUFFER: {
@@ -320,81 +310,6 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
PANIC_POSTCONDITION("Shader storage is not supported");
break;
}
case DescriptorType::SAMPLER_EXTERNAL: {
PANIC_POSTCONDITION("External Sampler is not supported");
break;
}
}
switch (fEntry.type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D;
break;
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2DArray;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA;
break;
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE;
break;
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::CubeArray;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA;
break;
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e3D;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D;
break;
default:
break;
}
switch (fEntry.type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
wEntry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
break;
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_3D_INT:
wEntry.texture.sampleType = wgpu::TextureSampleType::Sint;
break;
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_3D_UINT:
wEntry.texture.sampleType = wgpu::TextureSampleType::Uint;
break;
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
//Dummies complain if you set this correctly without having an associated dummy
wEntry.texture.sampleType = wgpu::TextureSampleType::Depth;
sEntry->sampler.type = wgpu::SamplerBindingType::Comparison;
break;
default:
break;
}
// fEntry.count is unused currently
}
@@ -410,12 +325,12 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
WebGPUDescriptorSetLayout::~WebGPUDescriptorSetLayout() {}
wgpu::Buffer WebGPUDescriptorSet::sDummyUniformBuffer = nullptr;
std::unordered_map<wgpu::TextureDimension, wgpu::Texture> WebGPUDescriptorSet::sDummyTextureMap;
std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> WebGPUDescriptorSet::sDummyTextureViewMap;
wgpu::Texture WebGPUDescriptorSet::sDummyTexture = nullptr;
wgpu::TextureView WebGPUDescriptorSet::sDummyTextureView = nullptr;
wgpu::Sampler WebGPUDescriptorSet::sDummySampler = nullptr;
void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device const& device,
wgpu::TextureFormat aColorFormat, wgpu::TextureFormat aDepthFormat) {
wgpu::TextureFormat aColorFormat) {
if (!sDummyUniformBuffer) {
wgpu::BufferDescriptor bufferDescriptor{
.label = "dummy_uniform_not_to_be_used",
@@ -426,75 +341,31 @@ void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device cons
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
<< "Failed to create dummy uniform buffer?";
}
if (sDummyTextureMap.empty() || sDummyTextureViewMap.empty()) {
if (!sDummyTexture || !sDummyTextureView) {
wgpu::TextureDescriptor textureDescriptor{
.label = "dummy_texture_not_to_be_used",
.usage = wgpu::TextureUsage::TextureBinding,
.dimension = wgpu::TextureDimension::e2D,
.size = wgpu::Extent3D{ .width = 4, .height = 4, .depthOrArrayLayers = 1 },
.format = aColorFormat,
// .viewFormatCount = 1,
// .viewFormats = &aDepthFormat
};
sDummyTextureMap[wgpu::TextureDimension::e2D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e2D])
<< "Failed to create dummy texture 2D?";
textureDescriptor.dimension = wgpu::TextureDimension::e3D;
sDummyTextureMap[wgpu::TextureDimension::e3D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e3D])
<< "Failed to create dummy texture 3D?";
//Hacking as an experiment, treating 1D as cube arbitrarilly since my map key was bad idea
textureDescriptor.dimension = wgpu::TextureDimension::e2D;
textureDescriptor.size.depthOrArrayLayers = 6;
sDummyTextureMap[wgpu::TextureDimension::e1D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e1D])
<< "Failed to create dummy texture 3D?";
wgpu::TextureViewDescriptor textureViewDescriptor{
.label = "dummy_texture_view_not_to_be_used",
};
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2D] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e3D;
sDummyTextureViewMap[wgpu::TextureViewDimension::e3D] =
sDummyTextureMap[wgpu::TextureDimension::e3D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e3D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.arrayLayerCount = 6;
textureViewDescriptor.dimension = wgpu::TextureViewDimension::Cube;
sDummyTextureViewMap[wgpu::TextureViewDimension::Cube] =
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::Cube])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::CubeArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray] =
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray])
<< "Failed to create dummy texture view?";
if (!sDummyTexture) {
sDummyTexture = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy texture?";
}
if (!sDummyTextureView) {
wgpu::TextureViewDescriptor textureViewDescriptor{
.label = "dummy_texture_view_not_to_be_used"
};
sDummyTextureView = sDummyTexture.CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
<< "Failed to create dummy texture view?";
}
}
if (!sDummySampler) {
wgpu::SamplerDescriptor samplerDescriptor{ .label = "dummy_sampler_not_to_be_used" , .addressModeU = wgpu::AddressMode::MirrorRepeat};
wgpu::SamplerDescriptor samplerDescriptor{
.label = "dummy_sampler_not_to_be_used"
};
sDummySampler = device.CreateSampler(&samplerDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy sampler?";
}
@@ -506,12 +377,12 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
assert_invariant(WebGPUDescriptorSet::sDummyUniformBuffer &&
"Dummy uniform buffer must have been created before "
"creating dummy bind group entries.");
/* assert_invariant(
assert_invariant(
WebGPUDescriptorSet::sDummyTexture &&
"Dummy texture must have been created before creating dummy bind group entries.");
assert_invariant(
WebGPUDescriptorSet::sDummyTextureView &&
"Dummy texture view must have been created before creating dummy bind group entries.");*/
"Dummy texture view must have been created before creating dummy bind group entries.");
assert_invariant(
WebGPUDescriptorSet::sDummySampler &&
"Dummy sampler must have been created before creating dummy bind group entries.");
@@ -523,31 +394,14 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
entry.binding = entryInfo.binding;
switch (entryInfo.type) {
case WebGPUDescriptorSetLayout::BindGroupEntryType::UNIFORM_BUFFER:
//entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW:
entry.textureView = WebGPUDescriptorSet::sDummyTextureView;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER:
// entry.sampler = WebGPUDescriptorSet::sDummySampler;
entry.sampler = WebGPUDescriptorSet::sDummySampler;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2D];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::Cube];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e3D];
break;
default: break;
}
}
std::sort(entries.begin(), entries.end(),
@@ -558,10 +412,9 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
}
WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label)
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries)
: mLayout(layout),
mEntriesSortedByBinding(createDummyEntriesSortedByBinding(bindGroupEntries)) {
bglLabel = label;
// Establish the size of entries based on the layout. This should be reliable and efficient.
assert_invariant(INVALID_INDEX > mEntryIndexByBinding.size());
for (size_t i = 0; i < mEntryIndexByBinding.size(); i++) {
@@ -596,20 +449,6 @@ wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn(const wgpu::Device& device) {
.entryCount = mEntriesSortedByBinding.size(),
.entries = mEntriesSortedByBinding.data()
};
for(auto e : mEntriesSortedByBinding){
if(e.sampler.Get() == sDummySampler.Get()){
printf("===R Dummy %s UBO %i\n", bglLabel.c_str(), e.binding/2);
}
for(auto dt : sDummyTextureViewMap){
if(e.textureView.Get() == dt.second.Get())
{
printf("===R Dummy %s Tex %i\n", bglLabel.c_str(), e.binding/2);
}
}
if(e.buffer.Get() == sDummyUniformBuffer.Get()){
printf("===R Dummy %s Sam %i\n", bglLabel.c_str(),(e.binding-1)/2);
}
}
mBindGroup = device.CreateBindGroup(&desc);
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
+5 -12
View File
@@ -103,15 +103,10 @@ struct WGPUBufferObject : HwBufferObject {
class WebGPUDescriptorSetLayout final : public HwDescriptorSetLayout {
public:
std::string label;
enum class BindGroupEntryType : uint8_t {
UNIFORM_BUFFER,
TEXTURE_VIEW_2D,
TEXTURE_VIEW_2DA,
TEXTURE_VIEW_CUBE,
TEXTURE_VIEW_CUBEA,
TEXTURE_VIEW_3D,
TEXTURE_VIEW,
SAMPLER
};
@@ -138,13 +133,11 @@ private:
class WebGPUDescriptorSet final : public HwDescriptorSet {
public:
std::string bglLabel;
static void initializeDummyResourcesIfNotAlready(wgpu::Device const&,
wgpu::TextureFormat aColorFormat,
wgpu::TextureFormat aDepthFormat);
wgpu::TextureFormat aColorFormat);
WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label);
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries);
~WebGPUDescriptorSet();
wgpu::BindGroup lockAndReturn(wgpu::Device const&);
@@ -155,8 +148,8 @@ public:
private:
static wgpu::Buffer sDummyUniformBuffer;
static std::unordered_map<wgpu::TextureDimension, wgpu::Texture> sDummyTextureMap;
static std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> sDummyTextureViewMap;
static wgpu::Texture sDummyTexture;
static wgpu::TextureView sDummyTextureView;
static wgpu::Sampler sDummySampler;
static std::vector<wgpu::BindGroupEntry> createDummyEntriesSortedByBinding(
+6 -24
View File
@@ -45,7 +45,6 @@ namespace test {
Backend BackendTest::sBackend = Backend::NOOP;
OperatingSystem BackendTest::sOperatingSystem = OperatingSystem::OTHER;
bool BackendTest::sIsMobilePlatform = false;
std::vector<std::string> BackendTest::sFailedImages;
void BackendTest::init(Backend backend, OperatingSystem operatingSystem, bool isMobilePlatform) {
sBackend = backend;
@@ -64,12 +63,11 @@ BackendTest::~BackendTest() {
flushAndWait();
mImageExpectations->evaluate();
// Note: Don't terminate the driver for OpenGL, as it wipes away the context and removes the buffer from the screen.
if (sBackend != Backend::OPENGL) {
driver->terminate();
delete driver;
if (sBackend == Backend::OPENGL) {
return;
}
recordFailedImages();
driver->terminate();
delete driver;
}
void BackendTest::initializeDriver() {
@@ -169,24 +167,8 @@ bool BackendTest::matchesEnvironment(OperatingSystem operatingSystem) {
return sOperatingSystem == operatingSystem;
}
void BackendTest::markImageAsFailure(std::string failedImageName) {
sFailedImages.emplace_back(std::move(failedImageName));
}
void BackendTest::recordFailedImages() {
if (!sFailedImages.empty()) {
std::string failedImages;
for (auto& failedTestImageName: sFailedImages) {
if (failedImages.empty()) {
failedImages = failedTestImageName;
} else {
failedImages.append(",");
failedImages.append(failedTestImageName);
}
}
RecordProperty("FailedImages", failedImages);
}
sFailedImages.clear();
bool BackendTest::matchesEnvironment(OperatingSystem operatingSystem, Backend backend) {
return matchesEnvironment(operatingSystem) && matchesEnvironment(backend);
}
class Environment : public ::testing::Environment {
+1 -9
View File
@@ -38,9 +38,6 @@ public:
static OperatingSystem sOperatingSystem;
static bool sIsMobilePlatform;
// Takes the name of the image that wasn't correct, without the .png suffix
static void markImageAsFailure(std::string failedImageName);
protected:
BackendTest();
@@ -76,13 +73,8 @@ protected:
static bool matchesEnvironment(Backend backend);
static bool matchesEnvironment(OperatingSystem operatingSystem);
static bool matchesEnvironment(OperatingSystem operatingSystem, Backend backend);
private:
// Adds all the images that failed an ImageExpectation to the XML metadata for the current tests
// case. Add --gtest_output=xml as a command line argument to generate a test_detail.xml file in
// the directory where the tests are run.
static void recordFailedImages();
static std::vector<std::string> sFailedImages;
filament::backend::Driver* driver = nullptr;
filament::backend::CommandBufferQueue commandBufferQueue;
+1 -14
View File
@@ -21,7 +21,6 @@
#include "utils/Hash.h"
#include <fstream>
#include "BackendTest.h"
#include "backend/PixelBufferDescriptor.h"
#include "private/backend/DriverApi.h"
@@ -33,8 +32,6 @@
#endif
namespace test {
ScreenshotParams::ScreenshotParams(int width, int height, std::string fileName,
uint32_t expectedHash, bool isSrgb)
: mWidth(width),
@@ -83,10 +80,6 @@ std::string ScreenshotParams::expectedFilePath() const {
return absl::StrFormat("%s/%s", expectedDirectoryPath(), expectedFileName());
}
const std::string ScreenshotParams::filePrefix() const {
return mFileName;
}
ImageExpectation::ImageExpectation(const char* fileName, int lineNumber,
filament::backend::DriverApi& api, ScreenshotParams params,
filament::backend::RenderTargetHandle renderTarget)
@@ -120,11 +113,7 @@ void ImageExpectation::compareImage() const {
#ifndef FILAMENT_IOS
LoadedPng loadedImage(mParams.expectedFilePath());
uint32_t loadedImageHash = loadedImage.hash();
auto compareToImageMatcher = testing::Eq(loadedImageHash);
if (!testing::Matches(compareToImageMatcher)(actualHash)) {
BackendTest::markImageAsFailure(mParams.filePrefix());
}
EXPECT_THAT(actualHash, compareToImageMatcher) << mParams.expectedFileName();
EXPECT_THAT(actualHash, testing::Eq(loadedImageHash)) << mParams.expectedFileName();
#endif
// For builds that can't load PNGs (currently iOS only) use the expected hash.
EXPECT_THAT(actualHash, testing::Eq(mParams.expectedHash())) << mParams.expectedFileName();
@@ -248,5 +237,3 @@ uint32_t LoadedPng::hash() const {
const std::vector<unsigned char>& LoadedPng::bytes() const {
return mBytes;
}
} // namespace test
@@ -35,8 +35,6 @@ do { \
screenshotParams); \
} while (0)
namespace test {
/**
* Stores user-provided configuration values for an image expectation
*/
@@ -56,7 +54,6 @@ public:
static std::string expectedDirectoryPath();
std::string expectedFileName() const;
std::string expectedFilePath() const;
const std::string filePrefix() const;
private:
int mWidth;
@@ -156,6 +153,4 @@ private:
std::vector<std::unique_ptr<ImageExpectation>> mExpectations;
};
} // namespace test
#endif //TNT_IMAGE_EXPECTATIONS_H
+1 -1
View File
@@ -57,7 +57,7 @@ Shader::Shader(DriverApi& api, Cleanup& cleanup, ShaderConfig config) : mCleanup
if (!kLayouts.empty()) {
mDescriptorSetLayout =
cleanup.add(api.createDescriptorSetLayout(DescriptorSetLayout{ .bindings = kLayouts }));
cleanup.add(api.createDescriptorSetLayout(DescriptorSetLayout{ kLayouts }));
}
}
+1 -1
View File
@@ -184,7 +184,7 @@ std::vector<UniformConfig> GetUniformConfig(ShaderUniformType type) {
"backend_test", "test_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::FLOAT, Precision::HIGH, false };
return {{
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
"test_tex", DescriptorType::SAMPLER, samplerInfo
}};
}
default:
@@ -1,143 +1,62 @@
import os, shutil, argparse, typing, xml.etree.ElementTree, subprocess, platform
import os, shutil, argparse, typing
def match_sufffix(file_name: str, suffix: str, accepted_prefixes: typing.List[str]) -> str:
"""
Check if the file name is one of the searched for ones with the given suffix and if so return it.
:param accepted_prefixes: If None accepts any prefix
:return: file_name with the suffix removed or "" if it doesn't match. This does mean a string that
is just the suffix is considered to not match as it will return the empty string.
"""
if file_name.endswith(suffix):
prefix = file_name.removesuffix(suffix)
if accepted_prefixes is None or prefix in accepted_prefixes:
return prefix
return ""
class TestResults(object):
ACTUAL_SUFFIX = '_actual.png'
EXPECTED_SUFFIX = '.png'
def __init__(self, results_directory: str, source_expected_directory: str):
self.results_directory = results_directory
self.actual_directory = os.path.join(self.results_directory, 'images', 'actual_images')
self.expected_directory = os.path.join(self.results_directory, 'images', 'expected_images')
self.source_expected_directory = source_expected_directory
def get_latest_failed_images(self) -> typing.List[str]:
failed_images = []
xml_tree = xml.etree.ElementTree.parse(
os.path.join(self.results_directory, 'test_detail.xml'))
testsuites = xml_tree.getroot()
for testsuite in testsuites.findall('testsuite'):
for testcase in testsuite.findall('testcase'):
for properties in testcase.findall('properties'):
for property in properties.findall('property'):
if property.get('name') == 'FailedImages':
failed_images.extend(property.get('value').split(','))
return failed_images
def handle_failed_image(self, failed_image):
self.show_images(failed_image)
print(f'Update {failed_image}\'s expected image? y/n')
while True:
user_input = input()
if user_input == 'y':
self.move_actual_to_source([failed_image])
break
elif user_input == 'n':
break
def handle_all_failed_images(self):
for failed_image in self.get_latest_failed_images():
self.handle_failed_image(failed_image)
def show_images(self, failed_image):
# TODO: Test more on non-mac systems
open_command: str
os_name = platform.system().lower()
if 'windows' in os_name:
open_command = 'start'
elif 'osx' in os_name or 'darwin' in os_name:
open_command = 'open'
else:
open_command = 'xdg-open'
subprocess.run(
[open_command,
os.path.join(self.actual_directory, failed_image + TestResults.ACTUAL_SUFFIX)])
subprocess.run(
[open_command,
os.path.join(self.expected_directory, failed_image + TestResults.EXPECTED_SUFFIX)])
def move_actual_to_source(self, file_prefixes: typing.List[str]):
replace_file_names(path=self.actual_directory, removed=TestResults.ACTUAL_SUFFIX,
replacement=TestResults.EXPECTED_SUFFIX,
output_path=self.source_expected_directory, prefixes=file_prefixes)
def batch_move(self, prefixes: typing.Optional[typing.List[str]] = None):
replace_file_names(path=self.actual_directory, removed=TestResults.ACTUAL_SUFFIX,
replacement=TestResults.EXPECTED_SUFFIX,
output_path=self.source_expected_directory, prefixes=prefixes)
def match_suffix(file_name: str, suffix: str, accepted_prefixes: typing.List[str]) -> str:
"""
Check if the file name is one of the searched for ones with the given suffix and if so return
it.
:param accepted_prefixes: If None accepts any prefix
:return: file_name with the suffix removed or "" if it doesn't match. This does mean a string
that is just the suffix is considered to not match as it will return the empty string.
"""
if file_name.endswith(suffix):
prefix = file_name.removesuffix(suffix)
if accepted_prefixes is None or prefix in accepted_prefixes:
return prefix
return ''
def replace_file_names(path: str, removed: str, replacement: str = '', output_path: str = '',
prefixes: typing.Optional[typing.List[str]] = None):
if not output_path:
output_path = path
for file_name in os.listdir(path=path):
prefix = match_suffix(file_name, removed, prefixes)
if prefix:
# Remove the prefix from the list so that prefixes is the list of intended but not yet
# found files.
if prefixes is not None:
prefixes.remove(prefix)
new_file_name = prefix + replacement
new_file_path = os.path.join(output_path, new_file_name)
old_file_path = os.path.join(path, file_name)
print(f'{old_file_path} to {new_file_path}')
shutil.copyfile(old_file_path, new_file_path)
if prefixes is not None:
for unfound_prefix in prefixes:
print(f'Failed to find {unfound_prefix}_actual.png')
def replace_file_names(path: str, removed: str, replacement: str = "", output_path: str = "",
prefixes: typing.List[str] = None):
if not output_path:
output_path = path
for file_name in os.listdir(path=path):
prefix = match_sufffix(file_name, removed, prefixes)
if prefix:
# Remove the prefix from the list so that prefixes is the list of intended but not yet found
# files.
if prefixes is not None:
prefixes.remove(prefix)
new_file_name = prefix + replacement
new_file_path = os.path.join(output_path, new_file_name)
old_file_path = os.path.join(path, file_name)
print(f'{old_file_path} to {new_file_path}')
shutil.move(old_file_path, new_file_path)
if prefixes is not None:
for unfound_prefix in prefixes:
print(f'Failed to find {unfound_prefix}_actual.png')
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog='Backend Test File Renamer',
description='Moves actual generated test images to the '
'expected images directory, to update the test '
'requirements. test_cases accepts multiple '
'arguments that should be the name of the '
'expected image file without the .png suffix. '
'Also --all can be passed to copy all images.\n'
'Remember to sync CMake after running this to '
'move the new expected images to the binary '
'directory.')
parser.add_argument('-r', '--results_path')
parser.add_argument('-s', '--source_expected_path', default="./expected_images")
# The mutually exclusive options for how to process the actual images
parser.add_argument('-b', '--batch', action='extend', nargs='*')
parser.add_argument('-a', '--all', action='store_true')
parser.add_argument('-t', '--tests', action='store_true')
parser.add_argument('-c', '--compare', action='extend', nargs='*')
parser = argparse.ArgumentParser(prog='Backend Test File Renamer',
description='Moves actual generated test images to the expected '
'images directory, to update the test requirements. '
'test_cases accepts multiple arguments that should '
'be the name of the expected image file without the '
'.png suffix. Also --all can be passed to copy all '
'images.\n'
'Remember to sync CMake after running this to move '
'the new expected images to the binary directory.')
parser.add_argument('-i', '--input_path')
parser.add_argument('-o', '--output_path', default="./expected_images")
parser.add_argument('-t', '--test_cases', action='extend', nargs='*')
parser.add_argument('-a', '--all', action='store_true')
args = parser.parse_args()
if not args.results_path:
raise AssertionError("No result path provided")
results_path = args.results_path
args = parser.parse_args()
input_path = "."
if args.input_path:
input_path = args.input_path
results = TestResults(results_directory=results_path,
source_expected_directory=args.source_expected_path)
prefixes = args.test_cases
if args.all:
prefixes = None
if args.all:
results.batch_move()
elif args.tests:
results.handle_all_failed_images()
elif args.compare:
for file_prefix in args.compare:
results.show_images(file_prefix)
else:
results.batch_move(args.batch)
replace_file_names(path=input_path, output_path=args.output_path, removed="_actual.png",
replacement=".png", prefixes=prefixes)
+1 -1
View File
@@ -118,7 +118,7 @@ TEST_F(BackendTest, FeedbackLoops) {
Shader shader = Shader(api, cleanup, ShaderConfig {
.vertexShader = fullscreenVs,
.fragmentShader = fullscreenFs,
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}, {"Params"}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}, {"Params"}}
});
TrianglePrimitive const triangle(getDriverApi());
+4 -4
View File
@@ -308,7 +308,7 @@ TEST_F(LoadImageTest, UpdateImage2D) {
Shader shader(api, cleanup, ShaderConfig{
.vertexShader = mVertexShader,
.fragmentShader= fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
});
// Create a Texture.
@@ -372,7 +372,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
getSamplerTypeName(textureFormat), fragmentTemplate);
Shader shader(api, cleanup, ShaderConfig{
.vertexShader = mVertexShader, .fragmentShader = fragment, .uniforms = {{
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
"test_tex", DescriptorType::SAMPLER, samplerInfo
}}});
// Create a texture.
@@ -447,7 +447,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
Shader shader(api, cleanup, ShaderConfig {
.vertexShader = mVertexShader,
.fragmentShader = fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
});
// Create a texture with 3 mip levels.
@@ -508,7 +508,7 @@ TEST_F(LoadImageTest, UpdateImage3D) {
Shader shader(api, cleanup, ShaderConfig {
.vertexShader = mVertexShader,
.fragmentShader = fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_ARRAY_FLOAT, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
});
// Create a texture.
+1 -1
View File
@@ -82,7 +82,7 @@ TEST_F(BackendTest, TextureViewLod) {
.vertexShader = vertexShader,
.fragmentShader = fragmentTexturedLod,
.uniforms = {{
"backend_test_sib_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
"backend_test_sib_tex", DescriptorType::SAMPLER, samplerInfo
}}
});
+5 -119
View File
@@ -21,17 +21,13 @@
#include <filament/FilamentAPI.h>
#include <filament/ToneMapper.h>
#include <filament/ColorSpace.h>
#include <utils/compiler.h>
#include <math/mathfwd.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <stdint.h>
#include <stddef.h>
#include <memory>
namespace filament {
@@ -205,14 +201,15 @@ public:
*
* The default tone mapping operator is ACESLegacyToneMapper.
*
* The ownership of the specified tone mapper is shared with the builder and built
* ColorGrading object.
* The specified tone mapper must have a lifecycle that exceeds the lifetime of
* this builder. Since the build(Engine&) method is synchronous, it is safe to
* delete the tone mapper object after that finishes executing.
*
* @param toneMapper The tone mapping operator to apply to the HDR color buffer
*
* @return This Builder, for chaining calls
*/
Builder& toneMapper(std::shared_ptr<ToneMapper> toneMapper) noexcept;
Builder& toneMapper(ToneMapper const* UTILS_NULLABLE toneMapper) noexcept;
/**
* Selects the tone mapping operator to apply to the HDR color buffer as the last
@@ -490,118 +487,7 @@ public:
friend class FColorGrading;
};
/** Returns the quality level used to create this ColorGrading object. */
QualityLevel getQuality() const noexcept;
/** Returns the LUT format used to create this ColorGrading object. */
LutFormat getLutFormat() const noexcept;
/** Returns the LUT dimensions used to create this ColorGrading object. */
uint8_t getLutDimensions() const noexcept;
/** Returns the tone mapper used to create this ColorGrading object. */
const ToneMapper& getToneMapper() const noexcept;
/** Returns whether luminance scaling was enabled during creation. */
bool isLuminanceScalingEnabled() const noexcept;
/** Returns whether gamut mapping was enabled during creation. */
bool isGamutMappingEnabled() const noexcept;
/** Returns the exposure value used to create this ColorGrading object. */
float getExposure() const noexcept;
/** Returns the night adaptation value used to create this ColorGrading object. */
float getNightAdaptation() const noexcept;
/** Returns the white balance temperature used to create this ColorGrading object. */
float getWhiteBalanceTemperature() const noexcept;
/** Returns the white balance tint used to create this ColorGrading object. */
float getWhiteBalanceTint() const noexcept;
/** Returns the channel mixer output for the red channel. */
math::float3 getChannelMixerOutRed() const noexcept;
/** Returns the channel mixer output for the green channel. */
math::float3 getChannelMixerOutGreen() const noexcept;
/** Returns the channel mixer output for the blue channel. */
math::float3 getChannelMixerOutBlue() const noexcept;
/** Returns the shadows adjustment used to create this ColorGrading object. */
math::float3 getShadows() const noexcept;
/** Returns the midtones adjustment used to create this ColorGrading object. */
math::float3 getMidtones() const noexcept;
/** Returns the highlights adjustment used to create this ColorGrading object. */
math::float3 getHighlights() const noexcept;
/** Returns the shadow/midtones/highlights ranges used to create this ColorGrading object. */
math::float4 getShadowMidtonesHighlightsRanges() const noexcept;
/** Returns the slope adjustment used to create this ColorGrading object. */
math::float3 getSlope() const noexcept;
/** Returns the offset adjustment used to create this ColorGrading object. */
math::float3 getOffset() const noexcept;
/** Returns the power adjustment used to create this ColorGrading object. */
math::float3 getPower() const noexcept;
/** Returns the contrast value used to create this ColorGrading object. */
float getContrast() const noexcept;
/** Returns the vibrance value used to create this ColorGrading object. */
float getVibrance() const noexcept;
/** Returns the saturation value used to create this ColorGrading object. */
float getSaturation() const noexcept;
/** Returns the shadow gamma curve adjustment used to create this ColorGrading object. */
math::float3 getCurvesShadowGamma() const noexcept;
/** Returns the mid-point curve adjustment used to create this ColorGrading object. */
math::float3 getCurvesMidPoint() const noexcept;
/** Returns the highlight scale curve adjustment used to create this ColorGrading object. */
math::float3 getCurvesHighlightScale() const noexcept;
/** Returns the output color space used to create this ColorGrading object. */
const color::ColorSpace& getOutputColorSpace() const noexcept;
protected :
struct Settings {
LutFormat lutFormat = LutFormat::INTEGER;
uint8_t lutDimensions = 32;
std::shared_ptr<ToneMapper> toneMapper = std::make_shared<ACESLegacyToneMapper>();
bool luminanceScaling = false;
bool gummapMapping = false;
float exposure = 0.0f;
float nightAdaptation = 0.0f;
float whiteBalanceTemperature = 0.0f;
float whiteBalanceTint = 0.0f;
math::float3 channelMixerOutRed{1.0f, 0.0f, 0.0f};
math::float3 channelMixerOutGreen{0.0f, 1.0f, 0.0f};
math::float3 channelMixerOutBlue{0.0f, 0.0f, 1.0f};
math::float3 shadows{1.0f, 1.0f, 1.0f};
math::float3 midtones{1.0f, 1.0f, 1.0f};
math::float3 highlights{1.0f, 1.0f, 1.0f};
math::float4 ShadowMidtonesHighlightsRanges{0.0f, 0.333f, 0.55f, 1.0f};
math::float3 slope{1.0f};
math::float3 offset{0.0f};
math::float3 power{1.0f};
float contrast = 1.0f;
float vibrance = 1.0f;
float saturation = 1.0f;
math::float3 curvesShadowGamma{1.0f, 1.0f, 1.0f};
math::float3 curvesMidPoint{1.0f, 1.0f, 1.0f};
math::float3 curvesHighlightScale{1.0f, 1.0f, 1.0f};
color::ColorSpace colorSpace = color::Rec709 - color::sRGB - color::D65;
};
Settings mSettings;
protected:
// prevent heap allocation
~ColorGrading() = default;
};
+2 -26
View File
@@ -54,8 +54,6 @@ namespace filament {
struct UTILS_PUBLIC ToneMapper {
ToneMapper() noexcept;
virtual ~ToneMapper() noexcept;
ToneMapper(ToneMapper const&) noexcept;
ToneMapper& operator=(ToneMapper const&) noexcept = default;
/**
* Maps an open domain (or "scene referred" values) color value to display
@@ -71,13 +69,6 @@ struct UTILS_PUBLIC ToneMapper {
*/
virtual math::float3 operator()(math::float3 c) const noexcept = 0;
/**
* Creates a copy of this tone mapper instance.
*
* @return A pointer to a new ToneMapper instance that is a copy of this instance.
*/
virtual ToneMapper* clone() const noexcept = 0;
/**
* If true, then this function holds that f(x) = vec3(f(x.r), f(x.g), f(x.b))
*
@@ -101,10 +92,8 @@ struct UTILS_PUBLIC ToneMapper {
struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
LinearToneMapper() noexcept;
~LinearToneMapper() noexcept final;
LinearToneMapper(LinearToneMapper const&) noexcept;
math::float3 operator()(math::float3 c) const noexcept override;
LinearToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return true; }
bool isLDR() const noexcept override { return true; }
};
@@ -117,10 +106,8 @@ struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
ACESToneMapper() noexcept;
~ACESToneMapper() noexcept final;
ACESToneMapper(ACESToneMapper const&) noexcept;
math::float3 operator()(math::float3 c) const noexcept override;
ACESToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return false; }
bool isLDR() const noexcept override { return false; }
};
@@ -134,10 +121,8 @@ struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
ACESLegacyToneMapper() noexcept;
~ACESLegacyToneMapper() noexcept final;
ACESLegacyToneMapper(ACESLegacyToneMapper const&) noexcept;
math::float3 operator()(math::float3 c) const noexcept override;
ACESLegacyToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return false; }
bool isLDR() const noexcept override { return false; }
};
@@ -151,10 +136,8 @@ struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
FilmicToneMapper() noexcept;
~FilmicToneMapper() noexcept final;
FilmicToneMapper(FilmicToneMapper const&) noexcept;
math::float3 operator()(math::float3 x) const noexcept override;
FilmicToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return true; }
bool isLDR() const noexcept override { return false; }
};
@@ -167,10 +150,8 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
struct UTILS_PUBLIC PBRNeutralToneMapper final : public ToneMapper {
PBRNeutralToneMapper() noexcept;
~PBRNeutralToneMapper() noexcept final;
PBRNeutralToneMapper(PBRNeutralToneMapper const&) noexcept;
math::float3 operator()(math::float3 x) const noexcept override;
virtual PBRNeutralToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return false; }
bool isLDR() const noexcept override { return false; }
};
@@ -192,10 +173,8 @@ struct UTILS_PUBLIC AgxToneMapper final : public ToneMapper {
*/
explicit AgxToneMapper(AgxLook look = AgxLook::NONE) noexcept;
~AgxToneMapper() noexcept final;
AgxToneMapper(AgxToneMapper const&) noexcept;
math::float3 operator()(math::float3 x) const noexcept override;
virtual AgxToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return false; }
bool isLDR() const noexcept override { return false; }
@@ -236,13 +215,12 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
) noexcept;
~GenericToneMapper() noexcept final;
GenericToneMapper(GenericToneMapper const& rhs) noexcept;
GenericToneMapper& operator=(GenericToneMapper const& rhs) noexcept;
GenericToneMapper(GenericToneMapper const&) = delete;
GenericToneMapper& operator=(GenericToneMapper const&) = delete;
GenericToneMapper(GenericToneMapper&& rhs) noexcept;
GenericToneMapper& operator=(GenericToneMapper&& rhs) noexcept;
math::float3 operator()(math::float3 x) const noexcept override;
GenericToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return true; }
bool isLDR() const noexcept override { return false; }
@@ -305,10 +283,8 @@ private:
struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
DisplayRangeToneMapper() noexcept;
~DisplayRangeToneMapper() noexcept override;
DisplayRangeToneMapper(DisplayRangeToneMapper const&) noexcept;
math::float3 operator()(math::float3 c) const noexcept override;
DisplayRangeToneMapper* clone() const noexcept override;
bool isOneDimensional() const noexcept override { return false; }
bool isLDR() const noexcept override { return false; }
};
+63 -49
View File
@@ -648,32 +648,44 @@ bool ChunkAttributeInfo::unflatten(Unflattener& unflattener,
bool ChunkDescriptorBindingsInfo::unflatten(Unflattener& unflattener,
MaterialParser::DescriptorBindingsContainer* container) {
static_assert(sizeof(DescriptorSetBindingPoints) == sizeof(uint8_t));
uint8_t descriptorCount;
if (!unflattener.read(&descriptorCount)) {
uint8_t setCount;
if (!unflattener.read(&setCount)) {
return false;
}
auto& descriptors = (*container)[+DescriptorSetBindingPoints::PER_MATERIAL];
descriptors.reserve(descriptorCount);
for (size_t i = 0; i < descriptorCount; i++) {
CString name;
if (!unflattener.read(&name)) {
for (size_t j = 0; j < setCount; j++) {
static_assert(sizeof(DescriptorSetBindingPoints) == sizeof(uint8_t));
DescriptorSetBindingPoints set;
if (!unflattener.read(reinterpret_cast<uint8_t*>(&set))) {
return false;
}
uint8_t type;
if (!unflattener.read(&type)) {
uint8_t descriptorCount;
if (!unflattener.read(&descriptorCount)) {
return false;
}
uint8_t binding;
if (!unflattener.read(&binding)) {
return false;
auto& descriptors = (*container)[+set];
descriptors.reserve(descriptorCount);
for (size_t i = 0; i < descriptorCount; i++) {
CString name;
if (!unflattener.read(&name)) {
return false;
}
uint8_t type;
if (!unflattener.read(&type)) {
return false;
}
uint8_t binding;
if (!unflattener.read(&binding)) {
return false;
}
descriptors.push_back({
std::move(name),
DescriptorType(type),
descriptor_binding_t(binding)});
}
descriptors.push_back({
std::move(name),
DescriptorType(type),
descriptor_binding_t(binding)});
}
return true;
@@ -681,40 +693,42 @@ bool ChunkDescriptorBindingsInfo::unflatten(Unflattener& unflattener,
bool ChunkDescriptorSetLayoutInfo::unflatten(Unflattener& unflattener,
MaterialParser::DescriptorSetLayoutContainer* container) {
uint8_t descriptorCount;
if (!unflattener.read(&descriptorCount)) {
return false;
}
auto& descriptors = container->bindings;
descriptors.reserve(descriptorCount);
for (size_t i = 0; i < descriptorCount; i++) {
uint8_t type;
if (!unflattener.read(&type)) {
for (size_t j = 0; j < 2; j++) {
uint8_t descriptorCount;
if (!unflattener.read(&descriptorCount)) {
return false;
}
uint8_t stageFlags;
if (!unflattener.read(&stageFlags)) {
return false;
auto& descriptors = (*container)[j].bindings;
descriptors.reserve(descriptorCount);
for (size_t i = 0; i < descriptorCount; i++) {
uint8_t type;
if (!unflattener.read(&type)) {
return false;
}
uint8_t stageFlags;
if (!unflattener.read(&stageFlags)) {
return false;
}
uint8_t binding;
if (!unflattener.read(&binding)) {
return false;
}
uint8_t flags;
if (!unflattener.read(&flags)) {
return false;
}
uint16_t count;
if (!unflattener.read(&count)) {
return false;
}
descriptors.push_back({
DescriptorType(type),
ShaderStageFlags(stageFlags),
descriptor_binding_t(binding),
DescriptorFlags(flags),
count,
});
}
uint8_t binding;
if (!unflattener.read(&binding)) {
return false;
}
uint8_t flags;
if (!unflattener.read(&flags)) {
return false;
}
uint16_t count;
if (!unflattener.read(&count)) {
return false;
}
descriptors.push_back({
DescriptorType(type),
ShaderStageFlags(stageFlags),
descriptor_binding_t(binding),
DescriptorFlags(flags),
count,
});
}
return true;
}
+1 -1
View File
@@ -93,7 +93,7 @@ public:
using DescriptorBindingsContainer = backend::Program::DescriptorSetInfo;
bool getDescriptorBindings(DescriptorBindingsContainer* container) const noexcept;
using DescriptorSetLayoutContainer = backend::DescriptorSetLayout;
using DescriptorSetLayoutContainer = std::array<backend::DescriptorSetLayout, 2>;
bool getDescriptorSetLayout(DescriptorSetLayoutContainer* container) const noexcept;
bool getDepthWriteSet(bool* value) const noexcept;
+3 -4
View File
@@ -232,7 +232,7 @@ PostProcessManager::~PostProcessManager() noexcept = default;
void PostProcessManager::setFrameUniforms(DriverApi& driver,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
mPostProcessDescriptorSet.setFrameUniforms(driver, uniforms);
mSsrPassDescriptorSet.setFrameUniforms(mEngine, uniforms);
mSsrPassDescriptorSet.setFrameUniforms(uniforms);
}
void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const noexcept {
@@ -504,7 +504,6 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph
FrameGraphTexture::Usage::DEPTH_ATTACHMENT);
if (config.picking) {
// FIXME: the DescriptorSetLayout must specify SAMPLER_FLOAT
data.picking = builder.createTexture("Picking Buffer", {
.width = width, .height = height,
.format = isES2 ? TextureFormat::RGBA8 : TextureFormat::RG32F });
@@ -654,7 +653,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
options, passBuilder = passBuilder]
(FrameGraphResources const& resources, auto const& data, DriverApi& driver) mutable {
// set structure sampler
mSsrPassDescriptorSet.prepareStructure(mEngine, data.structure ?
mSsrPassDescriptorSet.prepareStructure(data.structure ?
resources.getTexture(data.structure) : getOneTexture());
// set screen-space reflections and screen-space refractions
@@ -665,7 +664,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
// the history sampler is a regular texture2D
TextureHandle const history = data.history ?
resources.getTexture(data.history) : getZeroTexture();
mSsrPassDescriptorSet.prepareHistorySSR(mEngine, history, reprojection, uvFromViewMatrix, options);
mSsrPassDescriptorSet.prepareHistorySSR(history, reprojection, uvFromViewMatrix, options);
mSsrPassDescriptorSet.commit(mEngine);
+2 -13
View File
@@ -921,6 +921,7 @@ backend::Viewport RenderPass::Executor::applyScissorViewport(
UTILS_NOINLINE // no need to be inlined
void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
Command const* first, Command const* last) const noexcept {
SYSTRACE_CALL();
SYSTRACE_CONTEXT();
@@ -941,13 +942,6 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
driver.scissor(mScissor);
}
// If we have a mColorPassDescriptorSet, we need to use its idea of "VSM" to select
// the descriptor set layout. Materials always offer both.
// If we don't have a mColorPassDescriptorSet, it doesn't matter because the layout
// are chosen via the variant only.
bool const useVsmDescriptorSetLayout =
mColorPassDescriptorSet ? mColorPassDescriptorSet->isVSM() : false;
bool const polygonOffsetOverride = mPolygonOffsetOverride;
PipelineState pipeline{
// initialize with polygon offset override
@@ -1057,13 +1051,8 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
// Each material has its own version of the per-view descriptor-set layout,
// because it depends on the material features (e.g. lit/unlit)
// TODO: QUESTION: are
// Variant::isValidDepthVariant(info.materialVariant) and
// Variant::isSSRVariant(info.materialVariant)
// constant? If so we could precompute ma->getPerViewDescriptorSetLayout()
pipeline.pipelineLayout.setLayout[+DescriptorSetBindingPoints::PER_VIEW] =
ma->getPerViewDescriptorSetLayout(info.materialVariant,
useVsmDescriptorSetLayout).getHandle();
ma->getPerViewDescriptorSetLayout(info.materialVariant).getHandle();
// Each material has a per-material descriptor-set layout which encodes the
// material's parameters (ubo and samplers)
+2 -4
View File
@@ -205,13 +205,11 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
view.prepareSSAO(data.ssao ?
resources.getTexture(data.ssao) : engine.getOneTextureArray());
view.prepareShadowMapping(engine, view.getVsmShadowOptions().highPrecision);
view.prepareShadowMapping(view.getVsmShadowOptions().highPrecision);
// set shadow sampler
view.prepareShadow(data.shadows ?
resources.getTexture(data.shadows) :
(view.getShadowType() != ShadowType::PCF ?
engine.getOneTextureArray() : engine.getOneTextureArrayDepth()));
resources.getTexture(data.shadows) : engine.getOneTextureArray());
// set structure sampler
view.prepareStructure(data.structure ?
+2 -48
View File
@@ -188,8 +188,7 @@ float3 ACES(float3 color, float brightness) noexcept {
#define DEFAULT_CONSTRUCTORS(A) \
A::A() noexcept = default; \
A::~A() noexcept = default; \
A::A(A const&) noexcept = default;
A::~A() noexcept = default;
DEFAULT_CONSTRUCTORS(ToneMapper)
@@ -203,10 +202,6 @@ float3 LinearToneMapper::operator()(float3 const v) const noexcept {
return saturate(v);
}
LinearToneMapper* LinearToneMapper::clone() const noexcept {
return new LinearToneMapper(*this);
}
//------------------------------------------------------------------------------
// ACES tone mappers
//------------------------------------------------------------------------------
@@ -217,20 +212,12 @@ float3 ACESToneMapper::operator()(float3 const c) const noexcept {
return aces::ACES(c, 1.0f);
}
ACESToneMapper* ACESToneMapper::clone() const noexcept {
return new ACESToneMapper(*this);
}
DEFAULT_CONSTRUCTORS(ACESLegacyToneMapper)
float3 ACESLegacyToneMapper::operator()(float3 const c) const noexcept {
return aces::ACES(c, 1.0f / 0.6f);
}
ACESLegacyToneMapper* ACESLegacyToneMapper::clone() const noexcept {
return new ACESLegacyToneMapper(*this);
}
DEFAULT_CONSTRUCTORS(FilmicToneMapper)
float3 FilmicToneMapper::operator()(float3 const x) const noexcept {
@@ -243,10 +230,6 @@ float3 FilmicToneMapper::operator()(float3 const x) const noexcept {
return (x * (a * x + b)) / (x * (c * x + d) + e);
}
FilmicToneMapper* FilmicToneMapper::clone() const noexcept {
return new FilmicToneMapper(*this);
}
//------------------------------------------------------------------------------
// PBR Neutral tone mapper
//------------------------------------------------------------------------------
@@ -273,17 +256,12 @@ float3 PBRNeutralToneMapper::operator()(float3 color) const noexcept {
return mix(color, float3(newPeak), g);
}
PBRNeutralToneMapper* PBRNeutralToneMapper::clone() const noexcept {
return new PBRNeutralToneMapper(*this);
}
//------------------------------------------------------------------------------
// AgX tone mapper
//------------------------------------------------------------------------------
AgxToneMapper::AgxToneMapper(AgxLook const look) noexcept : look(look) {}
AgxToneMapper::~AgxToneMapper() noexcept = default;
AgxToneMapper::AgxToneMapper(AgxToneMapper const& rhs) noexcept = default;
// These matrices taken from Blender's implementation of AgX, which works with Rec.2020 primaries.
// https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBaseRec2020.py
@@ -378,10 +356,6 @@ float3 AgxToneMapper::operator()(float3 v) const noexcept {
return v;
}
AgxToneMapper* AgxToneMapper::clone() const noexcept {
return new AgxToneMapper(*this);
}
//------------------------------------------------------------------------------
// Display range tone mapper
//------------------------------------------------------------------------------
@@ -420,10 +394,6 @@ float3 DisplayRangeToneMapper::operator()(float3 const c) const noexcept {
return mix(debugColors[index], debugColors[index + 1], saturate(v - float(index)));
}
DisplayRangeToneMapper* DisplayRangeToneMapper::clone() const noexcept {
return new DisplayRangeToneMapper(*this);
}
//------------------------------------------------------------------------------
// Generic tone mapper
//------------------------------------------------------------------------------
@@ -484,19 +454,7 @@ GenericToneMapper::~GenericToneMapper() noexcept {
delete mOptions;
}
GenericToneMapper::GenericToneMapper(GenericToneMapper const& rhs) noexcept {
mOptions = new Options(*rhs.mOptions);
}
GenericToneMapper& GenericToneMapper::operator=(GenericToneMapper const& rhs) noexcept {
if (this != &rhs) {
delete mOptions;
mOptions = new Options(*rhs.mOptions);
}
return *this;
}
GenericToneMapper::GenericToneMapper(GenericToneMapper&& rhs) noexcept : mOptions(rhs.mOptions) {
GenericToneMapper::GenericToneMapper(GenericToneMapper&& rhs) noexcept : mOptions(rhs.mOptions) {
rhs.mOptions = nullptr;
}
@@ -511,10 +469,6 @@ float3 GenericToneMapper::operator()(float3 x) const noexcept {
return mOptions->outputScale * x / (x + mOptions->inputScale);
}
GenericToneMapper* GenericToneMapper::clone() const noexcept {
return new GenericToneMapper(*this);
}
float GenericToneMapper::getContrast() const noexcept { return mOptions->contrast; }
float GenericToneMapper::getMidGrayIn() const noexcept { return mOptions->midGrayIn; }
float GenericToneMapper::getMidGrayOut() const noexcept { return mOptions->midGrayOut; }
+12 -143
View File
@@ -49,7 +49,7 @@ using namespace backend;
//------------------------------------------------------------------------------
struct ColorGrading::BuilderDetails {
std::shared_ptr<ToneMapper> toneMapper = nullptr;
const ToneMapper* toneMapper = nullptr;
#if defined(__clang__)
#pragma clang diagnostic push
@@ -173,7 +173,7 @@ ColorGrading::Builder& ColorGrading::Builder::dimensions(uint8_t const dim) noex
return *this;
}
ColorGrading::Builder& ColorGrading::Builder::toneMapper(std::shared_ptr<ToneMapper> toneMapper) noexcept {
ColorGrading::Builder& ColorGrading::Builder::toneMapper(const ToneMapper* toneMapper) noexcept {
mImpl->toneMapper = toneMapper;
return *this;
}
@@ -271,110 +271,6 @@ ColorGrading::Builder& ColorGrading::Builder::outputColorSpace(
return *this;
}
ColorGrading::LutFormat ColorGrading::getLutFormat() const noexcept {
return mSettings.lutFormat;
}
uint8_t ColorGrading::getLutDimensions() const noexcept {
return mSettings.lutDimensions;
}
const ToneMapper& ColorGrading::getToneMapper() const noexcept {
return *mSettings.toneMapper;
}
bool ColorGrading::isLuminanceScalingEnabled() const noexcept {
return mSettings.luminanceScaling;
}
bool ColorGrading::isGamutMappingEnabled() const noexcept {
return mSettings.gummapMapping;
}
float ColorGrading::getExposure() const noexcept {
return mSettings.exposure;
}
float ColorGrading::getNightAdaptation() const noexcept {
return mSettings.nightAdaptation;
}
float ColorGrading::getWhiteBalanceTemperature() const noexcept {
return mSettings.whiteBalanceTemperature;
}
float ColorGrading::getWhiteBalanceTint() const noexcept {
return mSettings.whiteBalanceTint;
}
math::float3 ColorGrading::getChannelMixerOutRed() const noexcept {
return mSettings.channelMixerOutRed;
}
math::float3 ColorGrading::getChannelMixerOutGreen() const noexcept {
return mSettings.channelMixerOutGreen;
}
math::float3 ColorGrading::getChannelMixerOutBlue() const noexcept {
return mSettings.channelMixerOutBlue;
}
math::float3 ColorGrading::getShadows() const noexcept {
return mSettings.shadows;
}
math::float3 ColorGrading::getMidtones() const noexcept {
return mSettings.midtones;
}
math::float3 ColorGrading::getHighlights() const noexcept {
return mSettings.highlights;
}
math::float4 ColorGrading::getShadowMidtonesHighlightsRanges() const noexcept {
return mSettings.ShadowMidtonesHighlightsRanges;
}
math::float3 ColorGrading::getSlope() const noexcept {
return mSettings.slope;
}
math::float3 ColorGrading::getOffset() const noexcept {
return mSettings.offset;
}
math::float3 ColorGrading::getPower() const noexcept {
return mSettings.power;
}
float ColorGrading::getContrast() const noexcept {
return mSettings.contrast;
}
float ColorGrading::getVibrance() const noexcept {
return mSettings.vibrance;
}
float ColorGrading::getSaturation() const noexcept {
return mSettings.saturation;
}
math::float3 ColorGrading::getCurvesShadowGamma() const noexcept {
return mSettings.curvesShadowGamma;
}
math::float3 ColorGrading::getCurvesMidPoint() const noexcept {
return mSettings.curvesMidPoint;
}
math::float3 ColorGrading::getCurvesHighlightScale() const noexcept {
return mSettings.curvesHighlightScale;
}
const color::ColorSpace& ColorGrading::getOutputColorSpace() const noexcept {
return mSettings.colorSpace;
}
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -391,25 +287,30 @@ ColorGrading* ColorGrading::Builder::build(Engine& engine) {
if (needToneMapper) {
switch (mImpl->toneMapping) {
case ToneMapping::LINEAR:
mImpl->toneMapper = std::make_shared<LinearToneMapper>();
mImpl->toneMapper = new LinearToneMapper();
break;
case ToneMapping::ACES_LEGACY:
mImpl->toneMapper = std::make_shared<ACESLegacyToneMapper>();
mImpl->toneMapper = new ACESLegacyToneMapper();
break;
case ToneMapping::ACES:
mImpl->toneMapper = std::make_shared<ACESToneMapper>();
mImpl->toneMapper = new ACESToneMapper();
break;
case ToneMapping::FILMIC:
mImpl->toneMapper = std::make_shared<FilmicToneMapper>();
mImpl->toneMapper = new FilmicToneMapper();
break;
case ToneMapping::DISPLAY_RANGE:
mImpl->toneMapper = std::make_shared<DisplayRangeToneMapper>();
mImpl->toneMapper = new DisplayRangeToneMapper();
break;
}
}
FColorGrading* colorGrading = downcast(engine).createColorGrading(*this);
if (needToneMapper) {
delete mImpl->toneMapper;
mImpl->toneMapper = nullptr;
}
return colorGrading;
}
@@ -985,9 +886,6 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
data, lutElementCount * elementSize, format, type,
[](void* buffer, size_t, void*) { free(buffer); }
});
// Initialize settings from builder
initializeSettings(builder, mSettings);
}
FColorGrading::~FColorGrading() noexcept = default;
@@ -997,33 +895,4 @@ void FColorGrading::terminate(FEngine& engine) {
driver.destroyTexture(mLutHandle);
}
void FColorGrading::initializeSettings(const Builder& builder, Settings& settings) noexcept {
settings.lutFormat = builder->format;
settings.lutDimensions = builder->dimension;
settings.toneMapper = builder->toneMapper;
settings.luminanceScaling = builder->luminanceScaling;
settings.gummapMapping = builder->gamutMapping;
settings.exposure = builder->exposure;
settings.nightAdaptation = builder->nightAdaptation;
settings.whiteBalanceTemperature = builder->whiteBalance.x;
settings.whiteBalanceTint = builder->whiteBalance.y;
settings.channelMixerOutRed = builder->outRed;
settings.channelMixerOutGreen = builder->outGreen;
settings.channelMixerOutBlue = builder->outBlue;
settings.shadows = builder->shadows;
settings.midtones = builder->midtones;
settings.highlights = builder->highlights;
settings.ShadowMidtonesHighlightsRanges = builder->tonalRanges;
settings.slope = builder->slope;
settings.offset = builder->offset;
settings.power = builder->power;
settings.contrast = builder->contrast;
settings.vibrance = builder->vibrance;
settings.saturation = builder->saturation;
settings.curvesShadowGamma = builder->shadowGamma;
settings.curvesMidPoint = builder->midPoint;
settings.curvesHighlightScale = builder->highlightScale;
settings.colorSpace = builder->outputColorSpace;
}
} //namespace filament
-2
View File
@@ -51,8 +51,6 @@ private:
uint32_t mDimension;
bool mIsOneDimensional;
bool mIsLDR;
static void initializeSettings(const Builder& builder, Settings& settings) noexcept;
};
FILAMENT_DOWNCAST(ColorGrading)
+13 -30
View File
@@ -361,6 +361,8 @@ void FEngine::init() {
}
// initialize the dummy textures so that their contents are not undefined
static constexpr uint32_t zeroes[6] = {};
static constexpr uint32_t ones = 0xffffffff;
mDefaultIblTexture = downcast(Texture::Builder()
.width(1).height(1).levels(1)
@@ -369,8 +371,7 @@ void FEngine::init() {
.build(*this));
driverApi.update3DImage(mDefaultIblTexture->getHwHandle(), 0, 0, 0, 0, 1, 1, 6,
{ std::array<uint8_t, 6>{}.data(), 6,
Texture::Format::RGBA, Texture::Type::UBYTE });
{ zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE });
// 3 bands = 9 float3
constexpr float sh[9 * 3] = { 0.0f };
@@ -392,12 +393,10 @@ void FEngine::init() {
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
driverApi.update3DImage(mDummyOneTexture, 0, 0, 0, 0, 1, 1, 1,
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
driverApi.update3DImage(mDummyZeroTexture, 0, 0, 0, 0, 1, 1, 1,
{ std::array<uint8_t, 4>{}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
mPerViewDescriptorSetLayoutSsrVariant = {
@@ -424,28 +423,25 @@ void FEngine::init() {
} else
#endif
{
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
FMaterial::DefaultMaterialBuilder defaultMaterialBuilder;
switch (mConfig.stereoscopicType) {
case StereoscopicType::NONE:
case StereoscopicType::INSTANCED:
defaultMaterialBuilder.package(
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
break;
case StereoscopicType::MULTIVIEW:
#ifdef FILAMENT_ENABLE_MULTIVIEW
defaultMaterialBuilder.package(
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA,
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA, MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
#else
assert_invariant(false);
#endif
break;
}
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this));
}
if (UTILS_UNLIKELY(getSupportedFeatureLevel() >= FeatureLevel::FEATURE_LEVEL_1)) {
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
constexpr float3 dummyPositions[1] = {};
constexpr short4 dummyTangents[1] = {};
@@ -455,26 +451,14 @@ void FEngine::init() {
mDummyOneTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
mDummyOneTextureArrayDepth = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::DEPTH32F, 1, 1, 1, 1, TextureUsage::DEFAULT);
mDummyZeroTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
driverApi.update3DImage(mDummyOneTextureArray, 0, 0, 0, 0, 1, 1, 1,
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
driverApi.update3DImage(mDummyOneTextureArrayDepth, 0, 0, 0, 0, 1, 1, 1,
{ std::array<float, 1>{1.0f}.data(), 4,
Texture::Format::DEPTH_COMPONENT, Texture::Type::FLOAT });
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
driverApi.update3DImage(mDummyZeroTextureArray, 0, 0, 0, 0, 1, 1, 1,
{ std::array<uint8_t, 4>{}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
mDummyUniformBuffer = driverApi.createBufferObject(CONFIG_MINSPEC_UBO_SIZE,
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
mLightManager.init(*this);
mDFG.init(*this);
@@ -624,8 +608,6 @@ void FEngine::shutdown() {
driver.destroyTexture(std::move(mDummyZeroTexture));
driver.destroyTexture(std::move(mDummyZeroTextureArray));
driver.destroyBufferObject(std::move(mDummyUniformBuffer));
driver.destroyRenderTarget(std::move(mDefaultRenderTarget));
/*
@@ -730,7 +712,8 @@ int FEngine::loop() {
if (mPlatform == nullptr) {
mPlatform = PlatformFactory::create(&mBackend);
mOwnPlatform = true;
slog.i << "FEngine resolved backend: " << to_string(mBackend) << io::endl;
const char* const backend = backendToString(mBackend);
slog.i << "FEngine resolved backend: " << backend << io::endl;
if (mPlatform == nullptr) {
slog.e << "Selected backend not supported in this build." << io::endl;
mDriverBarrier.latch();
+4 -25
View File
@@ -486,29 +486,10 @@ public:
return mPerRenderableDescriptorSetLayout;
}
backend::Handle<backend::HwTexture> getOneTexture() const {
return mDummyOneTexture;
}
backend::Handle<backend::HwTexture> getOneTextureArray() const {
return mDummyOneTextureArray;
}
backend::Handle<backend::HwTexture> getOneTextureArrayDepth() const {
return mDummyOneTextureArrayDepth;
}
backend::Handle<backend::HwTexture> getZeroTexture() const {
return mDummyZeroTexture;
}
backend::Handle<backend::HwTexture> getZeroTextureArray() const {
return mDummyZeroTextureArray;
}
backend::Handle<backend::HwBufferObject> getDummyUniformBuffer() const {
return mDummyUniformBuffer;
}
backend::Handle<backend::HwTexture> getOneTexture() const { return mDummyOneTexture; }
backend::Handle<backend::HwTexture> getZeroTexture() const { return mDummyZeroTexture; }
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; }
static constexpr size_t MiB = 1024u * 1024u;
size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; }
@@ -647,10 +628,8 @@ private:
backend::Handle<backend::HwTexture> mDummyOneTexture;
backend::Handle<backend::HwTexture> mDummyOneTextureArray;
backend::Handle<backend::HwTexture> mDummyOneTextureArrayDepth;
backend::Handle<backend::HwTexture> mDummyZeroTextureArray;
backend::Handle<backend::HwTexture> mDummyZeroTexture;
backend::Handle<backend::HwBufferObject> mDummyUniformBuffer;
std::thread::id mMainThreadId{};
+24 -47
View File
@@ -96,7 +96,7 @@ static std::unique_ptr<MaterialParser> createParser(Backend const backend,
FILAMENT_CHECK_PRECONDITION(
materialResult != MaterialParser::ParseResult::ERROR_MISSING_BACKEND)
<< "the material was not built for any of the " << to_string(backend)
<< "the material was not built for any of the " << backendToString(backend)
<< " backend's supported shader languages (" << languageNames.c_str() << ")\n";
}
@@ -329,12 +329,11 @@ FMaterial::FMaterial(FEngine& engine, const Builder& builder,
parser->hasCustomDepthShader(&mHasCustomDepthShader);
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(isLit, isSSR, hasFog);
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(
mIsVariantLit,
mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE,
!(mVariantFilterMask & +UserVariantFilterBit::FOG));
processBlendingMode(parser);
processSpecializationConstants(engine, builder, parser);
@@ -408,7 +407,6 @@ void FMaterial::terminate(FEngine& engine) {
DriverApi& driver = engine.getDriverApi();
mPerViewDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
mPerViewDescriptorSetLayoutVsm.terminate(engine.getDescriptorSetLayoutFactory(), driver);
mDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
}
@@ -611,12 +609,9 @@ Program FMaterial::getProgramWithVariants(
program.attributes(mAttributeInfo);
}
program.descriptorBindings(+DescriptorSetBindingPoints::PER_VIEW,
mProgramDescriptorBindings[+DescriptorSetBindingPoints::PER_VIEW]);
program.descriptorBindings(+DescriptorSetBindingPoints::PER_RENDERABLE,
mProgramDescriptorBindings[+DescriptorSetBindingPoints::PER_RENDERABLE]);
program.descriptorBindings(+DescriptorSetBindingPoints::PER_MATERIAL,
mProgramDescriptorBindings[+DescriptorSetBindingPoints::PER_MATERIAL]);
program.descriptorBindings(0, mProgramDescriptorBindings[0]);
program.descriptorBindings(1, mProgramDescriptorBindings[1]);
program.descriptorBindings(2, mProgramDescriptorBindings[2]);
program.specializationConstants(mSpecializationConstants);
program.pushConstants(ShaderStage::VERTEX, mPushConstants[uint8_t(ShaderStage::VERTEX)]);
@@ -1145,55 +1140,37 @@ void FMaterial::precacheDepthVariants(FEngine& engine) {
void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* const parser) {
UTILS_UNUSED_IN_RELEASE bool success;
success = parser->getDescriptorBindings(&mProgramDescriptorBindings);
assert_invariant(success);
backend::DescriptorSetLayout descriptorSetLayout;
std::array<backend::DescriptorSetLayout, 2> descriptorSetLayout;
success = parser->getDescriptorSetLayout(&descriptorSetLayout);
assert_invariant(success);
// get the PER_VIEW descriptor binding info
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
// Setup Labels for debugging
utils::CString namestr;
utils::StaticString perViewStr = "_perView";
utils::StaticString singleStr = "_single";
auto perViewDescriptorSetLayout = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, false);
parser->getName(&namestr);
auto perViewDescriptorSetLayoutVsm = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, true);
utils::CString singleLabel(namestr.c_str(), namestr.length() + singleStr.length());
memccpy(singleLabel.c_str() + namestr.length(), singleStr.c_str(), '\0', singleStr.length());
// set the labels
descriptorSetLayout.label = CString{ mName }.append("_perMat");
perViewDescriptorSetLayout.label = CString{ mName }.append("_perView");
perViewDescriptorSetLayoutVsm.label = CString{ mName }.append("_perViewVsm");
utils::CString perViewLabel(namestr.c_str(), namestr.length() + perViewStr.length());
memccpy(perViewLabel.c_str() + namestr.length(), perViewStr.c_str(), '\0', perViewStr.length());
// get the PER_RENDERABLE and PER_VIEW descriptor binding info
for (auto&& [bindingPoint, descriptorSetLayout] : {
std::pair{ DescriptorSetBindingPoints::PER_RENDERABLE,
descriptor_sets::getPerRenderableLayout() },
std::pair{ DescriptorSetBindingPoints::PER_VIEW,
perViewDescriptorSetLayout }}) {
Program::DescriptorBindingsInfo& descriptors = mProgramDescriptorBindings[+bindingPoint];
descriptors.reserve(descriptorSetLayout.bindings.size());
for (auto const& entry: descriptorSetLayout.bindings) {
auto const& name = descriptor_sets::getDescriptorName(bindingPoint, entry.binding);
descriptors.push_back({ name, entry.type, entry.binding });
}
}
descriptorSetLayout[0].label = namestr;
descriptorSetLayout[1].label = perViewLabel;
mDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(descriptorSetLayout) };
engine.getDriverApi(), std::move(descriptorSetLayout[0]) };
mPerViewDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(perViewDescriptorSetLayout) };
mPerViewDescriptorSetLayoutVsm = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(perViewDescriptorSetLayoutVsm) };
engine.getDriverApi(), std::move(descriptorSetLayout[1]) };
}
descriptor_binding_t FMaterial::getSamplerBinding(
+1 -7
View File
@@ -93,8 +93,7 @@ public:
return mPerViewDescriptorSetLayout;
}
DescriptorSetLayout const& getPerViewDescriptorSetLayout(
Variant const variant, bool const useVsmDescriptorSetLayout) const noexcept {
DescriptorSetLayout const& getPerViewDescriptorSetLayout(Variant const variant) const noexcept {
if (Variant::isValidDepthVariant(variant)) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mEngine.getPerViewDescriptorSetLayoutDepthVariant();
@@ -103,10 +102,6 @@ public:
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mEngine.getPerViewDescriptorSetLayoutSsrVariant();
}
if (useVsmDescriptorSetLayout) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mPerViewDescriptorSetLayoutVsm;
}
return mPerViewDescriptorSetLayout;
}
@@ -317,7 +312,6 @@ private:
// try to order by frequency of use
mutable std::array<backend::Handle<backend::HwProgram>, VARIANT_COUNT> mCachedPrograms;
DescriptorSetLayout mPerViewDescriptorSetLayout;
DescriptorSetLayout mPerViewDescriptorSetLayoutVsm;
DescriptorSetLayout mDescriptorSetLayout;
backend::Program::DescriptorSetInfo mProgramDescriptorBindings;
+38 -62
View File
@@ -50,8 +50,6 @@
#include <string_view>
#include <utility>
#include <stddef.h>
using namespace filament::math;
using namespace utils;
@@ -76,17 +74,15 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
FEngine::DriverApi& driver = engine.getDriverApi();
// even if the material doesn't have any parameters, we allocate a small UBO because it's
// expected by the per-material descriptor-set layout
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
mUniforms = UniformBuffer(uboSize);
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
if (!material->getUniformInterfaceBlock().isEmpty()) {
mUniforms = UniformBuffer(material->getUniformInterfaceBlock().getSize());
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
}
// set the UBO, always descriptor 0
mDescriptorSet.setBuffer(material->getDescriptorSetLayout(),
0, mUbHandle, 0, mUniforms.getSize());
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
const RasterState& rasterState = material->getRasterState();
// At the moment, only MaterialInstances have a stencil state, but in the future it should be
@@ -146,15 +142,15 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
FEngine::DriverApi& driver = engine.getDriverApi();
FMaterial const* const material = other->getMaterial();
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
mUniforms = UniformBuffer(uboSize);
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
if (!material->getUniformInterfaceBlock().isEmpty()) {
mUniforms.setUniforms(other->getUniformBuffer());
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
}
// set the UBO, always descriptor 0
mDescriptorSet.setBuffer(mMaterial->getDescriptorSetLayout(),
0, mUbHandle, 0, mUniforms.getSize());
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
if (material->hasDoubleSidedCapability()) {
setDoubleSided(mIsDoubleSided);
@@ -227,8 +223,7 @@ void FMaterialInstance::commit(DriverApi& driver) const {
<< "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n";
Handle<HwTexture> const handle = p.texture->getHwHandleForSampling();
assert_invariant(handle);
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, handle, p.params);
mDescriptorSet.setSampler(binding, handle, p.params);
}
}
@@ -244,9 +239,7 @@ void FMaterialInstance::commit(DriverApi& driver) const {
void FMaterialInstance::setParameter(std::string_view const name,
Handle<HwTexture> texture, SamplerParams const params) {
auto const binding = mMaterial->getSamplerBinding(name);
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, texture, params);
mDescriptorSet.setSampler(binding, texture, params);
}
void FMaterialInstance::setParameterImpl(std::string_view const name,
@@ -273,21 +266,6 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
#endif
auto const binding = mMaterial->getSamplerBinding(name);
if (texture) {
auto const& descriptorSetLayout = mMaterial->getDescriptorSetLayout();
DescriptorType const descriptorType = descriptorSetLayout.getDescriptorType(binding);
TextureType const textureType = texture->getTextureType();
FILAMENT_CHECK_PRECONDITION(
DescriptorSet::isTextureCompatibleWithDescriptor(textureType, descriptorType))
<< "Texture format " << int(texture->getFormat())
<< " of type " << to_string(textureType)
<< " is not compatible with material \"" << getMaterial()->getName().c_str() << "\""
<< " parameter \"" << name << "\""
<< " of type " << to_string(descriptorType);
}
if (texture && texture->textureHandleCanMutate()) {
mTextureParameters[binding] = { texture, sampler.getSamplerParams() };
} else {
@@ -300,8 +278,7 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
handle = texture->getHwHandleForSampling();
assert_invariant(handle == texture->getHwHandle());
}
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, handle, sampler.getSamplerParams());
mDescriptorSet.setSampler(binding, handle, sampler.getSamplerParams());
}
}
@@ -418,30 +395,29 @@ void FMaterialInstance::fixMissingSamplers() const {
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
return item.binding == binding;
});
FEngine const& engine = mMaterial->getEngine();
// just safety-check, should never fail
if (UTILS_LIKELY(pos != list.end())) {
FEngine const& engine = mMaterial->getEngine();
filament::DescriptorSetLayout const& layout = mMaterial->getDescriptorSetLayout();
if (pos->format != SamplerFormat::FLOAT) {
// TODO: we only handle missing samplers that are FLOAT
switch (pos->type) {
case SamplerType::SAMPLER_2D:
mDescriptorSet.setSampler(layout,
binding, engine.getZeroTexture(), {});
break;
case SamplerType::SAMPLER_2D_ARRAY:
mDescriptorSet.setSampler(layout,
binding, engine.getZeroTextureArray(), {});
break;
case SamplerType::SAMPLER_CUBEMAP:
mDescriptorSet.setSampler(layout,
binding, engine.getDummyCubemap()->getHwHandle(), {});
break;
default:
// we're currently not able to fix-up other sampler types
break;
}
switch (pos->type) {
case SamplerType::SAMPLER_2D:
mDescriptorSet.setSampler(binding,
engine.getZeroTexture(), {});
break;
case SamplerType::SAMPLER_2D_ARRAY:
mDescriptorSet.setSampler(binding,
engine.getZeroTextureArray(), {});
break;
case SamplerType::SAMPLER_CUBEMAP:
mDescriptorSet.setSampler(binding,
engine.getDummyCubemap()->getHwHandle(), {});
break;
case SamplerType::SAMPLER_EXTERNAL:
case SamplerType::SAMPLER_3D:
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
// we're currently not able to fix-up those
break;
}
}
});
+1 -2
View File
@@ -114,8 +114,7 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder)
: mVertexCount(builder->mVertexCount),
mCount(builder->mCount) {
if (UTILS_UNLIKELY(engine.getSupportedFeatureLevel() <= FeatureLevel::FEATURE_LEVEL_0)) {
// feature level 0 doesn't support morph target buffers
if (UTILS_UNLIKELY(engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0)) {
return;
}
+1 -1
View File
@@ -977,7 +977,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
// this descriptor-set is also used for ssr/picking/structure and these could be stale
// it would be better to use a separate desriptor-set for those two cases so that we don't
// have to do this
view.unbindSamplers(engine);
view.unbindSamplers(driver);
view.commitUniformsAndSamplers(driver);
});
+2 -9
View File
@@ -64,7 +64,7 @@ using namespace math;
// this is a hack to be able to create a std::function<> with a non-copyable closure
template<class F>
static auto make_copyable_function(F&& f) {
auto make_copyable_function(F&& f) {
using dF = std::decay_t<F>;
auto spf = std::make_shared<dF>(std::forward<F>(f));
return [spf](auto&& ... args) -> decltype(auto) {
@@ -274,9 +274,7 @@ Texture* Texture::Builder::build(Engine& engine) {
// ------------------------------------------------------------------------------------------------
FTexture::FTexture(FEngine& engine, const Builder& builder)
: mHasBlitSrc(false),
mExternal(false) {
FTexture::FTexture(FEngine& engine, const Builder& builder) {
FEngine::DriverApi& driver = engine.getDriverApi();
mDriver = &driver; // this is unfortunately needed for getHwHandleForSampling()
mWidth = static_cast<uint32_t>(builder->mWidth);
@@ -290,7 +288,6 @@ FTexture::FTexture(FEngine& engine, const Builder& builder)
mTextureIsSwizzled = builder->mTextureIsSwizzled;
mHasBlitSrc = builder->mHasBlitSrc;
mExternal = builder->mExternal;
mTextureType = backend::getTextureType(mFormat);
bool const isImported = builder->mImportedId != 0;
if (mExternal && !isImported) {
@@ -719,10 +716,6 @@ size_t FTexture::getFormatSize(InternalFormat const format) noexcept {
return backend::getFormatSize(format);
}
TextureType FTexture::getTextureType() const noexcept {
return mTextureType;
}
void FTexture::generatePrefilterMipmap(FEngine& engine,
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
+8 -15
View File
@@ -27,9 +27,6 @@
#include <utils/compiler.h>
#include <array>
#include <cmath>
#include <stddef.h>
#include <stdint.h>
@@ -108,20 +105,18 @@ public:
// Size a of a pixel in bytes for the given format
static size_t getFormatSize(InternalFormat format) noexcept;
backend::TextureType getTextureType() const noexcept;
// Returns the with or height for a given mipmap level from the base value.
static size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
static inline size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
return std::max(size_t(1), baseLevelValue >> level);
}
// Returns the max number of levels for a texture of given max dimensions
static uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
static inline uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
return std::max(1, std::ilogbf(float(maxDimension)) + 1);
}
// Returns the max number of levels for a texture of given dimensions
static uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
static inline uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
uint32_t const maxDimension = std::max(width, height);
return maxLevelCount(maxDimension);
}
@@ -137,7 +132,7 @@ public:
void updateLodRange(uint8_t level) noexcept;
// TODO: remove in a future filament release. See below for description.
bool hasBlitSrcUsage() const noexcept {
inline bool hasBlitSrcUsage() const noexcept {
return mHasBlitSrc;
}
@@ -171,25 +166,23 @@ private:
uint32_t mWidth = 1;
uint32_t mHeight = 1;
uint32_t mDepth = 1;
InternalFormat mFormat = InternalFormat::RGBA8;
Sampler mTarget = Sampler::SAMPLER_2D;
uint8_t mLevelCount = 1;
uint8_t mSampleCount = 1;
std::array<Swizzle, 4> mSwizzle = {
Swizzle::CHANNEL_0, Swizzle::CHANNEL_1,
Swizzle::CHANNEL_2, Swizzle::CHANNEL_3 };
bool mTextureIsSwizzled;
Usage mUsage = Usage::DEFAULT;
backend::TextureType mTextureType;
// TODO: remove in a future filament release.
// Indicates whether the user has set the TextureUsage::BLIT_SRC usage. This will be used to
// temporarily validate whether this texture can be used for readPixels.
bool mHasBlitSrc : 1;
bool mExternal : 1;
bool mTextureIsSwizzled : 1;
bool mHasBlitSrc = false;
bool mExternal = false;
// there is 4 bytes of padding here
FStream* mStream = nullptr; // only needed for streaming textures
};
+44 -105
View File
@@ -68,36 +68,10 @@ FView::FView(FEngine& engine)
mFogEntity(engine.getEntityManager().create()),
mIsStereoSupported(engine.getDriverApi().isStereoSupported()),
mUniforms(engine.getDriverApi()),
mColorPassDescriptorSet{
{ engine, false, mUniforms },
{ engine, true, mUniforms } }
{
mColorPassDescriptorSet(engine, mUniforms) {
DriverApi& driver = engine.getDriverApi();
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
// initialize the common descriptor set with dummy descriptors
mCommonRenderableDescriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
mCommonRenderableDescriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
engine.getZeroTextureArray(), {});
FDebugRegistry& debugRegistry = engine.getDebugRegistry();
debugRegistry.registerProperty("d.view.camera_at_origin",
@@ -151,13 +125,11 @@ FView::FView(FEngine& engine)
mDefaultColorGrading = mColorGrading = engine.getDefaultColorGrading();
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
colorPassDescriptorSet.init(
engine,
mLightUbh,
mFroxelizer.getRecordBuffer(),
mFroxelizer.getFroxelBuffer());
}
mColorPassDescriptorSet.init(
engine,
mLightUbh,
mFroxelizer.getRecordBuffer(),
mFroxelizer.getFroxelBuffer());
}
FView::~FView() noexcept = default;
@@ -174,9 +146,7 @@ void FView::terminate(FEngine& engine) {
ShadowMapManager::terminate(engine, mShadowMapManager);
mUniforms.terminate(driver);
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
colorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
}
mColorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
mFroxelizer.terminate(driver);
mCommonRenderableDescriptorSet.terminate(driver);
@@ -459,7 +429,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
*/
const float exposure = Exposure::exposure(cameraInfo.ev100);
getColorPassDescriptorSet().prepareExposure(cameraInfo.ev100);
mColorPassDescriptorSet.prepareExposure(cameraInfo.ev100);
/*
* Indirect light (IBL)
@@ -476,7 +446,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
FSkybox const* const skybox = scene->getSkybox();
intensity = skybox ? skybox->getIntensity() : FIndirectLight::DEFAULT_INTENSITY;
}
getColorPassDescriptorSet().prepareAmbientLight(engine, *ibl, intensity, exposure);
mColorPassDescriptorSet.prepareAmbientLight(engine, *ibl, intensity, exposure);
/*
* Directional light (always at index 0)
@@ -484,7 +454,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
FLightManager::Instance const directionalLight = lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
const float3 sceneSpaceDirection = lightData.elementAt<FScene::DIRECTION>(0); // guaranteed normalized
getColorPassDescriptorSet().prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
mColorPassDescriptorSet.prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
}
CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept {
@@ -636,7 +606,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) {
// TODO: might be more consistent to do this in prepareLighting(), but it's not
// strictly necessary
getColorPassDescriptorSet().prepareDynamicLights(mFroxelizer);
mColorPassDescriptorSet.prepareDynamicLights(mFroxelizer);
}
// We need to pass viewMatrix by value here because it extends the scope of this
// function.
@@ -741,7 +711,6 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
scene->updateUBOs(merged, mRenderableUbh);
mCommonRenderableDescriptorSet.setBuffer(
engine.getPerRenderableDescriptorSetLayout(),
+PerRenderableBindingPoints::OBJECT_UNIFORMS, mRenderableUbh,
0, sizeof(PerRenderableUib));
@@ -765,65 +734,37 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
FRenderableManager& rcm = engine.getRenderableManager();
auto& descriptorSet = rcm.getDescriptorSet(ci);
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
// initialize the descriptor set the first time it's needed
if (UTILS_UNLIKELY(!descriptorSet.getHandle())) {
descriptorSet = DescriptorSet{ layout };
descriptorSet = DescriptorSet{ engine.getPerRenderableDescriptorSetLayout() };
}
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::OBJECT_UNIFORMS,
descriptorSet.setBuffer(+PerRenderableBindingPoints::OBJECT_UNIFORMS,
instance.handle ? instance.handle : mRenderableUbh,
0, sizeof(PerRenderableUib));
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
engine.getZeroTextureArray(), {});
if (UTILS_UNLIKELY(skinning.handle || morphing.handle)) {
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
descriptorSet.setBuffer(+PerRenderableBindingPoints::BONES_UNIFORMS,
skinning.handle, 0, sizeof(PerRenderableBoneUib));
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
descriptorSet.setSampler(+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
skinning.boneIndicesAndWeightHandle, {});
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
descriptorSet.setBuffer(+PerRenderableBindingPoints::MORPHING_UNIFORMS,
morphing.handle, 0, sizeof(PerRenderableMorphingUib));
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
morphing.morphTargetBuffer->getPositionsHandle(), {});
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
morphing.morphTargetBuffer->getTangentsHandle(), {});
}
descriptorSet.commit(layout, driver);
descriptorSet.commit(engine.getPerRenderableDescriptorSetLayout(), driver);
// write the descriptor-set handle to the sceneData array for access later
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
descriptorSet.getHandle();
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) = descriptorSet.getHandle();
} else {
// use the shared descriptor-set
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
@@ -847,13 +788,12 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
auto const& tcm = engine.getTransformManager();
auto const fogTransform = tcm.getWorldTransformAccurate(tcm.getInstance(mFogEntity));
auto& colorPassDescriptorSet = getColorPassDescriptorSet();
colorPassDescriptorSet.prepareTime(engine, userTime);
colorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
mColorPassDescriptorSet.prepareTime(engine, userTime);
mColorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
scene->getIndirectLight());
colorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
colorPassDescriptorSet.prepareBlending(needsAlphaChannel);
colorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
mColorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
mColorPassDescriptorSet.prepareBlending(needsAlphaChannel);
mColorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
}
void FView::computeVisibilityMasks(
@@ -914,12 +854,12 @@ void FView::prepareUpscaler(float2 const scale,
derivativesScale = 0.5f;
}
}
getColorPassDescriptorSet().prepareLodBias(bias, derivativesScale);
mColorPassDescriptorSet.prepareLodBias(bias, derivativesScale);
}
void FView::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept {
SYSTRACE_CALL();
getColorPassDescriptorSet().prepareCamera(engine, cameraInfo);
mColorPassDescriptorSet.prepareCamera(engine, cameraInfo);
}
void FView::prepareViewport(
@@ -928,23 +868,23 @@ void FView::prepareViewport(
SYSTRACE_CALL();
// TODO: we should pass viewport.{left|bottom} to the backend, so it can offset the
// scissor properly.
getColorPassDescriptorSet().prepareViewport(physicalViewport, logicalViewport);
mColorPassDescriptorSet.prepareViewport(physicalViewport, logicalViewport);
}
void FView::prepareSSAO(Handle<HwTexture> ssao) const noexcept {
getColorPassDescriptorSet().prepareSSAO(ssao, mAmbientOcclusionOptions);
mColorPassDescriptorSet.prepareSSAO(ssao, mAmbientOcclusionOptions);
}
void FView::prepareSSR(Handle<HwTexture> ssr,
bool const disableSSR,
float const refractionLodOffset,
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept {
getColorPassDescriptorSet().prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
mColorPassDescriptorSet.prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
}
void FView::prepareStructure(Handle<HwTexture> structure) const noexcept {
// sampler must be NEAREST
getColorPassDescriptorSet().prepareStructure(structure);
mColorPassDescriptorSet.prepareStructure(structure);
}
void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
@@ -956,38 +896,37 @@ void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
}
switch (mShadowType) {
case ShadowType::PCF:
getColorPassDescriptorSet().prepareShadowPCF(texture, uniforms);
mColorPassDescriptorSet.prepareShadowPCF(texture, uniforms);
break;
case ShadowType::VSM:
getColorPassDescriptorSet().prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
mColorPassDescriptorSet.prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
break;
case ShadowType::DPCF:
getColorPassDescriptorSet().prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
mColorPassDescriptorSet.prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
break;
case ShadowType::PCSS:
getColorPassDescriptorSet().prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
mColorPassDescriptorSet.prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
break;
case ShadowType::PCFd:
getColorPassDescriptorSet().prepareShadowPCFDebug(texture, uniforms);
mColorPassDescriptorSet.prepareShadowPCFDebug(texture, uniforms);
break;
}
}
void FView::prepareShadowMapping(FEngine const& engine, bool const highPrecision) const noexcept {
BufferObjectHandle ubo{ engine.getDummyUniformBuffer() };
void FView::prepareShadowMapping(bool const highPrecision) const noexcept {
if (mHasShadowing) {
assert_invariant(mShadowMapManager);
ubo = mShadowMapManager->getShadowUniformsHandle();
mColorPassDescriptorSet.prepareShadowMapping(
mShadowMapManager->getShadowUniformsHandle(), highPrecision);
}
getColorPassDescriptorSet().prepareShadowMapping(ubo, highPrecision);
}
void FView::commitUniformsAndSamplers(DriverApi& driver) const noexcept {
getColorPassDescriptorSet().commit(driver);
mColorPassDescriptorSet.commit(driver);
}
void FView::unbindSamplers(FEngine& engine) noexcept {
getColorPassDescriptorSet().unbindSamplers(engine);
void FView::unbindSamplers(DriverApi& driver) noexcept {
mColorPassDescriptorSet.unbindSamplers(driver);
}
void FView::commitFroxels(DriverApi& driverApi) const noexcept {
+4 -6
View File
@@ -178,11 +178,11 @@ public:
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept;
void prepareStructure(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadow(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadowMapping(FEngine const& engine, bool highPrecision) const noexcept;
void prepareShadowMapping(bool highPrecision) const noexcept;
void commitFroxels(backend::DriverApi& driverApi) const noexcept;
void commitUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
void unbindSamplers(FEngine& engine) noexcept;
void unbindSamplers(backend::DriverApi& driver) noexcept;
utils::JobSystem::Job* getFroxelizerSync() const noexcept { return mFroxelizerSync; }
void setFroxelizerSync(utils::JobSystem::Job* sync) noexcept { mFroxelizerSync = sync; }
@@ -440,9 +440,7 @@ public:
static void cullRenderables(utils::JobSystem& js, FScene::RenderableSoa& renderableData,
Frustum const& frustum, size_t bit) noexcept;
ColorPassDescriptorSet& getColorPassDescriptorSet() const noexcept {
return mColorPassDescriptorSet[mShadowType == ShadowType::PCF ? 0 : 1];
}
ColorPassDescriptorSet& getColorPassDescriptorSet() noexcept { return mColorPassDescriptorSet; }
// Returns the frame history FIFO. This is typically used by the FrameGraph to access
// previous frame data.
@@ -589,7 +587,7 @@ private:
RenderQuality mRenderQuality;
mutable TypedUniformBuffer<PerViewUib> mUniforms;
mutable ColorPassDescriptorSet mColorPassDescriptorSet[2];
mutable ColorPassDescriptorSet mColorPassDescriptorSet;
mutable FrameHistory mFrameHistory{};
+31 -34
View File
@@ -79,7 +79,7 @@ uint8_t ColorPassDescriptorSet::getIndex(
index |= 0x2;
}
if (fog) {
if (!fog) {
// this will remove samplers needed for fog
index |= 0x4;
}
@@ -88,18 +88,27 @@ uint8_t ColorPassDescriptorSet::getIndex(
return index;
}
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine, bool const vsm,
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept
: mUniforms(uniforms), mIsVsm(vsm) {
: mUniforms(uniforms) {
constexpr UserVariantFilterMask filterFog = UserVariantFilterMask(UserVariantFilterBit::FOG);
constexpr UserVariantFilterMask keepFog = UserVariantFilterMask(0);
for (bool const lit: { false, true }) {
for (bool const ssr: { false, true }) {
for (bool const fog: { false, true }) {
auto const index = getIndex(lit, ssr, fog);
auto index = getIndex(lit, ssr, fog);
mDescriptorSetLayout[index] = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(),
descriptor_sets::getPerViewDescriptorSetLayout(
MaterialDomain::SURFACE, lit, ssr, fog, vsm)
MaterialDomain::SURFACE,
fog ? keepFog : filterFog,
lit,
ssr ? ReflectionMode::SCREEN_SPACE : ReflectionMode::DEFAULT,
ssr ? RefractionMode::SCREEN_SPACE : RefractionMode::NONE)
};
mDescriptorSet[index] = DescriptorSet{ mDescriptorSetLayout[index] };
}
@@ -109,11 +118,11 @@ ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine, bool const vsm,
setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
engine.getDFG().isValid() ?
engine.getDFG().getTexture() : engine.getZeroTexture(), {
.filterMag = SamplerMagFilter::LINEAR
});
if (engine.getDFG().isValid()) {
TextureSampler const sampler(TextureSampler::MagFilter::LINEAR);
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
engine.getDFG().getTexture(), sampler.getSamplerParams());
}
}
void ColorPassDescriptorSet::init(
@@ -121,14 +130,12 @@ void ColorPassDescriptorSet::init(
BufferObjectHandle lights,
BufferObjectHandle recordBuffer,
BufferObjectHandle froxelBuffer) noexcept {
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto& descriptorSet = mDescriptorSet[i];
auto const& layout = mDescriptorSetLayout[i];
descriptorSet.setBuffer(layout, +PerViewBindingPoints::LIGHTS,
for (auto&& descriptorSet: mDescriptorSet) {
descriptorSet.setBuffer(+PerViewBindingPoints::LIGHTS,
lights, 0, CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib));
descriptorSet.setBuffer(layout, +PerViewBindingPoints::RECORD_BUFFER,
descriptorSet.setBuffer(+PerViewBindingPoints::RECORD_BUFFER,
recordBuffer, 0, sizeof(FroxelRecordUib));
descriptorSet.setBuffer(layout, +PerViewBindingPoints::FROXEL_BUFFER,
descriptorSet.setBuffer(+PerViewBindingPoints::FROXEL_BUFFER,
froxelBuffer, 0, Froxelizer::getFroxelBufferByteCount(engine.getDriverApi()));
}
}
@@ -298,7 +305,6 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer
void ColorPassDescriptorSet::prepareSSAO(Handle<HwTexture> ssao,
AmbientOcclusionOptions const& options) noexcept {
// High quality sampling is enabled only if AO itself is enabled and upsampling quality is at
// least set to high and of course only if upsampling is needed.
const bool highQualitySampling = options.upsampling >= QualityLevel::HIGH
@@ -531,28 +537,20 @@ void ColorPassDescriptorSet::commit(DriverApi& driver) noexcept {
driver.updateBufferObject(mUniforms.getUboHandle(),
mUniforms.toBufferDescriptor(driver), 0);
}
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
mDescriptorSet[i].commit(mDescriptorSetLayout[i], driver);
}
}
void ColorPassDescriptorSet::unbindSamplers(FEngine& engine) noexcept {
void ColorPassDescriptorSet::unbindSamplers(DriverApi&) noexcept {
// this needs to reset the sampler that are only set in RendererUtils::colorPass(), because
// this descriptor-set is also used for ssr/picking/structure and these could be stale
// it would be better to use a separate descriptor-set for those two cases so that we don't
// have to do this
setBuffer(+PerViewBindingPoints::SHADOWS,
engine.getDummyUniformBuffer(), 0, sizeof(ShadowUib));
setSampler(+PerViewBindingPoints::STRUCTURE,
engine.getZeroTexture(), {});
setSampler(+PerViewBindingPoints::SHADOW_MAP,
engine.getOneTextureArrayDepth(), {});
setSampler(+PerViewBindingPoints::SSAO,
engine.getZeroTextureArray(), {});
setSampler(+PerViewBindingPoints::SSR,
engine.getZeroTextureArray(), {});
setSampler(+PerViewBindingPoints::STRUCTURE, {}, {});
setSampler(+PerViewBindingPoints::SHADOW_MAP, {}, {});
setSampler(+PerViewBindingPoints::SSAO, {}, {});
setSampler(+PerViewBindingPoints::SSR, {}, {});
}
void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
@@ -560,7 +558,7 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto samplers = mDescriptorSetLayout[i].getSamplerDescriptors();
if (samplers[binding]) {
mDescriptorSet[i].setSampler(mDescriptorSetLayout[i], binding, th, params);
mDescriptorSet[i].setSampler(binding, th, params);
}
}
}
@@ -568,10 +566,9 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
void ColorPassDescriptorSet::setBuffer(descriptor_binding_t const binding,
BufferObjectHandle boh, uint32_t const offset, uint32_t const size) noexcept {
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto const& layout = mDescriptorSetLayout[i];
auto ubos = layout.getUniformBufferDescriptors();
auto ubos = mDescriptorSetLayout[i].getUniformBufferDescriptors();
if (ubos[binding]) {
mDescriptorSet[i].setBuffer(layout, binding, boh, offset, size);
mDescriptorSet[i].setBuffer(binding, boh, offset, size);
}
}
}
+8 -12
View File
@@ -66,16 +66,16 @@ class ColorPassDescriptorSet {
using LightManagerInstance = utils::EntityInstance<LightManager>;
using TextureHandle = backend::Handle<backend::HwTexture>;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCF = 0u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCF = 0u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
public:
static uint8_t getIndex(bool lit, bool ssr, bool fog) noexcept;
ColorPassDescriptorSet(FEngine& engine, bool vsm,
ColorPassDescriptorSet(FEngine& engine,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void init(
@@ -153,15 +153,13 @@ public:
// update local data into GPU UBO
void commit(backend::DriverApi& driver) noexcept;
void unbindSamplers(FEngine& engine) noexcept;
void unbindSamplers(backend::DriverApi& driver) noexcept;
// bind this UBO
void bind(backend::DriverApi& driver, uint8_t const index) const noexcept {
mDescriptorSet[index].bind(driver, DescriptorSetBindingPoints::PER_VIEW);
}
bool isVSM() const noexcept { return mIsVsm; }
private:
static constexpr size_t DESCRIPTOR_LAYOUT_COUNT = 8;
@@ -171,13 +169,11 @@ private:
void setBuffer(backend::descriptor_binding_t binding,
backend::BufferObjectHandle boh, uint32_t offset, uint32_t size) noexcept;
static void prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
TypedUniformBuffer<PerViewUib>& mUniforms;
std::array<DescriptorSetLayout, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSetLayout;
std::array<DescriptorSet, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSet;
bool const mIsVsm;
static void prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
};
} // namespace filament
+9 -85
View File
@@ -28,7 +28,6 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <utility>
#include <limits>
@@ -87,7 +86,6 @@ void DescriptorSet::commitSlow(DescriptorSetLayout const& layout,
mValid.forEachSetBit([&layout, &driver,
dsh = mDescriptorSetHandle, descriptors = mDescriptors.data()]
(backend::descriptor_binding_t const binding) {
assert_invariant(layout.isValid(binding));
if (layout.isSampler(binding)) {
driver.updateDescriptorSetTexture(dsh, binding,
descriptors[binding].texture.th,
@@ -115,7 +113,7 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
// within the renderpass. We have to comment the assert out since it crashed a client's debug
// build.
// assert_invariant(mDirty.none());
if (UTILS_VERY_UNLIKELY(mDirty.any() && !mSetAfterCommitWarning)) {
if (mDirty.any() && !mSetAfterCommitWarning) {
mDirty.forEachSetBit([&](uint8_t const binding) {
utils::slog.w << "Descriptor set (handle=" << mDescriptorSetHandle.getId()
<< ") binding=" << (int) binding
@@ -126,109 +124,35 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
driver.bindDescriptorSet(mDescriptorSetHandle, +set, std::move(dynamicOffsets));
}
void DescriptorSet::setBuffer(DescriptorSetLayout const& layout,
void DescriptorSet::setBuffer(
backend::descriptor_binding_t const binding,
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) {
// Validate it's the right kind of descriptor
using DSLB = backend::DescriptorSetLayoutBinding;
FILAMENT_CHECK_PRECONDITION(DSLB::isBuffer(layout.getDescriptorType(binding)))
<< "descriptor " << +binding << "is not a buffer";
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) noexcept {
// TODO: validate it's the right kind of descriptor
if (mDescriptors[binding].buffer.boh != boh || mDescriptors[binding].buffer.size != size) {
// we don't set the dirty bit if only offset changes
mDirty.set(binding);
}
mDescriptors[binding].buffer = { boh, offset, size };
mValid.set(binding, bool(boh));
mValid.set(binding, (bool)boh);
}
void DescriptorSet::setSampler(
DescriptorSetLayout const& layout,
backend::descriptor_binding_t const binding,
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) {
using namespace backend;
using DSLB = DescriptorSetLayoutBinding;
// Validate it's the right kind of descriptor
auto type = layout.getDescriptorType(binding);
FILAMENT_CHECK_PRECONDITION(DSLB::isSampler(type))
<< "descriptor " << +binding << " is not a sampler";
FILAMENT_CHECK_PRECONDITION(
!(params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE && !isDepthDescriptor(type)))
<< "descriptor " << +binding
<< " is not of type DEPTH, but sampler is in COMPARE_TO_TEXTURE mode";
FILAMENT_CHECK_PRECONDITION(
!(params.isFiltered() &&
isDepthDescriptor(type) &&
params.compareMode != SamplerCompareMode::COMPARE_TO_TEXTURE))
<< "descriptor " << +binding
<< " is of type filtered DEPTH, but sampler not in COMPARE_TO_TEXTURE mode";
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) noexcept {
// TODO: validate it's the right kind of descriptor
if (mDescriptors[binding].texture.th != th || mDescriptors[binding].texture.params != params) {
mDirty.set(binding);
}
mDescriptors[binding].texture = { th, params };
mValid.set(binding, bool(th));
mValid.set(binding, (bool)th);
}
DescriptorSet DescriptorSet::duplicate(DescriptorSetLayout const& layout) const noexcept {
DescriptorSet set{layout};
set.mDescriptors = mDescriptors; // Use the vector's assignment operator
set.mDirty = mValid | mDirty; // Dirty all valid descriptors so they're updated during commit
set.mDirty = mDirty;
set.mValid = mValid;
return set;
}
bool DescriptorSet::isTextureCompatibleWithDescriptor(
backend::TextureType t, backend::DescriptorType d) noexcept {
using namespace backend;
switch (d) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
// allows to specify which one, but not filament.
// Depth textures can be used as an unfiltered float sampler
return t == TextureType::FLOAT || t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_3D_INT:
return t == TextureType::INT;
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_3D_UINT:
return t == TextureType::UINT;
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
// allows to specify which one, but not filament.
return t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
case DescriptorType::SAMPLER_EXTERNAL:
case DescriptorType::UNIFORM_BUFFER:
case DescriptorType::SHADER_STORAGE_BUFFER:
case DescriptorType::INPUT_ATTACHMENT:
return false;
}
// should never happen
return false;
}
} // namespace filament
+4 -9
View File
@@ -62,16 +62,14 @@ public:
backend::DescriptorSetOffsetArray dynamicOffsets) const noexcept;
// sets a ubo/ssbo descriptor
void setBuffer(DescriptorSetLayout const& layout,
backend::descriptor_binding_t binding,
void setBuffer(backend::descriptor_binding_t binding,
backend::Handle<backend::HwBufferObject> boh,
uint32_t offset, uint32_t size);
uint32_t offset, uint32_t size) noexcept;
// sets a sampler descriptor
void setSampler(DescriptorSetLayout const& layout,
backend::descriptor_binding_t binding,
void setSampler(backend::descriptor_binding_t binding,
backend::Handle<backend::HwTexture> th,
backend::SamplerParams params);
backend::SamplerParams params) noexcept;
// Used for duplicating material
DescriptorSet duplicate(DescriptorSetLayout const& layout) const noexcept;
@@ -84,9 +82,6 @@ public:
return mValid;
}
static bool isTextureCompatibleWithDescriptor(
backend::TextureType t, backend::DescriptorType d) noexcept;
private:
struct Desc {
Desc() noexcept { }
+5 -12
View File
@@ -20,9 +20,6 @@
#include "details/Engine.h"
#include <utils/debug.h>
#include <utils/FixedCapacityVector.h>
#include <backend/DriverEnums.h>
#include <algorithm>
@@ -38,15 +35,11 @@ DescriptorSetLayout::DescriptorSetLayout(
backend::DescriptorSetLayout descriptorSetLayout) noexcept {
for (auto&& desc : descriptorSetLayout.bindings) {
mMaxDescriptorBinding = std::max(mMaxDescriptorBinding, desc.binding);
mSamplers.set(desc.binding, backend::DescriptorSetLayoutBinding::isSampler(desc.type));
mUniformBuffers.set(desc.binding, desc.type == backend::DescriptorType::UNIFORM_BUFFER);
}
assert_invariant(mMaxDescriptorBinding < utils::bitset64::BIT_COUNT);
mDescriptorTypes = utils::FixedCapacityVector<backend::DescriptorType>(mMaxDescriptorBinding + 1);
for (auto&& desc : descriptorSetLayout.bindings) {
mDescriptorTypes[desc.binding] = desc.type;
mSamplers.set(desc.binding,
desc.type == backend::DescriptorType::SAMPLER ||
desc.type == backend::DescriptorType::SAMPLER_EXTERNAL);
mUniformBuffers.set(desc.binding,
desc.type == backend::DescriptorType::UNIFORM_BUFFER);
}
mDescriptorSetLayoutHandle = factory.create(driver,
-11
View File
@@ -23,7 +23,6 @@
#include <backend/Handle.h>
#include <utils/bitset.h>
#include <utils/FixedCapacityVector.h>
#include <stddef.h>
#include <stdint.h>
@@ -57,10 +56,6 @@ public:
return mMaxDescriptorBinding;
}
bool isValid(backend::descriptor_binding_t const binding) const noexcept {
return mSamplers[binding] || mUniformBuffers[binding];
}
bool isSampler(backend::descriptor_binding_t const binding) const noexcept {
return mSamplers[binding];
}
@@ -73,17 +68,11 @@ public:
return mUniformBuffers;
}
backend::DescriptorType getDescriptorType(
backend::descriptor_binding_t const binding) const noexcept {
return mDescriptorTypes[binding];
}
private:
backend::DescriptorSetLayoutHandle mDescriptorSetLayoutHandle;
utils::bitset64 mSamplers;
utils::bitset64 mUniformBuffers;
uint8_t mMaxDescriptorBinding = 0;
utils::FixedCapacityVector<backend::DescriptorType> mDescriptorTypes;
};
+1 -2
View File
@@ -53,8 +53,7 @@ void PostProcessDescriptorSet::terminate(HwDescriptorSetLayoutFactory& factory,
void PostProcessDescriptorSet::setFrameUniforms(DriverApi& driver,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
// initialize the descriptor-set
mDescriptorSet.setBuffer(mDescriptorSetLayout,
+PerViewBindingPoints::FRAME_UNIFORMS,
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
mDescriptorSet.commit(mDescriptorSetLayout, driver);
+2 -2
View File
@@ -46,8 +46,8 @@ ShadowMapDescriptorSet::ShadowMapDescriptorSet(FEngine& engine) noexcept {
mDescriptorSet = DescriptorSet{ engine.getPerViewDescriptorSetLayoutDepthVariant() };
// initialize the descriptor-set
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutDepthVariant(),
+PerViewBindingPoints::FRAME_UNIFORMS, mUniformBufferHandle, 0, sizeof(PerViewUib));
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
mUniformBufferHandle, 0, sizeof(PerViewUib));
}
void ShadowMapDescriptorSet::terminate(DriverApi& driver) {
+10 -16
View File
@@ -53,32 +53,28 @@ void SsrPassDescriptorSet::terminate(DriverApi& driver) {
driver.destroyBufferObject(mShadowUbh);
}
void SsrPassDescriptorSet::setFrameUniforms(FEngine const& engine,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
void SsrPassDescriptorSet::setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
// initialize the descriptor-set
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::FRAME_UNIFORMS,
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
// This is actually not used for the SSR variants, but the descriptor-set layout needs
// to have this UBO because the fragment shader used is the "generic" one. Both Metal
// and GL would be okay without this, but Vulkan's validation layer would complain.
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
mDescriptorSet.setBuffer(+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
mUniforms = std::addressof(uniforms);
}
void SsrPassDescriptorSet::prepareHistorySSR(FEngine const& engine, Handle<HwTexture> ssr,
void SsrPassDescriptorSet::prepareHistorySSR(Handle<HwTexture> ssr,
mat4f const& historyProjection,
mat4f const& uvFromViewMatrix,
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept {
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::SSR, ssr, {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
});
mDescriptorSet.setSampler(+PerViewBindingPoints::SSR, ssr, {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
});
assert_invariant(mUniforms);
auto& s = mUniforms->edit();
@@ -90,11 +86,9 @@ void SsrPassDescriptorSet::prepareHistorySSR(FEngine const& engine, Handle<HwTex
s.ssrStride = ssrOptions.stride;
}
void SsrPassDescriptorSet::prepareStructure(FEngine const& engine,
Handle<HwTexture> structure) noexcept {
void SsrPassDescriptorSet::prepareStructure(Handle<HwTexture> structure) noexcept {
// sampler must be NEAREST
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::STRUCTURE, structure, {});
mDescriptorSet.setSampler(+PerViewBindingPoints::STRUCTURE, structure, {});
}
void SsrPassDescriptorSet::commit(FEngine& engine) noexcept {
+3 -3
View File
@@ -47,11 +47,11 @@ public:
void terminate(backend::DriverApi& driver);
void setFrameUniforms(FEngine const& engine, TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void prepareStructure(FEngine const& engine, TextureHandle structure) noexcept;
void prepareStructure(TextureHandle structure) noexcept;
void prepareHistorySSR(FEngine const& engine, TextureHandle ssr,
void prepareHistorySSR(TextureHandle ssr,
math::mat4f const& historyProjection,
math::mat4f const& uvFromViewMatrix,
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept;
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.59.5"
spec.version = "1.59.4"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.5/filament-v1.59.5-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.4/filament-v1.59.4-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
+1 -2
View File
@@ -102,8 +102,7 @@ project in Xcode to see changes take effect.
## Building iOS Samples with ASan / UBSan
1. Turn on ASan / UBSan in Filament's top-level CMakeLists.txt by passing
`-DFILAMENT_ENABLE_ASAN_UBSAN=1` to trigger the following line:
1. Turn on ASan / UBSan in Filament's top-level CMakeLists.txt by uncommenting the following line:
```
set(EXTRA_SANITIZE_OPTIONS "-fsanitize=undefined -fsanitize=address")
@@ -28,7 +28,7 @@
namespace filament {
// update this when a new version of filament wouldn't work with older materials
static constexpr size_t MATERIAL_VERSION = 60;
static constexpr size_t MATERIAL_VERSION = 59;
/**
* Supported shading models
@@ -20,7 +20,6 @@
#include <backend/DriverEnums.h>
#include <private/filament/EngineEnums.h>
#include <private/filament/Variant.h>
#include <filament/MaterialEnums.h>
@@ -35,20 +34,15 @@ backend::DescriptorSetLayout const& getPerRenderableLayout() noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain domain,
bool isLit, bool isSSR, bool hasFog,
bool isVSM) noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant variant,
MaterialDomain domain,
bool isLit, bool isSSR, bool hasFog) noexcept;
UserVariantFilterMask variantFilter,
bool isLit,
ReflectionMode reflectionMode,
RefractionMode refractionMode) noexcept;
utils::CString getDescriptorName(
DescriptorSetBindingPoints set,
filament::DescriptorSetBindingPoints set,
backend::descriptor_binding_t binding) noexcept;
backend::DescriptorType getDescriptorType(backend::SamplerType type, backend::SamplerFormat format);
} // namespace filament::descriptor_sets
@@ -23,8 +23,6 @@
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <private/filament/DescriptorSets.h>
#include <initializer_list>
#include <unordered_map>
#include <string_view>
@@ -130,9 +128,6 @@ public:
static utils::CString generateUniformName(const char* group, const char* sampler) noexcept;
static SamplerInfoList filterSamplerList(SamplerInfoList list,
backend::DescriptorSetLayout const& descriptorSetLayout);
private:
friend class Builder;
+48 -193
View File
@@ -17,151 +17,70 @@
#include "private/filament/DescriptorSets.h"
#include <private/filament/EngineEnums.h>
#include <private/filament/Variant.h>
#include <filament/MaterialEnums.h>
#include <backend/DriverEnums.h>
#include <utils/CString.h>
#include <utils/Panic.h>
#include <utils/StaticString.h>
#include <utils/debug.h>
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <string_view>
namespace filament::descriptor_sets {
using namespace backend;
// used for post-processing passes
static constexpr std::initializer_list<DescriptorSetLayoutBinding> postProcessDescriptorSetLayoutList = {
static DescriptorSetLayout const postProcessDescriptorSetLayout{
utils::StaticString("postProcess"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
}};
// used to generate shadow-maps
static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantDescriptorSetLayoutList = {
static DescriptorSetLayout const depthVariantDescriptorSetLayout{
utils::StaticString("depthVariant"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
}};
// ssrVariantDescriptorSetLayout must match perViewDescriptorSetLayout's vertex stage. This is
// because the SSR variant is always using the "standard" vertex shader (i.e. there is no
// dedicated SSR vertex shader), which uses perViewDescriptorSetLayout.
// This means that PerViewBindingPoints::SHADOWS must be in the layout even though it's not used
// by the SSR variant.
static constexpr std::initializer_list<DescriptorSetLayoutBinding> ssrVariantDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
};
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{
utils::StaticString("ssrVariant"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
}};
// Used for generating the color pass (i.e. the main pass). This is in fact a template that gets
// declined into 8 different layouts, based on variants.
//
// Note about the SHADOW_MAP binding points:
// This descriptor can either be a SAMPLER_FLOAT or a SAMPLER_DEPTH,
// and there are 3 cases to consider:
//
// | TextureType | CompareMode | Filtered | SamplerType | Variant |
// ---------+-------------+-------------+----------+-------------+---------+
// PCF | DEPTH | COMPARE | Yes | DEPTH | - |
// VSM | FLOAT | NONE | Yes | FLOAT | VSM |
// OTHER | DEPTH | NONE | No | FLOAT | VSM |
//
// The SamplerType to use depends on the Variant. Variant::VSM is set for all cases except PCM.
//
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perViewDescriptorSetLayoutList = {
static DescriptorSetLayout perViewDescriptorSetLayout = {
utils::StaticString("perView"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::RECORD_BUFFER },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FROXEL_BUFFER },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER_2D_ARRAY_DEPTH, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
};
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perRenderableDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
{ DescriptorType::SAMPLER_2D_ARRAY_INT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
};
struct PairSamplerTypeFormatHasher {
std::size_t operator()(const std::pair<SamplerType, SamplerFormat>& p) const {
using UnderlyingSamplerType = std::underlying_type_t<SamplerType>;
using UnderlyingSamplerFormat = std::underlying_type_t<SamplerFormat>;
std::size_t seed = 0;
std::size_t const hash1 = std::hash<UnderlyingSamplerType>{}(
static_cast<UnderlyingSamplerType>(p.first)
);
std::size_t const hash2 = std::hash<UnderlyingSamplerFormat>{}(
static_cast<UnderlyingSamplerFormat>(p.second)
);
seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
};
static const std::unordered_map<
std::pair<SamplerType, SamplerFormat>, DescriptorType, PairSamplerTypeFormatHasher> sDescriptorTypeMap{
{{ SamplerType::SAMPLER_2D, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_INT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_UINT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_FLOAT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_DEPTH },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_ARRAY_INT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_ARRAY_UINT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_ARRAY_FLOAT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_ARRAY_DEPTH },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_INT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_UINT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_FLOAT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_DEPTH },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_ARRAY_INT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_ARRAY_UINT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH },
{{ SamplerType::SAMPLER_3D, SamplerFormat::INT }, DescriptorType::SAMPLER_3D_INT },
{{ SamplerType::SAMPLER_3D, SamplerFormat::UINT }, DescriptorType::SAMPLER_3D_UINT },
{{ SamplerType::SAMPLER_3D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_3D_FLOAT },
{{ SamplerType::SAMPLER_EXTERNAL, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_EXTERNAL }
};
// used for post-processing passes
static DescriptorSetLayout const postProcessDescriptorSetLayout{ utils::StaticString("postProcess"),
postProcessDescriptorSetLayoutList };
// used to generate shadow-maps
static DescriptorSetLayout const depthVariantDescriptorSetLayout{
utils::StaticString("depthVariant"), depthVariantDescriptorSetLayoutList
};
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{ utils::StaticString("ssrVariant"),
ssrVariantDescriptorSetLayoutList };
// Used for generating the color pass (i.e. the main pass). This is in fact a template that gets
// declined into 8 different layouts, based on variants.
static DescriptorSetLayout perViewDescriptorSetLayout = { utils::StaticString("perView"),
perViewDescriptorSetLayoutList };
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
}};
static DescriptorSetLayout perRenderableDescriptorSetLayout = {
utils::StaticString("perRenderable"), perRenderableDescriptorSetLayoutList
};
utils::StaticString("perRenderable"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
}};
DescriptorSetLayout const& getPostProcessLayout() noexcept {
return postProcessDescriptorSetLayout;
@@ -179,8 +98,8 @@ DescriptorSetLayout const& getPerRenderableLayout() noexcept {
return perRenderableDescriptorSetLayout;
}
utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
descriptor_binding_t const binding) noexcept {
utils::CString getDescriptorName(DescriptorSetBindingPoints set,
descriptor_binding_t binding) noexcept {
using namespace std::literals;
static std::unordered_map<descriptor_binding_t, std::string_view> const set0{{
@@ -209,12 +128,12 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
switch (set) {
case DescriptorSetBindingPoints::PER_VIEW: {
auto const pos = set0.find(binding);
auto pos = set0.find(binding);
assert_invariant(pos != set0.end());
return { pos->second.data(), pos->second.size() };
}
case DescriptorSetBindingPoints::PER_RENDERABLE: {
auto const pos = set1.find(binding);
auto pos = set1.find(binding);
assert_invariant(pos != set1.end());
return { pos->second.data(), pos->second.size() };
}
@@ -223,13 +142,17 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
return "MaterialParams";
}
}
return "Unknown";
}
DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain const domain,
bool const isLit, bool const isSSR, bool const hasFog,
bool const isVSM) noexcept {
MaterialDomain domain,
UserVariantFilterMask variantFilter,
bool isLit,
ReflectionMode reflectionMode,
RefractionMode refractionMode) noexcept {
bool const ssr = reflectionMode == ReflectionMode::SCREEN_SPACE ||
refractionMode == RefractionMode::SCREEN_SPACE;
switch (domain) {
case MaterialDomain::SURFACE: {
@@ -248,7 +171,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
layout.bindings.end());
}
// remove descriptors not needed for SSRs
if (!isSSR) {
if (!ssr) {
layout.bindings.erase(
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& entry) {
@@ -258,7 +181,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
}
// remove fog descriptor if filtered out
if (!hasFog) {
if (variantFilter & (UserVariantFilterMask)UserVariantFilterBit::FOG) {
layout.bindings.erase(
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& entry) {
@@ -266,82 +189,14 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
}),
layout.bindings.end());
}
// change the SHADOW_MAP descriptor type for VSM
if (isVSM) {
auto const pos = std::find_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& v) {
return v.binding == PerViewBindingPoints::SHADOW_MAP;
});
if (pos != layout.bindings.end()) {
pos->type = DescriptorType::SAMPLER_2D_ARRAY_FLOAT;
}
}
return layout;
}
case MaterialDomain::POST_PROCESS:
return postProcessDescriptorSetLayout;
return descriptor_sets::getPostProcessLayout();
case MaterialDomain::COMPUTE:
// TODO: what's the layout for compute?
return postProcessDescriptorSetLayout;
return descriptor_sets::getPostProcessLayout();
}
}
DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant const variant,
MaterialDomain const domain,
bool const isLit, bool const isSSR, bool const hasFog) noexcept {
if (Variant::isValidDepthVariant(variant)) {
return depthVariantDescriptorSetLayout;
}
if (Variant::isSSRVariant(variant)) {
return ssrVariantDescriptorSetLayout;
}
// We need to filter out all the descriptors not included in the "resolved" layout below
return getPerViewDescriptorSetLayout(domain, isLit, isSSR, hasFog,
Variant::isVSMVariant(variant));
}
DescriptorType getDescriptorType(SamplerType const type, SamplerFormat const format) {
auto const pos = sDescriptorTypeMap.find({ type, format });
FILAMENT_CHECK_PRECONDITION(pos != sDescriptorTypeMap.end())
<< "Incompatible Sampler Format " << to_string(format)
<< " and Type " << to_string(type);
return pos->second;
}
template<class ITERATOR, class PREDICATE>
constexpr static ITERATOR find_if(ITERATOR first, ITERATOR last, PREDICATE pred) {
for (; first != last; ++first)
if (pred(*first)) break;
return first;
}
constexpr static bool checkConsistency() noexcept {
// check that all descriptors that apply to the vertex stage in perViewDescriptorSetLayout
// are present in ssrVariantDescriptorSetLayout; meaning that the latter is compatible
// with the former.
for (auto const& r: perViewDescriptorSetLayoutList) {
if (hasShaderType(r.stageFlags, ShaderStage::VERTEX)) {
auto const pos = find_if(
ssrVariantDescriptorSetLayoutList.begin(),
ssrVariantDescriptorSetLayoutList.end(),
[r](auto const& l) {
return l.count == r.count &&
l.type == r.type &&
l.binding == r.binding &&
l.flags == r.flags &&
l.stageFlags == r.stageFlags;
});
if (pos == ssrVariantDescriptorSetLayoutList.end()) {
return false;
}
}
}
return true;
}
static_assert(checkConsistency(), "ssrVariantDescriptorSetLayout is not compatible with "
"perViewDescriptorSetLayout");
} // namespace filament::descriptor_sets
+2 -21
View File
@@ -16,7 +16,6 @@
#include "private/filament/SamplerInterfaceBlock.h"
#include <private/filament/DescriptorSets.h>
#include <backend/DriverEnums.h>
@@ -103,7 +102,7 @@ const SamplerInterfaceBlock::SamplerInfo* SamplerInterfaceBlock::getSamplerInfo(
return &mSamplersInfoList[pos->second];
}
CString SamplerInterfaceBlock::generateUniformName(const char* group, const char* sampler) noexcept {
utils::CString SamplerInterfaceBlock::generateUniformName(const char* group, const char* sampler) noexcept {
char uniformName[256];
// sampler interface block name
@@ -118,27 +117,9 @@ CString SamplerInterfaceBlock::generateUniformName(const char* group, const char
std::min(sizeof(uniformName) / 2 - 2, strlen(sampler)),
prefix + 1);
*last++ = 0; // null terminator
assert_invariant(last <= std::end(uniformName));
assert(last <= std::end(uniformName));
return CString{ uniformName, size_t(last - uniformName) - 1u };
}
SamplerInterfaceBlock::SamplerInfoList SamplerInterfaceBlock::filterSamplerList(
SamplerInfoList list, backend::DescriptorSetLayout const& descriptorSetLayout) {
// remove all the samplers that are not included in the descriptor-set layout
list.erase(
std::remove_if(list.begin(), list.end(),
[&](auto const& entry) {
auto pos = std::find_if(
descriptorSetLayout.bindings.begin(),
descriptorSetLayout.bindings.end(),
[&entry](const auto& item) {
return item.binding == entry.binding;
});
return pos == descriptorSetLayout.bindings.end();
}), list.end());
return list;
}
} // namespace filament
@@ -603,7 +603,7 @@ public:
* extension will be derived from the shader stage. For example, mymaterial_0x0e.frag,
* mymaterial_0x18.vert, etc.
*/
MaterialBuilder& saveRawVariants(bool saveRawVariants) noexcept;
MaterialBuilder& saveRawVariants(bool saveVariants) noexcept;
//! If true, will include debugging information in generated SPIRV.
MaterialBuilder& generateDebugInfo(bool generateDebugInfo) noexcept;
@@ -635,7 +635,7 @@ public:
* Build the material. If you are using the Filament engine with this library, you should use
* the job system provided by Engine.
*/
Package build(utils::JobSystem& jobSystem);
Package build(utils::JobSystem& jobSystem) noexcept;
public:
// The methods and types below are for internal use
@@ -809,7 +809,7 @@ private:
// Multiple calls to findProperties accumulate the property sets across fragment
// and vertex shaders in mProperties.
bool findProperties(filament::backend::ShaderStage type,
MaterialBuilder::PropertyList const& allProperties,
MaterialBuilder::PropertyList& allProperties,
CodeGenParams const& semanticCodeGenParams) noexcept;
bool runSemanticAnalysis(MaterialInfo* inOutInfo,
+89 -102
View File
@@ -23,6 +23,7 @@
#include <spirv_glsl.hpp>
#include <spirv_msl.hpp>
#include "backend/DriverEnums.h"
#include "private/filament/DescriptorSets.h"
#include "sca/builtinResource.h"
#include "sca/GLSLTools.h"
@@ -33,26 +34,16 @@
#include "MetalArgumentBuffer.h"
#include "SpirvFixup.h"
#include "utils/ostream.h"
#include <filament/MaterialEnums.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <algorithm>
#include <optional>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
#ifdef FILAMENT_SUPPORTS_WEBGPU
#include <tint/tint.h>
#endif
@@ -75,7 +66,22 @@ using BindingIndexMap = std::unordered_map<std::string, uint16_t>;
#define DEBUG_LOG_DESCRIPTOR_SETS 0
#endif
static const char* toString(ShaderStageFlags const flags) {
const char* toString(DescriptorType type) {
switch (type) {
case DescriptorType::UNIFORM_BUFFER:
return "UNIFORM_BUFFER";
case DescriptorType::SHADER_STORAGE_BUFFER:
return "SHADER_STORAGE_BUFFER";
case DescriptorType::SAMPLER:
return "SAMPLER";
case DescriptorType::INPUT_ATTACHMENT:
return "INPUT_ATTACHMENT";
case DescriptorType::SAMPLER_EXTERNAL:
return "SAMPLER_EXTERNAL";
}
}
const char* toString(ShaderStageFlags flags) {
std::vector<const char*> stages;
if (any(flags & ShaderStageFlags::VERTEX)) {
stages.push_back("VERTEX");
@@ -100,14 +106,14 @@ static const char* toString(ShaderStageFlags const flags) {
return buffer;
}
static const char* prettyDescriptorFlags(DescriptorFlags const flags) {
const char* prettyDescriptorFlags(DescriptorFlags flags) {
if (flags == DescriptorFlags::DYNAMIC_OFFSET) {
return "DYNAMIC_OFFSET";
}
return "NONE";
}
static const char* prettyPrintSamplerType(SamplerType const type) {
const char* prettyPrintSamplerType(SamplerType type) {
switch (type) {
case SamplerType::SAMPLER_2D:
return "SAMPLER_2D";
@@ -134,37 +140,35 @@ DescriptorSetLayout getPerMaterialDescriptorSet(SamplerInterfaceBlock const& sib
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
+PerMaterialBindingPoints::MATERIAL_PARAMS, DescriptorFlags::NONE, 0 });
for (auto const& sampler: samplers) {
DescriptorSetLayoutBinding layoutBinding{
DescriptorType::SAMPLER_EXTERNAL,
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
sampler.binding,
DescriptorFlags::NONE,
0
};
if (sampler.type != SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
layoutBinding.type = descriptor_sets::getDescriptorType(sampler.type, sampler.format);
}
layout.bindings.push_back(layoutBinding);
for (auto const& sampler : samplers) {
layout.bindings.push_back(DescriptorSetLayoutBinding {
(sampler.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) ?
DescriptorType::SAMPLER_EXTERNAL : DescriptorType::SAMPLER,
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, sampler.binding,
DescriptorFlags::NONE, 0 });
}
return layout;
}
static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
static void collectDescriptorsForSet(filament::DescriptorSetBindingPoints set,
const GLSLPostProcessor::Config& config, DescriptorSetInfo& descriptors) {
const MaterialInfo& material = *config.materialInfo;
// get the descriptor set layout for the given pinding point
DescriptorSetLayout const descriptorSetLayout = [&] {
DescriptorSetLayout const info = [&]() {
switch (set) {
case DescriptorSetBindingPoints::PER_VIEW: {
bool const isLit = material.isLit || material.hasShadowMultiplier;
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
material.refractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(config.variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
return descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
config.variant, config.domain, isLit, isSSR, hasFog);
if (filament::Variant::isValidDepthVariant(config.variant)) {
return descriptor_sets::getDepthVariantLayout();
}
if (filament::Variant::isSSRVariant(config.variant)) {
return descriptor_sets::getSsrVariantLayout();
}
return descriptor_sets::getPerViewDescriptorSetLayout(config.domain,
config.variantFilter,
material.isLit || material.hasShadowMultiplier,
material.reflectionMode,
material.refractionMode);
}
case DescriptorSetBindingPoints::PER_RENDERABLE:
return descriptor_sets::getPerRenderableLayout();
@@ -175,8 +179,7 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
}
}();
// get the sampler list for this binding point
auto samplerList = [&] {
auto samplerList = [&]() {
switch (set) {
case DescriptorSetBindingPoints::PER_VIEW:
return SibGenerator::getPerViewSib(config.variant).getSamplerInfoList();
@@ -189,33 +192,42 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
}
}();
// filter the list with the descriptor set layout
auto const descriptorSetSamplerList =
SamplerInterfaceBlock::filterSamplerList(std::move(samplerList), descriptorSetLayout);
// remove all the samplers that are not included in the descriptor-set layout
samplerList.erase(std::remove_if(samplerList.begin(), samplerList.end(),
[&info](auto const& entry) {
auto pos = std::find_if(info.bindings.begin(),
info.bindings.end(), [&entry](const auto& item) {
return item.binding == entry.binding;
});
return pos == info.bindings.end();
}),
samplerList.end());
// helper to get the name of a descriptor for this set, given a binding.
auto getDescriptorName = [set, &descriptorSetSamplerList](descriptor_binding_t binding) {
auto getDescriptorName = [&](DescriptorSetBindingPoints set, descriptor_binding_t binding) {
if (set == DescriptorSetBindingPoints::PER_MATERIAL) {
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
auto pos = std::find_if(samplerList.begin(), samplerList.end(),
[&](const auto& entry) { return entry.binding == binding; });
if (pos == descriptorSetSamplerList.end()) {
if (pos == samplerList.end()) {
return descriptor_sets::getDescriptorName(set, binding);
}
return pos->uniformName;
SamplerInterfaceBlock::SamplerInfo& sampler = *pos;
return sampler.uniformName;
}
return descriptor_sets::getDescriptorName(set, binding);
};
for (auto const& layoutBinding : descriptorSetLayout.bindings) {
descriptor_binding_t binding = layoutBinding.binding;
auto name = getDescriptorName(binding);
if (DescriptorSetLayoutBinding::isSampler(layoutBinding.type)) {
auto const pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
for (size_t i = 0; i < info.bindings.size(); i++) {
backend::descriptor_binding_t binding = info.bindings[i].binding;
auto name = getDescriptorName(set, binding);
if (info.bindings[i].type == DescriptorType::SAMPLER ||
info.bindings[i].type == DescriptorType::SAMPLER_EXTERNAL) {
auto pos = std::find_if(samplerList.begin(), samplerList.end(),
[&](const auto& entry) { return entry.binding == binding; });
assert_invariant(pos != descriptorSetSamplerList.end());
descriptors.emplace_back(name, layoutBinding, *pos);
assert_invariant(pos != samplerList.end());
SamplerInterfaceBlock::SamplerInfo& sampler = *pos;
descriptors.emplace_back(name, info.bindings[i], sampler);
} else {
descriptors.emplace_back(name, layoutBinding, std::nullopt);
descriptors.emplace_back(name, info.bindings[i], std::nullopt);
}
}
@@ -224,8 +236,8 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
});
}
static void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) noexcept {
auto getName = [](uint8_t const set) {
void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) {
auto getName = [](uint8_t set) {
switch (set) {
case +DescriptorSetBindingPoints::PER_VIEW:
return "perViewDescriptorSetLayout";
@@ -242,23 +254,18 @@ static void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) noexc
printf("[DS] info (%s) = [\n", getName(setIndex));
for (auto const& descriptor : descriptors) {
auto const& [name, info, sampler] = descriptor;
if (DescriptorSetLayoutBinding::isSampler(info.type)) {
if (info.type == DescriptorType::SAMPLER ||
info.type == DescriptorType::SAMPLER_EXTERNAL) {
assert_invariant(sampler.has_value());
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
"%s, samplerType = %s}",
name.c_str_safe(), info.binding,
int(to_string(info.type).size()),
to_string(info.type).data(),
info.count,
name.c_str_safe(), info.binding, toString(info.type), info.count,
toString(info.stageFlags), prettyDescriptorFlags(info.flags),
prettyPrintSamplerType(sampler->type));
} else {
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
"%s}",
name.c_str_safe(), info.binding,
int(to_string(info.type).size()),
to_string(info.type).data(),
info.count,
name.c_str_safe(), info.binding, toString(info.type), info.count,
toString(info.stageFlags), prettyDescriptorFlags(info.flags));
}
printf(",\n");
@@ -358,7 +365,7 @@ static std::string stringifySpvOptimizerMessage(spv_message_level_t level, const
}
void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
ShaderStage stage, ShaderModel shaderModel,
filament::backend::ShaderStage stage, filament::backend::ShaderModel shaderModel,
bool useFramebufferFetch, const DescriptorSets& descriptorSets,
const ShaderMinifier* minifier) {
using namespace msl;
@@ -472,25 +479,7 @@ void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
break;
}
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_EXTERNAL: {
assert_invariant(sampler.has_value());
const std::string samplerName = std::string(name.c_str()) + "Smplr";
@@ -586,7 +575,7 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
//After splitting the image samplers, we need to remap the bindings to separate them.
rebindImageSamplerForWGSL(*spirv);
//Allow non-uniform derivatives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
//Allow non-uniform derivitives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
const tint::spirv::reader::Options readerOpts{true};
tint::wgsl::writer::Options writerOpts{};
@@ -625,9 +614,7 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
*outWsl = wgslOut->wgsl;
return true;
#else
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
" please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU"
<< io::endl;
slog.i << "Trying to emit WGSL without including WebGPU dependencies, please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU" << io::endl;
return false;
#endif
@@ -687,7 +674,7 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
// SpvRules should be enough.
// I think this could cause the compilation to fail on gl_VertexID.
using Type = std::underlying_type_t<EShMessages>;
msg = EShMessages(Type(msg) | Type(EShMsgVulkanRules));
msg = EShMessages(Type(msg) | Type(EShMessages::EShMsgVulkanRules));
}
bool const ok = tShader.parse(&DefaultTBuiltInResource, internalConfig.langVersion, false, msg);
@@ -697,7 +684,7 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
}
// add texture lod bias
if (config.shaderType == ShaderStage::FRAGMENT &&
if (config.shaderType == backend::ShaderStage::FRAGMENT &&
config.domain == MaterialDomain::SURFACE) {
GLSLTools::textureLodBias(tShader);
}
@@ -773,8 +760,8 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
return true;
}
bool GLSLPostProcessor::preprocessOptimization(TShader& tShader,
Config const& config, InternalConfig& internalConfig) const {
bool GLSLPostProcessor::preprocessOptimization(glslang::TShader& tShader,
GLSLPostProcessor::Config const& config, InternalConfig& internalConfig) const {
using TargetApi = MaterialBuilder::TargetApi;
assert_invariant(bool(internalConfig.spirvOutput) == (config.targetApi != TargetApi::OPENGL));
@@ -845,7 +832,7 @@ bool GLSLPostProcessor::preprocessOptimization(TShader& tShader,
}
bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
Config const& config, InternalConfig& internalConfig) const {
GLSLPostProcessor::Config const& config, InternalConfig& internalConfig) const {
SpirvBlob spirv;
bool const optimizeForSize = mOptimization == MaterialBuilderBase::Optimization::SIZE;
@@ -941,7 +928,7 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
#else
try {
*internalConfig.glslOutput = glslCompiler.compile();
} catch (CompilerError e) {
} catch (spirv_cross::CompilerError e) {
slog.e << "ERROR: " << e.what() << io::endl;
return false;
}
@@ -961,8 +948,8 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
return true;
}
std::shared_ptr<Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
auto optimizer = std::make_shared<Optimizer>(SPV_ENV_UNIVERSAL_1_3);
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
auto optimizer = std::make_shared<spvtools::Optimizer>(SPV_ENV_UNIVERSAL_1_3);
optimizer->SetMessageConsumer([](spv_message_level_t level,
const char* source, const spv_position_t& position, const char* message) {
if (!filterSpvOptimizerMessage(level)) {
@@ -974,7 +961,7 @@ std::shared_ptr<Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
return optimizer;
}
std::shared_ptr<Optimizer> GLSLPostProcessor::createOptimizer(
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
MaterialBuilder::Optimization optimization, Config const& config) {
auto optimizer = createEmptyOptimizer();
@@ -1013,7 +1000,7 @@ void GLSLPostProcessor::optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv)
}
void GLSLPostProcessor::fixupClipDistance(
SpirvBlob& spirv, Config const& config) const {
SpirvBlob& spirv, GLSLPostProcessor::Config const& config) const {
if (!config.usesClipDistance) {
return;
}
@@ -1053,7 +1040,7 @@ void GLSLPostProcessor::fixupClipDistance(
void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config const& config) {
auto RegisterPass = [&](Optimizer::PassToken&& pass,
auto RegisterPass = [&](spvtools::Optimizer::PassToken&& pass,
MaterialBuilder::TargetApi apiFilter = MaterialBuilder::TargetApi::ALL) {
if (!(config.targetApi & apiFilter)) {
return;
@@ -1098,7 +1085,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
}
void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& config) {
auto RegisterPass = [&](Optimizer::PassToken&& pass,
auto RegisterPass = [&](spvtools::Optimizer::PassToken&& pass,
MaterialBuilder::TargetApi apiFilter = MaterialBuilder::TargetApi::ALL) {
if (!(config.targetApi & apiFilter)) {
return;
File diff suppressed because it is too large Load Diff
+63 -1
View File
@@ -16,6 +16,8 @@
#include "MaterialVariants.h"
#include "shaders/ShaderGenerator.h"
#include <private/filament/EngineEnums.h>
#include <private/filament/Variant.h>
@@ -23,8 +25,16 @@
#include <filament/MaterialEnums.h>
#include <utils/compiler.h>
#include <utils/Panic.h>
#include <utils/Log.h>
#include <algorithm>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filamat {
std::vector<Variant> determineSurfaceVariants(
@@ -52,6 +62,58 @@ std::vector<Variant> determineSurfaceVariants(
if (fragmentVariant == variant) {
variants.emplace_back(variant, filament::backend::ShaderStage::FRAGMENT);
}
// Here we make sure that the combination of vertex and fragment variants have compatible
// PER_VIEW descriptor-set layouts. This could actually be a static/compile-time check
// because it is entirely decided in DescriptorSets.cpp. Unfortunately it's not possible
// to write this entirely as a constexpr.
if (UTILS_UNLIKELY(vertexVariant != fragmentVariant)) {
// fragment and vertex variants are different, we need to check the layouts are
// compatible.
using filament::ReflectionMode;
using filament::RefractionMode;
using filament::backend::ShaderStage;
// And we need to do that for all configurations of the "PER_VIEW" descriptor set
// layouts (there are eight).
// See ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant.
for (auto reflection: {
ReflectionMode::SCREEN_SPACE,
ReflectionMode::DEFAULT }) {
for (auto refraction: {
RefractionMode::SCREEN_SPACE,
RefractionMode::CUBEMAP,
RefractionMode::NONE }) {
auto const vdsl = ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant(
vertexVariant, userVariantFilter, isLit || shadowMultiplier,
reflection, refraction);
auto const fdsl = ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant(
fragmentVariant, userVariantFilter, isLit || shadowMultiplier,
reflection, refraction);
// Check that all bindings present in the vertex shader DescriptorSetLayout
// are also present in the fragment shader DescriptorSetLayout.
for (auto const& r: vdsl.bindings) {
if (!hasShaderType(r.stageFlags, ShaderStage::VERTEX)) {
// ignore descriptors that are of the fragment stage only
continue;
}
auto const pos = std::find_if(fdsl.bindings.begin(), fdsl.bindings.end(),
[r](auto const& l) {
return l.count == r.count && l.type == r.type &&
l.binding == r.binding && l.flags == r.flags &&
l.stageFlags == r.stageFlags;
});
// A mismatch is fatal. The material is ill-formed. This typically
// mean a bug / inconsistency in DescriptorsSets.cpp
FILAMENT_CHECK_POSTCONDITION(pos != fdsl.bindings.end())
<< "Variant " << +k << " has mismatched descriptorset layouts";
}
}
}
}
}
return variants;
}
@@ -71,7 +133,7 @@ std::vector<Variant> determinePostProcessVariants() {
std::vector<Variant> determineComputeVariants() {
// TODO: should we have variants for compute shaders?
std::vector<Variant> variants;
filament::Variant const variant(0);
filament::Variant variant(0);
variants.emplace_back(variant, filament::backend::ShaderStage::COMPUTE);
return variants;
}

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