Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7da1c0ad5 | ||
|
|
04ff88fab2 |
@@ -138,7 +138,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: presubmit-renderdiff-result
|
||||
path: ./out/renderdiff
|
||||
path: ./out/renderdiff_tests
|
||||
|
||||
validate-wgsl-webgpu:
|
||||
name: validate-wgsl-webgpu
|
||||
|
||||
@@ -6,4 +6,4 @@ We are chaning the way Vulkan buffers are handled. We need to switch over to a m
|
||||
**If you are cherry-picking a commit into an rc/ branch**: add the release note under the
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
## Release notes for next branch cut
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.62.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.61.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.62.0'
|
||||
pod 'Filament', '~> 1.61.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,10 +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.62.0
|
||||
|
||||
- Add new `unfilterable` field to Filament Material's `sampler` [⚠️ **New Material Version**]
|
||||
|
||||
## v1.61.2
|
||||
|
||||
- samples: samples now have a CLI to select backend api
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.62.0
|
||||
VERSION_NAME=1.61.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
BIN
Binary file not shown.
+1
-2
@@ -1,7 +1,6 @@
|
||||
#Wed Nov 17 10:40:18 PST 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
Vendored
+109
-173
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -17,99 +17,67 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
@@ -119,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@@ -130,120 +98,88 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
Vendored
+16
-19
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,8 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -41,13 +40,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +56,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -76,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
@@ -1027,11 +1027,8 @@ samplerCubemap | Cubemap texture
|
||||
[Table [materialParamsTypes]: Material parameter types]
|
||||
|
||||
Samplers
|
||||
: Sampler types can have the following fields:
|
||||
- `format` : which can be either `int` or `float` (defaults to `float`).
|
||||
- `multisample` : a boolean to indicate whether the sampler is meant for multisampling (defaults to `false`)
|
||||
- `unfilterable` : a boolean to indicate whether the sampling is not filtered (defaults to `false`)
|
||||
|
||||
: Sampler types can also specify a `format` which can be either `int` or `float` (defaults to
|
||||
`float`).
|
||||
|
||||
Arrays
|
||||
: A parameter can define an array of values by appending `[size]` after the type name, where
|
||||
|
||||
@@ -269,8 +269,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
src/webgpu/WebGPUDescriptorSetLayout.h
|
||||
src/webgpu/WebGPUDriver.cpp
|
||||
src/webgpu/WebGPUDriver.h
|
||||
src/webgpu/WebGPUFence.cpp
|
||||
src/webgpu/WebGPUFence.h
|
||||
src/webgpu/WebGPUIndexBuffer.cpp
|
||||
src/webgpu/WebGPUIndexBuffer.h
|
||||
src/webgpu/WebGPUPipelineCreation.cpp
|
||||
@@ -285,6 +283,8 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
src/webgpu/WebGPUSwapChain.h
|
||||
src/webgpu/WebGPUTexture.cpp
|
||||
src/webgpu/WebGPUTexture.h
|
||||
src/webgpu/WebGPUTimerQuery.cpp
|
||||
src/webgpu/WebGPUTimerQuery.h
|
||||
src/webgpu/WebGPUVertexBuffer.cpp
|
||||
src/webgpu/WebGPUVertexBuffer.h
|
||||
src/webgpu/WebGPUVertexBufferInfo.cpp
|
||||
@@ -505,20 +505,11 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
target_compile_definitions(${TARGET} PRIVATE $<$<BOOL:${FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING}>:FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING>)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Linker flags
|
||||
# ==================================================================================================
|
||||
|
||||
target_link_libraries(${TARGET} PRIVATE
|
||||
${OSMESA_LINKER_FLAGS}
|
||||
$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>:${LINUX_LINKER_OPTIMIZATION_FLAGS}>
|
||||
)
|
||||
|
||||
if (LINUX AND FILAMENT_SUPPORTS_WEBGPU)
|
||||
# Unclear why this needs to be explicit while other linux libs do not, but it is necessary for
|
||||
# WebGPU to build on linux.
|
||||
target_link_libraries(${TARGET} PRIVATE -lxcb)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Installation
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -474,12 +474,7 @@ constexpr std::string_view to_string(DescriptorType type) noexcept {
|
||||
|
||||
enum class DescriptorFlags : uint8_t {
|
||||
NONE = 0x00,
|
||||
|
||||
// Indicate a UNIFORM_BUFFER will have dynamic offsets.
|
||||
DYNAMIC_OFFSET = 0x01,
|
||||
|
||||
// To indicate a texture/sampler type should be unfiltered.
|
||||
UNFILTERABLE = 0x02,
|
||||
DYNAMIC_OFFSET = 0x01
|
||||
};
|
||||
|
||||
using descriptor_set_t = uint8_t;
|
||||
|
||||
@@ -107,36 +107,6 @@ public:
|
||||
MULTIVIEW,
|
||||
};
|
||||
|
||||
/**
|
||||
* This controls the priority level for GPU work scheduling, which helps prioritize the
|
||||
* submitted GPU work and enables preemption.
|
||||
*/
|
||||
enum class GpuContextPriority : uint8_t {
|
||||
/**
|
||||
* Backend default GPU context priority (typically MEDIUM)
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* For non-interactive, deferrable workloads. This should not interfere with standard
|
||||
* applications.
|
||||
*/
|
||||
LOW,
|
||||
/**
|
||||
* The default priority level for standard applications.
|
||||
*/
|
||||
MEDIUM,
|
||||
/**
|
||||
* For high-priority, latency-sensitive workloads that are more important than standard
|
||||
* applications.
|
||||
*/
|
||||
HIGH,
|
||||
/**
|
||||
* The highest priority, intended for system-critical, real-time applications where missing
|
||||
* deadlines is unacceptable (e.g., VR/AR compositors or other system-critical tasks).
|
||||
*/
|
||||
REALTIME,
|
||||
};
|
||||
|
||||
struct DriverConfig {
|
||||
/**
|
||||
* Size of handle arena in bytes. Setting to 0 indicates default value is to be used.
|
||||
@@ -186,13 +156,6 @@ public:
|
||||
* - PlatformMetal
|
||||
*/
|
||||
bool metalDisablePanicOnDrawableFailure = false;
|
||||
|
||||
/**
|
||||
* GPU context priority level. Controls GPU work scheduling and preemption.
|
||||
* This is only supported for:
|
||||
* - PlatformEGL
|
||||
*/
|
||||
GpuContextPriority gpuContextPriority = GpuContextPriority::DEFAULT;
|
||||
};
|
||||
|
||||
Platform() noexcept;
|
||||
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
* Destroys the object D at Handle<B> and construct a new D in its place
|
||||
* e.g.:
|
||||
* Handle<ConcreteTexture> h = allocateAndConstruct(w, h);
|
||||
* ConcreteTexture* p = destroyAndConstruct(h, w, h);
|
||||
* ConcreteTexture* p = reconstruct(h, w, h);
|
||||
*/
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
|
||||
@@ -209,42 +209,10 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& drive
|
||||
}
|
||||
#endif
|
||||
|
||||
// Configure GPU context priority level for scheduling and preemption
|
||||
if (driverConfig.gpuContextPriority != Platform::GpuContextPriority::DEFAULT) {
|
||||
if (extensions.has("EGL_IMG_context_priority")) {
|
||||
EGLint priorityLevel = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
|
||||
const char* priorityName;
|
||||
switch (driverConfig.gpuContextPriority) {
|
||||
case Platform::GpuContextPriority::DEFAULT:
|
||||
assert_invariant(false);
|
||||
break;
|
||||
case Platform::GpuContextPriority::LOW:
|
||||
priorityLevel = EGL_CONTEXT_PRIORITY_LOW_IMG;
|
||||
priorityName = "LOW";
|
||||
break;
|
||||
case Platform::GpuContextPriority::MEDIUM:
|
||||
priorityLevel = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
|
||||
priorityName = "MEDIUM";
|
||||
break;
|
||||
case Platform::GpuContextPriority::HIGH:
|
||||
priorityLevel = EGL_CONTEXT_PRIORITY_HIGH_IMG;
|
||||
priorityName = "HIGH";
|
||||
break;
|
||||
case Platform::GpuContextPriority::REALTIME:
|
||||
priorityLevel = EGL_CONTEXT_PRIORITY_HIGH_IMG;
|
||||
priorityName = "REALTIME(=HIGH)";
|
||||
break;
|
||||
}
|
||||
contextAttribs[EGL_CONTEXT_PRIORITY_LEVEL_IMG] = priorityLevel;
|
||||
LOG(INFO) << "EGL: Enabling GPU context priority: " << priorityName;
|
||||
} else {
|
||||
LOG(WARNING) << "EGL: GPU context priority requested but not supported";
|
||||
}
|
||||
}
|
||||
|
||||
// config use for creating the context
|
||||
EGLConfig eglConfig = EGL_NO_CONFIG_KHR;
|
||||
|
||||
|
||||
if (UTILS_UNLIKELY(!ext.egl.KHR_no_config_context)) {
|
||||
// find a config we can use if we don't have "EGL_KHR_no_config_context" and that we can use
|
||||
// for the dummy pbuffer surface.
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
#include "VulkanBufferProxy.h"
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanMemory.h"
|
||||
|
||||
#include "VulkanBufferCache.h"
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanContext.h"
|
||||
#include "VulkanMemory.h"
|
||||
|
||||
using namespace bluevk;
|
||||
@@ -36,38 +36,6 @@ VulkanBufferProxy::VulkanBufferProxy(VmaAllocator allocator, VulkanStagePool& st
|
||||
|
||||
void VulkanBufferProxy::loadFromCpu(VulkanCommandBuffer& commands, const void* cpuData,
|
||||
uint32_t byteOffset, uint32_t numBytes) {
|
||||
// The VulkanBuffer is available if the only object reference is hold by the
|
||||
// `VulkanBufferProxy`. This means that the buffer is not currently referenced by a
|
||||
// `VulkanCommandBuffer`.
|
||||
bool const isAvailable = mBuffer->getCount() == 1;
|
||||
|
||||
if (isAvailable) {
|
||||
// We are up to date with all the update operations, so no need to synchronize with previous
|
||||
// updates.
|
||||
mUpdatedBytes = 0;
|
||||
mUpdatedOffset = 0;
|
||||
}
|
||||
|
||||
// Keep track of the VulkanBuffer usage
|
||||
commands.acquire(mBuffer);
|
||||
|
||||
// Check if we can just memcpy directly to the GPU memory.
|
||||
// This is only allowed for UNIFORMS that are AVAILABLE and the memory is HOST_VISIBLE
|
||||
// (supports memcpy from host). This works regardless if it's a full or partial update of the
|
||||
// buffer.
|
||||
bool const isMemcopyable = mBuffer->getGpuBuffer()->allocationInfo.pMappedData != nullptr;
|
||||
bool const isUniform = getUsage() == VulkanBufferUsage::UNIFORM;
|
||||
bool const useMemcpy =
|
||||
isUniform && isMemcopyable && isAvailable && !FVK_FORCE_STAGING_FOR_BUFFER_UPDATES;
|
||||
if (useMemcpy) {
|
||||
char* dest = static_cast<char*>(mBuffer->getGpuBuffer()->allocationInfo.pMappedData) +
|
||||
byteOffset;
|
||||
memcpy(dest, cpuData, numBytes);
|
||||
vmaFlushAllocation(mAllocator, mBuffer->getGpuBuffer()->vmaAllocation, byteOffset,
|
||||
numBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: this should be stored within the command buffer before going out of
|
||||
// scope, so that the command buffer can manage its lifecycle.
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> stage = mStagePool.acquireStage(numBytes);
|
||||
@@ -160,4 +128,4 @@ VulkanBufferUsage VulkanBufferProxy::getUsage() const noexcept {
|
||||
return mBuffer->getGpuBuffer()->usage;
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -49,6 +49,6 @@ private:
|
||||
uint32_t mUpdatedBytes = 0;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
}// namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKANBUFFERPROXY_H
|
||||
#endif// TNT_FILAMENT_BACKEND_VULKANBUFFERPROXY_H
|
||||
|
||||
@@ -214,8 +214,4 @@ constexpr static const int FVK_MAX_PIPELINE_AGE = FVK_MAX_COMMAND_BUFFERS;
|
||||
// destroying any unused pipeline object.
|
||||
static_assert(FVK_MAX_PIPELINE_AGE >= FVK_MAX_COMMAND_BUFFERS);
|
||||
|
||||
// Whether the buffer updates always use staging or not. Otherwise its allowed to also use memcpy
|
||||
// for buffer updates. Default is false
|
||||
constexpr static const bool FVK_FORCE_STAGING_FOR_BUFFER_UPDATES = false;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -394,13 +394,7 @@ void VulkanDriver::collectGarbage() {
|
||||
void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||
int64_t refreshIntervalNs, uint32_t frameId) {
|
||||
FVK_PROFILE_MARKER(PROFILE_NAME_BEGINFRAME);
|
||||
|
||||
// Check if any command have finished and reset all its used resources. The resources
|
||||
// wont be destroyed but their reference count will decreased if the command is already
|
||||
// completed.
|
||||
//
|
||||
// This will let us check if any VulkanBuffer is currently in flight or not.
|
||||
mCommands.gc();
|
||||
// Do nothing.
|
||||
|
||||
if (mAppState.hasExternalSamplers()) {
|
||||
mExternalImageManager.onBeginFrame();
|
||||
@@ -1242,8 +1236,7 @@ void VulkanDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
|
||||
void VulkanDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh,
|
||||
BufferObjectStreamDescriptor&& streams) {
|
||||
void VulkanDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh, BufferObjectStreamDescriptor&& streams) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
|
||||
@@ -34,23 +34,16 @@ namespace {
|
||||
static constexpr uint32_t MAX_EMPTY_STAGES_TO_RETAIN = 1;
|
||||
constexpr uint32_t STAGE_SIZE = 1048576;
|
||||
|
||||
uint32_t alignValue(uint32_t valueToAlign, uint32_t alignment) {
|
||||
if (alignment == 0) {
|
||||
return valueToAlign;
|
||||
}
|
||||
|
||||
uint32_t remainder = valueToAlign % alignment;
|
||||
return remainder == 0 ? valueToAlign : valueToAlign + (alignment - remainder);
|
||||
}
|
||||
|
||||
}// namespace
|
||||
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStage::acquireSegment(
|
||||
fvkmemory::ResourceManager* resManager, uint32_t segmentOffset, uint32_t numBytes) {
|
||||
auto segment = fvkmemory::resource_ptr<Segment>::construct(resManager, this, numBytes,
|
||||
segmentOffset, [this](uint32_t offset) { mSegments.erase(offset); });
|
||||
mSegments.insert({ segmentOffset, segment.get() });
|
||||
mCurrentOffset = segmentOffset + numBytes;
|
||||
fvkmemory::ResourceManager* resManager, uint32_t numBytes) {
|
||||
auto segment = fvkmemory::resource_ptr<Segment>::construct(
|
||||
resManager, this, numBytes, mCurrentOffset, [this](uint32_t offset) {
|
||||
mSegments.erase(offset);
|
||||
});
|
||||
mSegments.insert({mCurrentOffset, segment.get()});
|
||||
mCurrentOffset += numBytes;
|
||||
return segment;
|
||||
}
|
||||
|
||||
@@ -61,8 +54,7 @@ VulkanStagePool::VulkanStagePool(VmaAllocator allocator, fvkmemory::ResourceMana
|
||||
mCommands(commands),
|
||||
mDeviceLimits(deviceLimits) {}
|
||||
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStagePool::acquireStage(uint32_t numBytes,
|
||||
uint32_t alignment) {
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStagePool::acquireStage(uint32_t numBytes) {
|
||||
// Apply alignment to the byte count to ensure that, when we later flush
|
||||
// data written by the host, we only flush the atoms that we modified, and
|
||||
// no adjacent atoms.
|
||||
@@ -72,35 +64,17 @@ fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStagePool::acquireStage(uint
|
||||
// equal to the requested size.
|
||||
auto iter = mStages.lower_bound(numBytes);
|
||||
|
||||
// If we have potential buffer candidates, loop through and try to find one
|
||||
// that works with our alignment. Also, set the offset for the buffer.
|
||||
// If we have no buffer, create a new one.
|
||||
VulkanStage* pStage = nullptr;
|
||||
uint32_t segmentOffset = 0;
|
||||
while (iter != mStages.end()) {
|
||||
segmentOffset = alignValue(iter->second->currentOffset(), alignment);
|
||||
|
||||
// Check for overflow + if there's space.
|
||||
if (segmentOffset >= iter->second->currentOffset() &&
|
||||
iter->second->capacity() - numBytes >= segmentOffset) {
|
||||
// This buffer has enough space.
|
||||
pStage = iter->second;
|
||||
mStages.erase(iter);
|
||||
break;
|
||||
}
|
||||
|
||||
// This buffer wasn't suitable. Check the next larger one.
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (!pStage) {
|
||||
VulkanStage* pStage;
|
||||
if (iter != mStages.end()) {
|
||||
pStage = iter->second;
|
||||
mStages.erase(iter);
|
||||
} else {
|
||||
pStage = allocateNewStage(std::max(numBytes, STAGE_SIZE));
|
||||
}
|
||||
|
||||
// Note: this allocation updates `currentOffset` and `segments` within
|
||||
// the parent stage. When destroyed, it will update `segments`.
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> pSegment =
|
||||
pStage->acquireSegment(mResManager, segmentOffset, numBytes);
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> pSegment = pStage->acquireSegment(mResManager, numBytes);
|
||||
|
||||
// Update the stage's metadata, and reinsert it with the remaining segment
|
||||
// capacity.
|
||||
@@ -112,7 +86,12 @@ fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStagePool::acquireStage(uint
|
||||
|
||||
uint32_t VulkanStagePool::alignToNonCoherentAtomSize(uint32_t bytes) {
|
||||
VkDeviceSize alignment = mDeviceLimits->nonCoherentAtomSize;
|
||||
return alignValue(bytes, alignment);
|
||||
if (alignment == 0) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
uint32_t remainder = bytes % alignment;
|
||||
return remainder == 0 ? bytes : bytes + (alignment - remainder);
|
||||
}
|
||||
|
||||
VulkanStage* VulkanStagePool::allocateNewStage(uint32_t capacity) {
|
||||
|
||||
@@ -105,11 +105,8 @@ public:
|
||||
// Marks a region of the block as "in-use", and provides information about
|
||||
// the allocated region to the caller. Note: this assumes that numBytes
|
||||
// is aligned to the physical device's nonCoherentAtomSize.
|
||||
// Takes the offset to use as the segment's start offset. It is assumed
|
||||
// that this is greater than the segment's current offset, and it is
|
||||
// undefined behavior if not.
|
||||
fvkmemory::resource_ptr<Segment> acquireSegment(fvkmemory::ResourceManager* resManager,
|
||||
uint32_t segmentOffset, uint32_t numBytes);
|
||||
uint32_t numBytes);
|
||||
|
||||
private:
|
||||
const VmaAllocation mMemory;
|
||||
@@ -147,10 +144,7 @@ public:
|
||||
// buffers so that we have less objects around that we have to keep track
|
||||
// of.
|
||||
// This function is NOT thread-safe.
|
||||
// numBytes - the number of bytes required by this segment.
|
||||
// alignment - the multiple to align the buffer offset to
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> acquireStage(uint32_t numBytes,
|
||||
uint32_t alignment = 0);
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> acquireStage(uint32_t numBytes);
|
||||
|
||||
// Images have VK_IMAGE_LAYOUT_GENERAL and must not be transitioned to any other layout
|
||||
VulkanStageImage const* acquireImage(PixelDataFormat format, PixelDataType type,
|
||||
|
||||
@@ -522,10 +522,8 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
||||
// Note: the following stageSegment must be stored within the command buffer
|
||||
// before going out of scope, to ensure proper bookkeeping within the
|
||||
// staging buffer pool.
|
||||
uint8_t alignment =
|
||||
fvkutils::getTexelBlockSize(fvkutils::getVkFormat(hostData->format, hostData->type));
|
||||
fvkmemory::resource_ptr<VulkanStage::Segment> stageSegment =
|
||||
mState->mStagePool.acquireStage(writeSize, alignment);
|
||||
mState->mStagePool.acquireStage(writeSize);
|
||||
assert_invariant(stageSegment->memory());
|
||||
adjustedMemcpy(stageSegment->mapping(), *hostData, width, height, depth);
|
||||
vmaFlushAllocation(mState->mAllocator, stageSegment->memory(), stageSegment->offset(),
|
||||
|
||||
@@ -71,8 +71,6 @@ struct Resource {
|
||||
restype(ResourceType::UNDEFINED_TYPE),
|
||||
mHandleConsideredDestroyed(false) {}
|
||||
|
||||
uint32_t getCount() const { return mCount; }
|
||||
|
||||
private:
|
||||
inline void inc() noexcept {
|
||||
mCount++;
|
||||
|
||||
@@ -832,9 +832,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
context.mPhysicalDeviceFeatures.features.shaderClipDistance = VK_FALSE;
|
||||
}
|
||||
|
||||
// TODO: Add support of VK_KHR_global_priority with `driverConfig.gpuContextPriority`
|
||||
// in VulkanPlatform::createDriver.
|
||||
|
||||
ExtensionSet deviceExts;
|
||||
// If using a shared context, we do not assume any extensions.
|
||||
if (!mImpl->mSharedContext) {
|
||||
@@ -926,7 +923,7 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
// Keep a copy of context for swapchains.
|
||||
mImpl->mContext = context;
|
||||
|
||||
return VulkanDriver::create(this, mImpl->mContext, driverConfig);
|
||||
return VulkanDriver::create(this, context, driverConfig);
|
||||
}
|
||||
|
||||
// This needs to be explictly written for
|
||||
|
||||
@@ -233,212 +233,6 @@ VkFormat getVkFormat(TextureFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
// As per VUID-vkCmdCopyBufferToImage-dstImage-07975 and
|
||||
// VUID-vkCmdCopyBufferToImage-dstImage-07978, these provide the texel block
|
||||
// sizes for each format (as confirmed using the table at
|
||||
// https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#formats-compatibility-classes).
|
||||
// We have not listed values for multi-plane formats, as we do not support them
|
||||
// unless they're externally provided.
|
||||
uint8_t getTexelBlockSize(VkFormat format) {
|
||||
switch (format) {
|
||||
// 8-bit formats.
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
case VK_FORMAT_R8_SNORM:
|
||||
case VK_FORMAT_R8_USCALED:
|
||||
case VK_FORMAT_R8_SSCALED:
|
||||
case VK_FORMAT_R8_UINT:
|
||||
case VK_FORMAT_R8_SINT:
|
||||
case VK_FORMAT_R8_SRGB:
|
||||
return 1;
|
||||
|
||||
// 16-bit formats.
|
||||
case VK_FORMAT_R16_UNORM:
|
||||
case VK_FORMAT_R16_SNORM:
|
||||
case VK_FORMAT_R16_USCALED:
|
||||
case VK_FORMAT_R16_SSCALED:
|
||||
case VK_FORMAT_R16_UINT:
|
||||
case VK_FORMAT_R16_SINT:
|
||||
case VK_FORMAT_R16_SFLOAT:
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
case VK_FORMAT_R8G8_SNORM:
|
||||
case VK_FORMAT_R8G8_USCALED:
|
||||
case VK_FORMAT_R8G8_SSCALED:
|
||||
case VK_FORMAT_R8G8_UINT:
|
||||
case VK_FORMAT_R8G8_SINT:
|
||||
case VK_FORMAT_R8G8_SRGB:
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
||||
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
|
||||
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
|
||||
return 2;
|
||||
|
||||
// 24-bit formats.
|
||||
case VK_FORMAT_R8G8B8_UNORM:
|
||||
case VK_FORMAT_R8G8B8_SNORM:
|
||||
case VK_FORMAT_R8G8B8_USCALED:
|
||||
case VK_FORMAT_R8G8B8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8_UINT:
|
||||
case VK_FORMAT_R8G8B8_SINT:
|
||||
case VK_FORMAT_R8G8B8_SRGB:
|
||||
case VK_FORMAT_B8G8R8_UNORM:
|
||||
case VK_FORMAT_B8G8R8_SNORM:
|
||||
case VK_FORMAT_B8G8R8_USCALED:
|
||||
case VK_FORMAT_B8G8R8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8_UINT:
|
||||
case VK_FORMAT_B8G8R8_SINT:
|
||||
case VK_FORMAT_B8G8R8_SRGB:
|
||||
return 3;
|
||||
|
||||
// 32-bit formats.
|
||||
case VK_FORMAT_R32_UINT:
|
||||
case VK_FORMAT_R32_SINT:
|
||||
case VK_FORMAT_R32_SFLOAT:
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
case VK_FORMAT_R16G16_SNORM:
|
||||
case VK_FORMAT_R16G16_USCALED:
|
||||
case VK_FORMAT_R16G16_SSCALED:
|
||||
case VK_FORMAT_R16G16_UINT:
|
||||
case VK_FORMAT_R16G16_SINT:
|
||||
case VK_FORMAT_R16G16_SFLOAT:
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_R8G8B8A8_SNORM:
|
||||
case VK_FORMAT_R8G8B8A8_USCALED:
|
||||
case VK_FORMAT_R8G8B8A8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8A8_UINT:
|
||||
case VK_FORMAT_R8G8B8A8_SINT:
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SNORM:
|
||||
case VK_FORMAT_B8G8R8A8_USCALED:
|
||||
case VK_FORMAT_B8G8R8A8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8A8_UINT:
|
||||
case VK_FORMAT_B8G8R8A8_SINT:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_UINT_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
// Depth and stencil formats.
|
||||
case VK_FORMAT_S8_UINT:
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
|
||||
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
|
||||
return 4;
|
||||
|
||||
// 48-bit formats.
|
||||
case VK_FORMAT_R16G16B16_UNORM:
|
||||
case VK_FORMAT_R16G16B16_SNORM:
|
||||
case VK_FORMAT_R16G16B16_USCALED:
|
||||
case VK_FORMAT_R16G16B16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16_UINT:
|
||||
case VK_FORMAT_R16G16B16_SINT:
|
||||
case VK_FORMAT_R16G16B16_SFLOAT:
|
||||
return 6;
|
||||
|
||||
// 64-bit formats.
|
||||
case VK_FORMAT_R32G32_UINT:
|
||||
case VK_FORMAT_R32G32_SINT:
|
||||
case VK_FORMAT_R32G32_SFLOAT:
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
case VK_FORMAT_R16G16B16A16_SNORM:
|
||||
case VK_FORMAT_R16G16B16A16_USCALED:
|
||||
case VK_FORMAT_R16G16B16A16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16A16_UINT:
|
||||
case VK_FORMAT_R16G16B16A16_SINT:
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
// Compressed formats.
|
||||
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC4_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC4_SNORM_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
|
||||
case VK_FORMAT_EAC_R11_UNORM_BLOCK:
|
||||
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
|
||||
return 8;
|
||||
|
||||
// 96-bit formats.
|
||||
case VK_FORMAT_R32G32B32_UINT:
|
||||
case VK_FORMAT_R32G32B32_SINT:
|
||||
case VK_FORMAT_R32G32B32_SFLOAT:
|
||||
return 12;
|
||||
|
||||
// 128-bit formats.
|
||||
case VK_FORMAT_R32G32B32A32_UINT:
|
||||
case VK_FORMAT_R32G32B32A32_SINT:
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
// Compressed formats.
|
||||
case VK_FORMAT_BC2_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC2_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC3_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC3_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC5_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC5_SNORM_BLOCK:
|
||||
case VK_FORMAT_BC6H_SFLOAT_BLOCK:
|
||||
case VK_FORMAT_BC6H_UFLOAT_BLOCK:
|
||||
case VK_FORMAT_BC7_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC7_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
|
||||
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
|
||||
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
|
||||
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
|
||||
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
|
||||
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
|
||||
return 16;
|
||||
|
||||
case VK_FORMAT_UNDEFINED:
|
||||
// In cases where we've explicitly already determined that the
|
||||
// format is not supported, let the rest of the system handle
|
||||
// that explicitly. Return '1' for no alignment.
|
||||
return 1;
|
||||
|
||||
default:
|
||||
// This is the case where there's a format that we added support
|
||||
// for in getVkFormat that we have not added support for in this
|
||||
// function, and should be treated as an error.
|
||||
assert_invariant(false && "Unknown data type, conversion is not supported.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type) {
|
||||
if (type == PixelDataType::USHORT_565) return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
if (type == PixelDataType::UINT_2_10_10_10_REV) return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
|
||||
@@ -49,9 +49,6 @@ VkFormat getVkFormatLinear(VkFormat format);
|
||||
// than a driver-level Texture format, and can account for a specified byte alignment.
|
||||
uint32_t getBytesPerPixel(TextureFormat format);
|
||||
|
||||
// Required for aligning textures in staging buffers.
|
||||
uint8_t getTexelBlockSize(VkFormat format);
|
||||
|
||||
VkCompareOp getCompareOp(SamplerCompareFunc func);
|
||||
VkBlendFactor getBlendFactor(BlendFunction mode);
|
||||
VkCullModeFlags getCullMode(CullingMode mode);
|
||||
|
||||
@@ -117,10 +117,10 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
samplerEntryInfo.binding = samplerEntry.binding;
|
||||
samplerEntry.visibility = wEntry.visibility;
|
||||
wEntry.texture.multisampled = isMultiSampledTypeDescriptor(fEntry.type);
|
||||
// TODO: Set once we have the filtering values
|
||||
if (isDepthDescriptor(fEntry.type)) {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::Comparison;
|
||||
} else if (isIntDescriptor(fEntry.type) ||
|
||||
any(fEntry.flags & DescriptorFlags::UNFILTERABLE)) {
|
||||
} else if (isIntDescriptor(fEntry.type)) {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering;
|
||||
} else {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::Filtering;
|
||||
@@ -151,11 +151,8 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
if (isDepthDescriptor(fEntry.type)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Depth;
|
||||
} else if (isFloatDescriptor(fEntry.type)) {
|
||||
if (any(fEntry.flags & DescriptorFlags::UNFILTERABLE)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
|
||||
} else {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Float;
|
||||
}
|
||||
// TODO: Set once we have the filtering values
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Float;
|
||||
} else if (isIntDescriptor(fEntry.type)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Sint;
|
||||
} else if (isUnsignedIntDescriptor(fEntry.type)) {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "WebGPUBufferObject.h"
|
||||
#include "WebGPUDescriptorSet.h"
|
||||
#include "WebGPUDescriptorSetLayout.h"
|
||||
#include "WebGPUFence.h"
|
||||
#include "WebGPUIndexBuffer.h"
|
||||
#include "WebGPUPipelineCreation.h"
|
||||
#include "WebGPUProgram.h"
|
||||
@@ -26,6 +25,7 @@
|
||||
#include "WebGPURenderTarget.h"
|
||||
#include "WebGPUSwapChain.h"
|
||||
#include "WebGPUTexture.h"
|
||||
#include "WebGPUTimerQuery.h"
|
||||
#include "WebGPUVertexBuffer.h"
|
||||
#include "WebGPUVertexBufferInfo.h"
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
@@ -102,7 +102,7 @@ template class ConcreteDispatcher<WebGPUDriver>;
|
||||
void WebGPUDriver::terminate() {
|
||||
}
|
||||
|
||||
void WebGPUDriver::tick(int) {
|
||||
void WebGPUDriver::tick(int /*dummy*/) {
|
||||
mDevice.Tick();
|
||||
mAdapter.GetInstance().ProcessEvents();
|
||||
}
|
||||
@@ -218,9 +218,6 @@ void WebGPUDriver::destroyStream(Handle<HwStream> sh) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyDescriptorSetLayout(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle) {
|
||||
if (descriptorSetLayoutHandle) {
|
||||
@@ -266,13 +263,35 @@ Handle<HwProgram> WebGPUDriver::createProgramS() noexcept {
|
||||
}
|
||||
|
||||
Handle<HwFence> WebGPUDriver::createFenceS() noexcept {
|
||||
// The handle must be constructed here, as a synchronous call to get the status
|
||||
// might happen before createFenceR is executed.
|
||||
return allocAndConstructHandle<WebGPUFence, HwFence>();
|
||||
return Handle<HwFence>((Handle<HwFence>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTimerQuery> WebGPUDriver::createTimerQueryS() noexcept {
|
||||
return Handle<HwTimerQuery>((Handle<HwTimerQuery>::HandleId) mNextFakeHandle++);
|
||||
return allocAndConstructHandle<WebGPUTimerQuery, HwTimerQuery>();
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> timerQueryHandle, int /*dummy*/) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||
if (timerQueryHandle) {
|
||||
destructHandle<WebGPUTimerQuery>(timerQueryHandle);
|
||||
}
|
||||
}
|
||||
|
||||
TimerQueryResult WebGPUDriver::getTimerQueryValue(Handle<HwTimerQuery> timerQueryHandle, uint64_t* elapsedTime) {
|
||||
auto* timerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||
return timerQuery->getQueryResult(elapsedTime) ? TimerQueryResult::AVAILABLE
|
||||
: TimerQueryResult::NOT_READY;
|
||||
}
|
||||
|
||||
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||
mTimerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||
}
|
||||
|
||||
void WebGPUDriver::endTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||
mTimerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||
}
|
||||
|
||||
Handle<HwIndexBuffer> WebGPUDriver::createIndexBufferS() noexcept {
|
||||
@@ -341,6 +360,9 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
mDevice, flags);
|
||||
assert_invariant(mSwapChain);
|
||||
|
||||
FWGPU_LOGW << "WebGPU support is highly experimental, in development, and tested for only a "
|
||||
"small set of simple samples (e.g. hellotriangle and texturedquad), thus issues "
|
||||
"are likely to be encountered at this stage.";
|
||||
#if !FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) && !defined(NDEBUG)
|
||||
char printSystemHex[16];
|
||||
snprintf(printSystemHex, sizeof(printSystemHex), "%#x", FWGPU_PRINT_SYSTEM);
|
||||
@@ -452,22 +474,17 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> renderTarge
|
||||
}
|
||||
|
||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
|
||||
const TargetBufferFlags targetFlags, const uint32_t width, const uint32_t height,
|
||||
const TargetBufferFlags targets, const uint32_t width, const uint32_t height,
|
||||
const uint8_t samples, const uint8_t layerCount, const MRT color,
|
||||
const TargetBufferInfo depth, const TargetBufferInfo stencil) {
|
||||
constructHandle<WebGPURenderTarget>(renderTargetHandle, width, height, samples, layerCount,
|
||||
color, depth, stencil, targetFlags);
|
||||
color, depth, stencil);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, const int /* dummy */) {
|
||||
// the handle was already constructed in createFenceS
|
||||
const auto fence = handleCast<WebGPUFence>(fenceHandle);
|
||||
assert_invariant(mQueue);
|
||||
fence->addMarkerToQueueState(mQueue);
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||
//todo
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
||||
backend::DescriptorSetLayout&& info) {
|
||||
@@ -516,18 +533,13 @@ void WebGPUDriver::updateStreams(CommandStream* driver) {
|
||||
//todo
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyFence(Handle<HwFence> fenceHandle) {
|
||||
if (fenceHandle) {
|
||||
destructHandle<WebGPUFence>(fenceHandle);
|
||||
}
|
||||
void WebGPUDriver::destroyFence(Handle<HwFence> fh) {
|
||||
//todo
|
||||
}
|
||||
|
||||
FenceStatus WebGPUDriver::getFenceStatus(Handle<HwFence> fenceHandle) {
|
||||
const auto fence = handleCast<WebGPUFence>(fenceHandle);
|
||||
if (!fence) {
|
||||
return FenceStatus::ERROR;
|
||||
}
|
||||
return fence->getStatus();
|
||||
FenceStatus WebGPUDriver::getFenceStatus(Handle<HwFence> fh) {
|
||||
//todo
|
||||
return FenceStatus::CONDITION_SATISFIED;
|
||||
}
|
||||
|
||||
// We create all textures using VK_IMAGE_TILING_OPTIMAL, so our definition of "supported" is that
|
||||
@@ -621,24 +633,11 @@ size_t WebGPUDriver::getMaxUniformBufferSize() {
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxTextureSize(const SamplerType target) {
|
||||
size_t result = 2048u;
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
result = mDeviceLimits.maxTextureDimension2D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
result = mDeviceLimits.maxTextureDimension3D;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
return 2048u;
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxArrayTextureLayers() {
|
||||
return mDeviceLimits.maxTextureArrayLayers;
|
||||
return 256u;
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateIndexBuffer(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
@@ -749,10 +748,6 @@ void WebGPUDriver::setupExternalImage(void* image) {
|
||||
//todo
|
||||
}
|
||||
|
||||
TimerQueryResult WebGPUDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint64_t* elapsedTime) {
|
||||
return TimerQueryResult::ERROR;
|
||||
}
|
||||
|
||||
void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
//todo
|
||||
}
|
||||
@@ -823,9 +818,10 @@ void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> renderTargetHandle,
|
||||
|
||||
std::array<wgpu::TextureView, MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT> customColorViews{};
|
||||
uint32_t customColorViewCount = 0;
|
||||
|
||||
wgpu::TextureView customDepthStencilView = nullptr;
|
||||
wgpu::TextureFormat customDepthStencilFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureView customDepthView = nullptr;
|
||||
wgpu::TextureFormat customDepthFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureFormat customStencilFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureView customStencilView = nullptr;
|
||||
|
||||
mCurrentRenderTarget = renderTarget;
|
||||
if (renderTarget->isDefaultRenderTarget()) {
|
||||
@@ -833,24 +829,6 @@ void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> renderTargetHandle,
|
||||
defaultColorView = mTextureView;
|
||||
defaultDepthStencilView = mSwapChain->getDepthTextureView();
|
||||
defaultDepthStencilFormat = mSwapChain->getDepthFormat();
|
||||
|
||||
if (any(renderTarget->getTargetFlags() & TargetBufferFlags::STENCIL) &&
|
||||
!(defaultDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth32FloatStencil8 ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Stencil8)) {
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Default render target requested stencil, but swap chain's depth format "
|
||||
<< (uint32_t)defaultDepthStencilFormat << " does not have a stencil aspect.";
|
||||
}
|
||||
|
||||
if (any(renderTarget->getTargetFlags() & TargetBufferFlags::DEPTH) &&
|
||||
!(defaultDepthStencilFormat == wgpu::TextureFormat::Depth16Unorm ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth32Float ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth24Plus ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth32FloatStencil8)) {
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Default render target requested depth, but swap chain's depth format "
|
||||
<< (uint32_t)defaultDepthStencilFormat << " does not have a depth aspect.";
|
||||
}
|
||||
} else {
|
||||
// Resolve views for custom render target
|
||||
const auto& colorInfos = renderTarget->getColorAttachmentInfos();
|
||||
@@ -870,63 +848,36 @@ void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> renderTargetHandle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto& depthInfo = renderTarget->getDepthAttachmentInfo();
|
||||
const auto& stencilInfo = renderTarget->getStencilAttachmentInfo();
|
||||
|
||||
Handle<HwTexture> depthStencilSourceHandle = {};
|
||||
uint8_t depthStencilMipLevel = 0;
|
||||
uint32_t depthStencilArrayLayer = 0;
|
||||
|
||||
if (depthInfo.handle && stencilInfo.handle) {
|
||||
auto const depthTexture{handleCast<WebGPUTexture>(depthInfo.handle)->getTexture()};
|
||||
auto const stencilTexture{handleCast<WebGPUTexture>(stencilInfo.handle)->getTexture()};
|
||||
FILAMENT_CHECK_POSTCONDITION(depthTexture.Get() == stencilTexture.Get())
|
||||
<< "Filament must reference the same resource if both depth and stencil "
|
||||
"textures are present";
|
||||
}
|
||||
|
||||
if (depthInfo.handle) {
|
||||
depthStencilSourceHandle = depthInfo.handle;
|
||||
depthStencilMipLevel = depthInfo.level;
|
||||
depthStencilArrayLayer = depthInfo.layer;
|
||||
} else if (stencilInfo.handle) {
|
||||
depthStencilSourceHandle = stencilInfo.handle;
|
||||
depthStencilMipLevel = stencilInfo.level;
|
||||
depthStencilArrayLayer = stencilInfo.layer;
|
||||
FILAMENT_CHECK_POSTCONDITION(depthInfo.layer < renderTarget->getLayerCount())
|
||||
<< "Depth attachment requests layer " << depthInfo.layer
|
||||
<< "but render target has only " << renderTarget->getLayerCount() << ".";
|
||||
auto depthTexture = handleCast<WebGPUTexture>(depthInfo.handle);
|
||||
if (depthTexture) {
|
||||
const uint8_t depthMipLevel = depthInfo.level;
|
||||
const uint32_t depthArrayLayer = depthInfo.layer;
|
||||
customDepthView =
|
||||
depthTexture->getOrMakeTextureView(depthMipLevel, depthArrayLayer);
|
||||
customDepthFormat = depthTexture->getViewFormat();
|
||||
}
|
||||
}
|
||||
|
||||
if (depthStencilSourceHandle) {
|
||||
auto dsTexture = handleCast<WebGPUTexture>(depthStencilSourceHandle);
|
||||
if (dsTexture) {
|
||||
customDepthStencilView = dsTexture->getOrMakeTextureView(depthStencilMipLevel, depthStencilArrayLayer);
|
||||
customDepthStencilFormat = dsTexture->getViewFormat();
|
||||
|
||||
if (any(renderTarget->getTargetFlags() & TargetBufferFlags::STENCIL) &&
|
||||
!(customDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
customDepthStencilFormat ==
|
||||
wgpu::TextureFormat::Depth32FloatStencil8 ||
|
||||
customDepthStencilFormat ==
|
||||
wgpu::TextureFormat::Stencil8)) {
|
||||
FILAMENT_CHECK_POSTCONDITION(false)
|
||||
<< "Custom render target requested stencil, but the provided texture"
|
||||
"format number"
|
||||
<< (uint32_t) customDepthStencilFormat
|
||||
<< " does not have a stencil aspect.";
|
||||
}
|
||||
if (any(renderTarget->getTargetFlags() & TargetBufferFlags::DEPTH) &&
|
||||
!(customDepthStencilFormat == wgpu::TextureFormat::Depth16Unorm ||
|
||||
customDepthStencilFormat == wgpu::TextureFormat::Depth32Float ||
|
||||
customDepthStencilFormat ==
|
||||
wgpu::TextureFormat::Depth24Plus ||
|
||||
customDepthStencilFormat ==
|
||||
wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
customDepthStencilFormat ==
|
||||
wgpu::TextureFormat::Depth32FloatStencil8)) {
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Custom render target requested depth, "
|
||||
"but the provided texture format number"
|
||||
<< (uint32_t) customDepthStencilFormat
|
||||
<< " does not have a depth aspect.";
|
||||
}
|
||||
const auto& stencilInfo = renderTarget->getStencilAttachmentInfo();
|
||||
if (stencilInfo.handle) {
|
||||
// If depth and stencil use the same texture handle, this will re-cast but that's fine.
|
||||
auto stencilTexture = handleCast<WebGPUTexture>(stencilInfo.handle);
|
||||
if (stencilTexture) {
|
||||
FILAMENT_CHECK_POSTCONDITION(stencilInfo.layer < renderTarget->getLayerCount())
|
||||
<< "Stencil attachment requests layer " << stencilInfo.layer
|
||||
<< " but render target has only " << renderTarget->getLayerCount()
|
||||
<< " layers.";
|
||||
const uint8_t stencilMipLevel = stencilInfo.level;
|
||||
const uint32_t stencilArrayLayer = stencilInfo.layer;
|
||||
customStencilView =
|
||||
stencilTexture->getOrMakeTextureView(stencilMipLevel, stencilArrayLayer);
|
||||
customStencilFormat = stencilTexture->getViewFormat();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -935,9 +886,13 @@ void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> renderTargetHandle,
|
||||
params,
|
||||
defaultColorView,
|
||||
defaultDepthStencilView,
|
||||
defaultDepthStencilFormat,
|
||||
customColorViews.data(),
|
||||
customColorViewCount,
|
||||
customDepthStencilView);
|
||||
customDepthView,
|
||||
customStencilView,
|
||||
customDepthFormat,
|
||||
customStencilFormat);
|
||||
|
||||
mRenderPassEncoder = mCommandEncoder.BeginRenderPass(&renderPassDescriptor);
|
||||
|
||||
@@ -972,25 +927,9 @@ void WebGPUDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
|
||||
wgpu::Extent2D surfaceSize = mPlatform.getSurfaceExtent(mNativeWindow);
|
||||
mTextureView = mSwapChain->getCurrentSurfaceTextureView(surfaceSize);
|
||||
assert_invariant(mTextureView);
|
||||
|
||||
assert_invariant(mDefaultRenderTarget);
|
||||
|
||||
wgpu::TextureFormat depthFormat = mSwapChain->getDepthFormat();
|
||||
TargetBufferFlags newTargetFlags = filament::backend::TargetBufferFlags::NONE;
|
||||
|
||||
//Assuming Color and Depth are always present.
|
||||
newTargetFlags |= filament::backend::TargetBufferFlags::COLOR;
|
||||
if (depthFormat != wgpu::TextureFormat::Undefined) {
|
||||
newTargetFlags |= filament::backend::TargetBufferFlags::DEPTH;
|
||||
|
||||
if (depthFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
depthFormat == wgpu::TextureFormat::Depth32FloatStencil8) {
|
||||
newTargetFlags |= filament::backend::TargetBufferFlags::STENCIL;
|
||||
}
|
||||
}
|
||||
mDefaultRenderTarget->setTargetFlags(newTargetFlags);
|
||||
|
||||
wgpu::CommandEncoderDescriptor commandEncoderDescriptor = { .label = "frame_command_encoder" };
|
||||
wgpu::CommandEncoderDescriptor commandEncoderDescriptor = {
|
||||
.label = "command_encoder"
|
||||
};
|
||||
mCommandEncoder = mDevice.CreateCommandEncoder(&commandEncoderDescriptor);
|
||||
assert_invariant(mCommandEncoder);
|
||||
}
|
||||
@@ -1002,8 +941,10 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
||||
mCommandBuffer = mCommandEncoder.Finish(&commandBufferDescriptor);
|
||||
assert_invariant(mCommandBuffer);
|
||||
mCommandEncoder = nullptr;
|
||||
if (mTimerQuery) {
|
||||
mTimerQuery->beginTimeElapsedQuery();
|
||||
}
|
||||
mQueue.Submit(1, &mCommandBuffer);
|
||||
|
||||
static bool firstRender = true;
|
||||
// For the first frame rendered, we need to make sure the work is done before presenting or we
|
||||
// get a purple flash
|
||||
@@ -1018,6 +959,15 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
||||
<< static_cast<uint32_t>(wStatus);
|
||||
}
|
||||
firstRender = false;
|
||||
} else {
|
||||
mQueue.OnSubmittedWorkDone(wgpu::CallbackMode::AllowSpontaneous,
|
||||
[=](wgpu::QueueWorkDoneStatus status) {
|
||||
if (status == wgpu::QueueWorkDoneStatus::Success) {
|
||||
if (mTimerQuery) {
|
||||
mTimerQuery->endTimeElapsedQuery();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
mCommandBuffer = nullptr;
|
||||
mTextureView = nullptr;
|
||||
@@ -1125,15 +1075,14 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
assert_invariant(vertexBufferInfo);
|
||||
|
||||
std::vector<wgpu::TextureFormat> pipelineColorFormats;
|
||||
wgpu::TextureFormat pipelineDepthStencilFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureFormat pipelineDepthFormat = wgpu::TextureFormat::Undefined;
|
||||
uint8_t pipelineSamples = 1;
|
||||
bool const requestedDepth = any(mCurrentRenderTarget->getTargetFlags() & TargetBufferFlags::DEPTH);
|
||||
bool const requestedStencil = any(mCurrentRenderTarget->getTargetFlags() & TargetBufferFlags::STENCIL);
|
||||
pipelineSamples = mCurrentRenderTarget->getSamples();
|
||||
|
||||
if (mCurrentRenderTarget->isDefaultRenderTarget()) {
|
||||
pipelineColorFormats.push_back(mSwapChain->getColorFormat());
|
||||
pipelineDepthStencilFormat = mSwapChain->getDepthFormat();
|
||||
pipelineDepthFormat = mSwapChain->getDepthFormat();
|
||||
pipelineSamples =
|
||||
mCurrentRenderTarget->getSamples();// Default RT should have samples (usually 1)
|
||||
} else {
|
||||
const auto& mrtColorAttachments = mCurrentRenderTarget->getColorAttachmentInfos();
|
||||
for (size_t i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; ++i) {
|
||||
@@ -1147,19 +1096,21 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
|
||||
const auto& depthInfo = mCurrentRenderTarget->getDepthAttachmentInfo();
|
||||
const auto& stencilInfo = mCurrentRenderTarget->getStencilAttachmentInfo();
|
||||
Handle<HwTexture> depthStencilHandle = {};
|
||||
if (depthInfo.handle) {
|
||||
depthStencilHandle = depthInfo.handle;
|
||||
} else if (stencilInfo.handle) {
|
||||
depthStencilHandle = stencilInfo.handle;
|
||||
}
|
||||
|
||||
if (depthStencilHandle) {
|
||||
const auto dsTexture = handleCast<WebGPUTexture>(depthStencilHandle);
|
||||
if (dsTexture) {
|
||||
pipelineDepthStencilFormat = dsTexture->getTexture().GetFormat();
|
||||
FILAMENT_CHECK_POSTCONDITION(!stencilInfo.handle)
|
||||
<< "depth and stencil attachments cannot both be provided for WebGPU";
|
||||
const auto depthTexture = handleCast<WebGPUTexture>(depthInfo.handle);
|
||||
if (depthTexture) pipelineDepthFormat = depthTexture->getTexture().GetFormat();
|
||||
} else {
|
||||
if (stencilInfo.handle) {
|
||||
const auto stencilTexture = handleCast<WebGPUTexture>(stencilInfo.handle);
|
||||
// Assuming combined depth/stencil format if only stencil is present
|
||||
if (stencilTexture) {
|
||||
pipelineDepthFormat = stencilTexture->getTexture().GetFormat();
|
||||
}
|
||||
}
|
||||
}
|
||||
pipelineSamples = mCurrentRenderTarget->getSamples();
|
||||
}
|
||||
|
||||
// TODO: We expected this to be a sane check, however it complains when running shadowtest.
|
||||
@@ -1171,7 +1122,7 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
wgpu::RenderPipeline pipeline = createWebGPURenderPipeline(mDevice, *program, *vertexBufferInfo,
|
||||
layout, pipelineState.rasterState, pipelineState.stencilState,
|
||||
pipelineState.polygonOffset, pipelineState.primitiveType, pipelineColorFormats,
|
||||
pipelineDepthStencilFormat, pipelineSamples, requestedDepth, requestedStencil);
|
||||
pipelineDepthFormat, pipelineSamples);
|
||||
assert_invariant(pipeline);
|
||||
mPipelineMap[hash] = pipeline;
|
||||
mRenderPassEncoder.SetPipeline(pipeline);
|
||||
@@ -1228,12 +1179,6 @@ void WebGPUDriver::scissor(
|
||||
//todo
|
||||
}
|
||||
|
||||
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::resetState(int) {
|
||||
//todo
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
namespace filament::backend {
|
||||
|
||||
class WebGPUSwapChain;
|
||||
class WebGPUTimerQuery;
|
||||
|
||||
/**
|
||||
* WebGPU backend (driver) implementation
|
||||
@@ -78,6 +79,7 @@ private:
|
||||
WebGPURenderTarget* mDefaultRenderTarget = nullptr;
|
||||
WebGPURenderTarget* mCurrentRenderTarget = nullptr;
|
||||
spd::MipmapGenerator mMipMapGenerator;
|
||||
WebGPUTimerQuery* mTimerQuery = nullptr;
|
||||
|
||||
tsl::robin_map<uint32_t, wgpu::RenderPipeline> mPipelineMap;
|
||||
|
||||
@@ -117,13 +119,13 @@ private:
|
||||
}
|
||||
|
||||
template<typename D, typename B, typename... ARGS>
|
||||
D* constructHandle(Handle<B>& handle, ARGS&&... args) noexcept {
|
||||
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
|
||||
Handle<B> allocAndConstructHandle(ARGS&&... args) {
|
||||
return mHandleAllocator.allocateAndConstruct<D>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
template<typename D, typename B, typename... ARGS>
|
||||
Handle<B> allocAndConstructHandle(ARGS&&... args) {
|
||||
return mHandleAllocator.allocateAndConstruct<D>(std::forward<ARGS>(args)...);
|
||||
D* constructHandle(Handle<B>& handle, ARGS&&... args) noexcept {
|
||||
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
template<typename D, typename B>
|
||||
|
||||
@@ -1,50 +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.
|
||||
*/
|
||||
|
||||
#include "WebGPUFence.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
FenceStatus WebGPUFence::getStatus() { return mStatus.load(); }
|
||||
|
||||
void WebGPUFence::addMarkerToQueueState(wgpu::Queue const& queue) {
|
||||
queue.OnSubmittedWorkDone(
|
||||
wgpu::CallbackMode::AllowSpontaneous,
|
||||
[](const wgpu::QueueWorkDoneStatus status,
|
||||
std::atomic<FenceStatus>* const fenceStatus) {
|
||||
if (!fenceStatus) {
|
||||
return;
|
||||
}
|
||||
switch (status) {
|
||||
case wgpu::QueueWorkDoneStatus::Success:
|
||||
fenceStatus->store(FenceStatus::CONDITION_SATISFIED);
|
||||
break;
|
||||
case wgpu::QueueWorkDoneStatus::CallbackCancelled:
|
||||
case wgpu::QueueWorkDoneStatus::Error:
|
||||
fenceStatus->store(FenceStatus::ERROR);
|
||||
break;
|
||||
}
|
||||
},
|
||||
&mStatus);
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
@@ -169,52 +169,39 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device,
|
||||
wgpu::PipelineLayout const& layout, RasterState const& rasterState,
|
||||
StencilState const& stencilState, PolygonOffset const& polygonOffset,
|
||||
const PrimitiveType primitiveType, std::vector<wgpu::TextureFormat> const& colorFormats,
|
||||
wgpu::TextureFormat const& depthStencilFormat, const uint8_t samplesCount, const bool requestedDepth, const bool requestedStencil) {
|
||||
const wgpu::TextureFormat depthFormat, const uint8_t samplesCount) {
|
||||
assert_invariant(program.vertexShaderModule);
|
||||
wgpu::DepthStencilState depthStencilState{};
|
||||
const bool depthOrStencilRequested = (requestedDepth || requestedStencil);
|
||||
if (depthFormat != wgpu::TextureFormat::Undefined) {
|
||||
depthStencilState.format = depthFormat;
|
||||
depthStencilState.depthWriteEnabled = rasterState.depthWrite;
|
||||
depthStencilState.depthCompare = toWebGPU(rasterState.depthFunc);
|
||||
depthStencilState.stencilFront = {
|
||||
.compare = toWebGPU(stencilState.front.stencilFunc),
|
||||
.failOp = toWebGPU(stencilState.front.stencilOpStencilFail),
|
||||
.depthFailOp = toWebGPU(stencilState.front.stencilOpDepthFail),
|
||||
.passOp = toWebGPU(stencilState.front.stencilOpDepthStencilPass),
|
||||
};
|
||||
depthStencilState.stencilBack = {
|
||||
.compare = toWebGPU(stencilState.back.stencilFunc),
|
||||
.failOp = toWebGPU(stencilState.back.stencilOpStencilFail),
|
||||
.depthFailOp = toWebGPU(stencilState.back.stencilOpDepthFail),
|
||||
.passOp = toWebGPU(stencilState.back.stencilOpDepthStencilPass),
|
||||
};
|
||||
depthStencilState.stencilReadMask =
|
||||
stencilState.front.readMask; // Use front face's comparison mask for read mask
|
||||
depthStencilState.stencilWriteMask = stencilState.stencilWrite ? 0xFFFFFFFF : 0u;
|
||||
depthStencilState.depthBias = static_cast<int32_t>(polygonOffset.constant);
|
||||
depthStencilState.depthBiasSlopeScale = polygonOffset.slope;
|
||||
depthStencilState.depthBiasClamp = 0.0f;
|
||||
|
||||
if (depthOrStencilRequested) {
|
||||
FILAMENT_CHECK_PRECONDITION(depthStencilFormat != wgpu::TextureFormat::Undefined)
|
||||
<< "Depth or Stencil requested for pipeline, but depthStencilFormat is "
|
||||
"wgpu::TextureFormat::Undefined.";
|
||||
depthStencilState.format = depthStencilFormat;
|
||||
|
||||
if (requestedDepth) {
|
||||
depthStencilState.depthWriteEnabled = rasterState.depthWrite;
|
||||
depthStencilState.depthCompare = toWebGPU(rasterState.depthFunc);
|
||||
depthStencilState.depthBias = static_cast<int32_t>(polygonOffset.constant);
|
||||
depthStencilState.depthBiasSlopeScale = polygonOffset.slope;
|
||||
depthStencilState.depthBiasClamp = 0.0f;
|
||||
} else {
|
||||
depthStencilState.depthWriteEnabled = false;
|
||||
depthStencilState.depthCompare = wgpu::CompareFunction::Undefined;
|
||||
depthStencilState.depthBias = 0;
|
||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
||||
depthStencilState.depthBiasClamp = 0.0f;
|
||||
}
|
||||
|
||||
if (hasStencilAspect(depthStencilFormat) && requestedStencil) {
|
||||
depthStencilState.stencilFront = {
|
||||
.compare = toWebGPU(stencilState.front.stencilFunc),
|
||||
.failOp = toWebGPU(stencilState.front.stencilOpStencilFail),
|
||||
.depthFailOp = toWebGPU(stencilState.front.stencilOpDepthFail),
|
||||
.passOp = toWebGPU(stencilState.front.stencilOpDepthStencilPass),
|
||||
};
|
||||
depthStencilState.stencilBack = {
|
||||
.compare = toWebGPU(stencilState.back.stencilFunc),
|
||||
.failOp = toWebGPU(stencilState.back.stencilOpStencilFail),
|
||||
.depthFailOp = toWebGPU(stencilState.back.stencilOpDepthFail),
|
||||
.passOp = toWebGPU(stencilState.back.stencilOpDepthStencilPass),
|
||||
};
|
||||
depthStencilState.stencilReadMask = stencilState.front.readMask;
|
||||
depthStencilState.stencilWriteMask = stencilState.stencilWrite ? stencilState.front.writeMask : 0u;
|
||||
} else {
|
||||
depthStencilState.stencilFront.compare = wgpu::CompareFunction::Undefined;
|
||||
if (!hasStencilAspect(depthFormat)) {
|
||||
depthStencilState.stencilFront.compare = wgpu::CompareFunction::Always;
|
||||
depthStencilState.stencilFront.failOp = wgpu::StencilOperation::Keep;
|
||||
depthStencilState.stencilFront.depthFailOp = wgpu::StencilOperation::Keep;
|
||||
depthStencilState.stencilFront.passOp = wgpu::StencilOperation::Keep;
|
||||
depthStencilState.stencilBack = depthStencilState.stencilFront;
|
||||
depthStencilState.stencilBack =
|
||||
depthStencilState.stencilFront; // Keep back and front consistent
|
||||
depthStencilState.stencilReadMask = 0;
|
||||
depthStencilState.stencilWriteMask = 0;
|
||||
}
|
||||
@@ -258,11 +245,11 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device,
|
||||
.unclippedDepth = !rasterState.depthClamp &&
|
||||
device.HasFeature(wgpu::FeatureName::DepthClipControl)
|
||||
},
|
||||
.depthStencil = depthOrStencilRequested ? &depthStencilState: nullptr,
|
||||
.depthStencil = depthFormat != wgpu::TextureFormat::Undefined ? &depthStencilState: nullptr,
|
||||
.multisample = {
|
||||
.count = samplesCount,
|
||||
.mask = 0xFFFFFFFF,
|
||||
.alphaToCoverageEnabled = (samplesCount > 1) && rasterState.alphaToCoverage
|
||||
.alphaToCoverageEnabled = rasterState.alphaToCoverage
|
||||
},
|
||||
.fragment = nullptr // will add below if fragment module is included
|
||||
};
|
||||
|
||||
@@ -40,8 +40,8 @@ class WebGPUProgram;
|
||||
[[nodiscard]] wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const&,
|
||||
WebGPUProgram const&, WebGPUVertexBufferInfo const&, wgpu::PipelineLayout const&,
|
||||
RasterState const&, StencilState const&, PolygonOffset const&, PrimitiveType primitiveType,
|
||||
std::vector<wgpu::TextureFormat> const& colorFormats, wgpu::TextureFormat const& depthStencilFormat,
|
||||
uint8_t samplesCount, bool requestedDepth, bool requestedStencil);
|
||||
std::vector<wgpu::TextureFormat> const& colorFormats, wgpu::TextureFormat depthFormat,
|
||||
uint8_t samplesCount);
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
|
||||
@@ -32,27 +32,24 @@ namespace filament::backend {
|
||||
|
||||
WebGPURenderTarget::WebGPURenderTarget(const uint32_t width, const uint32_t height,
|
||||
const uint8_t samples, const uint8_t layerCount, MRT const& colorAttachmentsMRT,
|
||||
Attachment const& depthAttachmentInfo, Attachment const& stencilAttachmentInfo, TargetBufferFlags const& targetFlags)
|
||||
Attachment const& depthAttachmentInfo, Attachment const& stencilAttachmentInfo)
|
||||
: HwRenderTarget{ width, height },
|
||||
mDefaultRenderTarget{ false },
|
||||
mTargetFlags{ targetFlags },
|
||||
mSamples{ samples },
|
||||
mLayerCount{ layerCount },
|
||||
mColorAttachments{ colorAttachmentsMRT },
|
||||
mDepthAttachment{ depthAttachmentInfo },
|
||||
mStencilAttachment{ stencilAttachmentInfo } {
|
||||
// TODO consider making this an array
|
||||
mColorAttachmentDesc.reserve(MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT);
|
||||
mColorAttachmentDescriptors.reserve(MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT);
|
||||
}
|
||||
|
||||
// Default constructor for the default render target
|
||||
WebGPURenderTarget::WebGPURenderTarget()
|
||||
: HwRenderTarget{ 0, 0 },
|
||||
mDefaultRenderTarget{ true },
|
||||
mTargetFlags{ TargetBufferFlags::NONE },
|
||||
mSamples{ 1 },
|
||||
mLayerCount{ 1 }
|
||||
{}
|
||||
mLayerCount{ 1 } {}
|
||||
|
||||
wgpu::LoadOp WebGPURenderTarget::getLoadOperation(RenderPassParams const& params,
|
||||
const TargetBufferFlags bufferToOperateOn) {
|
||||
@@ -60,7 +57,7 @@ wgpu::LoadOp WebGPURenderTarget::getLoadOperation(RenderPassParams const& params
|
||||
return wgpu::LoadOp::Clear;
|
||||
}
|
||||
if (any(params.flags.discardStart & bufferToOperateOn)) {
|
||||
return wgpu::LoadOp::Clear;
|
||||
return wgpu::LoadOp::Clear; // Or wgpu::LoadOp::Undefined if clear is not desired on discard
|
||||
}
|
||||
return wgpu::LoadOp::Load;
|
||||
}
|
||||
@@ -76,30 +73,55 @@ wgpu::StoreOp WebGPURenderTarget::getStoreOperation(RenderPassParams const& para
|
||||
void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& outDescriptor,
|
||||
RenderPassParams const& params, wgpu::TextureView const& defaultColorTextureView,
|
||||
wgpu::TextureView const& defaultDepthStencilTextureView,
|
||||
wgpu::TextureFormat const& defaultDepthStencilFormat,
|
||||
wgpu::TextureView const* customColorTextureViews, uint32_t customColorTextureViewCount,
|
||||
wgpu::TextureView const& customDepthStencilTextureView){
|
||||
mColorAttachmentDesc.clear();
|
||||
wgpu::TextureView const& customDepthTextureView,
|
||||
wgpu::TextureView const& customStencilTextureView,
|
||||
const wgpu::TextureFormat customDepthFormat,
|
||||
const wgpu::TextureFormat customStencilFormat) {
|
||||
mColorAttachmentDescriptors.clear();
|
||||
mHasDepthStencilAttachment = false;
|
||||
|
||||
const bool hasDepth = any(mTargetFlags & TargetBufferFlags::DEPTH);
|
||||
const bool hasStencil = any(mTargetFlags & TargetBufferFlags::STENCIL);
|
||||
mHasDepthStencilAttachment = hasDepth || hasStencil;
|
||||
bool const depthReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||
|
||||
// Color attachments
|
||||
if (mDefaultRenderTarget) {
|
||||
assert_invariant(defaultColorTextureView);
|
||||
mColorAttachmentDesc.push_back({
|
||||
.view = defaultColorTextureView,
|
||||
mColorAttachmentDescriptors.push_back({ .view = defaultColorTextureView,
|
||||
.resolveTarget = nullptr,
|
||||
.loadOp = WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::COLOR0),
|
||||
.storeOp = WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::COLOR0),
|
||||
.clearValue = { params.clearColor.r, params.clearColor.g, params.clearColor.b,
|
||||
params.clearColor.a } });
|
||||
} else {
|
||||
|
||||
if (defaultDepthStencilTextureView) {
|
||||
mDepthStencilAttachmentDescriptor = {
|
||||
.view = defaultDepthStencilTextureView,
|
||||
.depthLoadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH),
|
||||
.depthStoreOp =
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH),
|
||||
.depthClearValue = static_cast<float>(params.clearDepth),
|
||||
.depthReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0,
|
||||
.stencilLoadOp = wgpu::LoadOp::Undefined,
|
||||
.stencilStoreOp = wgpu::StoreOp::Undefined,
|
||||
.stencilClearValue = params.clearStencil,
|
||||
.stencilReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0,
|
||||
};
|
||||
|
||||
if (defaultDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Depth32FloatStencil8 ||
|
||||
defaultDepthStencilFormat == wgpu::TextureFormat::Stencil8) {
|
||||
mDepthStencilAttachmentDescriptor.stencilLoadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL);
|
||||
mDepthStencilAttachmentDescriptor.stencilStoreOp =
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::STENCIL);
|
||||
}
|
||||
mHasDepthStencilAttachment = true;
|
||||
}
|
||||
} else { // Custom Render Target
|
||||
for (uint32_t i = 0; i < customColorTextureViewCount; ++i) {
|
||||
if (customColorTextureViews[i]) {
|
||||
mColorAttachmentDesc.push_back({ .view = customColorTextureViews[i],
|
||||
mColorAttachmentDescriptors.push_back({ .view = customColorTextureViews[i],
|
||||
// .resolveTarget = nullptr; // TODO: MSAA resolve for custom RT
|
||||
.loadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, getTargetBufferFlagsAt(i)),
|
||||
@@ -111,62 +133,68 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor&
|
||||
.a = params.clearColor.a } });
|
||||
}
|
||||
}
|
||||
}
|
||||
outDescriptor.colorAttachmentCount = mColorAttachmentDesc.size();
|
||||
outDescriptor.colorAttachments = mColorAttachmentDesc.data();
|
||||
|
||||
// Depth/Stencil Attachments
|
||||
if (mHasDepthStencilAttachment) {
|
||||
wgpu::TextureView depthStencilViewToUse{nullptr};
|
||||
if (mDefaultRenderTarget) {
|
||||
depthStencilViewToUse = defaultDepthStencilTextureView;
|
||||
assert_invariant(depthStencilViewToUse);
|
||||
} else {
|
||||
if (customDepthStencilTextureView) {
|
||||
depthStencilViewToUse = customDepthStencilTextureView;
|
||||
}
|
||||
}
|
||||
FILAMENT_CHECK_POSTCONDITION(!(customDepthTextureView && customStencilTextureView))
|
||||
<< "WebGPU CANNOT support separate texture views for depth + stencil. depth + "
|
||||
"stencil needs to be in one texture view";
|
||||
|
||||
if (depthStencilViewToUse) {
|
||||
mDepthStencilAttachmentDesc = {};
|
||||
mDepthStencilAttachmentDesc.view = depthStencilViewToUse;
|
||||
const bool hasStencil =
|
||||
customStencilTextureView ||
|
||||
(customDepthFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
customDepthFormat == wgpu::TextureFormat::Depth32FloatStencil8);
|
||||
|
||||
const bool hasDepth =
|
||||
customDepthTextureView ||
|
||||
(customStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
|
||||
customDepthFormat == wgpu::TextureFormat::Depth32FloatStencil8);
|
||||
|
||||
if (customDepthTextureView || customStencilTextureView) {
|
||||
assert_invariant((hasDepth || hasStencil) &&
|
||||
"Depth or Texture view without a valid texture format");
|
||||
mDepthStencilAttachmentDescriptor = {};
|
||||
mDepthStencilAttachmentDescriptor.view =
|
||||
customDepthTextureView ? customDepthTextureView : customStencilTextureView;
|
||||
|
||||
if (hasDepth) {
|
||||
mDepthStencilAttachmentDesc.depthLoadOp = depthReadOnly ? wgpu::LoadOp::Undefined :getLoadOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDesc.depthStoreOp = depthReadOnly ? wgpu::StoreOp::Undefined :getStoreOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDesc.depthClearValue = static_cast<float>(params.clearDepth);
|
||||
mDepthStencilAttachmentDesc.depthReadOnly = depthReadOnly;
|
||||
mDepthStencilAttachmentDescriptor.depthLoadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDescriptor.depthStoreOp =
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDescriptor.depthClearValue =
|
||||
static_cast<float>(params.clearDepth);
|
||||
mDepthStencilAttachmentDescriptor.depthReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||
} else {
|
||||
mDepthStencilAttachmentDesc.depthLoadOp = wgpu::LoadOp::Undefined;
|
||||
mDepthStencilAttachmentDesc.depthStoreOp = wgpu::StoreOp::Undefined;
|
||||
mDepthStencilAttachmentDesc.depthReadOnly = true;
|
||||
mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined;
|
||||
mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined;
|
||||
mDepthStencilAttachmentDescriptor.depthReadOnly = true;
|
||||
}
|
||||
|
||||
if (hasStencil) {
|
||||
mDepthStencilAttachmentDesc.stencilLoadOp = getLoadOperation(params, TargetBufferFlags::STENCIL);
|
||||
mDepthStencilAttachmentDesc.stencilStoreOp = getStoreOperation(params, TargetBufferFlags::STENCIL);
|
||||
mDepthStencilAttachmentDesc.stencilClearValue = params.clearStencil;
|
||||
mDepthStencilAttachmentDesc.stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0;
|
||||
mDepthStencilAttachmentDescriptor.stencilLoadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL);
|
||||
mDepthStencilAttachmentDescriptor.stencilStoreOp =
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::STENCIL);
|
||||
mDepthStencilAttachmentDescriptor.stencilClearValue = params.clearStencil;
|
||||
mDepthStencilAttachmentDescriptor.stencilReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0;
|
||||
} else {
|
||||
mDepthStencilAttachmentDesc.stencilLoadOp = wgpu::LoadOp::Undefined;
|
||||
mDepthStencilAttachmentDesc.stencilStoreOp = wgpu::StoreOp::Undefined;
|
||||
mDepthStencilAttachmentDesc.stencilReadOnly = true;
|
||||
mDepthStencilAttachmentDescriptor.stencilLoadOp = wgpu::LoadOp::Undefined;
|
||||
mDepthStencilAttachmentDescriptor.stencilStoreOp = wgpu::StoreOp::Undefined;
|
||||
mDepthStencilAttachmentDescriptor.stencilReadOnly = true;
|
||||
}
|
||||
outDescriptor.depthStencilAttachment = &mDepthStencilAttachmentDesc;
|
||||
|
||||
} else {
|
||||
outDescriptor.depthStencilAttachment = nullptr;
|
||||
mDepthStencilAttachmentDesc = {};
|
||||
mHasDepthStencilAttachment = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
outDescriptor.depthStencilAttachment = nullptr;
|
||||
mDepthStencilAttachmentDesc = {};
|
||||
}
|
||||
|
||||
outDescriptor.colorAttachmentCount = mColorAttachmentDescriptors.size();
|
||||
outDescriptor.colorAttachments = mColorAttachmentDescriptors.data();
|
||||
outDescriptor.depthStencilAttachment =
|
||||
mHasDepthStencilAttachment ? &mDepthStencilAttachmentDescriptor : nullptr;
|
||||
|
||||
// descriptor.sampleCount was removed from the core spec. If your webgpu.h still has it,
|
||||
// and your Dawn version expects it, you might need to set it here based on this->samples.
|
||||
// e.g., descriptor.sampleCount = this->samples;
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -34,41 +34,44 @@ public:
|
||||
|
||||
WebGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount,
|
||||
MRT const& colorAttachments, Attachment const& depthAttachment,
|
||||
Attachment const& stencilAttachment, TargetBufferFlags const& targetFlags);
|
||||
Attachment const& stencilAttachment);
|
||||
|
||||
// Default constructor for the default render target
|
||||
WebGPURenderTarget();
|
||||
|
||||
// Updated signature: takes resolved views for custom RTs, and default views for default RT
|
||||
void setUpRenderPassAttachments(
|
||||
wgpu::RenderPassDescriptor& outDescriptor,
|
||||
RenderPassParams const& params,
|
||||
// For default render target:
|
||||
wgpu::TextureView const& defaultColorTextureView,
|
||||
wgpu::TextureView const& defaultDepthStencilTextureView,
|
||||
wgpu::TextureFormat const& defaultDepthStencilFormat,
|
||||
// For custom render targets:
|
||||
wgpu::TextureView const* customColorTextureViews, // Array of views
|
||||
uint32_t customColorTextureViewCount,
|
||||
wgpu::TextureView const& customDepthStencilTextureView);
|
||||
wgpu::TextureView const& customDepthTextureView,
|
||||
wgpu::TextureView const& customStencilTextureView,
|
||||
wgpu::TextureFormat customDepthFormat,
|
||||
wgpu::TextureFormat customStencilFormat);
|
||||
|
||||
[[nodiscard]] bool isDefaultRenderTarget() const { return mDefaultRenderTarget; }
|
||||
[[nodiscard]] uint8_t getSamples() const { return mSamples; }
|
||||
[[nodiscard]] uint8_t getLayerCount() const { return mLayerCount; }
|
||||
|
||||
// Accessors for the driver to get stored attachment info
|
||||
[[nodiscard]] MRT const& getColorAttachmentInfos() const { return mColorAttachments; }
|
||||
[[nodiscard]] Attachment const& getDepthAttachmentInfo() const { return mDepthAttachment; }
|
||||
[[nodiscard]] Attachment const& getStencilAttachmentInfo() const { return mStencilAttachment; }
|
||||
|
||||
// Static helpers for load/store operations
|
||||
[[nodiscard]] static wgpu::LoadOp getLoadOperation(RenderPassParams const& params,
|
||||
TargetBufferFlags buffer);
|
||||
[[nodiscard]] static wgpu::StoreOp getStoreOperation(RenderPassParams const& params,
|
||||
TargetBufferFlags buffer);
|
||||
|
||||
[[nodiscard]] TargetBufferFlags getTargetFlags() const { return mTargetFlags; }
|
||||
void setTargetFlags( TargetBufferFlags value) { mTargetFlags = value; }
|
||||
|
||||
private:
|
||||
bool mDefaultRenderTarget = false;
|
||||
TargetBufferFlags mTargetFlags = TargetBufferFlags::NONE;
|
||||
uint8_t mSamples = 1;
|
||||
uint8_t mLayerCount = 1;
|
||||
|
||||
@@ -79,8 +82,8 @@ private:
|
||||
Attachment mStencilAttachment{};
|
||||
|
||||
// Cached descriptors for the render pass
|
||||
std::vector<wgpu::RenderPassColorAttachment> mColorAttachmentDesc;
|
||||
wgpu::RenderPassDepthStencilAttachment mDepthStencilAttachmentDesc{};
|
||||
std::vector<wgpu::RenderPassColorAttachment> mColorAttachmentDescriptors;
|
||||
wgpu::RenderPassDepthStencilAttachment mDepthStencilAttachmentDescriptor{};
|
||||
bool mHasDepthStencilAttachment = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ template<typename WebGPUPrintable>
|
||||
return out.str();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string adapterInfoToString(wgpu::AdapterInfo const& info) {
|
||||
[[nodiscard]] std::string adapterInfoToString(wgpu::AdapterInfo const& info) {
|
||||
std::stringstream out;
|
||||
out << "vendor (" << info.vendorID << ") '" << info.vendor
|
||||
<< "' device (" << info.deviceID << ") '" << info.device
|
||||
|
||||
@@ -110,6 +110,7 @@ void printSurfaceConfiguration(wgpu::SurfaceConfiguration const& config,
|
||||
return wgpu::TextureFormat::Depth24PlusStencil8;
|
||||
}
|
||||
} else {
|
||||
// other options: Depth16Unorm or Depth24Plus
|
||||
return wgpu::TextureFormat::Depth32Float;
|
||||
}
|
||||
}
|
||||
@@ -216,9 +217,10 @@ void initConfig(wgpu::SurfaceConfiguration& config, wgpu::Device const& device,
|
||||
}
|
||||
|
||||
[[nodiscard]] wgpu::TextureView createDepthTextureView(wgpu::Texture const& depthTexture,
|
||||
wgpu::TextureFormat const& depthFormat, bool const needStencil) {
|
||||
wgpu::TextureFormat depthFormat, bool needStencil) {
|
||||
wgpu::TextureViewDescriptor descriptor{
|
||||
.label = "depth_texture_view",
|
||||
.format = depthFormat,
|
||||
.dimension = wgpu::TextureViewDimension::e2D,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
@@ -229,16 +231,6 @@ void initConfig(wgpu::SurfaceConfiguration& config, wgpu::Device const& device,
|
||||
};
|
||||
if (needStencil) {
|
||||
descriptor.aspect = wgpu::TextureAspect::All;
|
||||
descriptor.format = depthFormat;
|
||||
} else {
|
||||
descriptor.aspect = wgpu::TextureAspect::DepthOnly;
|
||||
if (depthFormat == wgpu::TextureFormat::Depth32FloatStencil8) {
|
||||
descriptor.format = wgpu::TextureFormat::Depth32Float;
|
||||
} else if (depthFormat == wgpu::TextureFormat::Depth24PlusStencil8) {
|
||||
descriptor.format = wgpu::TextureFormat::Depth24Plus;
|
||||
} else {
|
||||
descriptor.format = depthFormat;
|
||||
}
|
||||
}
|
||||
wgpu::TextureView depthTextureView = depthTexture.CreateView(&descriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(depthTextureView) << "Failed to create depth texture view";
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "WebGPUTimerQuery.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
void WebGPUTimerQuery::beginTimeElapsedQuery() {
|
||||
mStatus->elapsedNanoseconds = 0;
|
||||
// Capture the timer query status via a weak_ptr because the WGPUTimerQuery could be destroyed
|
||||
// before the block executes.
|
||||
std::weak_ptr<WebGPUTimerQuery::Status> statusPtr = mStatus;
|
||||
|
||||
if (auto s = statusPtr.lock()) {
|
||||
s->elapsedNanoseconds = std::chrono::steady_clock::now().time_since_epoch().count();
|
||||
}
|
||||
}
|
||||
|
||||
void WebGPUTimerQuery::endTimeElapsedQuery() {
|
||||
// Capture the timer query status via a weak_ptr because the WGPUTimerQuery could be destroyed
|
||||
// before the block executes.
|
||||
if (mStatus->elapsedNanoseconds != 0) {
|
||||
std::weak_ptr<WebGPUTimerQuery::Status> statusPtr = mStatus;
|
||||
if (auto s = statusPtr.lock()) {
|
||||
s->previousElapsed = s->elapsedNanoseconds =
|
||||
std::chrono::steady_clock::now().time_since_epoch().count() -
|
||||
s->elapsedNanoseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WebGPUTimerQuery::getQueryResult(uint64_t* outElapsedTime) {
|
||||
if (mStatus->previousElapsed == 0) {
|
||||
return false;
|
||||
}
|
||||
if (outElapsedTime) {
|
||||
*outElapsedTime = mStatus->previousElapsed;
|
||||
mStatus->previousElapsed = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
+19
-12
@@ -14,30 +14,37 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUFENCE_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUFENCE_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace wgpu {
|
||||
class Queue;
|
||||
} // namespace wgpu
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class WebGPUFence final : public HwFence {
|
||||
class WebGPUTimerQuery : public HwTimerQuery {
|
||||
public:
|
||||
[[nodiscard]] FenceStatus getStatus();
|
||||
WebGPUTimerQuery()
|
||||
: mStatus(std::make_shared<Status>()) {}
|
||||
|
||||
void addMarkerToQueueState(wgpu::Queue const&);
|
||||
void beginTimeElapsedQuery();
|
||||
void endTimeElapsedQuery();
|
||||
bool getQueryResult(uint64_t* outElapsedTimeNanoseconds);
|
||||
|
||||
private:
|
||||
std::atomic<FenceStatus> mStatus{ FenceStatus::TIMEOUT_EXPIRED };
|
||||
struct Status {
|
||||
std::atomic<uint64_t> elapsedNanoseconds{ 0 };
|
||||
std::atomic<uint64_t> previousElapsed{ 0 };
|
||||
};
|
||||
|
||||
std::shared_ptr<Status> mStatus;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_WEBGPUFENCE_H
|
||||
#endif //TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||
@@ -481,7 +481,6 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
uint8_t fieldType = 0;
|
||||
uint8_t fieldFormat = 0;
|
||||
uint8_t fieldPrecision = 0;
|
||||
bool fieldUnfilterable = false;
|
||||
bool fieldMultisample = false;
|
||||
|
||||
if (!unflattener.read(&fieldName)) {
|
||||
@@ -504,10 +503,6 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unflattener.read(&fieldUnfilterable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unflattener.read(&fieldMultisample)) {
|
||||
return false;
|
||||
}
|
||||
@@ -517,7 +512,6 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
SamplerInterfaceBlock::Type(fieldType),
|
||||
SamplerInterfaceBlock::Format(fieldFormat),
|
||||
SamplerInterfaceBlock::Precision(fieldPrecision),
|
||||
fieldUnfilterable,
|
||||
fieldMultisample);
|
||||
}
|
||||
|
||||
|
||||
@@ -442,7 +442,7 @@ void FTexture::setImage(FEngine& engine, size_t const level,
|
||||
// TODO: PBD should have a p.depth (# layers to skip)
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
bpp * (pbdWidth - p.left) * (pbdHeight - p.top) * (pbdDepth - 0) >=
|
||||
bpp * width * height * depth)
|
||||
bpp * (width - xoffset) * (height - yoffset) * (depth - zoffset))
|
||||
<< "buffer overflow: (size=" << size_t(p.size) << ", stride=" << size_t(p.stride)
|
||||
<< ", left=" << unsigned(p.left) << ", top=" << unsigned(p.top)
|
||||
<< ") smaller than specified region "
|
||||
|
||||
@@ -162,7 +162,8 @@ VertexBuffer* VertexBuffer::Builder::build(Engine& engine) {
|
||||
FILAMENT_CHECK_PRECONDITION(mImpl->mBufferCount <= DOCUMENTED_MAX_VERTEX_BUFFER_COUNT)
|
||||
<< "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT;
|
||||
} else if (mImpl->mBufferCount > DOCUMENTED_MAX_VERTEX_BUFFER_COUNT) {
|
||||
LOG(WARNING) << "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT;
|
||||
utils::slog.w << "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT
|
||||
<< utils::io::endl;
|
||||
}
|
||||
|
||||
// Next we check if any unused buffer slots have been allocated. This helps prevent errors
|
||||
|
||||
@@ -8,8 +8,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : float,
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
precision: medium
|
||||
},
|
||||
{
|
||||
type : float4,
|
||||
|
||||
@@ -9,8 +9,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : float4,
|
||||
@@ -78,3 +77,4 @@ fragment {
|
||||
postProcess.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
precision: medium
|
||||
},
|
||||
{
|
||||
type : float2,
|
||||
|
||||
@@ -9,8 +9,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
precision: medium
|
||||
},
|
||||
{
|
||||
type : float2,
|
||||
|
||||
@@ -5,8 +5,7 @@ material {
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
multisample : true,
|
||||
unfilterable: true
|
||||
multisample : true
|
||||
}
|
||||
],
|
||||
outputs : [
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
}
|
||||
],
|
||||
variables : [
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,8 +4,7 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
precision: high
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.62.0"
|
||||
spec.version = "1.61.1"
|
||||
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.62.0/filament-v1.62.0-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.61.1/filament-v1.61.1-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -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 = 62;
|
||||
static constexpr size_t MATERIAL_VERSION = 61;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
|
||||
@@ -61,7 +61,6 @@ public:
|
||||
Type type; // type of this sampler
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool unfilterable; // whether the sampling should be unfiltered.
|
||||
bool multisample; // multisample capable
|
||||
ShaderStageFlags stages; // stages the sampler can be accessed from
|
||||
};
|
||||
@@ -84,7 +83,6 @@ public:
|
||||
Type type; // type of this sampler
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool unfilterable = false; // whether the sampling should be unfiltered.
|
||||
bool multisample = false; // multisample capable
|
||||
ShaderStageFlags stages =
|
||||
ShaderStageFlags::ALL_SHADER_STAGE_FLAGS; // shader stages using this sampler
|
||||
@@ -97,8 +95,7 @@ public:
|
||||
|
||||
// Add a sampler
|
||||
Builder& add(std::string_view samplerName, Binding binding, Type type, Format format,
|
||||
Precision precision = Precision::MEDIUM, bool unfilterable = false,
|
||||
bool multisample = false,
|
||||
Precision precision = Precision::MEDIUM, bool multisample = false,
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS) noexcept;
|
||||
|
||||
// Add multiple samplers
|
||||
|
||||
@@ -50,12 +50,12 @@ SamplerInterfaceBlock::Builder::stageFlags(backend::ShaderStageFlags stageFlags)
|
||||
}
|
||||
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(std::string_view samplerName,
|
||||
Binding binding, Type type, Format format, Precision precision, bool unfilterable,
|
||||
bool multisample, ShaderStageFlags stages) noexcept {
|
||||
Binding binding, Type type, Format format, Precision precision, bool multisample,
|
||||
ShaderStageFlags stages) noexcept {
|
||||
mEntries.push_back({
|
||||
{ samplerName.data(), samplerName.size() }, // name
|
||||
{}, // uniform name
|
||||
binding, type, format, precision, unfilterable, multisample, stages });
|
||||
{ samplerName.data(), samplerName.size() }, // name
|
||||
{ }, // uniform name
|
||||
binding, type, format, precision, multisample, stages });
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -65,9 +65,8 @@ SamplerInterfaceBlock SamplerInterfaceBlock::Builder::build() {
|
||||
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(
|
||||
std::initializer_list<ListEntry> list) noexcept {
|
||||
for (auto& e: list) {
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.unfilterable, e.multisample,
|
||||
e.stages);
|
||||
for (auto& e : list) {
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.multisample, e.stages);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -324,8 +323,8 @@ public:
|
||||
*/
|
||||
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format = SamplerFormat::FLOAT,
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT, bool unfilterable = false,
|
||||
bool multisample = false, const char* transformName = "",
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT, bool multisample = false,
|
||||
const char* transformName = "",
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS);
|
||||
|
||||
MaterialBuilder& buffer(filament::BufferInterfaceBlock bib);
|
||||
@@ -659,39 +658,17 @@ public:
|
||||
|
||||
// Sampler
|
||||
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p,
|
||||
bool unfilterable, bool ms, const char* tn, ShaderStageFlags s)
|
||||
: name(paramName),
|
||||
size(1),
|
||||
precision(p),
|
||||
samplerType(t),
|
||||
format(f),
|
||||
unfilterable(unfilterable),
|
||||
multisample(ms),
|
||||
transformName(tn),
|
||||
stages(s),
|
||||
parameterType(SAMPLER) {}
|
||||
bool ms, const char* tn, ShaderStageFlags s)
|
||||
: name(paramName), size(1), precision(p), samplerType(t), format(f),
|
||||
parameterType(SAMPLER), multisample(ms), transformName(tn), stages(s) { }
|
||||
|
||||
// Uniform
|
||||
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
|
||||
: name(paramName),
|
||||
size(typeSize),
|
||||
uniformType(t),
|
||||
precision(p),
|
||||
format{ 0 },
|
||||
unfilterable(false),
|
||||
multisample(false),
|
||||
parameterType(UNIFORM) {}
|
||||
: name(paramName), size(typeSize), uniformType(t), precision(p), parameterType(UNIFORM) { }
|
||||
|
||||
// Subpass
|
||||
Parameter(const char* paramName, SubpassType t, SamplerFormat f, ParameterPrecision p)
|
||||
: name(paramName),
|
||||
size(1),
|
||||
precision(p),
|
||||
subpassType(t),
|
||||
format(f),
|
||||
unfilterable(false),
|
||||
multisample(false),
|
||||
parameterType(SUBPASS) {}
|
||||
: name(paramName), size(1), precision(p), subpassType(t), format(f), parameterType(SUBPASS) { }
|
||||
|
||||
utils::CString name;
|
||||
size_t size;
|
||||
@@ -700,7 +677,6 @@ public:
|
||||
SamplerType samplerType;
|
||||
SubpassType subpassType;
|
||||
SamplerFormat format;
|
||||
bool unfilterable;
|
||||
bool multisample;
|
||||
utils::CString transformName;
|
||||
ShaderStageFlags stages;
|
||||
|
||||
@@ -300,19 +300,19 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, UniformType const
|
||||
return parameter(name, 1, type, precision);
|
||||
}
|
||||
|
||||
|
||||
MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format, ParameterPrecision precision, bool unfilterable, bool multisample,
|
||||
SamplerFormat format, ParameterPrecision precision, bool multisample,
|
||||
const char* transformName, ShaderStageFlags stages) {
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
!multisample || (format != SamplerFormat::SHADOW &&
|
||||
(samplerType == SamplerType::SAMPLER_2D ||
|
||||
samplerType == SamplerType::SAMPLER_2D_ARRAY)))
|
||||
FILAMENT_CHECK_PRECONDITION(!multisample ||
|
||||
(format != SamplerFormat::SHADOW &&
|
||||
(samplerType == SamplerType::SAMPLER_2D ||
|
||||
samplerType == SamplerType::SAMPLER_2D_ARRAY)))
|
||||
<< "multisample samplers only possible with SAMPLER_2D or SAMPLER_2D_ARRAY,"
|
||||
" as long as type is not SHADOW";
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT) << "Too many parameters";
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, unfilterable,
|
||||
multisample, transformName, stages };
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample, transformName, stages };
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -639,12 +639,10 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept {
|
||||
assert_invariant(!param.isSubpass());
|
||||
if (param.isSampler()) {
|
||||
sbb.add({ param.name.data(), param.name.size() }, binding, param.samplerType,
|
||||
param.format, param.precision, param.unfilterable, param.multisample,
|
||||
param.stages);
|
||||
param.format, param.precision, param.multisample, param.stages);
|
||||
if (!param.transformName.empty()) {
|
||||
ibb.add({ { { param.transformName.data(), param.transformName.size() },
|
||||
uint8_t(binding), 0, UniformType::MAT3, Precision::DEFAULT,
|
||||
FeatureLevel::FEATURE_LEVEL_0 } });
|
||||
ibb.add({{{ param.transformName.data(), param.transformName.size() }, uint8_t(binding),
|
||||
0, UniformType::MAT3, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }});
|
||||
}
|
||||
binding++;
|
||||
} else if (param.isUniform()) {
|
||||
|
||||
@@ -77,7 +77,6 @@ void MaterialSamplerInterfaceBlockChunk::flatten(Flattener& f) {
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.type));
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.format));
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.precision));
|
||||
f.writeBool(sInfo.unfilterable);
|
||||
f.writeBool(sInfo.multisample);
|
||||
}
|
||||
}
|
||||
@@ -231,11 +230,7 @@ void MaterialDescriptorSetLayoutChunk::flatten(Flattener& f) {
|
||||
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
|
||||
f.writeUint8(uint8_t(entry.stages));
|
||||
f.writeUint8(entry.binding);
|
||||
if (entry.unfilterable) {
|
||||
f.writeUint8(uint8_t(DescriptorFlags::UNFILTERABLE));
|
||||
} else {
|
||||
f.writeUint8(uint8_t(DescriptorFlags::NONE));
|
||||
}
|
||||
f.writeUint8(uint8_t(DescriptorFlags::NONE));
|
||||
f.writeUint16(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,6 @@ static bool printParametersInfo(ostream& text, const ChunkContainer& container)
|
||||
uint64_t fieldSize;
|
||||
uint8_t fieldType;
|
||||
uint8_t fieldPrecision;
|
||||
uint8_t fieldAssociatedSampler;
|
||||
|
||||
if (!uib.read(&fieldName)) {
|
||||
return false;
|
||||
@@ -214,10 +213,6 @@ static bool printParametersInfo(ostream& text, const ChunkContainer& container)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!uib.read(&fieldAssociatedSampler)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
text << " "
|
||||
<< setw(alignment) << fieldName.c_str()
|
||||
<< setw(shortAlignment) << toString(UniformType(fieldType))
|
||||
@@ -232,7 +227,6 @@ static bool printParametersInfo(ostream& text, const ChunkContainer& container)
|
||||
uint8_t fieldType;
|
||||
uint8_t fieldFormat;
|
||||
uint8_t fieldPrecision;
|
||||
bool fieldUnfilterable;
|
||||
bool fieldMultisample;
|
||||
|
||||
if (!sib.read(&fieldName)) {
|
||||
@@ -254,10 +248,6 @@ static bool printParametersInfo(ostream& text, const ChunkContainer& container)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sib.read(&fieldUnfilterable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sib.read(&fieldMultisample)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,14 +82,10 @@ class GoldenManager:
|
||||
self._git_exec('checkout main')
|
||||
self._git_exec('rebase')
|
||||
|
||||
def _git_exec(self, cmd, capture_output=False):
|
||||
return execute(f'git {cmd}', cwd=self._assets_dir(),
|
||||
capture_output=capture_output)
|
||||
def _git_exec(self, cmd):
|
||||
return execute(f'git {cmd}', cwd=self._assets_dir(), capture_output=False)
|
||||
|
||||
# Merge a local branch to the main branch.
|
||||
# - `tag` is a hash in the filament repo that this merge is associated with
|
||||
# - `push_to_remote` indicates that the local changes should be pushed to the
|
||||
# remote branch.
|
||||
# tag represent a hash in the filament repo that this merge is associated with
|
||||
def merge_to_main(self, branch, tag, push_to_remote=False):
|
||||
self.update()
|
||||
assets_dir = self._assets_dir()
|
||||
@@ -112,12 +108,6 @@ class GoldenManager:
|
||||
self._git_exec(f'push origin main')
|
||||
self.update()
|
||||
|
||||
# Create a branch on the local repo by copying the content from a source directory.
|
||||
# The change/diff is indicated by the 'updates' and the 'deletes' list,
|
||||
# - Files in 'updates' need to be present in both src_dir and in the repo.
|
||||
# - Files in 'deletes' only need to be present in the repo.
|
||||
# If caller wants the changes to be pushed to remote, set the `push_to_remote`
|
||||
# value to True.
|
||||
def source_from(self, src_dir, commit_msg, branch,
|
||||
updates=[], deletes=[], push_to_remote=False):
|
||||
assets_dir = self._assets_dir()
|
||||
@@ -149,16 +139,12 @@ class GoldenManager:
|
||||
self._git_exec(f'push -f origin {branch}')
|
||||
self.update()
|
||||
|
||||
# Download the content of a branch to a directory.
|
||||
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)
|
||||
code, o = self._git_exec(f'rev-parse HEAD', capture_output=True)
|
||||
with open(os.path.join(dest_dir, 'GIT_COMMIT_HASH'), 'w') as f:
|
||||
f.write(o)
|
||||
|
||||
# The main entry point will enable download content of a branch to a directory
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -185,13 +185,6 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
}
|
||||
}
|
||||
|
||||
const JsonishValue* unfilterableValue = jsonObject.getValue("unfilterable");
|
||||
if (unfilterableValue) {
|
||||
if (unfilterableValue->getType() != JsonishValue::BOOL) {
|
||||
std::cerr << "parameters: unfilterable must be a BOOL." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const JsonishValue* multiSampleValue = jsonObject.getValue("multisample");
|
||||
if (multiSampleValue) {
|
||||
if (multiSampleValue->getType() != JsonishValue::BOOL) {
|
||||
@@ -267,7 +260,6 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
auto precision = precisionValue ? Enums::toEnum<ParameterPrecision>(
|
||||
precisionValue->toJsonString()->getString()) : ParameterPrecision::DEFAULT;
|
||||
|
||||
auto unfilterable = unfilterableValue ? unfilterableValue->toJsonBool()->getBool() : false;
|
||||
auto multisample = multiSampleValue ? multiSampleValue->toJsonBool()->getBool() : false;
|
||||
|
||||
if (stages == ShaderStageFlags::NONE) {
|
||||
@@ -284,11 +276,10 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
return false;
|
||||
}
|
||||
auto transformName = transformNameValue->toJsonString()->getString();
|
||||
builder.parameter(nameString.c_str(), type, format, precision, unfilterable,
|
||||
multisample, transformName.c_str(), stages);
|
||||
builder.parameter(nameString.c_str(), type, format, precision, multisample,
|
||||
transformName.c_str(), stages);
|
||||
} else {
|
||||
builder.parameter(nameString.c_str(), type, format, precision, unfilterable,
|
||||
multisample, "", stages);
|
||||
builder.parameter(nameString.c_str(), type, format, precision, multisample, "", stages);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.62.0",
|
||||
"version": "1.61.1",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user