Compare commits

..
101 changed files with 934 additions and 2826 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
+1 -1
View File
@@ -8,4 +8,4 @@ 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**]
- materials: remove dependence on per-view descset layout from filamat. [⚠️ **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()
+34 -183
View File
@@ -37,7 +37,6 @@
#include <array>
#include <type_traits>
#include <variant>
#include <string_view>
#include <stddef.h>
#include <stdint.h>
@@ -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);
}
-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:
+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");
+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());
@@ -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)
+84 -85
View File
@@ -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) {
@@ -1069,98 +1069,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) {
+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
@@ -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; }
};
+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{};
+16 -28
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);
}
@@ -1151,23 +1149,17 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
backend::DescriptorSetLayout descriptorSetLayout;
success = parser->getDescriptorSetLayout(&descriptorSetLayout);
assert_invariant(success);
auto perMatLabel = mName;
perMatLabel.append("_perMat");
descriptorSetLayout.label = std::move(perMatLabel);
// 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));
auto perViewDescriptorSetLayout = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, false);
auto perViewDescriptorSetLayoutVsm = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, true);
// set the labels
descriptorSetLayout.label = CString{ mName }.append("_perMat");
perViewDescriptorSetLayout.label = CString{ mName }.append("_perView");
perViewDescriptorSetLayoutVsm.label = CString{ mName }.append("_perViewVsm");
auto perViewDescriptorSetLayout =
descriptor_sets::getPerViewDescriptorSetLayout(mMaterialDomain, mVariantFilterMask,
mIsVariantLit || mHasShadowMultiplier, mReflectionMode, mRefractionMode);
auto perViewLabel = mName;
perViewLabel.append("_perView");
perViewDescriptorSetLayout.label = std::move(perViewLabel);
// get the PER_RENDERABLE and PER_VIEW descriptor binding info
for (auto&& [bindingPoint, descriptorSetLayout] : {
@@ -1189,11 +1181,7 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
mPerViewDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(perViewDescriptorSetLayout) };
mPerViewDescriptorSetLayoutVsm = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(perViewDescriptorSetLayoutVsm) };
engine.getDriverApi(), perViewDescriptorSetLayout };
}
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
@@ -35,20 +35,23 @@ backend::DescriptorSetLayout const& getPerRenderableLayout() noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain domain,
bool isLit, bool isSSR, bool hasFog,
bool isVSM) noexcept;
UserVariantFilterMask variantFilter,
bool isLit,
ReflectionMode reflectionMode,
RefractionMode refractionMode) 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,
backend::descriptor_binding_t binding) noexcept;
backend::DescriptorType getDescriptorType(backend::SamplerType type, backend::SamplerFormat format);
} // namespace filament::descriptor_sets
+34 -107
View File
@@ -24,28 +24,21 @@
#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>
namespace filament::descriptor_sets {
using namespace backend;
// used for post-processing passes
static constexpr std::initializer_list<DescriptorSetLayoutBinding> postProcessDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
// used to generate shadow-maps
static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
@@ -58,88 +51,32 @@ static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantD
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 },
{ 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 = {
{ 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 },
{ 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 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 }
{ 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 },
};
// used for post-processing passes
@@ -209,12 +146,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 +160,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 {
UserVariantFilterMask const variantFilter,
bool const isLit,
ReflectionMode const reflectionMode,
RefractionMode const refractionMode) noexcept {
bool const ssr = reflectionMode == ReflectionMode::SCREEN_SPACE ||
refractionMode == RefractionMode::SCREEN_SPACE;
switch (domain) {
case MaterialDomain::SURFACE: {
@@ -248,7 +189,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 +199,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,17 +207,6 @@ 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:
@@ -289,8 +219,11 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant const variant,
MaterialDomain const domain,
bool const isLit, bool const isSSR, bool const hasFog) noexcept {
MaterialDomain domain,
UserVariantFilterMask const variantFilter,
bool const isLit,
ReflectionMode const reflectionMode,
RefractionMode const refractionMode) noexcept {
if (Variant::isValidDepthVariant(variant)) {
return depthVariantDescriptorSetLayout;
}
@@ -298,17 +231,11 @@ DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
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));
return getPerViewDescriptorSetLayout(domain, variantFilter,
isLit, reflectionMode, refractionMode);
}
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) {
+47 -67
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"
@@ -44,15 +45,10 @@
#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 +71,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 +111,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,18 +145,12 @@ 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;
@@ -159,12 +164,11 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
DescriptorSetLayout const descriptorSetLayout = [&] {
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);
config.variant, config.domain, config.variantFilter,
material.isLit || material.hasShadowMultiplier,
material.reflectionMode,
material.refractionMode);
}
case DescriptorSetBindingPoints::PER_RENDERABLE:
return descriptor_sets::getPerRenderableLayout();
@@ -206,16 +210,17 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
return descriptor_sets::getDescriptorName(set, binding);
};
for (auto const& layoutBinding : descriptorSetLayout.bindings) {
descriptor_binding_t binding = layoutBinding.binding;
for (auto descriptor : descriptorSetLayout.bindings) {
descriptor_binding_t binding = descriptor.binding;
auto name = getDescriptorName(binding);
if (DescriptorSetLayoutBinding::isSampler(layoutBinding.type)) {
auto const pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
if (descriptor.type == DescriptorType::SAMPLER ||
descriptor.type == DescriptorType::SAMPLER_EXTERNAL) {
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
[&](const auto& entry) { return entry.binding == binding; });
assert_invariant(pos != descriptorSetSamplerList.end());
descriptors.emplace_back(name, layoutBinding, *pos);
descriptors.emplace_back(name, descriptor, *pos);
} else {
descriptors.emplace_back(name, layoutBinding, std::nullopt);
descriptors.emplace_back(name, descriptor, std::nullopt);
}
}
@@ -224,8 +229,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 +247,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");
@@ -472,25 +472,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 +568,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 +607,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
@@ -27,10 +27,7 @@
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/debug.h>
#include <utils/FixedCapacityVector.h>
#include <utility>
@@ -197,7 +194,11 @@ void MaterialDescriptorBindingsChuck::flatten(Flattener& f) {
// all the material's sampler descriptors
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
f.writeString({ entry.uniformName.data(), entry.uniformName.size() });
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
} else {
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
}
f.writeUint8(entry.binding);
}
}
@@ -227,7 +228,11 @@ void MaterialDescriptorSetLayoutChunk::flatten(Flattener& f) {
// all the material's sampler descriptors
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
} else {
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
}
f.writeUint8(uint8_t(ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT));
f.writeUint8(entry.binding);
f.writeUint8(uint8_t(DescriptorFlags::NONE));
+55 -60
View File
@@ -36,7 +36,6 @@
#include <algorithm>
#include <iterator>
#include <utility>
#include <stddef.h>
#include <stdint.h>
@@ -47,9 +46,9 @@ using namespace filament;
using namespace filament::backend;
using namespace utils;
void ShaderGenerator::generateSurfaceMaterialVariantDefines(io::sstream& out,
ShaderStage const stage, MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant const variant) noexcept {
void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream& out,
ShaderStage stage, MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant variant) noexcept {
bool const litVariants = material.isLit || material.hasShadowMultiplier;
@@ -229,25 +228,25 @@ void ShaderGenerator::generateSurfaceMaterialVariantProperties(io::sstream& out,
}
}
void ShaderGenerator::generateVertexDomainDefines(io::sstream& out, VertexDomain const domain) noexcept {
void ShaderGenerator::generateVertexDomainDefines(io::sstream& vs, VertexDomain domain) noexcept {
switch (domain) {
case VertexDomain::OBJECT:
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_OBJECT", true);
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_OBJECT", true);
break;
case VertexDomain::WORLD:
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_WORLD", true);
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_WORLD", true);
break;
case VertexDomain::VIEW:
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_VIEW", true);
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_VIEW", true);
break;
case VertexDomain::DEVICE:
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_DEVICE", true);
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_DEVICE", true);
break;
}
}
void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out,
PostProcessVariant const variant) noexcept {
PostProcessVariant variant) noexcept {
switch (variant) {
case PostProcessVariant::OPAQUE:
CodeGenerator::generateDefine(out, "POST_PROCESS_OPAQUE", 1u);
@@ -259,7 +258,7 @@ void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out
}
void ShaderGenerator::appendShader(io::sstream& ss,
const CString& shader, size_t const lineOffset) noexcept {
const CString& shader, size_t lineOffset) noexcept {
auto countLines = [](const char* s) -> size_t {
size_t lines = 0;
@@ -315,9 +314,9 @@ ShaderGenerator::ShaderGenerator(
MaterialBuilder::PreprocessorDefineList const& defines,
MaterialBuilder::ConstantList const& constants,
MaterialBuilder::PushConstantList const& pushConstants,
CString const& materialCode, size_t const lineOffset,
CString const& materialVertexCode, size_t const vertexLineOffset,
MaterialBuilder::MaterialDomain const materialDomain) noexcept {
CString const& materialCode, size_t lineOffset,
CString const& materialVertexCode, size_t vertexLineOffset,
MaterialBuilder::MaterialDomain materialDomain) noexcept {
if (materialDomain == MaterialBuilder::MaterialDomain::COMPUTE) {
// we shouldn't have a vertex shader in a compute material
@@ -361,8 +360,8 @@ ShaderGenerator::ShaderGenerator(
}
}
void ShaderGenerator::fixupExternalSamplers(ShaderModel const sm, std::string& shader,
MaterialBuilder::FeatureLevel const featureLevel,
void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material) noexcept {
// External samplers are only supported on GL ES at the moment, we must
// skip the fixup on desktop targets
@@ -371,11 +370,11 @@ void ShaderGenerator::fixupExternalSamplers(ShaderModel const sm, std::string& s
}
}
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material, const filament::Variant variant, Interpolation const interpolation,
VertexDomain const vertexDomain) const noexcept {
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant variant, Interpolation interpolation,
VertexDomain vertexDomain) const noexcept {
assert_invariant(filament::Variant::isValid(variant));
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
@@ -417,23 +416,23 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel const shader
AttributeBitset attributes = material.requiredAttributes;
if (hasSkinningOrMorphing(variant, featureLevel)) {
attributes.set(BONE_INDICES);
attributes.set(BONE_WEIGHTS);
attributes.set(VertexAttribute::BONE_INDICES);
attributes.set(VertexAttribute::BONE_WEIGHTS);
if (material.useLegacyMorphing) {
attributes.set(MORPH_POSITION_0);
attributes.set(MORPH_POSITION_1);
attributes.set(MORPH_POSITION_2);
attributes.set(MORPH_POSITION_3);
attributes.set(MORPH_TANGENTS_0);
attributes.set(MORPH_TANGENTS_1);
attributes.set(MORPH_TANGENTS_2);
attributes.set(MORPH_TANGENTS_3);
attributes.set(VertexAttribute::MORPH_POSITION_0);
attributes.set(VertexAttribute::MORPH_POSITION_1);
attributes.set(VertexAttribute::MORPH_POSITION_2);
attributes.set(VertexAttribute::MORPH_POSITION_3);
attributes.set(VertexAttribute::MORPH_TANGENTS_0);
attributes.set(VertexAttribute::MORPH_TANGENTS_1);
attributes.set(VertexAttribute::MORPH_TANGENTS_2);
attributes.set(VertexAttribute::MORPH_TANGENTS_3);
}
}
MaterialBuilder::PushConstantList vertexPushConstants;
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
std::back_insert_iterator(vertexPushConstants),
std::back_insert_iterator<MaterialBuilder::PushConstantList>(vertexPushConstants),
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::VERTEX;
});
@@ -506,11 +505,11 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel const shader
return vs.c_str();
}
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant variant,
Interpolation const interpolation, UserVariantFilterMask const variantFilter) const noexcept {
Interpolation interpolation, UserVariantFilterMask variantFilter) const noexcept {
assert_invariant(filament::Variant::isValid(variant));
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
@@ -530,8 +529,8 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shad
generateSurfaceMaterialVariantDefines(
fs, ShaderStage::FRAGMENT, featureLevel, material, variant);
auto const defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
auto defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
auto specularAO = material.specularAOSet ? material.specularAO : defaultSpecularAO;
CodeGenerator::generateDefine(fs, "SPECULAR_AMBIENT_OCCLUSION", uint32_t(specularAO));
@@ -543,12 +542,12 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shad
MaterialBuilder::PushConstantList fragmentPushConstants;
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
std::back_insert_iterator(fragmentPushConstants),
std::back_insert_iterator<MaterialBuilder::PushConstantList>(fragmentPushConstants),
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::FRAGMENT;
});
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes,
interpolation, fragmentPushConstants);
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation,
fragmentPushConstants);
CodeGenerator::generateSurfaceTypes(fs, ShaderStage::FRAGMENT);
@@ -606,16 +605,12 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shad
if (featureLevel >= FeatureLevel::FEATURE_LEVEL_1) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
// this is the list of samplers we need to filter
bool const isLit = material.isLit || material.hasShadowMultiplier;
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
material.refractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
auto const list = SamplerInterfaceBlock::filterSamplerList(
SibGenerator::getPerViewSib(variant).getSamplerInfoList(),
descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
variant, mMaterialDomain, isLit, isSSR, hasFog));
variant, mMaterialDomain, variantFilter,
material.isLit || material.hasShadowMultiplier,
material.reflectionMode, material.refractionMode));
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
}
@@ -670,9 +665,9 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shad
return fs.c_str();
}
std::string ShaderGenerator::createSurfaceComputeProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material) const noexcept {
assert_invariant(mMaterialDomain == MaterialBuilder::MaterialDomain::COMPUTE);
assert_invariant(featureLevel >= FeatureLevel::FEATURE_LEVEL_2);
@@ -713,9 +708,9 @@ std::string ShaderGenerator::createSurfaceComputeProgram(ShaderModel const shade
return s.c_str();
}
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel const sm,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant::type_t variantKey) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream vs;
@@ -723,7 +718,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel const sm
generateUserSpecConstants(cg, vs, mConstants);
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(POSITION));
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(VertexAttribute::POSITION));
// custom material variables
size_t variableIndex = 0;
@@ -757,9 +752,9 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel const sm
return vs.c_str();
}
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel const sm,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, uint8_t variant) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream fs;
@@ -816,7 +811,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel const
}
bool ShaderGenerator::hasSkinningOrMorphing(
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
return variant.hasSkinningOrMorphing()
// HACK(exv): Ignore skinning/morphing variant when targeting ESSL 1.0. We should
// either properly support skinning on FL0 or build a system in matc which allows
@@ -825,7 +820,7 @@ bool ShaderGenerator::hasSkinningOrMorphing(
}
bool ShaderGenerator::hasStereo(
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
return variant.hasStereo()
// HACK(exv): Ignore stereo variant when targeting ESSL 1.0. We should properly build a
// system in matc which allows the set of included variants to differ per-feature level.
+17 -72
View File
@@ -23,7 +23,6 @@
#include <utils/ostream.h>
#include <string_view>
#include <utility>
#include <assert.h>
#include <stddef.h>
@@ -98,7 +97,11 @@ public:
return *this;
}
~CString() noexcept;
~CString() noexcept {
if (mData) {
free(mData - 1);
}
}
void swap(CString& other) noexcept {
// don't use std::swap(), we don't want an STL dependency in this file
@@ -107,8 +110,8 @@ public:
other.mCStr = temp;
}
const_pointer c_str() const noexcept { return mCStr; }
pointer c_str() noexcept { return mCStr; }
const_pointer c_str() const noexcept { return const_cast<CString*>(this)->c_str(); }
const_pointer c_str_safe() const noexcept { return mData ? c_str() : ""; }
const_pointer data() const noexcept { return c_str(); }
pointer data() noexcept { return c_str(); }
@@ -116,89 +119,33 @@ public:
size_type length() const noexcept { return size(); }
bool empty() const noexcept { return size() == 0; }
iterator begin() noexcept { return c_str(); }
iterator begin() noexcept { return mCStr; }
iterator end() noexcept { return begin() + length(); }
const_iterator begin() const noexcept { return data(); }
const_iterator end() const noexcept { return begin() + length(); }
const_iterator cbegin() const noexcept { return begin(); }
const_iterator cend() const noexcept { return end(); }
// replace
template<size_t N>
CString& replace(size_type const pos,
size_type const len, const StringLiteral<N>& str) & noexcept {
return replace(pos, len, str, N - 1);
}
CString& replace(size_type pos, size_type len, const CString& str) noexcept;
CString& insert(size_type pos, const CString& str) noexcept { return replace(pos, 0, str); }
CString& append(const CString& str) noexcept { return insert(length(), str); }
CString& replace(size_type const pos, size_type const len, const CString& str) & noexcept {
return replace(pos, len, str.c_str_safe(), str.size());
}
template<size_t N>
CString&& replace(size_type const pos,
size_type const len, const StringLiteral<N>& str) && noexcept {
return std::move(replace(pos, len, str));
}
CString&& replace(size_type const pos, size_type const len, const CString& str) && noexcept {
return std::move(replace(pos, len, str));
}
// insert
template<size_t N>
CString& insert(size_type const pos, const StringLiteral<N>& str) & noexcept {
return replace(pos, 0, str);
}
CString& insert(size_type const pos, const CString& str) & noexcept {
return replace(pos, 0, str);
}
template<size_t N>
CString&& insert(size_type const pos, const StringLiteral<N>& str) && noexcept {
return std::move(*this).replace(pos, 0, str);
}
CString&& insert(size_type const pos, const CString& str) && noexcept {
return std::move(*this).replace(pos, 0, str);
}
// append
template<size_t N>
CString& append(const StringLiteral<N>& str) & noexcept {
return insert(length(), str);
}
CString& append(const CString& str) & noexcept {
return insert(length(), str);
}
template<size_t N>
CString&& append(const StringLiteral<N>& str) && noexcept {
return std::move(*this).insert(length(), str);
}
CString&& append(const CString& str) && noexcept {
return std::move(*this).insert(length(), str);
}
const_reference operator[](size_type const pos) const noexcept {
const_reference operator[](size_type pos) const noexcept {
assert(pos < size());
return begin()[pos];
}
reference operator[](size_type const pos) noexcept {
reference operator[](size_type pos) noexcept {
assert(pos < size());
return begin()[pos];
}
const_reference at(size_type const pos) const noexcept {
const_reference at(size_type pos) const noexcept {
assert(pos < size());
return begin()[pos];
}
reference at(size_type const pos) noexcept {
reference at(size_type pos) noexcept {
assert(pos < size());
return begin()[pos];
}
@@ -224,7 +171,7 @@ public:
}
// placement new declared as "throw" to avoid the compiler's null-check
void* operator new(size_t, void* ptr) {
inline void* operator new(size_t, void* ptr) {
assert(ptr);
return ptr;
}
@@ -238,8 +185,6 @@ public:
};
private:
CString& replace(size_type pos, size_type len, char const* str, size_t l) & noexcept;
#if !defined(NDEBUG)
friend io::ostream& operator<<(io::ostream& out, const CString& rhs);
#endif
@@ -280,7 +225,7 @@ private:
}
};
// Implement this for your type for automatic conversion to CString. Failing to do so leads
// implement this for your type for automatic conversion to CString. Failing to do so leads
// to a compile-time failure.
template<typename T>
CString to_string(T value) noexcept;
@@ -304,7 +249,7 @@ public:
pointer c_str() noexcept { return mData; }
private:
value_type mData[N] = {};
value_type mData[N] = {0};
};
} // namespace utils
+16 -25
View File
@@ -20,30 +20,27 @@
#include <utils/ostream.h>
#include <algorithm>
#include <cstdlib>
#include <memory>
namespace utils {
UTILS_NOINLINE
CString::CString(const char* cstr, size_t const length) {
CString::CString(const char* cstr, size_t length) {
if (length && cstr) {
Data* const p = static_cast<Data*>(std::malloc(sizeof(Data) + length + 1));
p->length = size_type(length);
mCStr = reinterpret_cast<value_type*>(p + 1);
Data* p = (Data*)malloc(sizeof(Data) + length + 1);
p->length = (size_type)length;
mCStr = (value_type*)(p + 1);
// we don't use memcpy here to avoid a call to libc, the generated code is pretty good.
std::uninitialized_copy_n(cstr, length, mCStr);
mCStr[length] = '\0';
}
}
CString::CString(size_t const length) {
CString::CString(size_t length) {
if (length) {
Data* const p = static_cast<Data*>(std::malloc(sizeof(Data) + length + 1));
p->length = size_type(length);
mCStr = reinterpret_cast<value_type*>(p + 1);
Data* p = (Data*)malloc(sizeof(Data) + length + 1);
p->length = (size_type)length;
mCStr = (value_type*)(p + 1);
std::fill_n(mCStr, length, 0);
mCStr[length] = '\0';
}
@@ -61,30 +58,24 @@ CString& CString::operator=(const CString& rhs) {
if (this != &rhs) {
auto *const p = mData ? mData - 1 : nullptr;
new(this) CString(rhs);
std::free(p);
free(p);
}
return *this;
}
CString::~CString() noexcept {
if (mData) {
std::free(mData - 1);
}
}
CString& CString::replace(size_type const pos, size_type len, char const* str, size_t const l) & noexcept {
CString& CString::replace(size_type pos, size_type len, const CString& str) noexcept {
assert(pos <= size());
len = std::min(len, size() - pos);
// The new size of the string, after the replacement.
const size_type newSize = size() - len + l;
const size_type newSize = size() - len + str.size();
// Allocate enough memory to hold the new string.
Data* const p = static_cast<Data*>(std::malloc(sizeof(Data) + newSize + 1));
Data* p = (Data*) malloc(sizeof(Data) + newSize + 1);
assert(p);
p->length = newSize;
value_type* newStr = reinterpret_cast<value_type*>(p + 1);
value_type* newStr = (value_type*) (p + 1);
const value_type* beginning = mCStr;
const value_type* replacementStart = mCStr + pos;
@@ -93,7 +84,7 @@ CString& CString::replace(size_type const pos, size_type len, char const* str, s
value_type* ptr = newStr;
ptr = std::uninitialized_copy(beginning, replacementStart, ptr);
ptr = std::uninitialized_copy_n(str, l, ptr);
ptr = std::uninitialized_copy_n(str.c_str_safe(), str.length(), ptr);
ptr = std::uninitialized_copy(replacementEnd, end, ptr);
// null-terminator
@@ -101,14 +92,14 @@ CString& CString::replace(size_type const pos, size_type len, char const* str, s
std::swap(mCStr, newStr);
if (newStr) {
std::free(reinterpret_cast<Data*>(newStr) - 1);
free((Data*) newStr - 1);
}
return *this;
}
#if !defined(NDEBUG)
io::ostream& operator<<(io::ostream& out, const CString& rhs) {
io::ostream& operator<<(io::ostream& out, const utils::CString& rhs) {
return out << rhs.c_str_safe();
}
#endif
+2 -2
View File
@@ -700,8 +700,7 @@ constexpr ToneMapper* createToneMapper(const ColorGradingSettings& settings) noe
}
ColorGrading* createColorGrading(const ColorGradingSettings& settings, Engine* engine) {
ToneMapper* toneMapperRaw = createToneMapper(settings);
std::shared_ptr<ToneMapper> toneMapper(toneMapperRaw);
ToneMapper* toneMapper = createToneMapper(settings);
ColorGrading *colorGrading = ColorGrading::Builder()
.quality(settings.quality)
.exposure(settings.exposure)
@@ -724,6 +723,7 @@ ColorGrading* createColorGrading(const ColorGradingSettings& settings, Engine* e
.gamutMapping(settings.gamutMapping)
.outputColorSpace(settings.colorspace)
.build(*engine);
delete toneMapper;
return colorGrading;
}
-143
View File
@@ -1,143 +0,0 @@
# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import shutil
import re
from utils import execute, ArgParseImpl, mkdir_p
GOLDENS_DIR = 'renderdiff'
ACCESS_TYPE_TOKEN = 'token'
ACCESS_TYPE_SSH = 'ssh'
ACCESS_TYPE_READ_ONLY = 'read-only'
def _read_git_config(curdir):
with open(os.path.join(curdir, './.git/config'), 'r') as f:
return f.read()
def _write_git_config(curdir, config_str):
with open(os.path.join(curdir, './.git/config'), 'w') as f:
return f.write(config_str)
class GoldenManager:
def __init__(self, working_dir, access_type=ACCESS_TYPE_READ_ONLY, access_token=None):
self.working_dir_ = working_dir
self.access_token_ = access_token
self.access_type_ = access_type
assert os.path.isdir(self.working_dir_),\
f"working directory {self.working_dir_} does not exist"
self._prepare()
def _assets_dir(self):
return os.path.join(self.working_dir_, "filament-assets")
# Returns the directory containing the goldens
def directory(self):
return os.path.join(self._assets_dir(), GOLDENS_DIR)
def _get_repo_url(self):
protocol = ''
protocol_separator = ''
if self.access_type_ == ACCESS_TYPE_SSH:
protocol = 'git@'
protocol_separator = ':'
else:
protocol = 'https://' + \
(f'x-access-token:{self.access_token_}@' if self.access_token_ else '')
protocol_separator = '/'
return f'{protocol}github.com{protocol_separator}google/filament-assets.git'
def _prepare(self):
assets_dir = self._assets_dir()
if not os.path.exists(assets_dir):
execute(
f'git clone --depth=1 {self._get_repo_url()}',
cwd=self.working_dir_,
capture_output=False
)
else:
if self.access_type_ == ACCESS_TYPE_SSH:
config = _read_git_config(self._assets_dir())
https_url = r'https://github\.com\/google\/filament\.git'
config = re.sub(https_url, self._get_repo_url(), config)
_write_git_config(self._assets_dir(), config)
self.update()
def update(self):
self._git_exec('fetch')
self._git_exec('checkout main')
self._git_exec('rebase')
def _git_exec(self, cmd):
execute(f'git {cmd}', cwd=self._assets_dir(), capture_output=False)
def merge_to_main(self, branch, push_to_remote=False):
self.update()
assets_dir = self._assets_dir()
self._git_exec(f'checkout main')
self._git_exec(f'merge --no-ff {branch}')
if push_to_remote and \
(self.access_token_ or self.access_type_ == ACCESS_TYPE_SSH):
self._git_exec(f'push origin main')
self.update()
def source_from(self, src_dir, commit_msg, branch,
updates=[], deletes=[], push_to_remote=False):
assets_dir = self._assets_dir()
self._git_exec(f'checkout main')
# Force create the branch (note will overwrite the old branch)
self._git_exec(f'switch -C {branch}')
rdiff_dir = os.path.join(assets_dir, GOLDENS_DIR)
if len(updates) == 0 and len(deletes) == 0:
shutil.rmtree(rdiff_dir, ignore_errors=True)
mkdir_p(rdiff_dir)
shutil.copytree(src_dir, rdiff_dir, dirs_exist_ok=True)
self._git_exec(f'add {GOLDENS_DIR}')
else:
for f in deletes:
self._git_exec(f'remove {os.path.join(GOLDENS_DIR, f)}')
for f in updates:
shutil.copy2(
os.path.join(src_dir, f),
os.path.join(rdiff_dir, f))
self._git_exec(f'add {os.path.join(GOLDENS_DIR, f)}')
TMP_GOLDEN_COMMIT_FILE = '/tmp/golden_commit.txt'
with open(TMP_GOLDEN_COMMIT_FILE, 'w') as f:
f.write(commit_msg)
self._git_exec(f'commit -a -F {TMP_GOLDEN_COMMIT_FILE}')
if push_to_remote and \
(self.access_token_ or self.access_type_ == ACCESS_TYPE_SSH):
self._git_exec(f'push -f origin {branch}')
self.update()
def download_to(self, dest_dir, branch='main'):
self._git_exec(f'checkout {branch}')
assets_dir = self._assets_dir()
mkdir_p(dest_dir)
rdiff_dir = os.path.join(assets_dir, GOLDENS_DIR)
shutil.copytree(rdiff_dir, dest_dir, dirs_exist_ok=True)
# For testing only
if __name__ == "__main__":
golden_manager = GoldenManager(os.getcwd())
# golden_manager.source_from_and_commit(
# os.path.join(os.getcwd(), 'out/renderdiff_tests'),
# 'First commit (local)',
# branch='branch-test')
# golden_manager.merge_to_main('branch-test', push_to_remote=True)
# golden_manager.download_to(os.path.join(os.getcwd(), 'tmp/goldens'))
-43
View File
@@ -1,43 +0,0 @@
# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import tifffile
import numpy
def same_image(tiff_file_a, tiff_file_b):
try:
img1_data = tifffile.imread(tiff_file_a)
img2_data = tifffile.imread(tiff_file_b)
# If the dimensions (height, width, number of channels, number of pages/frames)
# are different, the images are not the same.
if img1_data.shape != img2_data.shape:
print(f"Images have different shapes: {img1_data.shape} vs {img2_data.shape}")
return False
# numpy.array_equal() checks if two arrays have the same shape and elements.
if numpy.array_equal(img1_data, img2_data):
return True
else:
return False
except FileNotFoundError:
print(f"Error: One or both files not found ('{file_path1}', '{file_path2}').")
return False
except tifffile.TiffFileError as e:
print(f"Error: One or both files are not valid TIFF files or could not be read. Details: {e}")
return False
except Exception as e:
print(f"An unexpected error occurred: {e}")
return False
+39 -85
View File
@@ -14,14 +14,9 @@
import sys
import os
import json
import glob
import shutil
from utils import execute, ArgParseImpl, mkdir_p, mv_f
from utils import execute, ArgParseImpl
from parse_test_json import parse_test_config_from_path
from golden_manager import GoldenManager
from image_diff import same_image
def important_print(msg):
lines = msg.split('\n')
@@ -33,21 +28,13 @@ def important_print(msg):
print(information)
print('-' * (max_len + 8))
RESULT_OK = 'ok'
RESULT_FAILED_TO_RENDER = 'failed-to-render'
RESULT_FAILED_IMAGE_DIFF = 'failed-image-diff'
RESULT_FAILED_NO_GOLDEN = 'failed-no-golden'
def run_test(gltf_viewer,
test_config,
output_dir,
opengl_lib=None,
vk_icd=None):
def render_test(gltf_viewer, test_config, output_dir,
opengl_lib=None, vk_icd=None):
assert os.path.isdir(output_dir), f"output directory {output_dir} does not exist"
assert os.access(gltf_viewer, os.X_OK)
named_output_dir = os.path.join(output_dir, test_config.name)
mkdir_p(named_output_dir)
execute(f'mkdir -p {named_output_dir}')
results = []
for test in test_config.tests:
@@ -73,45 +60,43 @@ def run_test(gltf_viewer,
important_print(f'Rendering {test_desc}')
out_code, _ = execute(
f'{gltf_viewer} -a {backend} --batch={test_json_path} -e {model_path} --headless',
env=env, capture_output=False
)
res, _ = execute(f'{gltf_viewer} -a {backend} --batch={test_json_path} -e {model_path} --headless',
env=env, capture_output=False)
result = ''
if out_code == 0:
result = RESULT_OK
out_tif_basename = f'{out_name}.tif'
out_tif_name = f'{named_output_dir}/{out_tif_basename}'
mv_f(f'{test.name}0.tif', out_tif_name)
mv_f(f'{test.name}0.json', f'{named_output_dir}/{test.name}.json')
if res == 0:
execute(f'mv -f {test.name}0.tif {named_output_dir}/{out_name}.tif', capture_output=False)
execute(f'mv -f {test.name}0.json {named_output_dir}/{test.name}.json', capture_output=False)
else:
result = RESULT_FAILED_TO_RENDER
important_print(f'{test_desc} rendering failed with error={out_code}')
important_print(f'{test_desc} failed with error={res}')
print('')
results.append({
'name': out_name,
'result': result,
'result_code': out_code,
})
return named_output_dir, results
results.append((out_name, res))
return results
def compare_goldens(render_results, output_dir, goldens):
for result in render_results:
if result['result'] != RESULT_OK:
continue
GOLDENS_DIR = 'renderdiff_goldens'
out_tif_basename = f"{result['name']}.tif"
out_tif_name = f'{output_dir}/{out_tif_basename}'
golden_path = goldens.get(out_tif_basename)
if not golden_path:
result['result'] = RESULT_FAILED_NO_GOLDEN
result['result_code'] = 1
elif not same_image(golden_path, out_tif_name):
result['result'] = RESULT_FAILED_IMAGE_DIFF
result['result_code'] = 1
# We pull the goldens from the filament-assets repo
def pull_goldens(output_dir):
assert os.path.isdir(output_dir), f"output directory {output_dir} does not exist"
golden_dir = os.path.join(output_dir, "golden")
assets_dir = os.path.join(output_dir, "filament-assets")
return render_results
if not os.path.exists(assets_dir):
execute('git clone --depth 1 git@github.com:google/filament-assets.git', cwd=output_dir)
else:
execute('git fetch', cwd=assets_dir)
execute('git checkout main ', cwd=assets_dir)
execute('git rebase', cwd=assets_dir)
if os.path.exists(golden_dir):
execute('rm -f goldens/*', cwd=output_dir)
execute(f'cp filament-assets/{GOLDENS_DIR}/* goldens', cwd=output_dir)
def push_goldens(output_dir, test_name, filter_func=lambda a:True):
for test in test_config.tests:
for backend in test_config.backends:
for model in test.models:
pass
if __name__ == "__main__":
parser = ArgParseImpl()
@@ -120,43 +105,12 @@ if __name__ == "__main__":
parser.add_argument('--output_dir', help='Output Directory', required=True)
parser.add_argument('--opengl_lib', help='Path to the folder containing OpenGL driver lib (for LD_LIBRARY_PATH)')
parser.add_argument('--vk_icd', help='Path to VK ICD file')
parser.add_argument('--golden_branch', help='Branch of the golden repo to compare against')
args, _ = parser.parse_known_args(sys.argv[1:])
test = parse_test_config_from_path(args.test)
render_result = render_test(args.gltf_viewer, test, args.output_dir, opengl_lib=args.opengl_lib, vk_icd=args.vk_icd)
output_dir, results = \
run_test(args.gltf_viewer,
test,
args.output_dir,
opengl_lib=args.opengl_lib,
vk_icd=args.vk_icd)
do_compare = False
# The presence of this argument indicates comparison against a set of goldens.
if args.golden_branch:
# prepare goldens working directory
tmp_golden_dir = '/tmp/renderdiff-goldens'
mkdir_p(tmp_golden_dir)
# Download the golden repo into the current working directory
golden_manager = GoldenManager(os.getcwd())
golden_manager.download_to(tmp_golden_dir, branch=args.golden_branch)
goldens = {
os.path.basename(fpath) : fpath for fpath in \
glob.glob(f'{os.path.join(tmp_golden_dir, test.name)}/**/*.tif', recursive=True)
}
results = compare_goldens(results, output_dir, goldens)
do_compare = True
with open(f'{output_dir}/results.json', 'w') as f:
f.write(json.dumps(results))
shutil.copy2(args.test, f'{output_dir}/test.json')
failed = [f" {k['name']}" for k in results if k['result'] != RESULT_OK]
success_count = len(results) - len(failed)
op = 'tested' if do_compare else 'rendered'
important_print(f'Successfully {op} {success_count} / {len(results)}' +
failed = [f' {tname}' for tname, res in render_result if res != 0]
success_count = len(render_result) - len(failed )
important_print(f'Successfully rendered {success_count} / {len(render_result)}' +
('\nFailed:\n' + ('\n'.join(failed)) if len(failed) > 0 else ''))
-171
View File
@@ -1,171 +0,0 @@
# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import os
import glob
import time
from golden_manager import GoldenManager, ACCESS_TYPE_SSH, ACCESS_TYPE_TOKEN
from image_diff import same_image
from utils import execute, ArgParseImpl
from utils import prompt_helper, PROMPT_YES, PROMPT_NO
def line_prompt(prompt, validator=lambda a:True):
while True:
res = input(f'{prompt} => ').strip()
if validator(res):
return res
return None
CONFIG_NEW_SRC_DIR = 'goldens_dir'
CONFIG_GOLDENS_BRANCH = 'goldens_branch'
CONFIG_GOLDENS_UPDATES = 'goldens_updates'
CONFIG_GOLDENS_DELETES = 'goldens_deletes'
CONFIG_AUTO_COMMIT = 'auto-commit'
CONFIG_COMMIT_MSG = 'commit_msg'
def _get_current_branch():
code, res = execute('git branch --show-current')
return res.strip()
def _file_as_str(fpath):
with open(fpath, 'r') as f:
return f.read()
def _do_update(golden_manager, config):
deletes = config[CONFIG_GOLDENS_DELETES]
updates = config[CONFIG_GOLDENS_UPDATES]
if len(deletes) == 0 and len(updates) == 0:
print('Nothing to update. Exiting...')
exit(0)
branch = config[CONFIG_GOLDENS_BRANCH]
src_dir = config[CONFIG_NEW_SRC_DIR]
auto_commit = config[CONFIG_AUTO_COMMIT]
commit_msg = config[CONFIG_COMMIT_MSG]
golden_manager.source_from(src_dir, commit_msg, branch,
updates=updates,
deletes=deletes,
push_to_remote=auto_commit)
def _get_deletes_updates(update_dir, golden_dir):
ret_delete = []
ret_update = []
for ext in ['tif', 'json']:
base = set(glob.glob(f'./**/*.{ext}', root_dir=golden_dir, recursive=True))
new = set(glob.glob(f'./**/*.{ext}', root_dir=update_dir, recursive=True))
delete = list(base - new)
update = list(new - base)
for fpath in base.intersection(new):
base_fpath = os.path.join(golden_dir, fpath)
new_fpath = os.path.join(update_dir, fpath)
if (ext == 'tif' and not same_image(new_fpath, base_fpath)) or \
(ext == 'json' and _file_as_str(new_fpath) != _file_as_str(base_fpath)):
update.append(fpath)
ret_update += update
ret_delete += delete
return ret_delete, ret_update
# Ask a bunch of questions to gather the configuration for the update
def _interactive_mode(base_golden_dir):
config = {}
cur_branch = _get_current_branch()
if prompt_helper(
f'Generate the new goldens from your local ' \
f'Filament branch? (branch={cur_branch})') == PROMPT_YES:
code, res = execute('bash ./test/renderdiff/test.sh generate',
capture_output=False)
if code != 0:
print('Failed to generate new goldens')
exit(1)
config[CONFIG_NEW_SRC_DIR] = os.path.join(os.getcwd(), './out/renderdiff_tests/')
else:
def validator(src_dir):
if not os.path.exists(src_dir):
print(f'Cannot find directory {src_dir}. Please try again.')
return False
return True
config[CONFIG_NEW_SRC_DIR] = line_prompt(
'Please provide path of directory containing new goldens',
validator)
if prompt_helper(f'Update new goldens to branch={cur_branch}? '
'(Note that this refers to a branch in the goldens repo, not the Filament repo.)'
) == PROMPT_YES:
config[CONFIG_GOLDENS_BRANCH] = cur_branch
else:
config[CONFIG_GOLDENS_BRANCH] = line_prompt('Please provide new branch name for update')
if prompt_helper(f'Provide a commit message?') == PROMPT_YES:
config[CONFIG_COMMIT_MSG] = line_prompt('Message:')
else:
config[CONFIG_COMMIT_MSG] = f'Update {time.time()} from filament ({cur_branch})'
new_golden_dir = config[CONFIG_NEW_SRC_DIR]
deletes, updates = _get_deletes_updates(new_golden_dir, base_golden_dir)
if len(deletes) + len(updates) != 0:
prompt = 'The following files will be changed:\n' + \
'\n'.join([f' {fname} [delete]' for fname in deletes]) + \
'\n'.join([f' {fname} [update]' for fname in updates]) + \
'\nIs that ok?'
if prompt_helper(prompt) == PROMPT_YES:
config[CONFIG_GOLDENS_DELETES] = deletes
config[CONFIG_GOLDENS_UPDATES] = updates
else:
# We cannot proceed if user answered no.
exit(1)
else:
config[CONFIG_GOLDENS_DELETES] = []
config[CONFIG_GOLDENS_UPDATES] = []
config[CONFIG_AUTO_COMMIT] = \
prompt_helper(f'Commit golden repo changes to remote?') == PROMPT_YES
return config
if __name__ == "__main__":
parser = ArgParseImpl()
parser.add_argument('--branch', help='Branch of the golden repo to write to')
parser.add_argument('--source', help='Directory containing the new goldens')
parser.add_argument('--commit-msg', help='Message for the commit to the golden repo')
parser.add_argument('--golden-repo-token', help='Access token for the golden repo')
args, _ = parser.parse_known_args(sys.argv[1:])
config = {}
golden_manager = GoldenManager(
os.getcwd(),
access_type=ACCESS_TYPE_SSH if not args.golden_repo_token else ACCESS_TYPE_TOKEN,
access_token=args.golden_repo_token
)
base_golden_dir = golden_manager.directory()
if args.branch and args.source and args.commit_msg:
assert os.path.exists(args.source), f'{args.source} (--source) directory not found'
deletes, updates = _get_deletes_updates(args.source, base_golden_dir)
config = {
CONFIG_AUTO_COMMIT: True,
CONFIG_GOLDENS_BRANCH: args.branch,
CONFIG_NEW_SRC_DIR: args.source,
CONFIG_GOLDENS_UPDATES: updates,
CONFIG_GOLDENS_DELETES: deletes,
CONFIG_COMMIT_MSG: args.commit_msg,
}
else:
config = _interactive_mode(base_golden_dir)
_do_update(golden_manager, config)
-40
View File
@@ -16,7 +16,6 @@ import subprocess
import os
import argparse
import sys
import pathlib
def execute(cmd,
cwd=None,
@@ -67,42 +66,3 @@ class ArgParseImpl(argparse.ArgumentParser):
sys.stderr.write('error: %s\n' % message)
self.print_help()
sys.exit(1)
PROMPT_YES = 'y'
PROMPT_NO = 'n'
PROMPT_YES_NO = f'{PROMPT_YES}{PROMPT_NO}'
class GetCh:
def __init__(self):
pass
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
getch = GetCh()
def prompt_helper(prompt_str, keys=PROMPT_YES_NO):
while True:
print(f'{prompt_str}: [' + ', '.join(keys) + '] => ', end='', flush=True)
val = getch()
print(val)
if val in keys or ord(val) == 3: # If user pressed Ctrl+c
if ord(val) == 3:
exit(1)
return val
def mkdir_p(path_str):
pathlib.Path(path_str).mkdir(parents=True, exist_ok=True)
def mv_f(src_str, dst_str):
src = pathlib.Path(src_str)
src.replace(dst_str)
+5 -16
View File
@@ -17,29 +17,18 @@ from utils import execute
def get_last_commit():
res, o = execute('git log -1')
commit, author, date, _, title, *desc = o.split('\n')
commit = commit.split(' ')[1]
title = title.strip()
desc = [l.strip() for l in desc[1:]]
while len(desc) > 0 and len(desc[0]) == 0:
if len(desc) > 0 and len(desc[0]) == 0:
desc = desc[1:]
return (
commit,
title,
desc
)
commit.split(' ')[1],
title.strip(),
desc)
def sanitized_split(line, split_atom='\n'):
return list(
filter(
lambda x: len(x) > 0,
map(
lambda x: x.strip(),
line.split(split_atom)
)
)
)
return list(filter(lambda x: len(x) > 0, map(lambda x: x.strip(), line.split(split_atom))))
RDIFF_UPDATE_GOLDEN_STR = 'RDIFF_UPDATE_GOLDEN'
+8 -41
View File
@@ -16,9 +16,8 @@
OUTPUT_DIR="$(pwd)/out/renderdiff_tests"
RENDERDIFF_TEST_DIR="$(pwd)/test/renderdiff"
BUILD_COMMON_DIR="$(pwd)/build/common"
TEST_UTILS_DIR="$(pwd)/test/utils"
MESA_DIR="$(pwd)/mesa/out/"
VENV_DIR="$(pwd)/venv"
os_name=$(uname -s)
if [[ "$os_name" == "Linux" ]]; then
@@ -30,33 +29,9 @@ else
exit 1
fi
function start_() {
if [[ "$GITHUB_WORKFLOW" ]]; then
set -ex
else
if [ ! -d ${MESA_LIB_DIR} ]; then
bash ${BUILD_COMMON_DIR}/get-mesa.sh
fi
# Install python deps
python3 -m venv ${VENV_DIR}
source ${VENV_DIR}/bin/activate
NEEDED_PYTHON_DEPS=("numpy" "tifffile")
for cmd in "${NEEDED_PYTHON_DEPS[@]}"; do
if ! python3 -m pip show -q "${cmd}"; then
python3 -m pip install ${cmd}
fi
done
fi
}
function end_() {
if [[ "$GITHUB_WORKFLOW" ]]; then
set +ex
else
deactivate # End python virtual env
function prepare_mesa() {
if [ ! -d ${MESA_LIB_DIR} ]; then
bash ${TEST_UTILS_DIR}/get_mesa.sh
fi
}
@@ -66,19 +41,11 @@ function end_() {
# - Run the python script that runs the test
# - Zip up the result
GOLDEN_BRANCH_PARAM='--golden_branch=main'
if [ "$1" == "generate" ]; then
GOLDEN_BRANCH_PARAM=''
fi
start_ && \
set -ex && prepare_mesa && \
mkdir -p ${OUTPUT_DIR} && \
CXX=`which clang++` CC=`which clang` ./build.sh -f -X ${MESA_DIR} -p desktop debug gltf_viewer && \
python3 ${RENDERDIFF_TEST_DIR}/src/run.py \
CXX=`which clang++` CC=`which clang` ./build.sh -X ${MESA_DIR} -p desktop debug gltf_viewer && \
python3 ${RENDERDIFF_TEST_DIR}/src/run.py \
--gltf_viewer="$(pwd)/out/cmake-debug/samples/gltf_viewer" \
--test=${RENDERDIFF_TEST_DIR}/tests/presubmit.json \
--output_dir=${OUTPUT_DIR} \
--opengl_lib=${MESA_LIB_DIR} \
${GOLDEN_BRANCH_PARAM} && \
end_
--opengl_lib=${MESA_LIB_DIR}
@@ -14,9 +14,9 @@
#!/usr/bin/bash
set -e
set -x
if [[ "$GITHUB_WORKFLOW" ]]; then
set -x
set -e
fi
OS_NAME=$(uname -s)
@@ -35,7 +35,7 @@ source ${ORIG_DIR}/venv/bin/activate
NEEDED_PYTHON_DEPS=("mako" "setuptools" "pyyaml")
for cmd in "${NEEDED_PYTHON_DEPS[@]}"; do
if ! python3 -m pip show -q "${cmd}" >/dev/null 2>&1; then
if ! python3 -m pip show "${cmd}" >/dev/null 2>&1; then
python3 -m pip install ${cmd}
fi
done
@@ -145,6 +145,6 @@ deactivate
popd
if [[ "$GITHUB_WORKFLOW" ]]; then
set +x
set +e
fi
set +e
set +x

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