Compare commits

..
Author SHA1 Message Date
raviola 8e72e67bce Add fgdbg::Session.h, Pass.h, Resource.h dtos/models 2022-11-04 15:43:42 +11:00
raviola a0c486f608 pr feedback 2022-10-21 14:28:59 +11:00
raviola eb7447fd17 fgdbg client project structure + simple server connection 2022-10-20 13:48:48 +11:00
Fernando Raviola a870d01475 Add DebugServer for fgdbg with support for Websockets (#6169)
* Add dummy DebugServer for fgdbg with support for Websockets

* PR feedback
2022-10-20 11:00:13 +11:00
raviola 83e747b732 rename debug.server to debug.matdbg 2022-10-20 11:00:13 +11:00
raviola ca5cc32dc1 Use smart pointer 2022-10-20 11:00:13 +11:00
raviola 5c03e290c2 PR suggestions 2022-10-20 11:00:13 +11:00
Fernando RaviolaandMathias Agopian e4953ada3f Concat namespaces
Co-authored-by: Mathias Agopian <mathias@google.com>
2022-10-20 11:00:13 +11:00
Fernando Raviola 10022f983b Add FrameGraph debugger lib: package structure + CmakeLists.txt 2022-10-20 11:00:13 +11:00
106 changed files with 2199 additions and 4794 deletions
+16 -9
View File
@@ -337,23 +337,19 @@ endif()
# ==================================================================================================
# Release compiler flags
# ==================================================================================================
if (NOT MSVC AND NOT IOS)
# Omitting stack frame pointers prevents the generation of readable stack traces in crash reports on iOS
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer")
# These aren't compatible with -fembed-bitcode (and seem to have no effect on Apple platforms anyway)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
if (NOT IOS)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
endif()
endif()
# On Android RELEASE builds, we disable exceptions and RTTI to save some space (about 75 KiB
# saved by -fno-exception and 10 KiB saved by -fno-rtti).
if (ANDROID OR IOS OR WEBGL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-rtti")
if (ANDROID OR WEBGL)
# Omitting unwind info prevents the generation of readable stack traces in crash reports on iOS
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-unwind-tables -fno-asynchronous-unwind-tables")
endif()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
endif()
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
@@ -463,6 +459,13 @@ else()
option(FILAMENT_ENABLE_MATDBG "Enable the material debugger" OFF)
endif()
# By default, link in fgdbg for Desktop + Debug
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND IS_HOST_PLATFORM)
option(FILAMENT_ENABLE_FGDBG "Enable the framegraph debugger" ON)
else()
option(FILAMENT_ENABLE_FGDBG "Enable the framegraph debugger" OFF)
endif()
# Only optimize materials in Release mode (so error message lines match the source code)
if (CMAKE_BUILD_TYPE MATCHES Release)
option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" OFF)
@@ -689,6 +692,10 @@ if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
if (FILAMENT_ENABLE_MATDBG OR IS_HOST_PLATFORM)
add_subdirectory(${LIBRARIES}/matdbg)
endif()
if (FILAMENT_ENABLE_FGDBG OR IS_HOST_PLATFORM)
add_subdirectory(${LIBRARIES}/fgdbg)
endif()
endif()
if (FILAMENT_SUPPORTS_VULKAN)
+3 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.28.2'
implementation 'com.google.android.filament:filament-android:1.28.0'
}
```
@@ -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:
```
pod 'Filament', '~> 1.28.2'
pod 'Filament', '~> 1.28.0'
```
### Snapshots
@@ -313,6 +313,7 @@ and tools.
- `bluegl`: OpenGL bindings for macOS, Linux and Windows
- `bluevk`: Vulkan bindings for macOS, Linux, Windows and Android
- `camutils`: Camera manipulation utilities
- `fgdbg`: Frame Graph inspector and debugger (debug builds only)
- `filabridge`: Library shared by the Filament engine and host tools
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
-11
View File
@@ -5,17 +5,6 @@ A new header is inserted each time a *tag* is created.
## main branch
- gltfio: calculate primitive's AABB correctly.
- gltfio: recompute bounding boxes with morph targets
- engine: add missing getters on `MaterialInstance`
## v1.28.3
- backend: add support for GGP platform
- engine: primitives with `CullingMode::FRONT_AND_BACK` are now skipped.
## v1.28.2
- gltfio: support EXT_meshopt_compression
- release packaging: fixed location of default IBL file
@@ -452,84 +452,3 @@ Java_com_google_android_filament_MaterialInstance_nDuplicate(JNIEnv* env, jclass
}
return (jlong)mi;
}
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_MaterialInstance_nGetMaskThreshold(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nGetMaskThreshold()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->getMaskThreshold();
}
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingVariance(JNIEnv* env,
jclass clazz, jlong nativeMaterialInstance) {
// TODO: implement nGetSpecularAntiAliasingVariance()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->getSpecularAntiAliasingVariance();
}
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingThreshold(JNIEnv* env,
jclass clazz, jlong nativeMaterialInstance) {
// TODO: implement nGetSpecularAntiAliasingThreshold()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->getSpecularAntiAliasingThreshold();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsDoubleSided(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nIsDoubleSided()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isDoubleSided();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MaterialInstance_nGetCullingMode(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nGetCullingMode()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return (jint)instance->getCullingMode();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nIsColorWriteEnabled()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isColorWriteEnabled();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsDepthWriteEnabled(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nIsDepthWriteEnabled()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isDepthWriteEnabled();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsStencilWriteEnabled(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nIsStencilWriteEnabled()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isStencilWriteEnabled();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsDepthCullingEnabled(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
// TODO: implement nIsDepthCullingEnabled()
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isDepthCullingEnabled();
}
@@ -24,7 +24,6 @@ import com.google.android.filament.proguard.UsedByNative;
@UsedByNative("AssetLoader.cpp")
public class MaterialInstance {
private static final Material.CullingMode[] sCullingModeValues = Material.CullingMode.values();
private Material mMaterial;
private String mName;
private long mNativeObject;
@@ -474,14 +473,6 @@ public class MaterialInstance {
nSetMaskThreshold(getNativeObject(), threshold);
}
/**
* Gets the minimum alpha value a fragment must have to not be discarded when the blend
* mode is MASKED
*/
public float getMaskThreshold() {
return nGetMaskThreshold(getNativeObject());
}
/**
* Sets the screen space variance of the filter kernel used when applying specular
* anti-aliasing. The default value is set to 0.15. The specified value should be between
@@ -495,14 +486,6 @@ public class MaterialInstance {
nSetSpecularAntiAliasingVariance(getNativeObject(), variance);
}
/**
* Gets the screen space variance of the filter kernel used when applying specular
* anti-aliasing.
*/
public float getSpecularAntiAliasingVariance() {
return nGetSpecularAntiAliasingVariance(getNativeObject());
}
/**
* Sets the clamping threshold used to suppress estimation errors when applying specular
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
@@ -516,14 +499,6 @@ public class MaterialInstance {
nSetSpecularAntiAliasingThreshold(getNativeObject(), threshold);
}
/**
* Gets the clamping threshold used to suppress estimation errors when applying specular
* anti-aliasing.
*/
public float getSpecularAntiAliasingThreshold() {
return nGetSpecularAntiAliasingThreshold(getNativeObject());
}
/**
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
@@ -537,14 +512,6 @@ public class MaterialInstance {
nSetDoubleSided(getNativeObject(), doubleSided);
}
/**
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
* capability.
*/
public boolean isDoubleSided() {
return nIsDoubleSided(getNativeObject());
}
/**
* Overrides the default triangle culling state that was set on the material.
*
@@ -552,18 +519,10 @@ public class MaterialInstance {
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
* Rasterization: culling</a>
*/
public void setCullingMode(@NonNull Material.CullingMode mode) {
public void setCullingMode(Material.CullingMode mode) {
nSetCullingMode(getNativeObject(), mode.ordinal());
}
/**
* Returns the face culling mode.
*/
@NonNull
public Material.CullingMode getCullingMode() {
return sCullingModeValues[nGetCullingMode(getNativeObject())];
}
/**
* Overrides the default color-buffer write state that was set on the material.
*
@@ -575,13 +534,6 @@ public class MaterialInstance {
nSetColorWrite(getNativeObject(), enable);
}
/**
* Returns whether color write is enabled.
*/
public boolean isColorWriteEnabled() {
return nIsColorWriteEnabled(getNativeObject());
}
/**
* Overrides the default depth-buffer write state that was set on the material.
*
@@ -593,27 +545,10 @@ public class MaterialInstance {
nSetDepthWrite(getNativeObject(), enable);
}
/**
* Returns whether depth write is enabled.
*/
public boolean isDepthWriteEnabled() {
return nIsDepthWriteEnabled(getNativeObject());
}
/**
* Enables or Disable stencil writes
*/
public void setStencilWrite(boolean enable) {
nSetStencilWrite(getNativeObject(), enable);
}
/**
* Returns whether stencil write is enabled.
*/
public boolean isStencilWriteEnabled() {
return nIsStencilWriteEnabled(getNativeObject());
}
/**
* Overrides the default depth testing state that was set on the material.
*
@@ -625,13 +560,6 @@ public class MaterialInstance {
nSetDepthCulling(getNativeObject(), enable);
}
/**
* Returns whether depth culling is enabled.
*/
public boolean isDepthCullingEnabled() {
return nIsDepthCullingEnabled(getNativeObject());
}
/**
* Sets the stencil comparison function (default is {@link TextureSampler.CompareFunction#ALWAYS}).
*
@@ -928,15 +856,4 @@ public class MaterialInstance {
private static native long nGetMaterial(long nativeMaterialInstance);
private static native long nDuplicate(long otherNativeMaterialInstance, String name);
private static native float nGetMaskThreshold(long nativeMaterialInstance);
private static native float nGetSpecularAntiAliasingVariance(long nativeMaterialInstance);
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance);
private static native boolean nIsDoubleSided(long nativeMaterialInstance);
private static native int nGetCullingMode(long nativeMaterialInstance);
private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance);
}
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.28.2
VERSION_NAME=1.28.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+6
View File
@@ -162,6 +162,8 @@ EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
MATDBG_GRADLE_OPTION=""
FGDBG_OPTION="-DFILAMENT_ENABLE_FGDBG=OFF"
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -221,6 +223,7 @@ function build_desktop_target {
${SWIFTSHADER_OPTION} \
${EGL_ON_LINUX_OPTION} \
${MATDBG_OPTION} \
${FGDBG_OPTION} \
${deployment_target} \
${architectures} \
../..
@@ -347,6 +350,7 @@ function build_android_target {
-DCMAKE_INSTALL_PREFIX="../android-${lc_target}/filament" \
-DCMAKE_TOOLCHAIN_FILE="../../build/toolchain-${arch}-linux-android.cmake" \
${MATDBG_OPTION} \
${FGDBG_OPTION} \
${VULKAN_ANDROID_OPTION} \
../..
fi
@@ -576,6 +580,7 @@ function build_ios_target {
-DIOS=1 \
-DCMAKE_TOOLCHAIN_FILE=../../third_party/clang/iOS.cmake \
${MATDBG_OPTION} \
${FGDBG_OPTION} \
../..
fi
@@ -760,6 +765,7 @@ while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
PRINT_MATDBG_HELP=true
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_DISABLE_MATOPT=ON, -DFILAMENT_BUILD_FILAMAT=ON"
MATDBG_GRADLE_OPTION="-Pcom.google.android.filament.matdbg"
FGDBG_OPTION="-DFILAMENT_ENABLE_FGDBG=ON"
;;
f)
ISSUE_CMAKE_ALWAYS=true
-99
View File
@@ -1,99 +0,0 @@
#!/usr/bin/env bash
set -e
function print_help {
local self_name=$(basename "$0")
echo "This tool verifies that every Metal shader in the given Filament material file(s) successfully compiles."
echo "Requires the matinfo tool and xcrun to be on the system PATH."
echo ""
echo "Usage:"
echo " $self_name [options] [<material> ...]"
echo ""
echo "Options:"
echo " -h"
echo " Print this help message."
echo " -w"
echo " Pass the -w flag to the Metal compiler, to disable warnings."
echo ""
}
COMP_FLAGS=""
while getopts ":hw" opt; do
case ${opt} in
h)
print_help
exit 1
;;
w)
COMP_FLAGS="${COMP_FLAGS} -w"
;;
esac
done
shift $((OPTIND - 1))
if [[ "$#" == "0" ]]; then
print_help
exit 1
fi
# Make sure matinfo and xcrun are available.
if [[ ! $(command -v matinfo) ]]; then
echo "Error: matinfo not on PATH."
exit 1
fi
if [[ ! $(command -v xcrun) ]]; then
echo "Error: xcrun not on PATH."
exit 1
fi
function check_material {
local material="$1"
tmpdir="$(mktemp -d /tmp/check_metal_shaders.XXXXX)"
# First check that the material is valid.
if [[ ! $(matinfo "${material}") ]]; then
echo "Invalid material file: ${material}"
exit 1
fi
echo "Checking that Metal shaders compile: ${material}"
set +e
local i=0
while true; do
# The file must have a .metal extension.
metalFile="${tmpdir}/${i}.metal"
# Extract shader i. matinfo will return a non-zero exit code if the shader doesn't exist,
# which means we're finished with this material.
matinfo --print-metal=${i} "${material}" > "${metalFile}" 2> /dev/null
if [[ "$?" -ne 0 ]]; then
break
fi
echo "Testing Metal shader ${i}"
# Attempt to compile the Metal shader.
xcrun -sdk macosx metal ${COMP_FLAGS} -c "${metalFile}" -o /dev/null
if [[ "$?" -ne 0 ]]; then
echo "Error compiling Metal shader: ${metalFile}"
exit 1
fi
((i++))
done
set -e
rm -r "${tmpdir}"
}
for material in "$@"
do
check_material "${material}"
done
+1 -1
View File
File diff suppressed because one or more lines are too long
+12 -11
View File
@@ -1432,13 +1432,12 @@ non-shader data.
</p><dl><table><tbody><tr valign="top"><td><dt>Type</dt></td><td><dd><p> <code>number</code>
</p></dd></td></tr><tr valign="top"><td><dt>Value</dt></td><td><dd><p> An integer value, either 1, 2 or 3. Defaults to 1.
</p></dd></td></tr><tr valign="top"><td><dt>Value</dt></td><td><dd><p> An integer value, either 1 or 2. Defaults to 1.
</p></dd></td></tr></tbody></table></dl><div class="table">
<table class="table"><tbody><tr><th style="text-align:left"> Feature Level </th><th style="text-align:left"> Guaranteed features </th></tr>
<tr><td style="text-align:left"> 1 </td><td style="text-align:left"> 9 textures per material </td></tr>
<tr><td style="text-align:left"> 2 </td><td style="text-align:left"> 9 textures per material, cubemap arrays, ESSL 3.10 </td></tr>
<tr><td style="text-align:left"> 3 </td><td style="text-align:left"> 12 textures per material, cubemap arrays, ESSL 3.10 </td></tr>
<tr><td style="text-align:left"> 2 </td><td style="text-align:left"> 12 textures per material, cubemap arrays, ESSL 3.10 </td></tr>
</tbody></table><center><div class="tablecaption"><a class="target" name="table_featurelevels">&nbsp;</a><b style="font-style:normal;">Table&nbsp;13:</b> Feature levels</div></center></div>
<p></p><p>
@@ -2037,21 +2036,23 @@ and sorting issues are minimized or eliminated</span></center></div></center>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
</p></dd><dt>Description</dt><dd><p> Enables two-sided rendering and its capability to be toggled at run time. When set to <code>true</code>,
<code>culling</code> is automatically set to <code>none</code>; if the triangle is back-facing, the triangle's
normal is flipped to become front-facing. When explicitly set to <code>false</code>, this allows the
double-sidedness to be toggled at run time.
</p></dd><dt>Description</dt><dd><p> Only available in the <code>unlit</code> shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> name : <span class="hljs-string">"Double sided material"</span>,</span>
<span class="line"> shadingModel : lit,</span>
<span class="line"> doubleSided : <span class="hljs-literal">true</span></span>
<span class="line"> name : <span class="hljs-string">"Invisible shadow plane"</span>,</span>
<span class="line"> shadingModel : unlit,</span>
<span class="line"> shadowMultiplier : <span class="hljs-literal">true</span>,</span>
<span class="line"> blending : transparent</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">fragment {</span>
<span class="line"> void material(inout MaterialInputs material) {</span>
<span class="line"> prepareMaterial(material);</span>
<span class="line"> material.baseColor = materialParams.albedo;</span>
<span class="line"> <span class="hljs-comment">// baseColor defines the color and opacity of the final shadow</span></span>
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:reflections">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:reflections">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3>Lighting: reflections</h3>
+10 -8
View File
@@ -1582,22 +1582,24 @@ Value
: `true` or `false`. Defaults to `false`.
Description
: Enables two-sided rendering and its capability to be toggled at run time. When set to `true`,
`culling` is automatically set to `none`; if the triangle is back-facing, the triangle's
normal is flipped to become front-facing. When explicitly set to `false`, this allows the
double-sidedness to be toggled at run time.
: Only available in the `unlit` shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
name : "Double sided material",
shadingModel : lit,
doubleSided : true
name : "Invisible shadow plane",
shadingModel : unlit,
shadowMultiplier : true,
blending : transparent
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = materialParams.albedo;
// baseColor defines the color and opacity of the final shadow
material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+7 -3
View File
@@ -48,7 +48,6 @@ set(PUBLIC_HDRS
)
set(SRCS
src/AtlasAllocator.cpp
src/Box.cpp
src/BufferObject.cpp
src/Camera.cpp
@@ -73,7 +72,6 @@ set(SRCS
src/MaterialParser.cpp
src/MorphTargetBuffer.cpp
src/PerViewUniforms.cpp
src/PerShadowMapUniforms.cpp
src/PostProcessManager.cpp
src/RenderPass.cpp
src/RenderPrimitive.cpp
@@ -147,7 +145,6 @@ set(PRIVATE_HDRS
src/Intersections.h
src/MaterialParser.h
src/PerViewUniforms.h
src/PerShadowMapUniforms.h
src/PIDController.h
src/PostProcessManager.h
src/RendererUtils.h
@@ -540,6 +537,13 @@ target_link_libraries(${TARGET} PUBLIC filaflat)
target_link_libraries(${TARGET} PUBLIC filabridge)
target_link_libraries(${TARGET} PUBLIC ibl-lite)
if (FILAMENT_ENABLE_FGDBG)
target_link_libraries(${TARGET} PUBLIC fgdbg)
add_definitions(-DFILAMENT_ENABLE_FGDBG=1)
else()
add_definitions(-DFILAMENT_ENABLE_FGDBG=0)
endif()
if (FILAMENT_ENABLE_MATDBG)
target_link_libraries(${TARGET} PUBLIC matdbg)
add_definitions(-DFILAMENT_ENABLE_MATDBG=1)
@@ -220,7 +220,8 @@ enum class PrimitiveType : uint8_t {
LINES = 1, //!< lines
LINE_STRIP = 3, //!< line strip
TRIANGLES = 4, //!< triangles
TRIANGLE_STRIP = 5 //!< triangle strip
TRIANGLE_STRIP = 5, //!< triangle strip
NONE = 0xFF
};
/**
+2 -6
View File
@@ -42,9 +42,7 @@
#include "vulkan/PlatformVkCocoa.h"
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
#include "vulkan/PlatformVkLinuxGGP.h"
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
#if defined(FILAMENT_SUPPORTS_WAYLAND)
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinuxWayland.h"
#endif
@@ -122,9 +120,7 @@ DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
#elif defined(IOS)
return new PlatformVkCocoaTouch();
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
return new PlatformVkLinuxGGP();
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
#if defined(FILAMENT_SUPPORTS_WAYLAND)
return new PlatformVkLinuxWayland();
#elif defined(FILAMENT_SUPPORTS_X11)
return new PlatformVkLinuxX11();
@@ -91,14 +91,12 @@ blitterFrag(VertexOut in [[stage_in]],
{
FragmentOut out = {};
#if defined(BLIT_COLOR) || defined(BLIT_DEPTH)
// These coordinates match the Vulkan vkCmdBlitImage spec:
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdBlitImage.html
float2 uvbase = in.position.xy; // unnormalized coordinates at center of texel: (1.5, 2.5, etc)
float2 uvoffset = uvbase - args->dstOffset;
float2 uvscaled = uvoffset * args->scale;
float2 uv = uvscaled + args->srcOffset;
#endif
#ifdef BLIT_COLOR
#ifdef MSAA_COLOR_SOURCE
@@ -64,7 +64,6 @@ struct MetalContext {
// Supported features.
bool supportsTextureSwizzling = false;
bool supportsAutoDepthResolve = false;
bool supportsMemorylessRenderTargets = false;
uint8_t maxColorRenderTargets = 4;
struct {
+2 -9
View File
@@ -92,13 +92,6 @@ MetalDriver::MetalDriver(MetalPlatform* platform, const Platform::DriverConfig&
mContext->highestSupportedGpuFamily.mac >= 2; // newer macOS GPUs
}
// In order to support resolve store action on depth attachment, the GPU needs to support it.
// Note that support for depth resolve implies support for stencil resolve using .sample0 resolve filter.
// (Other resolve filters are supported starting .apple5 and .mac2 families).
mContext->supportsAutoDepthResolve =
mContext->highestSupportedGpuFamily.apple >= 3 ||
mContext->highestSupportedGpuFamily.mac >= 2;
// In order to support memoryless render targets, an Apple GPU is needed.
// Available starting macOS 11.0, the first version to run on Apple GPUs.
// On iOS, it's available on all OS versions.
@@ -703,7 +696,7 @@ bool MetalDriver::isFrameTimeSupported() {
}
bool MetalDriver::isAutoDepthResolveSupported() {
return mContext->supportsAutoDepthResolve;
return true;
}
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
@@ -900,7 +893,7 @@ void MetalDriver::updateSamplerGroup(Handle<HwSamplerGroup> sbh, BufferDescripto
auto& encoderCache = mContext->argumentEncoderCache;
id<MTLArgumentEncoder> encoder =
encoderCache.getOrCreateState(ArgumentEncoderState(std::move(textureTypes)));
sb->reset(getPendingCommandBuffer(mContext), encoder, mContext->device);
sb->reset(getPendingCommandBuffer(mContext), encoder);
// In a perfect world, all the MTLTexture bindings would be known at updateSamplerGroup time.
// However, there are two special cases preventing this:
+2
View File
@@ -337,6 +337,8 @@ constexpr inline MTLPrimitiveType getMetalPrimitiveType(PrimitiveType type) noex
case PrimitiveType::LINE_STRIP: return MTLPrimitiveTypeLineStrip;
case PrimitiveType::TRIANGLES: return MTLPrimitiveTypeTriangle;
case PrimitiveType::TRIANGLE_STRIP: return MTLPrimitiveTypeTriangleStrip;
case PrimitiveType::NONE:
ASSERT_POSTCONDITION(false, "NONE is not a valid primitive type.");
}
}
+1 -1
View File
@@ -305,7 +305,7 @@ public:
// the texture types have changed.
// Mutate re-encodes the current set of samplers/textures into the new argument
// buffer.
void reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e, id<MTLDevice> device);
void reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e);
void mutate(id<MTLCommandBuffer> cmdBuffer);
id<MTLBuffer> getArgumentBuffer() const {
+2 -8
View File
@@ -828,8 +828,7 @@ void MetalSamplerGroup::finalize() {
finalized = true;
}
void MetalSamplerGroup::reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e,
id<MTLDevice> device) {
void MetalSamplerGroup::reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e) {
encoder = e;
// The number of slots in the ring buffer we use to manage argument buffer allocations.
@@ -847,7 +846,7 @@ void MetalSamplerGroup::reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEnco
// Chances are, even though the MTLArgumentEncoder might change, the required size and alignment
// probably won't. So we can re-use the previous ring buffer.
if (UTILS_UNLIKELY(!argBuffer || !argBuffer->canAccomodateLayout(argBufferLayout))) {
argBuffer = std::make_unique<MetalRingBuffer>(device, MTLResourceStorageModeShared,
argBuffer = std::make_unique<MetalRingBuffer>(encoder.device, MTLResourceStorageModeShared,
argBufferLayout, METAL_ARGUMENT_BUFFER_SLOTS);
} else {
argBuffer->createNewAllocation(cmdBuffer);
@@ -1054,7 +1053,6 @@ void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* desc
descriptor.depthAttachment.slice = 0;
const bool discard = any(discardFlags & TargetBufferFlags::DEPTH);
if (!discard) {
assert_invariant(context->supportsAutoDepthResolve);
descriptor.depthAttachment.resolveTexture = depthAttachment.getTexture();
descriptor.depthAttachment.resolveLevel = depthAttachment.level;
descriptor.depthAttachment.resolveSlice = depthAttachment.layer;
@@ -1087,14 +1085,10 @@ void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* desc
descriptor.stencilAttachment.slice = 0;
const bool discard = any(discardFlags & TargetBufferFlags::STENCIL);
if (!discard) {
assert_invariant(context->supportsAutoDepthResolve);
descriptor.stencilAttachment.resolveTexture = stencilAttachment.getTexture();
descriptor.stencilAttachment.resolveLevel = stencilAttachment.level;
descriptor.stencilAttachment.resolveSlice = stencilAttachment.layer;
descriptor.stencilAttachment.storeAction = MTLStoreActionMultisampleResolve;
if (@available(iOS 12.0, *)) {
descriptor.stencilAttachment.stencilResolveFilter = MTLMultisampleStencilResolveFilterSample0;
}
}
}
}
+1
View File
@@ -54,6 +54,7 @@ io::ostream& operator<<(io::ostream& out, PrimitiveType type) {
CASE(PrimitiveType, LINES)
CASE(PrimitiveType, LINE_STRIP)
CASE(PrimitiveType, POINTS)
CASE(PrimitiveType, NONE)
}
return out;
}
@@ -1,74 +0,0 @@
/*
* Copyright (C) 2018 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 "vulkan/PlatformVkLinuxGGP.h"
#include <bluevk/BlueVK.h>
#if defined(FILAMENT_SUPPORTS_GGP)
#include <ggp_c/ggp.h>
#endif
#include <utils/Panic.h>
#include "VulkanDriverFactory.h"
using namespace bluevk;
namespace filament::backend {
Driver* PlatformVkLinuxGGP::createDriver(
void* const sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
#if defined(FILAMENT_SUPPORTS_GGP)
ASSERT_PRECONDITION(sharedContext == nullptr,
"Vulkan does not support shared contexts.");
const char* requiredInstanceExtensions[] = {
VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME};
return VulkanDriverFactory::create(this, requiredInstanceExtensions,
sizeof(requiredInstanceExtensions) /
sizeof(requiredInstanceExtensions[0]),
driverConfig);
#else
PANIC_PRECONDITION("Filament does not support GGP.");
return nullptr;
#endif
}
void* PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept {
#if defined(FILAMENT_SUPPORTS_GGP)
VkStreamDescriptorSurfaceCreateInfoGGP surface_create_info = {
VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP};
surface_create_info.streamDescriptor = kGgpPrimaryStreamDescriptor;
PFN_vkCreateStreamDescriptorSurfaceGGP fpCreateStreamDescriptorSurfaceGGP =
reinterpret_cast<PFN_vkCreateStreamDescriptorSurfaceGGP>(
vkGetInstanceProcAddr(static_cast<VkInstance>(instance),
"vkCreateStreamDescriptorSurfaceGGP"));
ASSERT_PRECONDITION(fpCreateStreamDescriptorSurfaceGGP != nullptr,
"Error getting VkInstance "
"function vkCreateStreamDescriptorSurfaceGGP");
VkSurfaceKHR surface = nullptr;
VkResult res = fpCreateStreamDescriptorSurfaceGGP(
static_cast<VkInstance>(instance), &surface_create_info, nullptr,
&surface);
ASSERT_PRECONDITION(res == VK_SUCCESS, "Error in vulkan: %d", res);
return surface;
#else
PANIC_PRECONDITION("Filament does not support GGP.");
return nullptr;
#endif
}
} // namespace filament::backend
@@ -1,41 +0,0 @@
/*
* Copyright (C) 2018 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.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKAN_PLATFORM_VK_LINUX_GGP_H
#define TNT_FILAMENT_BACKEND_VULKAN_PLATFORM_VK_LINUX_GGP_H
#include <backend/DriverEnums.h>
#include <stdint.h>
#include "VulkanPlatform.h"
namespace filament::backend {
class PlatformVkLinuxGGP final : public VulkanPlatform {
public:
Driver* createDriver(
void* const sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
void* createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept override;
int getOSVersion() const noexcept override { return 0; }
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_VULKAN_PLATFORM_VK_LINUX_GGP_H
@@ -263,6 +263,7 @@ VulkanBufferObject::VulkanBufferObject(VulkanContext& context, VulkanStagePool&
void VulkanRenderPrimitive::setPrimitiveType(PrimitiveType pt) {
this->type = pt;
switch (pt) {
case PrimitiveType::NONE:
case PrimitiveType::POINTS:
primitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
break;
+9 -76
View File
@@ -11,7 +11,7 @@
</style>
**Vulkan Backend**
*Last updated: 26 October 2022*
*Last updated: 11 June 2021*
![](../../docs/images/filament_logo.png)
@@ -47,7 +47,7 @@ single `VkDevice` and `VkInstance`.
* | | | | *
* |------------------------------------------| |-----------------------------------------| *
* | | | | *
* | Helpers VulkanContext | | VulkanTexture VulkanTexture | *
* | Helpers VulkanContext | | SwapContext SwapContext | *
* | .--------------. .---------------. | | .----------------+----------------. | *
* | | PipelineCache| | VkDevice | | | | VkImage | VkImage | | *
* | +--------------+ | VkInstance | | | | VkImageView | VkImageView | | *
@@ -91,14 +91,13 @@ that are defined in `DriverBase.h`.
Most of the handle types do not contain much logic, but they often do more than mere wrapping of
Vk objects. Notably, `VulkanRenderTarget` does not have a straightforward mapping to any one Vk
object. See its class comment for details. Also, `VulkanTexture` and `VulkanSwapChain` have their
own cpps file because of complexity around layouts and subresources.
object. See its class comment for details.
VulkanProgram
: Descends from `HwProgram`, owns a pair of `VkShaderModule`.
VulkanRenderTarget
: Descends from `HwRenderTarget`, contains references to `VulkanTexture` objects.
: Descends from `HwRenderTarget`, contains references to `VkImage` objects.
VulkanSwapChain
: Descends from `HwSwapChain`, has a reference to `VkSurfaceKHR` and `VkSwapchainKHR`.
@@ -128,16 +127,14 @@ they do follow a common set of conventions. For example, most of them implement
that is called once per frame to free unused objects.
VulkanPipelineCache
: Cache of VkDescriptorSet, VkPipeline, and VkPipelineLayout.
: Cache of VkDescriptorSet and VkPipeline.
VulkanDisposer
: Holds reference counts to Vulkan objects in order to defer their destruction.
VulkanFboCache
: Cache of VkRenderPass and VkFramebuffer. Contains weak references to VkImage handles, but does not
own any pixel data. The cache key for render passes is quite complex because it needs to include
image layout information in a compact way. For details see the comments in the `RenderPassKey`
declaration.
own any pixel data.
VulkanStagePool
: Pool of VkBuffer objects that can be memory mapped (shared between host and device).
@@ -152,71 +149,6 @@ no subfolders. All backend-specific types and functions live directly in the `fi
namespace, and we simply prefix our names with "Vulkan" when necessary to avoid ambiguation with
OpenGL.
# Image Layout Strategy
Adhering to a coherent strategy for image layout transitions is crucial. Without this, validation
errors (and actual black screens with some GPU vendors) occur far too easily and can feel like
whack-a-mole.
Vulkan provides several mechanisms for transitioning layout (render passes, barriers) so the
strategy outlined below specifies which mechanism should be used in various scenarios.
The current image layouts are tracked at the subresource level in `VulkanTexture` using a
specialized STL-ish container that we designed for this purpose:
[RangeMap](https://github.com/google/filament/blob/main/libs/utils/include/utils/RangeMap.h).
In the past we tried to avoid tracking since it theoritically duplicates state that exists in the
GPU vendor's driver. However in practice this was impossible to manage, because complex logic was
required to deduce the current layout. Also, tracking lets us use `assert_invariant` in many places
to ensure that the behavior described in this document is implemented properly. It is much easier
to catch errors with asserts than with validation.
As of this writing, the current rules are:
(1) **Read-Only Color Textures**
These should be created in an UNDEFINED state and stay that way until data gets uploaded into them,
at which point the appropriate subresources are transitioned to TRANSFER_DST_OPTIMAL for the upload,
then to SHADER_READ_ONLY_OPTIMAL, both times using a barrier. Note that a subresource might be
updated several times; each time it undergoes these two transitions.
If a shader samples from a texture whose mipmaps are only partially loaded, we might see validation
warnings about how some subresources are in an UNDEFINED layout. However if we are properly using
the `setMinMaxLevels` driver API, then the Vulkan backend will not bind those particular
subresources, so validation should not complain.
(2) **Writeable Color Textures**
During construction of the HwTexture, these are transitioned to GENERAL using a barrier.
GENERAL layout is not recommended by AMD best practices but in our case we wish to avoid thrashing
the layout between COLOR_ATTACHMENT_OPTIMAL and SHADER_READ_ONLY_OPTIMAL for post-processing
effects. Moreover we do not have a priori knowledge about blitting and read pixels usage.
(3) **Depth Textures**
During construction of the HwTexture, these are transitioned to GENERAL using a barrier.
Note that some post-processing passes (e.g. SSAO) sample from the depth buffer while also enabling
depth testing. Using GENERAL makes this legal.
(4) **Swap Chain Textures**
During construction, these are transitioned to GENERAL using a barrier. They are then transitioned
to PRESENT at the end of the frame using a barrier, and transitioned back to GENERAL using the first
render pass of the frame.
Note that we transition to PRESENT using a barrier, but with some GPU vendors it might be preferable
to transition them using the last render pass. However we have no way of knowing ahead of time which
pass is last.
Note that Filament allows swap chains to be used as blit targets and blit sources (e.g. for
ReadPixels). Using GENERAL makes this easier to manage.
(5) **Headless Swap Chain Textures**
These follow the same rules as writeable color texture and depth textures.
# VulkanPipelineCache
Uniforms, samplers, and shaders are not directly bindable in Vulkan; instead they are bound through
@@ -229,6 +161,8 @@ public methods. See its header file for details.
The pipeline cache also manages the *layout objects*, which constrain the number of uniform buffers
and samplers that can be bound simultaneously (see `VkDescriptorSetLayout` and `VkPipelineLayout`).
Here we take advantage of Filament's opinionated shading model in order to keep things simple, which
allows us to create only one layout for the entire lifetime of the app.
# Memory Allocation
@@ -262,8 +196,7 @@ Here we list some of the most significant issues and to-be-done items for the Vu
- Improve the UBO strategy
- Currently we use staging buffers and perform lots of copies (host-to-host, then host-to-device)
- Consider an approach similar to MetalDriver, which effectively implements double-buffering
using a pool of shared mem buffers
- Consider an approach similar to MetalDriver, which effectively implements double-buffering using a pool of shared mem buffers
- Consider using subpasses for the depth prepass
- We lazily create pipeline objects
1. This is notoriously slow in Vulkan
@@ -277,12 +277,6 @@ public:
*/
void setMaskThreshold(float threshold) noexcept;
/**
* Gets the minimum alpha value a fragment must have to not be discarded when the blend
* mode is MASKED
*/
float getMaskThreshold() const noexcept;
/**
* Sets the screen space variance of the filter kernel used when applying specular
* anti-aliasing. The default value is set to 0.15. The specified value should be between
@@ -290,12 +284,6 @@ public:
*/
void setSpecularAntiAliasingVariance(float variance) noexcept;
/**
* Gets the screen space variance of the filter kernel used when applying specular
* anti-aliasing.
*/
float getSpecularAntiAliasingVariance() const noexcept;
/**
* Sets the clamping threshold used to suppress estimation errors when applying specular
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
@@ -303,12 +291,6 @@ public:
*/
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
/**
* Gets the clamping threshold used to suppress estimation errors when applying specular
* anti-aliasing.
*/
float getSpecularAntiAliasingThreshold() const noexcept;
/**
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
@@ -316,72 +298,36 @@ public:
*/
void setDoubleSided(bool doubleSided) noexcept;
/**
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
* capability.
*/
bool isDoubleSided() const noexcept;
/**
* Specifies how transparent objects should be rendered (default is DEFAULT).
*/
void setTransparencyMode(TransparencyMode mode) noexcept;
/**
* Returns the transparency mode.
*/
TransparencyMode getTransparencyMode() const noexcept;
/**
* Overrides the default triangle culling state that was set on the material.
*/
void setCullingMode(CullingMode culling) noexcept;
/**
* Returns the face culling mode.
*/
CullingMode getCullingMode() const noexcept;
/**
* Overrides the default color-buffer write state that was set on the material.
*/
void setColorWrite(bool enable) noexcept;
/**
* Returns whether color write is enabled.
*/
bool isColorWriteEnabled() const noexcept;
/**
* Overrides the default depth-buffer write state that was set on the material.
*/
void setDepthWrite(bool enable) noexcept;
/**
* Returns whether depth write is enabled.
*/
bool isDepthWriteEnabled() const noexcept;
/**
* Overrides the default depth testing state that was set on the material.
*/
void setDepthCulling(bool enable) noexcept;
/**
* Returns whether depth culling is enabled.
*/
bool isDepthCullingEnabled() const noexcept;
/**
* Overrides the default stencil-buffer write state that was set on the material.
*/
void setStencilWrite(bool enable) noexcept;
/**
* Returns whether stencil write is enabled.
*/
bool isStencilWriteEnabled() const noexcept;
/**
* Sets the stencil comparison function (default is StencilCompareFunc::A).
*
-161
View File
@@ -1,161 +0,0 @@
/*
* Copyright (C) 2022 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 "AtlasAllocator.h"
#include <utils/debug.h>
namespace filament {
using namespace utils;
static inline constexpr std::pair<uint8_t, uint8_t> unmorton(uint16_t m) noexcept {
uint32_t r = (m | (uint32_t(m) << 15u)) & 0x55555555u;
r = (r | (r >> 1u)) & 0x33333333u;
r = (r | (r >> 2u)) & 0x0f0f0f0fu;
r = r | (r >> 4u);
return { uint8_t(r), uint8_t(r >> 16u) };
}
AtlasAllocator::AtlasAllocator(size_t maxTextureSize) noexcept {
// round to power-of-two immediately inferior or equal to the size specified.
mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - utils::clz(maxTextureSize);
}
Viewport AtlasAllocator::allocate(size_t textureSize) noexcept {
Viewport result{};
const size_t powerOfTwo = (sizeof(textureSize) * 8 - 1u) - utils::clz(textureSize);
// asked for a texture size too large
if (UTILS_UNLIKELY(powerOfTwo > mMaxTextureSizePot)) {
return result;
}
// asked for a texture size too small
if (UTILS_UNLIKELY(mMaxTextureSizePot - powerOfTwo >= QuadTree::height())) {
return result;
}
const size_t layer = mMaxTextureSizePot - powerOfTwo;
const NodeId loc = allocateInLayer(layer);
if (loc.l >= 0) {
assert_invariant(loc.l == int8_t(layer));
size_t dimension = 1u << powerOfTwo;
// find the location of in the texture from the morton code (quadtree position)
auto [x, y] = unmorton(loc.code);
// scale to our maximum allocation size
result.left = int32_t(x) << powerOfTwo;
result.bottom = int32_t(y) << powerOfTwo;
result.width = dimension;
result.height = dimension;
}
return result;
}
void AtlasAllocator::clear(size_t maxTextureSize) noexcept {
std::fill(mQuadTree.begin(), mQuadTree.end(), Node{});
mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - utils::clz(maxTextureSize);
}
AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcept {
using namespace QuadTreeUtils;
NodeId candidate{ -1, 0 };
if (UTILS_UNLIKELY(maxHeight > QuadTree::height())) {
return candidate;
}
const int8_t n = int8_t(maxHeight);
QuadTree::traverse(0, 0, n,
[this, n, &candidate](NodeId const& curr) -> QuadTree::TraversalResult {
// we should never reach a level higher than n
assert_invariant(curr.l <= n);
// get the node being processed
const size_t i = index(curr.l, curr.code);
Node const& node = mQuadTree[i];
// if the node is allocated, the whole tree below it is unavailable
if (node.isAllocated()) {
// if a node is allocated it can't have children
assert_invariant(!node.hasChildren());
return QuadTree::TraversalResult::SKIP_CHILDREN;
}
// we're looking for the `deepest` unallocated node that has no children,
// up to the depth we're trying to allocate
if (curr.l > candidate.l && !node.hasChildren()) {
candidate = curr;
// Special case where we found a fitting node, just exit.
if (curr.l == n) {
return QuadTree::TraversalResult::EXIT;
}
}
// We only want to find a fitting node that already has siblings, in order
// to accomplish a "best fit" allocation. So if we're a parent of a 'fitting'
// node and don't have children, we skip the children recursion.
if (curr.l == n - 1 && !node.hasChildren()) {
return QuadTree::TraversalResult::SKIP_CHILDREN;
}
// continue going down the tree
return QuadTree::TraversalResult::RECURSE;
});
if (candidate.l >= 0) {
const size_t i = index(candidate.l, candidate.code);
Node& allocation = mQuadTree[i];
if (candidate.l == n) {
allocation.allocated = true;
if (UTILS_LIKELY(n > 0)) {
// the root doesn't have a parent
const size_t p = parent(candidate.l, candidate.code);
Node& parent = mQuadTree[p];
assert_invariant(!parent.isAllocated());
assert_invariant(parent.hasChildren());
assert_invariant(!parent.hasAllChildren());
parent.children++;
}
} else if (candidate.l < int8_t(QuadTree::height())) {
// we need to create the hierarchy down to the level we need
assert_invariant(!allocation.isAllocated());
assert_invariant(!allocation.hasChildren());
NodeId found{};
QuadTree::traverse(candidate.l, candidate.code,
[this, n, &found](NodeId const& curr) -> QuadTree::TraversalResult {
size_t i = index(curr.l, curr.code);
Node& node = mQuadTree[i];
if (curr.l == n) {
found = curr;
node.allocated = true;
return QuadTree::TraversalResult::EXIT;
}
node.children++;
return QuadTree::TraversalResult::RECURSE;
});
candidate = found;
}
}
return candidate;
}
} // namespace filament
-95
View File
@@ -1,95 +0,0 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef TNT_FILAMENT_ATLASALLOCATOR_H
#define TNT_FILAMENT_ATLASALLOCATOR_H
#include <utils/QuadTree.h>
#include <filament/Viewport.h>
class AtlasAllocator_AllocateFirstLevel_Test;
class AtlasAllocator_AllocateSecondLevel_Test;
class AtlasAllocator_AllocateMixed0_Test;
class AtlasAllocator_AllocateMixed1_Test;
class AtlasAllocator_AllocateMixed2_Test;
namespace filament {
/*
* A 2D allocator. Allocations must be square and have a power-of-two size.
* AtlasAllocator hard codes a depth of 4, that is only 4 allocation sizes are permitted.
* This doesn't actually allocate memory, just manages space within an abstract 2D image.
*/
class AtlasAllocator {
/*
* A quadtree is used to track the allocated regions. Each node of the quadtree stores a
* `Node` data structure below.
* The `Node` tracks if it is allocated as well as the number of children it has. It doesn't
* track which children though.
*/
struct Node {
// whether this node is allocated. Implies no children.
constexpr bool isAllocated() const noexcept { return allocated; }
// whether this node has children. Implies it's not allocated.
constexpr bool hasChildren() const noexcept { return children != 0; }
// whether this node has all four children. Implies hasChildren().
constexpr bool hasAllChildren() const noexcept { return children == 4; }
bool allocated : 1; // true / false
uint8_t children : 3; // 0, 1, 2, 3, 4
};
static constexpr size_t QUAD_TREE_DEPTH = 4u;
using QuadTree = utils::QuadTreeArray<Node, QUAD_TREE_DEPTH>;
using NodeId = QuadTree::NodeId;
public:
/*
* Create allocator and specify the maximum texture size. Must be a power of two.
* Allocations size allowed are the four power-of-two smaller or equal to this size.
*/
explicit AtlasAllocator(size_t maxTextureSize = 1024) noexcept;
/*
* Allocates a square of size `textureSize`. Must be one of the power-of-two allowed
* (see above).
* Returns the location of the allocation within the maxTextureSize^2 square.
*/
Viewport allocate(size_t textureSize) noexcept;
/*
* Frees all allocations and reset the maximum texture size.
*/
void clear(size_t maxTextureSize = 1024) noexcept;
private:
friend AtlasAllocator_AllocateFirstLevel_Test;
friend AtlasAllocator_AllocateSecondLevel_Test;
friend AtlasAllocator_AllocateMixed0_Test;
friend AtlasAllocator_AllocateMixed1_Test;
friend AtlasAllocator_AllocateMixed2_Test;
QuadTree::NodeId allocateInLayer(size_t n) noexcept;
// quad-tree array to store the allocated list
QuadTree mQuadTree{};
uint8_t mMaxTextureSizePot = 0;
};
} // namespace filament
#endif // TNT_FILAMENT_ATLASALLOCATOR_H
-40
View File
@@ -292,44 +292,4 @@ MaterialInstance* MaterialInstance::duplicate(MaterialInstance const* other, con
}
float MaterialInstance::getMaskThreshold() const noexcept {
return downcast(this)->getMaskThreshold();
}
float MaterialInstance::getSpecularAntiAliasingVariance() const noexcept {
return downcast(this)->getSpecularAntiAliasingVariance();
}
float MaterialInstance::getSpecularAntiAliasingThreshold() const noexcept {
return downcast(this)->getSpecularAntiAliasingThreshold();
}
bool MaterialInstance::isDoubleSided() const noexcept {
return downcast(this)->isDoubleSided();
}
TransparencyMode MaterialInstance::getTransparencyMode() const noexcept {
return downcast(this)->getTransparencyMode();
}
CullingMode MaterialInstance::getCullingMode() const noexcept {
return downcast(this)->getCullingMode();
}
bool MaterialInstance::isColorWriteEnabled() const noexcept {
return downcast(this)->isColorWriteEnabled();
}
bool MaterialInstance::isDepthWriteEnabled() const noexcept {
return downcast(this)->isDepthWriteEnabled();
}
bool MaterialInstance::isStencilWriteEnabled() const noexcept {
return downcast(this)->isStencilWriteEnabled();
}
bool MaterialInstance::isDepthCullingEnabled() const noexcept {
return downcast(this)->isDepthCullingEnabled();
}
} // namespace filament
-169
View File
@@ -1,169 +0,0 @@
/*
* Copyright (C) 2022 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 "PerShadowMapUniforms.h"
#include "ShadowMapManager.h"
#include "details/Camera.h"
#include "details/Engine.h"
#include <private/filament/EngineEnums.h>
namespace filament {
using namespace backend;
using namespace math;
PerShadowMapUniforms::PerShadowMapUniforms(FEngine& engine) noexcept {
DriverApi& driver = engine.getDriverApi();
mUniformBufferHandle = driver.createBufferObject(sizeof(PerViewUib),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
}
void PerShadowMapUniforms::terminate(DriverApi& driver) {
driver.destroyBufferObject(mUniformBufferHandle);
}
PerViewUib& PerShadowMapUniforms::edit(Transaction const& transaction) noexcept {
assert_invariant(transaction.uniforms);
return *transaction.uniforms;
}
void PerShadowMapUniforms::prepareCamera(Transaction const& transaction,
FEngine& engine, const CameraInfo& camera) noexcept {
mat4f const& viewFromWorld = camera.view;
mat4f const& worldFromView = camera.model;
mat4f const& clipFromView = camera.projection;
const mat4f viewFromClip{ inverse((mat4)camera.projection) };
const mat4f clipFromWorld{ highPrecisionMultiply(clipFromView, viewFromWorld) };
const mat4f worldFromClip{ highPrecisionMultiply(worldFromView, viewFromClip) };
auto& s = edit(transaction);
s.viewFromWorldMatrix = viewFromWorld; // view
s.worldFromViewMatrix = worldFromView; // model
s.clipFromViewMatrix = clipFromView; // projection
s.viewFromClipMatrix = viewFromClip; // 1/projection
s.clipFromWorldMatrix = clipFromWorld; // projection * view
s.worldFromClipMatrix = worldFromClip; // 1/(projection * view)
s.clipTransform = camera.clipTransfrom;
s.cameraPosition = float3{ camera.getPosition() };
s.worldOffset = camera.getWorldOffset();
s.cameraFar = camera.zf;
s.oneOverFarMinusNear = 1.0f / (camera.zf - camera.zn);
s.nearOverFarMinusNear = camera.zn / (camera.zf - camera.zn);
// with a clip-space of [-w, w] ==> z' = -z
// with a clip-space of [0, w] ==> z' = (w - z)/2
s.clipControl = engine.getDriverApi().getClipSpaceParams();
}
void PerShadowMapUniforms::prepareLodBias(Transaction const& transaction,
float bias) noexcept {
auto& s = edit(transaction);
s.lodBias = bias;
}
void PerShadowMapUniforms::prepareViewport(Transaction const& transaction,
const filament::Viewport& viewport,
uint32_t xoffset, uint32_t yoffset) noexcept {
const float w = float(viewport.width);
const float h = float(viewport.height);
auto& s = edit(transaction);
s.resolution = float4{ w, h, 1.0f / w, 1.0f / h };
s.origin = float2{ viewport.left, viewport.bottom };
s.offset = float2{ xoffset, yoffset };
}
void PerShadowMapUniforms::prepareTime(Transaction const& transaction,
FEngine& engine, math::float4 const& userTime) noexcept {
auto& s = edit(transaction);
const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1000000000;
const float fraction = float(double(oneSecondRemainder) / 1000000000.0);
s.time = fraction;
s.userTime = userTime;
}
void PerShadowMapUniforms::prepareDirectionalLight(Transaction const& transaction,
FEngine& engine,
float exposure,
float3 const& sceneSpaceDirection,
PerShadowMapUniforms::LightManagerInstance directionalLight) noexcept {
FLightManager& lcm = engine.getLightManager();
auto& s = edit(transaction);
const float3 l = -sceneSpaceDirection; // guaranteed normalized
if (directionalLight.isValid()) {
const float4 colorIntensity = {
lcm.getColor(directionalLight), lcm.getIntensity(directionalLight) * exposure };
s.lightDirection = l;
s.lightColorIntensity = colorIntensity;
s.lightChannels = lcm.getLightChannels(directionalLight);
const bool isSun = lcm.isSunLight(directionalLight);
// The last parameter must be < 0.0f for regular directional lights
float4 sun{ 0.0f, 0.0f, 0.0f, -1.0f };
if (UTILS_UNLIKELY(isSun && colorIntensity.w > 0.0f)) {
// currently we have only a single directional light, so it's probably likely that it's
// also the Sun. However, conceptually, most directional lights won't be sun lights.
float radius = lcm.getSunAngularRadius(directionalLight);
float haloSize = lcm.getSunHaloSize(directionalLight);
float haloFalloff = lcm.getSunHaloFalloff(directionalLight);
sun.x = std::cos(radius);
sun.y = std::sin(radius);
sun.z = 1.0f / (std::cos(radius * haloSize) - sun.x);
sun.w = haloFalloff;
}
s.sun = sun;
} else {
// Disable the sun if there's no directional light
s.sun = float4{ 0.0f, 0.0f, 0.0f, -1.0f };
}
}
void PerShadowMapUniforms::prepareShadowMapping(Transaction const& transaction,
bool highPrecision) noexcept {
auto& s = edit(transaction);
constexpr float low = 5.54f; // ~ std::log(std::numeric_limits<math::half>::max()) * 0.5f;
constexpr float high = 42.0f; // ~ std::log(std::numeric_limits<float>::max()) * 0.5f;
s.vsmExponent = highPrecision ? high : low;
}
PerShadowMapUniforms::Transaction PerShadowMapUniforms::open(backend::DriverApi& driver) noexcept {
Transaction transaction;
// TODO: use out-of-line buffer if too large
transaction.uniforms = (PerViewUib *)driver.allocate(sizeof(PerViewUib));
assert_invariant(transaction.uniforms);
return transaction;
}
void PerShadowMapUniforms::commit(Transaction& transaction,
backend::DriverApi& driver) noexcept {
driver.updateBufferObject(mUniformBufferHandle, {
transaction.uniforms, sizeof(PerViewUib) }, 0);
transaction.uniforms = nullptr;
}
void PerShadowMapUniforms::bind(backend::DriverApi& driver) noexcept {
driver.bindUniformBuffer(+UniformBindingPoints::PER_VIEW, mUniformBufferHandle);
}
} // namespace filament
-95
View File
@@ -1,95 +0,0 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef TNT_FILAMENT_PERSHADOWMAPUNIFORMS_H
#define TNT_FILAMENT_PERSHADOWMAPUNIFORMS_H
#include <filament/Viewport.h>
#include <private/filament/UibStructs.h>
#include <private/backend/SamplerGroup.h>
#include "TypedUniformBuffer.h"
#include <backend/Handle.h>
#include <utils/EntityInstance.h>
#include <random>
namespace filament {
struct CameraInfo;
class FEngine;
class LightManager;
/*
* PerShadowMapUniforms manages the UBO needed to generate our shadow maps. Internally it just
* holds onto a `PerViewUniform` UBO handle, but doesn't keep any shadow copy of it, instead it
* writes the data directly into the commandstream, for this reason partial update of the data
* is not possible.
*/
class PerShadowMapUniforms {
using LightManagerInstance = utils::EntityInstance<LightManager>;
public:
class Transaction {
friend PerShadowMapUniforms;
PerViewUib* uniforms = nullptr;
Transaction() = default; // disallow creation by the caller
};
explicit PerShadowMapUniforms(FEngine& engine) noexcept;
void terminate(backend::DriverApi& driver);
static void prepareCamera(Transaction const& transaction,
FEngine& engine, const CameraInfo& camera) noexcept;
static void prepareLodBias(Transaction const& transaction,
float bias) noexcept;
static void prepareViewport(Transaction const& transaction,
const filament::Viewport& viewport, uint32_t xoffset, uint32_t yoffset) noexcept;
static void prepareTime(Transaction const& transaction,
FEngine& engine, math::float4 const& userTime) noexcept;
static void prepareShadowMapping(Transaction const& transaction,
bool highPrecision) noexcept;
static void prepareDirectionalLight(Transaction const& transaction,
FEngine& engine, float exposure,
math::float3 const& sceneSpaceDirection, LightManagerInstance instance) noexcept;
static Transaction open(backend::DriverApi& driver) noexcept;
// update local data into GPU UBO
void commit(Transaction& transaction, backend::DriverApi& driver) noexcept;
// bind this UBO
void bind(backend::DriverApi& driver) noexcept;
private:
static PerViewUib& edit(Transaction const& transaction) noexcept;
backend::Handle<backend::HwBufferObject> mUniformBufferHandle;
};
} // namespace filament
#endif //TNT_FILAMENT_PERSHADOWMAPUNIFORMS_H
+24 -17
View File
@@ -34,13 +34,15 @@
#include <math/mat4.h>
namespace filament {
using namespace backend;
using namespace math;
PerViewUniforms::PerViewUniforms(FEngine& engine) noexcept
: mSamplers(PerViewSib::SAMPLER_COUNT) {
: mEngine(engine),
mSamplers(PerViewSib::SAMPLER_COUNT) {
DriverApi& driver = engine.getDriverApi();
mSamplerGroupHandle = driver.createSamplerGroup(mSamplers.getSize());
@@ -48,6 +50,10 @@ PerViewUniforms::PerViewUniforms(FEngine& engine) noexcept
mUniformBufferHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
// with a clip-space of [-w, w] ==> z' = -z
// with a clip-space of [0, w] ==> z' = (w - z)/2
mClipControl = driver.getClipSpaceParams();
if (engine.getDFG().isValid()) {
TextureSampler sampler(TextureSampler::MagFilter::LINEAR);
mSamplers.setSampler(PerViewSib::IBL_DFG_LUT,
@@ -60,7 +66,7 @@ void PerViewUniforms::terminate(DriverApi& driver) {
driver.destroySamplerGroup(mSamplerGroupHandle);
}
void PerViewUniforms::prepareCamera(FEngine& engine, const CameraInfo& camera) noexcept {
void PerViewUniforms::prepareCamera(const CameraInfo& camera) noexcept {
mat4f const& viewFromWorld = camera.view;
mat4f const& worldFromView = camera.model;
mat4f const& clipFromView = camera.projection;
@@ -82,15 +88,17 @@ void PerViewUniforms::prepareCamera(FEngine& engine, const CameraInfo& camera) n
s.cameraFar = camera.zf;
s.oneOverFarMinusNear = 1.0f / (camera.zf - camera.zn);
s.nearOverFarMinusNear = camera.zn / (camera.zf - camera.zn);
// with a clip-space of [-w, w] ==> z' = -z
// with a clip-space of [0, w] ==> z' = (w - z)/2
s.clipControl = engine.getDriverApi().getClipSpaceParams();
s.clipControl = mClipControl;
}
void PerViewUniforms::prepareLodBias(float bias) noexcept {
void PerViewUniforms::prepareUpscaler(math::float2 scale,
DynamicResolutionOptions const& options) noexcept {
auto& s = mUniforms.edit();
s.lodBias = bias;
if (options.quality >= QualityLevel::HIGH) {
s.lodBias = std::log2(std::min(scale.x, scale.y));
} else {
s.lodBias = 0.0f;
}
}
void PerViewUniforms::prepareExposure(float ev100) noexcept {
@@ -110,19 +118,17 @@ void PerViewUniforms::prepareViewport(const filament::Viewport& viewport,
s.offset = float2{ xoffset, yoffset };
}
void PerViewUniforms::prepareTime(FEngine& engine, math::float4 const& userTime) noexcept {
void PerViewUniforms::prepareTime(math::float4 const& userTime) noexcept {
auto& s = mUniforms.edit();
const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1000000000;
const uint64_t oneSecondRemainder = mEngine.getEngineTime().count() % 1000000000;
const float fraction = float(double(oneSecondRemainder) / 1000000000.0);
s.time = fraction;
s.userTime = userTime;
}
void PerViewUniforms::prepareTemporalNoise(FEngine& engine,
TemporalAntiAliasingOptions const& options) noexcept {
std::uniform_real_distribution<float> uniformDistribution{ 0.0f, 1.0f };
void PerViewUniforms::prepareTemporalNoise(TemporalAntiAliasingOptions const& options) noexcept {
auto& s = mUniforms.edit();
const float temporalNoise = uniformDistribution(engine.getRandomEngine());
const float temporalNoise = mUniformDistribution(mEngine.getRandomEngine());
s.temporalNoise = options.enabled ? temporalNoise : 0.0f;
}
@@ -211,11 +217,11 @@ void PerViewUniforms::prepareStructure(Handle<HwTexture> structure) noexcept {
mSamplers.setSampler(PerViewSib::STRUCTURE, { structure, {}});
}
void PerViewUniforms::prepareDirectionalLight(FEngine& engine,
void PerViewUniforms::prepareDirectionalLight(
float exposure,
float3 const& sceneSpaceDirection,
PerViewUniforms::LightManagerInstance directionalLight) noexcept {
FLightManager& lcm = engine.getLightManager();
FLightManager& lcm = mEngine.getLightManager();
auto& s = mUniforms.edit();
const float3 l = -sceneSpaceDirection; // guaranteed normalized
@@ -249,8 +255,9 @@ void PerViewUniforms::prepareDirectionalLight(FEngine& engine,
}
}
void PerViewUniforms::prepareAmbientLight(FEngine& engine, FIndirectLight const& ibl,
void PerViewUniforms::prepareAmbientLight(FIndirectLight const& ibl,
float intensity, float exposure) noexcept {
auto& engine = mEngine;
auto& s = mUniforms.edit();
// Set up uniforms and sampler for the IBL, guaranteed to be non-null at this point.
+9 -12
View File
@@ -48,11 +48,6 @@ class FIndirectLight;
class Froxelizer;
class LightManager;
/*
* PerViewUniforms manages the UBO and samplers needed to render the color passes. Internally it
* holds onto handles for the PER_VIEW UBO and SamplerGroup. This class maintains a shadow copy
* of the UBO/sampler data, so it is possible to partially update it between commits.
*/
class PerViewUniforms {
using LightManagerInstance = utils::EntityInstance<LightManager>;
@@ -68,8 +63,8 @@ public:
void terminate(backend::DriverApi& driver);
void prepareCamera(FEngine& engine, const CameraInfo& camera) noexcept;
void prepareLodBias(float bias) noexcept;
void prepareCamera(const CameraInfo& camera) noexcept;
void prepareUpscaler(math::float2 scale, DynamicResolutionOptions const& options) noexcept;
/*
* @param viewport viewport (should be same as RenderPassParams::viewport)
@@ -80,8 +75,8 @@ public:
*/
void prepareViewport(const filament::Viewport& viewport, uint32_t xoffset, uint32_t yoffset) noexcept;
void prepareTime(FEngine& engine, math::float4 const& userTime) noexcept;
void prepareTemporalNoise(FEngine& engine, TemporalAntiAliasingOptions const& options) noexcept;
void prepareTime(math::float4 const& userTime) noexcept;
void prepareTemporalNoise(TemporalAntiAliasingOptions const& options) noexcept;
void prepareExposure(float ev100) noexcept;
void prepareFog(math::float3 const& cameraPosition, FogOptions const& options) noexcept;
void prepareStructure(TextureHandle structure) noexcept;
@@ -100,11 +95,10 @@ public:
void prepareShadowMapping(bool highPrecision) noexcept;
void prepareDirectionalLight(FEngine& engine, float exposure,
void prepareDirectionalLight(float exposure,
math::float3 const& sceneSpaceDirection, LightManagerInstance instance) noexcept;
void prepareAmbientLight(FEngine& engine,
FIndirectLight const& ibl, float intensity, float exposure) noexcept;
void prepareAmbientLight(FIndirectLight const& ibl, float intensity, float exposure) noexcept;
void prepareDynamicLights(Froxelizer& froxelizer) noexcept;
@@ -132,10 +126,13 @@ public:
void unbindSamplers() noexcept;
private:
FEngine& mEngine;
math::float2 mClipControl{};
TypedUniformBuffer<PerViewUib> mUniforms;
backend::SamplerGroup mSamplers;
backend::Handle<backend::HwBufferObject> mUniformBufferHandle;
backend::Handle<backend::HwSamplerGroup> mSamplerGroupHandle;
std::uniform_real_distribution<float> mUniformDistribution{ 0.0f, 1.0f };
static void prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
};
+1 -1
View File
@@ -2476,7 +2476,7 @@ void PostProcessManager::prepareTaa(FrameGraph& fg, filament::Viewport const& sv
fg.addTrivialSideEffectPass("Jitter Camera",
[=, &uniforms] (DriverApi& driver) {
uniforms.prepareCamera(mEngine, *inoutCameraInfo);
uniforms.prepareCamera(*inoutCameraInfo);
uniforms.commit(driver);
});
}
+47 -51
View File
@@ -79,12 +79,25 @@ void RenderPass::setCamera(const CameraInfo& camera) noexcept {
mCameraForwardVector = camera.getForwardVector();
}
void RenderPass::overridePolygonOffset(backend::PolygonOffset const* polygonOffset) noexcept {
if ((mPolygonOffsetOverride = (polygonOffset != nullptr))) {
mPolygonOffset = *polygonOffset;
}
}
void RenderPass::setScissorViewport(backend::Viewport viewport) noexcept {
assert_invariant(viewport.width <= std::numeric_limits<int32_t>::max());
assert_invariant(viewport.height <= std::numeric_limits<int32_t>::max());
mScissorViewport = viewport;
}
void RenderPass::overrideScissor(backend::Viewport const* scissor) noexcept {
if ((mScissorOverride = (scissor != nullptr))) {
mScissor = *scissor;
}
}
void RenderPass::appendCommands(FEngine& engine, CommandTypeFlags const commandTypeFlags) noexcept {
SYSTRACE_CONTEXT();
@@ -183,22 +196,6 @@ void RenderPass::sortCommands(FEngine& engine) noexcept {
}
}
void RenderPass::execute(FEngine& engine, const char* name,
backend::Handle<backend::HwRenderTarget> renderTarget,
backend::RenderPassParams params) const noexcept {
DriverApi& driver = engine.getDriverApi();
// this is a good time to flush the CommandStream, because we're about to potentially
// output a lot of commands. This guarantees here that we have at least
// FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB bytes (1MiB by default).
engine.flush();
driver.beginRenderPass(renderTarget, params);
getExecutor().execute(engine, name);
driver.endRenderPass();
}
void RenderPass::instanceify(FEngine& engine) noexcept {
SYSTRACE_NAME("instanceify");
@@ -358,8 +355,8 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
cmdDraw.primitive.rasterState.inverseFrontFaces = inverseFrontFaces;
cmdDraw.primitive.rasterState.culling = mi->getCullingMode();
cmdDraw.primitive.rasterState.colorWrite = mi->isColorWriteEnabled();
cmdDraw.primitive.rasterState.depthWrite = mi->isDepthWriteEnabled();
cmdDraw.primitive.rasterState.colorWrite = mi->getColorWrite();
cmdDraw.primitive.rasterState.depthWrite = mi->getDepthWrite();
cmdDraw.primitive.rasterState.depthFunc = mi->getDepthFunc();
cmdDraw.primitive.mi = mi;
cmdDraw.primitive.materialVariant = variant;
@@ -544,6 +541,11 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
*/
for (size_t pi = 0, c = primitives.size(); pi < c; ++pi) {
auto const& primitive = primitives[pi];
// handle the case where this primitive is empty / no-op
if (primitive.getPrimitiveType() == PrimitiveType::NONE) {
continue;
}
auto const& morphTargets = morphing.targets[pi];
FMaterialInstance const* const mi = primitive.getMaterialInstance();
FMaterial const* const ma = mi->getMaterial();
@@ -606,9 +608,6 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
// cancel command if asked to filter translucent objects
key |= select(filterTranslucentObjects);
// cancel command if both front and back faces are culled
key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
*curr = cmdColor;
curr->key = key;
++curr;
@@ -635,10 +634,6 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
}
*curr = cmdColor;
// cancel command if both front and back faces are culled
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
++curr;
}
@@ -663,16 +658,11 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
// FIXME: should writeDepthForShadowCasters take precedence over mi->getDepthWrite()?
cmdDepth.primitive.rasterState.depthWrite = (1 // only keep bit 0
& (mi->isDepthWriteEnabled() | (mode == TransparencyMode::TWO_PASSES_ONE_SIDE))
& (mi->getDepthWrite() | (mode == TransparencyMode::TWO_PASSES_ONE_SIDE))
& !(filterTranslucentObjects & translucent)
& !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage))
| writeDepthForShadowCasters;
*curr = cmdDepth;
// cancel command if both front and back faces are culled
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
++curr;
}
}
@@ -695,25 +685,24 @@ void RenderPass::updateSummedPrimitiveCounts(
// ------------------------------------------------------------------------------------------------
void RenderPass::Executor::overridePolygonOffset(backend::PolygonOffset const* polygonOffset) noexcept {
if ((mPolygonOffsetOverride = (polygonOffset != nullptr))) {
mPolygonOffset = *polygonOffset;
}
}
void RenderPass::Executor::execute(FEngine& engine, const char* name,
backend::Handle<backend::HwRenderTarget> renderTarget,
backend::RenderPassParams const& params) const noexcept {
DriverApi& driver = engine.getDriverApi();
void RenderPass::Executor::overrideScissor(backend::Viewport const* scissor) noexcept {
if ((mScissorOverride = (scissor != nullptr))) {
mScissor = *scissor;
}
}
// this is a good time to flush the CommandStream, because we're about to potentially
// output a lot of commands. This guarantees here that we have at least
// FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB bytes (1MiB by default).
engine.flush();
void RenderPass::Executor::execute(FEngine& engine, const char* name) const noexcept {
execute(engine.getDriverApi(), mCommands.begin(), mCommands.end());
driver.beginRenderPass(renderTarget, params);
recordDriverCommands(engine, driver, mBegin, mEnd, params.readOnlyDepthStencil);
driver.endRenderPass();
}
UTILS_NOINLINE // no need to be inlined
void RenderPass::Executor::execute(backend::DriverApi& driver,
const Command* first, const Command* last) const noexcept {
void RenderPass::Executor::recordDriverCommands(FEngine& engine, backend::DriverApi& driver,
const Command* first, const Command* last, uint16_t readOnlyDepthStencil) const noexcept {
SYSTRACE_CALL();
if (first != last) {
@@ -733,7 +722,7 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
Handle<HwBufferObject> uboHandle = mUboHandle;
FMaterialInstance const* UTILS_RESTRICT mi = nullptr;
FMaterial const* UTILS_RESTRICT ma = nullptr;
auto const* UTILS_RESTRICT pCustomCommands = mCustomCommands.data();
auto customCommands = mCustomCommands.data();
first--;
while (++first != last) {
@@ -746,7 +735,7 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
if (UTILS_UNLIKELY((first->key & CUSTOM_MASK) != uint64_t(CustomCommand::PASS))) {
uint32_t index = (first->key & CUSTOM_INDEX_MASK) >> CUSTOM_INDEX_SHIFT;
assert_invariant(index < mCustomCommands.size());
pCustomCommands[index]();
customCommands[index]();
continue;
}
@@ -754,6 +743,11 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
const PrimitiveInfo info = first->primitive;
pipeline.rasterState = info.rasterState;
#ifndef NDEBUG
const bool readOnlyDepthGuaranteed = readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH;
assert_invariant(!readOnlyDepthGuaranteed || !pipeline.rasterState.depthWrite);
#endif
if (UTILS_UNLIKELY(mi != info.mi)) {
// this is always taken the first time
mi = info.mi;
@@ -835,13 +829,15 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
// ------------------------------------------------------------------------------------------------
RenderPass::Executor::Executor(RenderPass const* pass, Command const* b, Command const* e) noexcept
: mCommands(b, e),
mCustomCommands(pass->mCustomCommands.data(), pass->mCustomCommands.size()),
: mBegin(b), mEnd(e),
mCustomCommands(pass->mCustomCommands),
mUboHandle(pass->mUboHandle),
mInstancedUboHandle(pass->mInstancedUboHandle),
mPolygonOffset(pass->mPolygonOffset),
mScissor(pass->mScissor),
mScissorViewport(pass->mScissorViewport),
mPolygonOffsetOverride(false),
mScissorOverride(false) {
mPolygonOffsetOverride(pass->mPolygonOffsetOverride),
mScissorOverride(pass->mScissorOverride) {
assert_invariant(b >= pass->begin());
assert_invariant(e <= pass->end());
}
+40 -36
View File
@@ -276,9 +276,15 @@ public:
// allocated commands ARE NOT freed, they're owned by the Arena
~RenderPass() noexcept;
// if non-null, overrides the material's polygon offset
void overridePolygonOffset(backend::PolygonOffset const* polygonOffset) noexcept;
// a box that both offsets the viewport and clips it
void setScissorViewport(backend::Viewport viewport) noexcept;
// if non-null, overrides the material's scissor
void overrideScissor(backend::Viewport const* scissor) noexcept;
// specifies the geometry to generate commands for
void setGeometry(FScene::RenderableSoa const& soa, utils::Range<uint32_t> vr,
backend::Handle<backend::HwBufferObject> uboHandle) noexcept;
@@ -312,61 +318,49 @@ public:
// Helper to execute all the commands generated by this RenderPass
void execute(FEngine& engine, const char* name,
backend::Handle<backend::HwRenderTarget> renderTarget,
backend::RenderPassParams params) const noexcept;
backend::RenderPassParams params) const noexcept {
getExecutor().execute(engine, name, renderTarget, params);
}
/*
* Executor holds the range of commands to execute for a given pass
*/
class Executor {
using CustomCommandFn = std::function<void()>;
using CustomCommandVector = std::vector<CustomCommandFn,
utils::STLAllocator<CustomCommandFn, LinearAllocatorArena>>;
friend class RenderPass;
// these fields are constant after creation
utils::Slice<Command> mCommands;
utils::Slice<CustomCommandFn> mCustomCommands;
backend::Handle<backend::HwBufferObject> mUboHandle;
backend::Handle<backend::HwBufferObject> mInstancedUboHandle;
backend::Viewport mScissorViewport;
backend::Viewport mScissor{}; // value of scissor override
backend::PolygonOffset mPolygonOffset{}; // value of the override
bool mPolygonOffsetOverride : 1; // whether to override the polygon offset setting
bool mScissorOverride : 1; // whether to override the polygon offset setting
Command const* mBegin;
Command const* mEnd;
const CustomCommandVector mCustomCommands;
const backend::Handle<backend::HwBufferObject> mUboHandle;
const backend::Handle<backend::HwBufferObject> mInstancedUboHandle;
const backend::PolygonOffset mPolygonOffset;
const backend::Viewport mScissor;
const backend::Viewport mScissorViewport;
const bool mPolygonOffsetOverride : 1;
const bool mScissorOverride : 1;
Executor(RenderPass const* pass, Command const* b, Command const* e) noexcept;
void execute(backend::DriverApi& driver,
const Command* first, const Command* last) const noexcept;
void recordDriverCommands(FEngine& engine, backend::DriverApi& driver,
const Command* first, const Command* last, uint16_t readOnlyDepthStencil) const noexcept;
public:
Executor() = default;
Executor(Executor const& rhs);
Executor& operator=(Executor const& rhs) = default;
~Executor() noexcept;
// if non-null, overrides the material's polygon offset
void overridePolygonOffset(backend::PolygonOffset const* polygonOffset) noexcept;
// if non-null, overrides the material's scissor
void overrideScissor(backend::Viewport const* scissor) noexcept;
void execute(FEngine& engine, const char* name) const noexcept;
void execute(FEngine& engine, const char* name,
backend::Handle<backend::HwRenderTarget> renderTarget,
backend::RenderPassParams const& params) const noexcept;
};
// returns a new executor for this pass
Executor getExecutor() {
return { this, mCommandBegin, mCommandEnd };
}
Executor getExecutor() const {
return { this, mCommandBegin, mCommandEnd };
}
// returns a new executor for this pass with a custom range
Executor getExecutor(Command const* b, Command const* e) {
return { this, b, e };
}
Executor getExecutor(Command const* b, Command const* e) const {
return { this, b, e };
}
@@ -444,14 +438,24 @@ private:
// Additional visibility mask
FScene::VisibleMaskType mVisibilityMask = std::numeric_limits<FScene::VisibleMaskType>::max();
// whether to override the polygon offset setting
bool mPolygonOffsetOverride = false;
// whether to override the polygon offset setting
bool mScissorOverride = false;
// value of the override
backend::PolygonOffset mPolygonOffset{};
// value of scissor override
backend::Viewport mScissor{};
backend::Viewport mScissorViewport{ 0, 0,
std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max() };
// a vector for our custom commands
using CustomCommandVector = std::vector<Executor::CustomCommandFn,
utils::STLAllocator<Executor::CustomCommandFn, LinearAllocatorArena>>;
mutable CustomCommandVector mCustomCommands;
mutable Executor::CustomCommandVector mCustomCommands;
};
} // namespace filament
+1 -1
View File
@@ -71,7 +71,7 @@ private:
AttributeBitset mEnabledAttributes = {};
uint16_t mBlendOrder = 0;
bool mGlobalBlendOrderEnabled = false;
backend::PrimitiveType mPrimitiveType = backend::PrimitiveType::TRIANGLES;
backend::PrimitiveType mPrimitiveType = backend::PrimitiveType::NONE;
UTILS_UNUSED uint8_t reserved[4] = {};
};
+2 -10
View File
@@ -173,7 +173,7 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
view.prepareSSAO(data.ssao ?
resources.getTexture(data.ssao) : engine.getOneTextureArray());
view.prepareShadowMapping(view.getVsmShadowOptions().highPrecision);
view.prepareShadowMap(view.getVsmShadowOptions().highPrecision);
// set shadow sampler
view.prepareShadow(data.shadows ?
@@ -200,7 +200,6 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
view.prepareViewport(static_cast<filament::Viewport&>(out.params.viewport),
config.xoffset, config.yoffset);
view.commitUniforms(driver);
out.params.clearColor = data.clearColor;
@@ -218,14 +217,7 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
if (colorGradingConfig.asSubpass || colorGradingConfig.customResolve) {
out.params.subpassMask = 1;
}
// this is a good time to flush the CommandStream, because we're about to potentially
// output a lot of commands. This guarantees here that we have at least
// FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB bytes (1MiB by default).
engine.flush();
driver.beginRenderPass(out.target, out.params);
passExecutor.execute(engine, resources.getPassName());
driver.endRenderPass();
passExecutor.execute(engine, resources.getPassName(), out.target, out.params);
// color pass is typically heavy, and we don't have much CPU work left after
// this point, so flushing now allows us to start the GPU earlier and reduce
+3 -71
View File
@@ -41,10 +41,8 @@ using namespace backend;
static constexpr bool USE_DEPTH_CLAMP = false;
ShadowMap::ShadowMap(FEngine& engine) noexcept
: mPerShadowMapUniforms(engine),
mShadowType(ShadowType::DIRECTIONAL),
mHasVisibleShadows(false),
mFace(0) {
: mShadowType(ShadowType::DIRECTIONAL),
mHasVisibleShadows(false) {
Entity entities[2];
engine.getEntityManager().create(2, entities);
mCamera = engine.createCamera(entities[0]);
@@ -62,19 +60,16 @@ void ShadowMap::terminate(FEngine& engine) {
engine.destroyCameraComponent(e);
}
engine.getEntityManager().destroy(sizeof(entities) / sizeof(Entity), entities);
mPerShadowMapUniforms.terminate(engine.getDriverApi());
}
ShadowMap::~ShadowMap() = default;
void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType,
uint16_t shadowIndex, uint8_t face,
void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex,
LightManager::ShadowOptions const* options) {
mLightIndex = lightIndex;
mShadowIndex = shadowIndex;
mOptions = options;
mShadowType = shadowType;
mFace = face;
}
mat4f ShadowMap::getDirectionalLightViewMatrix(float3 direction, float3 position) noexcept {
@@ -1243,67 +1238,4 @@ void ShadowMap::updateSceneInfoSpot(mat4f const& Mv, FScene const& scene,
);
}
filament::Viewport ShadowMap::getViewport() const noexcept {
// We set a viewport with a 1-texel border for when we index outside the
// texture.
// DON'T CHANGE this unless ShadowMap::getTextureCoordsMapping() is updated too.
// see: ShadowMap::getTextureCoordsMapping()
//
// For floating-point depth textures, the 1-texel border could be set to
// FLOAT_MAX to avoid clamping in the shadow shader (see sampleDepth inside
// shadowing.fs). Unfortunately, the APIs don't seem let us clear depth
// attachments to anything greater than 1.0, so we'd need a way to do this other
// than clearing.
const uint32_t dim = mOptions->mapSize;
if (isPointShadow()) {
// for point-light we don't have a border
return { 0, 0, dim, dim };
} else {
return { 1, 1, dim - 2, dim - 2 };
}
}
// ------------------------------------------------------------------------------------------------
void ShadowMap::prepareCamera(Transaction const& transaction,
FEngine& engine, const CameraInfo& cameraInfo) noexcept {
PerShadowMapUniforms::prepareCamera(transaction, engine, cameraInfo);
PerShadowMapUniforms::prepareLodBias(transaction, 0.0f);
}
void ShadowMap::prepareViewport(Transaction const& transaction,
const filament::Viewport& viewport) noexcept {
PerShadowMapUniforms::prepareViewport(transaction, viewport, 0, 0);
}
void ShadowMap::prepareTime(Transaction const& transaction,
FEngine& engine, math::float4 const& userTime) noexcept {
PerShadowMapUniforms::prepareTime(transaction, engine, userTime);
}
void ShadowMap::prepareDirectionalLight(Transaction const& transaction,
FEngine& engine, math::float3 const& sceneSpaceDirection,
LightManager::Instance instance) noexcept {
PerShadowMapUniforms::prepareDirectionalLight(transaction,
engine, 1.0f, sceneSpaceDirection, instance);
}
void ShadowMap::prepareShadowMapping(Transaction const& transaction,
bool highPrecision) noexcept {
PerShadowMapUniforms::prepareShadowMapping(transaction, highPrecision);
}
PerShadowMapUniforms::Transaction ShadowMap::open(DriverApi& driver) noexcept {
return PerShadowMapUniforms::open(driver);
}
void ShadowMap::commit(Transaction& transaction,
backend::DriverApi& driver) const noexcept {
mPerShadowMapUniforms.commit(transaction, driver);
}
void ShadowMap::bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept {
mPerShadowMapUniforms.bind(driver);
}
} // namespace filament
+8 -34
View File
@@ -19,14 +19,12 @@
#include "components/LightManager.h"
#include "PerShadowMapUniforms.h"
#include "details/Camera.h"
#include "details/Scene.h"
#include "private/backend/DriverApi.h"
#include <filament/Viewport.h>
#include "backend/DriverApiForward.h"
#include "private/backend/SamplerGroup.h"
#include "math/mat4.h"
#include <math/mat4.h>
#include <math/vec4.h>
@@ -124,7 +122,7 @@ public:
static math::mat4f getPointLightViewMatrix(backend::TextureCubemapFace face,
math::float3 position) noexcept;
void initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex, uint8_t face,
void initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex,
LightManager::ShadowOptions const* options);
struct ShaderParameters {
@@ -174,8 +172,6 @@ public:
static void updateSceneInfoSpot(const math::mat4f& Mv, FScene const& scene,
SceneInfo& sceneInfo);
filament::Viewport getViewport() const noexcept;
LightManager::ShadowOptions const* getShadowOptions() const noexcept { return mOptions; }
size_t getLightIndex() const { return mLightIndex; }
uint16_t getShadowIndex() const { return mShadowIndex; }
@@ -185,25 +181,6 @@ public:
bool isSpotShadow() const noexcept { return mShadowType == ShadowType::SPOT; }
bool isPointShadow() const noexcept { return mShadowType == ShadowType::POINT; }
ShadowType getShadowType() const noexcept { return mShadowType; }
uint8_t getFace() const noexcept { return mFace; }
using Transaction = PerShadowMapUniforms::Transaction;
static void prepareCamera(Transaction const& transaction,
FEngine& engine, const CameraInfo& cameraInfo) noexcept;
static void prepareViewport(Transaction const& transaction,
const filament::Viewport& viewport) noexcept;
static void prepareTime(Transaction const& transaction,
FEngine& engine, math::float4 const& userTime) noexcept;
static void prepareDirectionalLight(Transaction const& transaction,
FEngine& engine, math::float3 const& sceneSpaceDirection,
LightManager::Instance instance) noexcept;
static void prepareShadowMapping(Transaction const& transaction,
bool highPrecision) noexcept;
static PerShadowMapUniforms::Transaction open(backend::DriverApi& driver) noexcept;
void commit(Transaction& transaction,
backend::DriverApi& driver) const noexcept;
void bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
private:
struct Segment {
@@ -301,10 +278,8 @@ private:
{ 2, 6, 7, 3 }, // top
};
mutable PerShadowMapUniforms mPerShadowMapUniforms; // 4
FCamera* mCamera = nullptr; // 8
FCamera* mDebugCamera = nullptr; // 8
FCamera* mCamera = nullptr; // 8
FCamera* mDebugCamera = nullptr; // 8
// The data below technically belongs to ShadowMapManager, but it simplifies allocations
// to store it here. This data is always associated with this shadow map anyway.
@@ -312,9 +287,8 @@ private:
uint32_t mLightIndex = 0; // which light are we shadowing // 4
uint16_t mShadowIndex = 0; // our index in the shadowMap vector // 2
uint8_t mLayer = 0; // our layer in the shadowMap texture // 1
ShadowType mShadowType : 2; // :2
bool mHasVisibleShadows : 2; // :2
uint8_t mFace : 3; // :3
ShadowType mShadowType : 2;
bool mHasVisibleShadows : 2;
};
} // namespace filament
+84 -80
View File
@@ -98,34 +98,22 @@ void ShadowMapManager::setDirectionalShadowMap(size_t lightIndex,
assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES);
for (size_t c = 0; c < options->shadowCascades; c++) {
auto* pShadowMap = getCascadeShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, 0, options);
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, options);
mCascadeShadowMaps.push_back(pShadowMap);
}
}
void ShadowMapManager::addShadowMap(size_t lightIndex, bool spotlight,
LightManager::ShadowOptions const* options) noexcept {
if (spotlight) {
const size_t c = mSpotShadowMaps.size();
assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL);
auto* pShadowMap = getPointOrSpotShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::SPOT, c, 0, options);
mSpotShadowMaps.push_back(pShadowMap);
} else {
// point-light
for (size_t face = 0; face < 6; face++) {
const size_t c = mSpotShadowMaps.size();
assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL);
auto* pShadowMap = getPointOrSpotShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::POINT, c, face, options);
mSpotShadowMaps.push_back(pShadowMap);
}
}
const size_t c = mSpotShadowMaps.size();
assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL);
auto* pShadowMap = getPointOrSpotShadowMap(c);
pShadowMap->initialize(lightIndex, spotlight ? ShadowType::SPOT : ShadowType::POINT, c, options);
mSpotShadowMaps.push_back(pShadowMap);
}
FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameGraph& fg,
RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo,
float4 const& userTime) noexcept {
FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FrameGraph& fg, FEngine& engine,
RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo) noexcept {
const float moment2 = std::numeric_limits<half>::max();
const float moment1 = std::sqrt(moment2);
@@ -144,10 +132,12 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
struct PrepareShadowPassData {
struct ShadowPass {
mutable RenderPass::Executor executor;
mutable RenderPass pass;
mutable CameraInfo cameraInfo;
ShadowMap* shadowMap;
utils::Range<uint32_t> range;
FScene::VisibleMaskType visibilityMask;
uint8_t face = 0;
};
// the actual shadow map atlas (currently a 2D texture array)
FrameGraphId<FrameGraphTexture> shadows;
@@ -176,7 +166,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// for the directional light, we already know if it has visible shadows.
if (pShadowMap->hasVisibleShadows()) {
passList.push_back({
{}, pShadowMap, directionalShadowCastersRange,
pass, {}, pShadowMap, directionalShadowCastersRange,
VISIBLE_DIR_SHADOW_RENDERABLE });
}
}
@@ -188,8 +178,16 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
for (auto* pShadowMap : mSpotShadowMaps) {
assert_invariant(!pShadowMap->isDirectionalShadow());
passList.push_back({
{}, pShadowMap, spotShadowCastersRange,
pass, {}, pShadowMap, spotShadowCastersRange,
VISIBLE_DYN_SHADOW_RENDERABLE });
if (pShadowMap->isPointShadow()) {
// add the 5 extra faces
for (uint8_t face = 1; face < 6; face++) {
passList.push_back({
pass, {}, pShadowMap, spotShadowCastersRange,
VISIBLE_DYN_SHADOW_RENDERABLE, face });
}
}
}
}
@@ -199,8 +197,10 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// "read" from one of its resource (only writes), so the FrameGraph culls it.
builder.sideEffect();
},
[this, &engine, &view, scene, mainCameraInfo, userTime, passTemplate = pass](
[this, &engine, &view, scene, &mainCameraInfo](
FrameGraphResources const& resources, auto const& data, DriverApi& driver) {
// set uniforms needed to render this ShadowMap
view.prepareShadowMap(view.getVsmShadowOptions().highPrecision);
// Note: we could almost parallel_for the loop below, the problem currently is
// that updatePrimitivesLod() updates temporary global state.
@@ -215,6 +215,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// for spot shadow map, we need to do the culling
switch (shadowMap.getShadowType()) {
case ShadowType::DIRECTIONAL:
// nothing to do, it's been done already
break;
case ShadowType::SPOT:
prepareSpotShadowMap(shadowMap, engine, view, mainCameraInfo,
@@ -224,7 +225,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
case ShadowType::POINT:
preparePointShadowMap(shadowMap, engine, view, mainCameraInfo,
scene->getRenderableData(), entry.range,
scene->getLightData(), mSceneInfo);
scene->getLightData(), entry.face, mSceneInfo);
break;
}
@@ -242,50 +243,33 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// cameraInfo only valid after calling update
const CameraInfo cameraInfo{ shadowMap.getCamera() };
auto transaction = ShadowMap::open(driver);
ShadowMap::prepareCamera(transaction, engine, cameraInfo);
ShadowMap::prepareViewport(transaction, shadowMap.getViewport());
ShadowMap::prepareTime(transaction, engine, userTime);
ShadowMap::prepareShadowMapping(transaction,
view.getVsmShadowOptions().highPrecision);
if (shadowMap.getShadowType() == ShadowType::DIRECTIONAL) {
ShadowMap::prepareDirectionalLight(transaction, engine,
scene->getLightData().elementAt<FScene::DIRECTION>(0),
scene->getLightData().elementAt<FScene::LIGHT_INSTANCE>(0));
}
shadowMap.commit(transaction, driver);
// updatePrimitivesLod must be run before RenderPass::appendCommands.
view.updatePrimitivesLod(engine,
cameraInfo, scene->getRenderableData(), entry.range);
RenderPass pass(passTemplate);
pass.setCamera(cameraInfo);
pass.setVisibilityMask(entry.visibilityMask);
pass.setGeometry(scene->getRenderableData(),
entry.range, scene->getRenderableUBO());
pass.appendCommands(engine, RenderPass::SHADOW);
pass.sortCommands(engine);
entry.executor = pass.getExecutor();
if (!view.hasVSM()) {
auto li = scene->getLightData().elementAt<FScene::LIGHT_INSTANCE>(
entry.shadowMap->getLightIndex());
shadowMap.getLightIndex());
auto const& params = engine.getLightManager().getShadowParams(li);
const PolygonOffset polygonOffset = { // handle reversed Z
.slope = -params.options.polygonOffsetSlope,
.constant = -params.options.polygonOffsetConstant
};
entry.executor.overridePolygonOffset(&polygonOffset);
entry.pass.overridePolygonOffset(&polygonOffset);
}
constexpr const backend::Viewport disabledScissor{ 0, 0,
(uint32_t)std::numeric_limits<int32_t>::max(),
(uint32_t)std::numeric_limits<int32_t>::max() };
entry.executor.overrideScissor(&disabledScissor);
entry.pass.setCamera(cameraInfo);
entry.pass.setVisibilityMask(entry.visibilityMask);
entry.pass.setGeometry(scene->getRenderableData(),
entry.range, scene->getRenderableUBO());
entry.pass.overrideScissor(&disabledScissor);
entry.pass.appendCommands(engine, RenderPass::SHADOW);
entry.pass.sortCommands(engine);
entry.cameraInfo = cameraInfo;
}
}
@@ -303,7 +287,8 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
struct ShadowPassData {
FrameGraphId<FrameGraphTexture> tempBlurSrc{}; // temporary shadowmap when blurring
FrameGraphId<FrameGraphTexture> output;
uint32_t rt{};
uint32_t blurRt{};
uint32_t shadowRt{};
};
auto const& passList = prepareShadowPass.getData().passList;
@@ -312,7 +297,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
continue;
}
const uint8_t layer = entry.shadowMap->getLayer();
const uint8_t layer = entry.shadowMap->getLayer() + entry.face;
const auto* options = entry.shadowMap->getShadowOptions();
auto& shadowPass = fg.addPass<ShadowPassData>("Shadow Pass",
@@ -361,7 +346,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
data.tempBlurSrc = builder.write(data.tempBlurSrc,
FrameGraphTexture::Usage::COLOR_ATTACHMENT);
data.rt = builder.declareRenderPass("Temp Shadow RT", {
data.blurRt = builder.declareRenderPass("Temp Shadow RT", {
.attachments = {
.color = { data.tempBlurSrc },
.depth = depth },
@@ -380,13 +365,9 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
}
// finally, create the shadowmap render target -- one per layer.
auto rt = builder.declareRenderPass("Shadow RT", renderTargetDesc);
// render either directly into the shadowmap, or to the temporary texture for
// blurring.
data.rt = blur ? data.rt : rt;
data.shadowRt = builder.declareRenderPass("Shadow RT", renderTargetDesc);
},
[=, &engine, &entry](FrameGraphResources const& resources,
[=, &engine, &entry, &view](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
// Note: we capture entry by reference here. That's actually okay because
@@ -396,15 +377,41 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// It wouldn't work to capture by copy because entry.pass wouldn't be
// initialized, as this happens in an `execute` block.
entry.shadowMap->bindPerViewUniformsAndSamplers(driver);
CameraInfo const& cameraInfo = entry.cameraInfo;
auto rt = resources.getRenderPassInfo(data.rt);
rt.params.viewport = entry.shadowMap->getViewport();
const auto& executor = entry.pass.getExecutor();
const bool blur = view.hasVSM() && options->vsm.blurWidth > 0.0f;
engine.flush();
driver.beginRenderPass(rt.target, rt.params);
entry.executor.execute(engine, "Shadow Pass");
driver.endRenderPass();
// set uniforms relative to the camera
view.prepareCamera(cameraInfo);
// We set a viewport with a 1-texel border for when we index outside the
// texture.
// DON'T CHANGE this unless ShadowMap::getTextureCoordsMapping() is updated too.
// see: ShadowMap::getTextureCoordsMapping()
//
// For floating-point depth textures, the 1-texel border could be set to
// FLOAT_MAX to avoid clamping in the shadow shader (see sampleDepth inside
// shadowing.fs). Unfortunately, the APIs don't seem let us clear depth
// attachments to anything greater than 1.0, so we'd need a way to do this other
// than clearing.
const uint32_t dim = options->mapSize;
filament::Viewport viewport{ 1, 1, dim - 2, dim - 2 };
if (entry.shadowMap->isPointShadow()) {
// for point-light we don't have a border
viewport = { 0, 0, dim, dim };
}
view.prepareViewport(viewport, 0, 0);
view.commitUniforms(driver);
// render either directly into the shadowmap, or to the temporary texture for
// blurring.
auto rt = resources.getRenderPassInfo(blur ? data.blurRt : data.shadowRt);
rt.params.viewport = viewport;
executor.execute(engine, "Shadow Pass", rt.target, rt.params);
});
@@ -694,10 +701,9 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
FEngine& engine, FView& view, CameraInfo const& mainCameraInfo,
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
FScene::LightSoa& lightData,
FScene::LightSoa& lightData, uint8_t face,
ShadowMap::SceneInfo const& sceneInfo) noexcept {
const uint8_t face = shadowMap.getFace();
const size_t lightIndex = shadowMap.getLightIndex();
FLightManager::ShadowOptions const* const options = shadowMap.getShadowOptions();
@@ -788,15 +794,9 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
for (auto const* pShadowMap : mSpotShadowMaps) {
const size_t lightIndex = pShadowMap->getLightIndex();
// FIXME: currently we have one slot per shadowmap in the UBO, but we now have up to
// 6 shadowmap per light. So for now, we only write the data of the face 0,
// and the shader will figure out where to find the other face (layer+face)
if (pShadowMap->getFace() == 0) {
shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly?
shadowInfo[lightIndex].index = pShadowMap->getShadowIndex();
shadowInfo[lightIndex].layer = pShadowMap->getLayer();
}
shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly?
shadowInfo[lightIndex].index = pShadowMap->getShadowIndex();
shadowInfo[lightIndex].layer = pShadowMap->getLayer();
}
}
@@ -837,6 +837,10 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view
maxDimension = std::max(maxDimension, options->mapSize);
elvsm = elvsm || options->vsm.elvsm;
pShadowMap->setLayer(layer++);
if (pShadowMap->isPointShadow()) {
// FIXME: we need to make sure we don't exceed 256
layer += 5;
}
}
const uint8_t layersNeeded = layer;
+5 -5
View File
@@ -90,8 +90,8 @@ public:
FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept;
// Renders all the shadow maps.
FrameGraphId<FrameGraphTexture> render(FEngine& engine, FrameGraph& fg, RenderPass const& pass,
FView& view, CameraInfo const& mainCameraInfo, math::float4 const& userTime) noexcept;
FrameGraphId<FrameGraphTexture> render(FrameGraph& fg, FEngine& engine,
RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo) noexcept;
ShadowMap* getCascadeShadowMap(size_t cascade) noexcept {
assert_invariant(cascade < CONFIG_MAX_SHADOW_CASCADES);
@@ -140,7 +140,7 @@ private:
void preparePointShadowMap(ShadowMap& map,
FEngine& engine, FView& view, CameraInfo const& mainCameraInfo,
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
FScene::LightSoa& lightData,
FScene::LightSoa& lightData, uint8_t face,
ShadowMap::SceneInfo const& sceneInfo) noexcept;
static void updateSpotVisibilityMasks(
@@ -205,7 +205,7 @@ private:
mutable TypedUniformBuffer<ShadowUib> mShadowUb;
backend::Handle<backend::HwBufferObject> mShadowUbh;
ShadowMappingUniforms mShadowMappingUniforms = {};
ShadowMappingUniforms mShadowMappingUniforms;
ShadowMap::SceneInfo mSceneInfo;
@@ -219,7 +219,7 @@ private:
// inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
// because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
// Each ShadowMap is currently 40 bytes (total of 2.5KB for 64 shadow maps)
// Each ShadowMap is currently 32 bytes.
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap), alignof(ShadowMap)>::type;
std::array<ShadowMapStorage, CONFIG_MAX_SHADOW_LAYERS> mShadowMapCache;
};
+1 -1
View File
@@ -46,7 +46,7 @@ public:
// return if any uniform has been changed
bool isDirty() const noexcept { return mSomethingDirty; }
// mark the whole buffer as "clean" (no modified uniforms)
// mark the whole buffer as clean (no modified uniforms)
void clean() const noexcept { mSomethingDirty = false; }
// helper functions
@@ -747,8 +747,4 @@ bool FRenderableManager::getLightChannel(Instance ci, unsigned int channel) cons
return false;
}
size_t FRenderableManager::getPrimitiveCount(Instance instance, uint8_t level) const noexcept {
return getRenderPrimitives(instance, level).size();
}
} // namespace filament
+5 -1
View File
@@ -160,7 +160,7 @@ public:
}
inline size_t getLevelCount(Instance) const noexcept { return 1; }
size_t getPrimitiveCount(Instance instance, uint8_t level) const noexcept;
inline size_t getPrimitiveCount(Instance instance, uint8_t level) const noexcept;
void setMaterialInstanceAt(Instance instance, uint8_t level,
size_t primitiveIndex, FMaterialInstance const* materialInstance);
MaterialInstance* getMaterialInstanceAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept;
@@ -411,6 +411,10 @@ utils::Slice<FRenderableManager::MorphTargets>& FRenderableManager::getMorphTarg
return mManager[instance].morphTargets;
}
size_t FRenderableManager::getPrimitiveCount(Instance instance, uint8_t level) const noexcept {
return getRenderPrimitives(instance, level).size();
}
} // namespace filament
#endif // TNT_FILAMENT_COMPONENTS_RENDERABLEMANAGER_H
+22 -6
View File
@@ -258,6 +258,12 @@ uint32_t FEngine::getJobSystemThreadPoolSize() noexcept {
void FEngine::init() {
SYSTRACE_CALL();
#if FILAMENT_ENABLE_FGDBG
if (!debug.fgdbg) {
debug.fgdbg = std::make_unique<fgdbg::DebugServer>();
}
#endif
// this must be first.
assert_invariant( intptr_t(&mDriverApiStorage) % alignof(DriverApi) == 0 );
::new(&mDriverApiStorage) DriverApi(*mDriver, mCommandBufferQueue.getCircularBuffer());
@@ -606,16 +612,16 @@ int FEngine::loop() {
#endif
if (portString != nullptr) {
const int port = atoi(portString);
debug.server = new matdbg::DebugServer(mBackend, port);
debug.matdbg = std::make_unique<matdbg::DebugServer>(mBackend, port);
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
// When this occurs, carry onward, developers can look at civetweb.txt for details.
if (!debug.server->isReady()) {
delete debug.server;
debug.server = nullptr;
if (!debug.matdbg->isReady()) {
delete debug.matdbg.get();
debug.matdbg = nullptr;
} else {
debug.server->setEditCallback(FMaterial::onEditCallback);
debug.server->setQueryCallback(FMaterial::onQueryCallback);
debug.matdbg->setEditCallback(FMaterial::onEditCallback);
debug.matdbg->setQueryCallback(FMaterial::onQueryCallback);
}
}
#endif
@@ -640,6 +646,16 @@ int FEngine::loop() {
uint32_t id = std::thread::hardware_concurrency() - 1;
while (true) {
#if FILAMENT_ENABLE_FGDBG
// TODO (@feresr): Only for testing purposes, remove
if (debug.fgdbg) {
static int fgdbgMessage = 0;
fgdbgMessage++;
if (fgdbgMessage % 100 == 0) {
debug.fgdbg->sendMessage(fgdbgMessage/100);
}
}
#endif
// looks like thread affinity needs to be reset regularly (on Android)
JobSystem::setThreadAffinityById(id);
if (!execute()) {
+10 -1
View File
@@ -57,6 +57,14 @@
#include <filament/Texture.h>
#include <filament/VertexBuffer.h>
#if FILAMENT_ENABLE_FGDBG
#include <fgdbg/DebugServer.h>
#else
namespace filament::fgdbg {
class DebugServer;
} // namespace filament::fgdbg
#endif
#if FILAMENT_ENABLE_MATDBG
#include <matdbg/DebugServer.h>
#else
@@ -519,7 +527,8 @@ public:
// capture to file. At the moment, only supported by the Metal backend.
bool doFrameCapture = false;
} renderer;
matdbg::DebugServer* server = nullptr;
std::unique_ptr<matdbg::DebugServer> matdbg = nullptr;
std::unique_ptr<fgdbg::DebugServer> fgdbg = nullptr;
} debug;
};
+2 -2
View File
@@ -168,7 +168,7 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
#if FILAMENT_ENABLE_MATDBG
// Register the material with matdbg.
matdbg::DebugServer* server = downcast(engine).debug.server;
matdbg::DebugServer* server = downcast(engine).debug.matdbg.get();
if (UTILS_UNLIKELY(server)) {
auto details = builder.mImpl;
mDebuggerId = server->addMaterial(mName, details->mPayload, details->mSize, this);
@@ -319,7 +319,7 @@ void FMaterial::terminate(FEngine& engine) {
#if FILAMENT_ENABLE_MATDBG
// Unregister the material with matdbg.
matdbg::DebugServer* server = downcast(mEngine).debug.server;
matdbg::DebugServer* server = downcast(mEngine).debug.matdbg.get();
if (UTILS_UNLIKELY(server)) {
server->removeMaterial(mDebuggerId);
}
+5 -55
View File
@@ -35,30 +35,17 @@ namespace filament {
using namespace backend;
FMaterialInstance::FMaterialInstance() noexcept
: mCulling(CullingMode::BACK),
mDepthFunc(RasterState::DepthFunc::LE),
mColorWrite(false),
mDepthWrite(false),
mHasScissor(false),
mIsDoubleSided(false),
mTransparencyMode(TransparencyMode::DEFAULT) {
}
FMaterialInstance::FMaterialInstance() noexcept = default;
FMaterialInstance::FMaterialInstance(FEngine& engine,
FMaterialInstance const* other, const char* name)
: mMaterial(other->mMaterial),
mPolygonOffset(other->mPolygonOffset),
mStencilState(other->mStencilState),
mMaskThreshold(other->mMaskThreshold),
mSpecularAntiAliasingVariance(other->mSpecularAntiAliasingVariance),
mSpecularAntiAliasingThreshold(other->mSpecularAntiAliasingThreshold),
mCulling(other->mCulling),
mDepthFunc(other->mDepthFunc),
mColorWrite(other->mColorWrite),
mDepthWrite(other->mDepthWrite),
mHasScissor(false),
mIsDoubleSided(other->mIsDoubleSided),
mStencilState(other->mStencilState),
mDepthFunc(other->mDepthFunc),
mScissorRect(other->mScissorRect),
mName(name ? CString(name) : other->mName) {
@@ -76,23 +63,10 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
mSbHandle = driver.createSamplerGroup(mSamplers.getSize());
}
if (material->hasDoubleSidedCapability()) {
setDoubleSided(mIsDoubleSided);
}
if (material->getBlendingMode() == BlendingMode::MASKED) {
setMaskThreshold(mMaskThreshold);
}
if (material->hasSpecularAntiAliasing()) {
setSpecularAntiAliasingThreshold(mSpecularAntiAliasingThreshold);
setSpecularAntiAliasingVariance(mSpecularAntiAliasingVariance);
}
setTransparencyMode(material->getTransparencyMode());
mMaterialSortingKey = RenderPass::makeMaterialSortingKey(
material->getId(), material->generateMaterialInstanceId());
setTransparencyMode(material->getTransparencyMode());
}
FMaterialInstance* FMaterialInstance::duplicate(
@@ -209,29 +183,14 @@ void FMaterialInstance::setParameterImpl(std::string_view name,
void FMaterialInstance::setMaskThreshold(float threshold) noexcept {
setParameter("_maskThreshold", math::saturate(threshold));
mMaskThreshold = math::saturate(threshold);
}
float FMaterialInstance::getMaskThreshold() const noexcept {
return mMaskThreshold;
}
void FMaterialInstance::setSpecularAntiAliasingVariance(float variance) noexcept {
setParameter("_specularAntiAliasingVariance", math::saturate(variance));
mSpecularAntiAliasingVariance = math::saturate(variance);
}
float FMaterialInstance::getSpecularAntiAliasingVariance() const noexcept {
return mSpecularAntiAliasingVariance;
}
void FMaterialInstance::setSpecularAntiAliasingThreshold(float threshold) noexcept {
setParameter("_specularAntiAliasingThreshold", math::saturate(threshold * threshold));
mSpecularAntiAliasingThreshold = std::sqrt(math::saturate(threshold * threshold));
}
float FMaterialInstance::getSpecularAntiAliasingThreshold() const noexcept {
return mSpecularAntiAliasingThreshold;
}
void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
@@ -243,11 +202,6 @@ void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
if (doubleSided) {
setCullingMode(CullingMode::NONE);
}
mIsDoubleSided = doubleSided;
}
bool FMaterialInstance::isDoubleSided() const noexcept {
return mIsDoubleSided;
}
void FMaterialInstance::setTransparencyMode(TransparencyMode mode) noexcept {
@@ -258,10 +212,6 @@ void FMaterialInstance::setDepthCulling(bool enable) noexcept {
mDepthFunc = enable ? RasterState::DepthFunc::GE : RasterState::DepthFunc::A;
}
bool FMaterialInstance::isDepthCullingEnabled() const noexcept {
return mDepthFunc != RasterState::DepthFunc::A;
}
const char* FMaterialInstance::getName() const noexcept {
// To decide whether to use the parent material name as a fallback, we check for the nullness of
// the instance's CString rather than calling empty(). This allows instances to override the
+11 -30
View File
@@ -89,11 +89,9 @@ public:
backend::CullingMode getCullingMode() const noexcept { return mCulling; }
bool isColorWriteEnabled() const noexcept { return mColorWrite; }
bool getColorWrite() const noexcept { return mColorWrite; }
bool isDepthWriteEnabled() const noexcept { return mDepthWrite; }
bool isStencilWriteEnabled() const noexcept { return mStencilState.stencilWrite; }
bool getDepthWrite() const noexcept { return mDepthWrite; }
backend::StencilState getStencilState() const noexcept { return mStencilState; }
@@ -110,20 +108,12 @@ public:
void setMaskThreshold(float threshold) noexcept;
float getMaskThreshold() const noexcept;
void setSpecularAntiAliasingVariance(float variance) noexcept;
float getSpecularAntiAliasingVariance() const noexcept;
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
float getSpecularAntiAliasingThreshold() const noexcept;
void setDoubleSided(bool doubleSided) noexcept;
bool isDoubleSided() const noexcept;
void setTransparencyMode(TransparencyMode mode) noexcept;
void setCullingMode(CullingMode culling) noexcept { mCulling = culling; }
@@ -136,8 +126,6 @@ public:
void setDepthCulling(bool enable) noexcept;
bool isDepthCullingEnabled() const noexcept;
void setStencilCompareFunction(StencilCompareFunc func, StencilFace face) noexcept {
if (any(face & StencilFace::FRONT)) {
mStencilState.front.stencilFunc = func;
@@ -234,26 +222,19 @@ private:
// keep these grouped, they're accessed together in the render-loop
FMaterial const* mMaterial = nullptr;
backend::Handle<backend::HwBufferObject> mUbHandle;
backend::Handle<backend::HwSamplerGroup> mSbHandle;
UniformBuffer mUniforms;
backend::SamplerGroup mSamplers;
backend::PolygonOffset mPolygonOffset{};
backend::StencilState mStencilState{};
float mMaskThreshold = 0.0f;
float mSpecularAntiAliasingVariance = 0.0f;
float mSpecularAntiAliasingThreshold = 0.0f;
backend::CullingMode mCulling : 2;
backend::RasterState::DepthFunc mDepthFunc : 3;
bool mColorWrite : 1;
bool mDepthWrite : 1;
bool mHasScissor : 1;
bool mIsDoubleSided : 1;
TransparencyMode mTransparencyMode : 2;
backend::PolygonOffset mPolygonOffset;
backend::CullingMode mCulling;
bool mColorWrite;
bool mDepthWrite;
bool mHasScissor = false;
backend::StencilState mStencilState = {};
backend::RasterState::DepthFunc mDepthFunc;
TransparencyMode mTransparencyMode;
uint64_t mMaterialSortingKey = 0;
+5 -8
View File
@@ -656,7 +656,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
RenderPass shadowPass(pass);
shadowPass.setVariant(shadowVariant);
auto shadows = view.renderShadowMaps(engine, fg, cameraInfo, mShaderUserTime, shadowPass);
auto shadows = view.renderShadowMaps(fg, engine, cameraInfo, shadowPass);
blackboard["shadows"] = shadows;
}
@@ -740,8 +740,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// view set-ups that need to happen before rendering
fg.addTrivialSideEffectPass("Prepare View Uniforms",
[=, &view, &engine](DriverApi& driver) {
view.prepareCamera(engine, cameraInfo);
[=, &uniforms = view.getPerViewUniforms()](DriverApi& driver) {
uniforms.prepareCamera(cameraInfo);
// The code here is a little fragile. In theory, we need to call prepareViewport()
// for each render pass, because the viewport parameters depend on the resolution.
@@ -761,14 +761,11 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// The reason why this bug is acceptable is that the viewport parameters are
// currently only used for generating noise, so it's not too bad.
view.prepareViewport(svp,
uniforms.prepareViewport(svp,
xvp.left * aoOptions.resolution,
xvp.bottom * aoOptions.resolution);
view.commitUniforms(driver);
// set uniforms and samplers for the color passes
view.bindPerViewUniformsAndSamplers(driver);
uniforms.commit(driver);
});
// --------------------------------------------------------------------------------------------
+13 -25
View File
@@ -383,7 +383,7 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
intensity = skybox ? skybox->getIntensity() : FIndirectLight::DEFAULT_INTENSITY;
}
mPerViewUniforms.prepareAmbientLight(engine, *ibl, intensity, exposure);
mPerViewUniforms.prepareAmbientLight(*ibl, intensity, exposure);
/*
* Directional light (always at index 0)
@@ -391,7 +391,7 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
FLightManager::Instance directionalLight = lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
const float3 sceneSpaceDirection = lightData.elementAt<FScene::DIRECTION>(0); // guaranteed normalized
mPerViewUniforms.prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
mPerViewUniforms.prepareDirectionalLight(exposure, sceneSpaceDirection, directionalLight);
mHasDirectionalLight = directionalLight.isValid();
}
@@ -602,23 +602,13 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena,
* Update driver state
*/
mPerViewUniforms.prepareTime(engine, userTime);
mPerViewUniforms.prepareTime(userTime);
mPerViewUniforms.prepareFog(cameraInfo.getPosition(), mFogOptions);
mPerViewUniforms.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
mPerViewUniforms.prepareTemporalNoise(mTemporalAntiAliasingOptions);
mPerViewUniforms.prepareBlending(needsAlphaChannel);
}
void FView::bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept {
mPerViewUniforms.bind(driver);
driver.bindUniformBuffer(+UniformBindingPoints::LIGHTS,
mLightUbh);
driver.bindUniformBuffer(+UniformBindingPoints::SHADOW,
mShadowMapManager.getShadowUniformsHandle());
driver.bindUniformBuffer(+UniformBindingPoints::FROXEL_RECORDS,
mFroxelizer.getRecordBuffer());
// set uniforms and samplers
bindPerViewUniformsAndSamplers(driver);
}
void FView::computeVisibilityMasks(
@@ -666,14 +656,12 @@ UTILS_NOINLINE
void FView::prepareUpscaler(float2 scale) const noexcept {
SYSTRACE_CALL();
const float bias = (mDynamicResolution.quality >= QualityLevel::HIGH) ?
std::log2(std::min(scale.x, scale.y)) : 0.0f;
mPerViewUniforms.prepareLodBias(bias);
mPerViewUniforms.prepareUpscaler(scale, mDynamicResolution);
}
void FView::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept {
void FView::prepareCamera(const CameraInfo& cameraInfo) const noexcept {
SYSTRACE_CALL();
mPerViewUniforms.prepareCamera(engine, cameraInfo);
mPerViewUniforms.prepareCamera(cameraInfo);
}
void FView::prepareViewport(const filament::Viewport& viewport,
@@ -723,7 +711,7 @@ void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
}
}
void FView::prepareShadowMapping(bool highPrecision) const noexcept {
void FView::prepareShadowMap(bool highPrecision) const noexcept {
mPerViewUniforms.prepareShadowMapping(highPrecision);
}
@@ -906,9 +894,9 @@ void FView::updatePrimitivesLod(FEngine& engine, const CameraInfo&,
}
}
FrameGraphId<FrameGraphTexture> FView::renderShadowMaps(FEngine& engine, FrameGraph& fg,
CameraInfo const& cameraInfo, float4 const& userTime, RenderPass const& pass) noexcept {
return mShadowMapManager.render(engine, fg, pass, *this, cameraInfo, userTime);
FrameGraphId<FrameGraphTexture> FView::renderShadowMaps(FrameGraph& fg, FEngine& engine,
CameraInfo const& cameraInfo, RenderPass const& pass) noexcept {
return mShadowMapManager.render(fg, engine, pass, *this, cameraInfo);
}
void FView::commitFrameHistory(FEngine& engine) noexcept {
+11 -7
View File
@@ -92,8 +92,6 @@ public:
filament::Viewport const& viewport, CameraInfo const& cameraInfo,
math::float4 const& userTime, bool needsAlphaChannel) noexcept;
void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept;
void setScene(FScene* scene) { mScene = scene; }
FScene const* getScene() const noexcept { return mScene; }
FScene* getScene() noexcept { return mScene; }
@@ -134,7 +132,7 @@ public:
}
void prepareUpscaler(math::float2 scale) const noexcept;
void prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept;
void prepareCamera(const CameraInfo& cameraInfo) const noexcept;
void prepareViewport(const Viewport& viewport, uint32_t xoffset, uint32_t yoffset) const noexcept;
void prepareShadowing(FEngine& engine, backend::DriverApi& driver,
FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData,
@@ -150,7 +148,7 @@ public:
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept;
void prepareStructure(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadow(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadowMapping(bool highPrecision) const noexcept;
void prepareShadowMap(bool highPrecision) const noexcept;
void cleanupRenderPasses() const noexcept;
void froxelize(FEngine& engine, math::mat4f const& viewMatrix) const noexcept;
@@ -167,9 +165,8 @@ public:
bool hasPCSS() const noexcept { return mShadowType == ShadowType::PCSS; }
bool hasPicking() const noexcept { return mActivePickingQueriesList != nullptr; }
FrameGraphId<FrameGraphTexture> renderShadowMaps(FEngine& engine, FrameGraph& fg,
CameraInfo const& cameraInfo, math::float4 const& userTime,
RenderPass const& pass) noexcept;
FrameGraphId<FrameGraphTexture> renderShadowMaps(FrameGraph& fg, FEngine& engine,
CameraInfo const& cameraInfo, RenderPass const& pass) noexcept;
void updatePrimitivesLod(
FEngine& engine, const CameraInfo& camera,
@@ -454,6 +451,13 @@ private:
Culler::result_type* visibleMask,
size_t count);
void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept {
mPerViewUniforms.bind(driver);
driver.bindUniformBuffer(+UniformBindingPoints::LIGHTS, mLightUbh);
driver.bindUniformBuffer(+UniformBindingPoints::SHADOW, mShadowMapManager.getShadowUniformsHandle());
driver.bindUniformBuffer(+UniformBindingPoints::FROXEL_RECORDS, mFroxelizer.getRecordBuffer());
}
// Clean-up the whole history, free all resources. This is typically called when the View is
// being terminated.
void drainFrameHistory(FEngine& engine) noexcept;
-1
View File
@@ -42,7 +42,6 @@ list(APPEND RESGEN_SOURCE ${DUMMY_SRC})
# away in Release builds
if (TNT_DEV)
add_executable(test_${TARGET}
filament_AtlasAllocator_test.cpp
filament_test_exposure.cpp
filament_rendering_test.cpp
filament_framegraph_test.cpp
@@ -1,149 +0,0 @@
/*
* Copyright (C) 2022 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 <gtest/gtest.h>
#include "AtlasAllocator.h"
using namespace filament;
TEST(AtlasAllocator, AllocateFirstLevel) {
AtlasAllocator allocator;
auto a = allocator.allocateInLayer(0);
EXPECT_TRUE(a.l == 0 && a.code == 0);
auto b = allocator.allocateInLayer(1);
EXPECT_TRUE(b.l < 0);
auto c = allocator.allocateInLayer(2);
EXPECT_TRUE(c.l < 0);
auto d = allocator.allocateInLayer(5);
EXPECT_TRUE(d.l < 0);
}
TEST(AtlasAllocator, AllocateSecondLevel) {
AtlasAllocator allocator;
auto d0 = allocator.allocateInLayer(1);
EXPECT_TRUE(d0.l == 1 && d0.code == 0);
auto d1 = allocator.allocateInLayer(1);
EXPECT_TRUE(d1.l == 1 && d1.code == 1);
auto d2 = allocator.allocateInLayer(1);
EXPECT_TRUE(d2.l == 1 && d2.code == 2);
auto d3 = allocator.allocateInLayer(1);
EXPECT_TRUE(d3.l == 1 && d3.code == 3);
}
TEST(AtlasAllocator, AllocateMixed0) {
AtlasAllocator allocator;
auto e0 = allocator.allocateInLayer(1);
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
auto e1 = allocator.allocateInLayer(1);
EXPECT_TRUE(e1.l == 1 && e1.code == 1);
auto e2 = allocator.allocateInLayer(1);
EXPECT_TRUE(e2.l == 1 && e2.code == 2);
auto e3 = allocator.allocateInLayer(2);
EXPECT_TRUE(e3.l == 2 && e3.code == 12);
auto e4 = allocator.allocateInLayer(1);
EXPECT_TRUE(e4.l < 0);
}
TEST(AtlasAllocator, AllocateMixed1) {
AtlasAllocator allocator;
auto e0 = allocator.allocateInLayer(1);
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
auto e1 = allocator.allocateInLayer(1);
EXPECT_TRUE(e1.l == 1 && e1.code == 1);
auto e2 = allocator.allocateInLayer(2);
EXPECT_TRUE(e2.l == 2 && e2.code == 8);
auto e3 = allocator.allocateInLayer(1);
EXPECT_TRUE(e3.l == 1 && e3.code == 3);
}
TEST(AtlasAllocator, AllocateMixed2) {
AtlasAllocator allocator;
auto e0 = allocator.allocateInLayer(1);
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
auto e1 = allocator.allocateInLayer(1);
EXPECT_TRUE(e1.l == 1 && e1.code == 1);
auto c0 = allocator.allocateInLayer(2);
EXPECT_TRUE(c0.l == 2 && c0.code == 8);
auto c1 = allocator.allocateInLayer(2);
EXPECT_TRUE(c1.l == 2 && c1.code == 9);
auto c2 = allocator.allocateInLayer(2);
EXPECT_TRUE(c2.l == 2 && c2.code == 10);
auto c3 = allocator.allocateInLayer(2);
EXPECT_TRUE(c3.l == 2 && c3.code == 11);
auto c4 = allocator.allocateInLayer(2);
EXPECT_TRUE(c4.l == 2 && c4.code == 12);
auto c5 = allocator.allocateInLayer(2);
EXPECT_TRUE(c5.l == 2 && c5.code == 13);
auto c6 = allocator.allocateInLayer(2);
EXPECT_TRUE(c6.l == 2 && c6.code == 14);
auto c7 = allocator.allocateInLayer(2);
EXPECT_TRUE(c7.l == 2 && c7.code == 15);
}
TEST(AtlasAllocator, AllocateBySize) {
AtlasAllocator allocator(256);
Viewport vp(0,0,256,256);
auto vp0 = allocator.allocate(256);
EXPECT_EQ(vp0, vp);
auto vp1 = allocator.allocate(128);
EXPECT_TRUE(vp1.empty());
}
TEST(AtlasAllocator, AllocateBySizeOneOfEach) {
AtlasAllocator allocator(256);
Viewport r0(0,0,128,128);
Viewport r1(128,0,64,64);
Viewport r2(192,0,32,32);
auto vp0 = allocator.allocate(128);
auto vp1 = allocator.allocate(64);
auto vp2 = allocator.allocate(32);
auto vp3 = allocator.allocate(16);
EXPECT_EQ(vp0, r0);
EXPECT_EQ(vp1, r1);
EXPECT_EQ(vp2, r2);
EXPECT_TRUE(vp3.empty());
}
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.28.2"
spec.version = "1.28.0"
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.28.2/filament-v1.28.2-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.28.0/filament-v1.28.0-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
-17
View File
@@ -1,17 +0,0 @@
## Updating Vulkan headers
To update the Vulkan headers, perform the following steps.
First, find the latest version of the Vulkan headers here:
https://github.com/KhronosGroup/Vulkan-Headers/tags
Replace `v1.3.232` with the latest version of the headers in the following commands.
```
cd libs/bluevk
curl -OL https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v1.3.232.zip
unzip v1.3.232.zip
rsync -r Vulkan-Headers-1.3.232/include/vulkan/ include/vulkan --delete
rsync -r Vulkan-Headers-1.3.232/include/vk_video/ include/vk_video --delete
rm include/vulkan/*.hpp
rm -r Vulkan-Headers-1.3.232 v1.3.232.zip
```
-21
View File
@@ -37,27 +37,6 @@
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#if defined(__ANDROID__)
#define VK_USE_PLATFORM_ANDROID_KHR 1
#elif defined(IOS)
#define VK_USE_PLATFORM_IOS_MVK 1
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_XCB)
#define VK_USE_PLATFORM_XCB_KHR 1
#endif
#if defined(FILAMENT_SUPPORTS_XLIB)
#define VK_USE_PLATFORM_XLIB_KHR 1
#endif
#if defined(FILAMENT_SUPPORTS_WAYLAND)
#define VK_USE_PLATFORM_WAYLAND_KHR 1
#endif
#elif defined(__APPLE__)
#define VK_USE_PLATFORM_MACOS_MVK 1
#elif defined(WIN32)
#define VK_USE_PLATFORM_WIN32_KHR 1
#endif
#include <vulkan/vulkan.h>
#endif
@@ -21,13 +21,16 @@ extern "C" {
#define vulkan_video_codec_h264std 1
#include <stdint.h>
// Vulkan 0.9 provisional Vulkan video H.264 encode and decode std specification version number
#define VK_STD_VULKAN_VIDEO_CODEC_H264_API_VERSION_0_9_5 VK_MAKE_VIDEO_STD_VERSION(0, 9, 5) // Patch version should always be set to 0
#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32
#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6
#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16
#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6
#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 2
#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64
#define STD_VIDEO_H264_MAX_NUM_LIST_REF 32
#define STD_VIDEO_H264_MAX_CHROMA_PLANES 2
#define VK_STD_VULKAN_VIDEO_CODEC_H264_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_API_VERSION_0_9_5
#define VK_STD_VULKAN_VIDEO_CODEC_H264_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264"
typedef enum StdVideoH264ChromaFormatIdc {
STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0,
@@ -47,29 +50,29 @@ typedef enum StdVideoH264ProfileIdc {
STD_VIDEO_H264_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264ProfileIdc;
typedef enum StdVideoH264LevelIdc {
STD_VIDEO_H264_LEVEL_IDC_1_0 = 0,
STD_VIDEO_H264_LEVEL_IDC_1_1 = 1,
STD_VIDEO_H264_LEVEL_IDC_1_2 = 2,
STD_VIDEO_H264_LEVEL_IDC_1_3 = 3,
STD_VIDEO_H264_LEVEL_IDC_2_0 = 4,
STD_VIDEO_H264_LEVEL_IDC_2_1 = 5,
STD_VIDEO_H264_LEVEL_IDC_2_2 = 6,
STD_VIDEO_H264_LEVEL_IDC_3_0 = 7,
STD_VIDEO_H264_LEVEL_IDC_3_1 = 8,
STD_VIDEO_H264_LEVEL_IDC_3_2 = 9,
STD_VIDEO_H264_LEVEL_IDC_4_0 = 10,
STD_VIDEO_H264_LEVEL_IDC_4_1 = 11,
STD_VIDEO_H264_LEVEL_IDC_4_2 = 12,
STD_VIDEO_H264_LEVEL_IDC_5_0 = 13,
STD_VIDEO_H264_LEVEL_IDC_5_1 = 14,
STD_VIDEO_H264_LEVEL_IDC_5_2 = 15,
STD_VIDEO_H264_LEVEL_IDC_6_0 = 16,
STD_VIDEO_H264_LEVEL_IDC_6_1 = 17,
STD_VIDEO_H264_LEVEL_IDC_6_2 = 18,
STD_VIDEO_H264_LEVEL_IDC_INVALID = 0x7FFFFFFF,
STD_VIDEO_H264_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264LevelIdc;
typedef enum StdVideoH264Level {
STD_VIDEO_H264_LEVEL_1_0 = 0,
STD_VIDEO_H264_LEVEL_1_1 = 1,
STD_VIDEO_H264_LEVEL_1_2 = 2,
STD_VIDEO_H264_LEVEL_1_3 = 3,
STD_VIDEO_H264_LEVEL_2_0 = 4,
STD_VIDEO_H264_LEVEL_2_1 = 5,
STD_VIDEO_H264_LEVEL_2_2 = 6,
STD_VIDEO_H264_LEVEL_3_0 = 7,
STD_VIDEO_H264_LEVEL_3_1 = 8,
STD_VIDEO_H264_LEVEL_3_2 = 9,
STD_VIDEO_H264_LEVEL_4_0 = 10,
STD_VIDEO_H264_LEVEL_4_1 = 11,
STD_VIDEO_H264_LEVEL_4_2 = 12,
STD_VIDEO_H264_LEVEL_5_0 = 13,
STD_VIDEO_H264_LEVEL_5_1 = 14,
STD_VIDEO_H264_LEVEL_5_2 = 15,
STD_VIDEO_H264_LEVEL_6_0 = 16,
STD_VIDEO_H264_LEVEL_6_1 = 17,
STD_VIDEO_H264_LEVEL_6_2 = 18,
STD_VIDEO_H264_LEVEL_INVALID = 0x7FFFFFFF,
STD_VIDEO_H264_LEVEL_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264Level;
typedef enum StdVideoH264PocType {
STD_VIDEO_H264_POC_TYPE_0 = 0,
@@ -194,7 +197,6 @@ typedef struct StdVideoH264HrdParameters {
uint8_t cpb_cnt_minus1;
uint8_t bit_rate_scale;
uint8_t cpb_size_scale;
uint8_t reserved1;
uint32_t bit_rate_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
uint32_t cpb_size_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
uint8_t cbr_flag[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
@@ -205,22 +207,19 @@ typedef struct StdVideoH264HrdParameters {
} StdVideoH264HrdParameters;
typedef struct StdVideoH264SequenceParameterSetVui {
StdVideoH264SpsVuiFlags flags;
StdVideoH264AspectRatioIdc aspect_ratio_idc;
uint16_t sar_width;
uint16_t sar_height;
uint8_t video_format;
uint8_t colour_primaries;
uint8_t transfer_characteristics;
uint8_t matrix_coefficients;
uint32_t num_units_in_tick;
uint32_t time_scale;
uint8_t max_num_reorder_frames;
uint8_t max_dec_frame_buffering;
uint8_t chroma_sample_loc_type_top_field;
uint8_t chroma_sample_loc_type_bottom_field;
uint32_t reserved1;
const StdVideoH264HrdParameters* pHrdParameters;
StdVideoH264AspectRatioIdc aspect_ratio_idc;
uint16_t sar_width;
uint16_t sar_height;
uint8_t video_format;
uint8_t color_primaries;
uint8_t transfer_characteristics;
uint8_t matrix_coefficients;
uint32_t num_units_in_tick;
uint32_t time_scale;
StdVideoH264HrdParameters* pHrdParameters;
uint8_t max_num_reorder_frames;
uint8_t max_dec_frame_buffering;
StdVideoH264SpsVuiFlags flags;
} StdVideoH264SequenceParameterSetVui;
typedef struct StdVideoH264SpsFlags {
@@ -243,38 +242,36 @@ typedef struct StdVideoH264SpsFlags {
} StdVideoH264SpsFlags;
typedef struct StdVideoH264ScalingLists {
uint16_t scaling_list_present_mask;
uint16_t use_default_scaling_matrix_mask;
uint8_t ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS];
uint8_t ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS];
uint8_t scaling_list_present_mask;
uint8_t use_default_scaling_matrix_mask;
uint8_t ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS];
uint8_t ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS];
} StdVideoH264ScalingLists;
typedef struct StdVideoH264SequenceParameterSet {
StdVideoH264SpsFlags flags;
StdVideoH264ProfileIdc profile_idc;
StdVideoH264LevelIdc level_idc;
StdVideoH264ChromaFormatIdc chroma_format_idc;
uint8_t seq_parameter_set_id;
uint8_t bit_depth_luma_minus8;
uint8_t bit_depth_chroma_minus8;
uint8_t log2_max_frame_num_minus4;
StdVideoH264PocType pic_order_cnt_type;
int32_t offset_for_non_ref_pic;
int32_t offset_for_top_to_bottom_field;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
uint8_t num_ref_frames_in_pic_order_cnt_cycle;
uint8_t max_num_ref_frames;
uint8_t reserved1;
uint32_t pic_width_in_mbs_minus1;
uint32_t pic_height_in_map_units_minus1;
uint32_t frame_crop_left_offset;
uint32_t frame_crop_right_offset;
uint32_t frame_crop_top_offset;
uint32_t frame_crop_bottom_offset;
uint32_t reserved2;
const int32_t* pOffsetForRefFrame;
const StdVideoH264ScalingLists* pScalingLists;
const StdVideoH264SequenceParameterSetVui* pSequenceParameterSetVui;
StdVideoH264ProfileIdc profile_idc;
StdVideoH264Level level_idc;
uint8_t seq_parameter_set_id;
StdVideoH264ChromaFormatIdc chroma_format_idc;
uint8_t bit_depth_luma_minus8;
uint8_t bit_depth_chroma_minus8;
uint8_t log2_max_frame_num_minus4;
StdVideoH264PocType pic_order_cnt_type;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
int32_t offset_for_non_ref_pic;
int32_t offset_for_top_to_bottom_field;
uint8_t num_ref_frames_in_pic_order_cnt_cycle;
uint8_t max_num_ref_frames;
uint32_t pic_width_in_mbs_minus1;
uint32_t pic_height_in_map_units_minus1;
uint32_t frame_crop_left_offset;
uint32_t frame_crop_right_offset;
uint32_t frame_crop_top_offset;
uint32_t frame_crop_bottom_offset;
StdVideoH264SpsFlags flags;
int32_t* pOffsetForRefFrame;
StdVideoH264ScalingLists* pScalingLists;
StdVideoH264SequenceParameterSetVui* pSequenceParameterSetVui;
} StdVideoH264SequenceParameterSet;
typedef struct StdVideoH264PpsFlags {
@@ -282,24 +279,25 @@ typedef struct StdVideoH264PpsFlags {
uint32_t redundant_pic_cnt_present_flag : 1;
uint32_t constrained_intra_pred_flag : 1;
uint32_t deblocking_filter_control_present_flag : 1;
uint32_t weighted_bipred_idc_flag : 1;
uint32_t weighted_pred_flag : 1;
uint32_t bottom_field_pic_order_in_frame_present_flag : 1;
uint32_t pic_order_present_flag : 1;
uint32_t entropy_coding_mode_flag : 1;
uint32_t pic_scaling_matrix_present_flag : 1;
} StdVideoH264PpsFlags;
typedef struct StdVideoH264PictureParameterSet {
StdVideoH264PpsFlags flags;
uint8_t seq_parameter_set_id;
uint8_t pic_parameter_set_id;
uint8_t num_ref_idx_l0_default_active_minus1;
uint8_t num_ref_idx_l1_default_active_minus1;
StdVideoH264WeightedBipredIdc weighted_bipred_idc;
int8_t pic_init_qp_minus26;
int8_t pic_init_qs_minus26;
int8_t chroma_qp_index_offset;
int8_t second_chroma_qp_index_offset;
const StdVideoH264ScalingLists* pScalingLists;
uint8_t seq_parameter_set_id;
uint8_t pic_parameter_set_id;
uint8_t num_ref_idx_l0_default_active_minus1;
uint8_t num_ref_idx_l1_default_active_minus1;
StdVideoH264WeightedBipredIdc weighted_bipred_idc;
int8_t pic_init_qp_minus26;
int8_t pic_init_qs_minus26;
int8_t chroma_qp_index_offset;
int8_t second_chroma_qp_index_offset;
StdVideoH264PpsFlags flags;
StdVideoH264ScalingLists* pScalingLists;
} StdVideoH264PictureParameterSet;
@@ -20,12 +20,8 @@ extern "C" {
#define vulkan_video_codec_h264std_decode 1
// Vulkan 0.9 provisional Vulkan video H.264 decode std specification version number
#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_0_9_8 VK_MAKE_VIDEO_STD_VERSION(0, 9, 8) // Patch version should always be set to 0
#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2
#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_0_9_8
#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode"
#define STD_VIDEO_DECODE_H264_MVC_REF_LIST_SIZE 15
typedef enum StdVideoDecodeH264FieldOrderCount {
STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0,
@@ -43,30 +39,57 @@ typedef struct StdVideoDecodeH264PictureInfoFlags {
} StdVideoDecodeH264PictureInfoFlags;
typedef struct StdVideoDecodeH264PictureInfo {
StdVideoDecodeH264PictureInfoFlags flags;
uint8_t seq_parameter_set_id;
uint8_t pic_parameter_set_id;
uint8_t reserved1;
uint8_t reserved2;
uint16_t reserved;
uint16_t frame_num;
uint16_t idr_pic_id;
int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE];
StdVideoDecodeH264PictureInfoFlags flags;
} StdVideoDecodeH264PictureInfo;
typedef struct StdVideoDecodeH264ReferenceInfoFlags {
uint32_t top_field_flag : 1;
uint32_t bottom_field_flag : 1;
uint32_t used_for_long_term_reference : 1;
uint32_t is_long_term : 1;
uint32_t is_non_existing : 1;
} StdVideoDecodeH264ReferenceInfoFlags;
typedef struct StdVideoDecodeH264ReferenceInfo {
StdVideoDecodeH264ReferenceInfoFlags flags;
uint16_t FrameNum;
uint16_t reserved;
int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE];
int32_t PicOrderCnt[2];
StdVideoDecodeH264ReferenceInfoFlags flags;
} StdVideoDecodeH264ReferenceInfo;
typedef struct StdVideoDecodeH264MvcElementFlags {
uint32_t non_idr : 1;
uint32_t anchor_pic : 1;
uint32_t inter_view : 1;
} StdVideoDecodeH264MvcElementFlags;
typedef struct StdVideoDecodeH264MvcElement {
StdVideoDecodeH264MvcElementFlags flags;
uint16_t viewOrderIndex;
uint16_t viewId;
uint16_t temporalId;
uint16_t priorityId;
uint16_t numOfAnchorRefsInL0;
uint16_t viewIdOfAnchorRefsInL0[STD_VIDEO_DECODE_H264_MVC_REF_LIST_SIZE];
uint16_t numOfAnchorRefsInL1;
uint16_t viewIdOfAnchorRefsInL1[STD_VIDEO_DECODE_H264_MVC_REF_LIST_SIZE];
uint16_t numOfNonAnchorRefsInL0;
uint16_t viewIdOfNonAnchorRefsInL0[STD_VIDEO_DECODE_H264_MVC_REF_LIST_SIZE];
uint16_t numOfNonAnchorRefsInL1;
uint16_t viewIdOfNonAnchorRefsInL1[STD_VIDEO_DECODE_H264_MVC_REF_LIST_SIZE];
} StdVideoDecodeH264MvcElement;
typedef struct StdVideoDecodeH264Mvc {
uint32_t viewId0;
uint32_t mvcElementCount;
StdVideoDecodeH264MvcElement* pMvcElements;
} StdVideoDecodeH264Mvc;
#ifdef __cplusplus
}
@@ -20,32 +20,6 @@ extern "C" {
#define vulkan_video_codec_h264std_encode 1
// Vulkan 0.9 provisional Vulkan video H.264 encode std specification version number
#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8 VK_MAKE_VIDEO_STD_VERSION(0, 9, 8) // Patch version should always be set to 0
#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8
#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode"
typedef struct StdVideoEncodeH264WeightTableFlags {
uint32_t luma_weight_l0_flag;
uint32_t chroma_weight_l0_flag;
uint32_t luma_weight_l1_flag;
uint32_t chroma_weight_l1_flag;
} StdVideoEncodeH264WeightTableFlags;
typedef struct StdVideoEncodeH264WeightTable {
StdVideoEncodeH264WeightTableFlags flags;
uint8_t luma_log2_weight_denom;
uint8_t chroma_log2_weight_denom;
int8_t luma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF];
int8_t luma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF];
int8_t chroma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
int8_t chroma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
int8_t luma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF];
int8_t luma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF];
int8_t chroma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
int8_t chroma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
} StdVideoEncodeH264WeightTable;
typedef struct StdVideoEncodeH264SliceHeaderFlags {
uint32_t direct_spatial_mv_pred_flag : 1;
uint32_t num_ref_idx_active_override_flag : 1;
@@ -57,11 +31,11 @@ typedef struct StdVideoEncodeH264SliceHeaderFlags {
typedef struct StdVideoEncodeH264PictureInfoFlags {
uint32_t idr_flag : 1;
uint32_t is_reference_flag : 1;
uint32_t used_for_long_term_reference : 1;
uint32_t long_term_reference_flag : 1;
} StdVideoEncodeH264PictureInfoFlags;
typedef struct StdVideoEncodeH264ReferenceInfoFlags {
uint32_t used_for_long_term_reference : 1;
uint32_t is_long_term : 1;
} StdVideoEncodeH264ReferenceInfoFlags;
typedef struct StdVideoEncodeH264RefMgmtFlags {
@@ -84,19 +58,17 @@ typedef struct StdVideoEncodeH264RefPicMarkingEntry {
} StdVideoEncodeH264RefPicMarkingEntry;
typedef struct StdVideoEncodeH264RefMemMgmtCtrlOperations {
StdVideoEncodeH264RefMgmtFlags flags;
uint8_t refList0ModOpCount;
const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations;
uint8_t refList1ModOpCount;
const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations;
uint8_t refPicMarkingOpCount;
const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations;
StdVideoEncodeH264RefMgmtFlags flags;
uint8_t refList0ModOpCount;
StdVideoEncodeH264RefListModEntry* pRefList0ModOperations;
uint8_t refList1ModOpCount;
StdVideoEncodeH264RefListModEntry* pRefList1ModOperations;
uint8_t refPicMarkingOpCount;
StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations;
} StdVideoEncodeH264RefMemMgmtCtrlOperations;
typedef struct StdVideoEncodeH264PictureInfo {
StdVideoEncodeH264PictureInfoFlags flags;
uint8_t seq_parameter_set_id;
uint8_t pic_parameter_set_id;
StdVideoH264PictureType pictureType;
uint32_t frame_num;
int32_t PicOrderCnt;
@@ -114,6 +86,8 @@ typedef struct StdVideoEncodeH264SliceHeader {
StdVideoEncodeH264SliceHeaderFlags flags;
uint32_t first_mb_in_slice;
StdVideoH264SliceType slice_type;
uint8_t seq_parameter_set_id;
uint8_t pic_parameter_set_id;
uint16_t idr_pic_id;
uint8_t num_ref_idx_l0_active_minus1;
uint8_t num_ref_idx_l1_active_minus1;
@@ -121,7 +95,6 @@ typedef struct StdVideoEncodeH264SliceHeader {
StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc;
int8_t slice_alpha_c0_offset_div2;
int8_t slice_beta_offset_div2;
const StdVideoEncodeH264WeightTable* pWeightTable;
} StdVideoEncodeH264SliceHeader;
@@ -20,7 +20,10 @@ extern "C" {
#define vulkan_video_codec_h265std 1
#define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7
// Vulkan 0.5 version number WIP
#define VK_STD_VULKAN_VIDEO_CODEC_H265_API_VERSION_0_9_5 VK_MAKE_VIDEO_STD_VERSION(0, 9, 5) // Patch version should always be set to 0
#define STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE 7
#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32
#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6
#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16
@@ -32,16 +35,11 @@ extern "C" {
#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64
#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3
#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128
#define STD_VIDEO_H265_MAX_DPB_SIZE 16
#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32
#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6
#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19
#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21
#define STD_VIDEO_H265_MAX_NUM_LIST_REF 15
#define STD_VIDEO_H265_MAX_CHROMA_PLANES 2
#define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64
#define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16
#define STD_VIDEO_H265_MAX_DELTA_POC 48
#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6
#define VK_STD_VULKAN_VIDEO_CODEC_H265_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_API_VERSION_0_9_5
#define VK_STD_VULKAN_VIDEO_CODEC_H265_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265"
typedef enum StdVideoH265ChromaFormatIdc {
STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0,
@@ -62,23 +60,23 @@ typedef enum StdVideoH265ProfileIdc {
STD_VIDEO_H265_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH265ProfileIdc;
typedef enum StdVideoH265LevelIdc {
STD_VIDEO_H265_LEVEL_IDC_1_0 = 0,
STD_VIDEO_H265_LEVEL_IDC_2_0 = 1,
STD_VIDEO_H265_LEVEL_IDC_2_1 = 2,
STD_VIDEO_H265_LEVEL_IDC_3_0 = 3,
STD_VIDEO_H265_LEVEL_IDC_3_1 = 4,
STD_VIDEO_H265_LEVEL_IDC_4_0 = 5,
STD_VIDEO_H265_LEVEL_IDC_4_1 = 6,
STD_VIDEO_H265_LEVEL_IDC_5_0 = 7,
STD_VIDEO_H265_LEVEL_IDC_5_1 = 8,
STD_VIDEO_H265_LEVEL_IDC_5_2 = 9,
STD_VIDEO_H265_LEVEL_IDC_6_0 = 10,
STD_VIDEO_H265_LEVEL_IDC_6_1 = 11,
STD_VIDEO_H265_LEVEL_IDC_6_2 = 12,
STD_VIDEO_H265_LEVEL_IDC_INVALID = 0x7FFFFFFF,
STD_VIDEO_H265_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH265LevelIdc;
typedef enum StdVideoH265Level {
STD_VIDEO_H265_LEVEL_1_0 = 0,
STD_VIDEO_H265_LEVEL_2_0 = 1,
STD_VIDEO_H265_LEVEL_2_1 = 2,
STD_VIDEO_H265_LEVEL_3_0 = 3,
STD_VIDEO_H265_LEVEL_3_1 = 4,
STD_VIDEO_H265_LEVEL_4_0 = 5,
STD_VIDEO_H265_LEVEL_4_1 = 6,
STD_VIDEO_H265_LEVEL_5_0 = 7,
STD_VIDEO_H265_LEVEL_5_1 = 8,
STD_VIDEO_H265_LEVEL_5_2 = 9,
STD_VIDEO_H265_LEVEL_6_0 = 10,
STD_VIDEO_H265_LEVEL_6_1 = 11,
STD_VIDEO_H265_LEVEL_6_2 = 12,
STD_VIDEO_H265_LEVEL_INVALID = 0x7FFFFFFF,
STD_VIDEO_H265_LEVEL_MAX_ENUM = 0x7FFFFFFF
} StdVideoH265Level;
typedef enum StdVideoH265SliceType {
STD_VIDEO_H265_SLICE_TYPE_B = 0,
@@ -96,33 +94,10 @@ typedef enum StdVideoH265PictureType {
STD_VIDEO_H265_PICTURE_TYPE_INVALID = 0x7FFFFFFF,
STD_VIDEO_H265_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoH265PictureType;
typedef enum StdVideoH265AspectRatioIdc {
STD_VIDEO_H265_ASPECT_RATIO_IDC_UNSPECIFIED = 0,
STD_VIDEO_H265_ASPECT_RATIO_IDC_SQUARE = 1,
STD_VIDEO_H265_ASPECT_RATIO_IDC_12_11 = 2,
STD_VIDEO_H265_ASPECT_RATIO_IDC_10_11 = 3,
STD_VIDEO_H265_ASPECT_RATIO_IDC_16_11 = 4,
STD_VIDEO_H265_ASPECT_RATIO_IDC_40_33 = 5,
STD_VIDEO_H265_ASPECT_RATIO_IDC_24_11 = 6,
STD_VIDEO_H265_ASPECT_RATIO_IDC_20_11 = 7,
STD_VIDEO_H265_ASPECT_RATIO_IDC_32_11 = 8,
STD_VIDEO_H265_ASPECT_RATIO_IDC_80_33 = 9,
STD_VIDEO_H265_ASPECT_RATIO_IDC_18_11 = 10,
STD_VIDEO_H265_ASPECT_RATIO_IDC_15_11 = 11,
STD_VIDEO_H265_ASPECT_RATIO_IDC_64_33 = 12,
STD_VIDEO_H265_ASPECT_RATIO_IDC_160_99 = 13,
STD_VIDEO_H265_ASPECT_RATIO_IDC_4_3 = 14,
STD_VIDEO_H265_ASPECT_RATIO_IDC_3_2 = 15,
STD_VIDEO_H265_ASPECT_RATIO_IDC_2_1 = 16,
STD_VIDEO_H265_ASPECT_RATIO_IDC_EXTENDED_SAR = 255,
STD_VIDEO_H265_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF,
STD_VIDEO_H265_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH265AspectRatioIdc;
typedef struct StdVideoH265DecPicBufMgr {
uint32_t max_latency_increase_plus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
uint8_t max_dec_pic_buffering_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
uint8_t max_num_reorder_pics[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
uint32_t max_latency_increase_plus1[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
uint8_t max_dec_pic_buffering_minus1[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
uint8_t max_num_reorder_pics[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
} StdVideoH265DecPicBufMgr;
typedef struct StdVideoH265SubLayerHrdParameters {
@@ -144,21 +119,20 @@ typedef struct StdVideoH265HrdFlags {
} StdVideoH265HrdFlags;
typedef struct StdVideoH265HrdParameters {
StdVideoH265HrdFlags flags;
uint8_t tick_divisor_minus2;
uint8_t du_cpb_removal_delay_increment_length_minus1;
uint8_t dpb_output_delay_du_length_minus1;
uint8_t bit_rate_scale;
uint8_t cpb_size_scale;
uint8_t cpb_size_du_scale;
uint8_t initial_cpb_removal_delay_length_minus1;
uint8_t au_cpb_removal_delay_length_minus1;
uint8_t dpb_output_delay_length_minus1;
uint8_t cpb_cnt_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
uint16_t elemental_duration_in_tc_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
uint16_t reserved[3];
const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersNal;
const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersVcl;
uint8_t tick_divisor_minus2;
uint8_t du_cpb_removal_delay_increment_length_minus1;
uint8_t dpb_output_delay_du_length_minus1;
uint8_t bit_rate_scale;
uint8_t cpb_size_scale;
uint8_t cpb_size_du_scale;
uint8_t initial_cpb_removal_delay_length_minus1;
uint8_t au_cpb_removal_delay_length_minus1;
uint8_t dpb_output_delay_length_minus1;
uint8_t cpb_cnt_minus1[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
uint16_t elemental_duration_in_tc_minus1[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersNal[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersVcl[STD_VIDEO_H265_SUBLAYERS_MINUS1_LIST_SIZE];
StdVideoH265HrdFlags flags;
} StdVideoH265HrdParameters;
typedef struct StdVideoH265VpsFlags {
@@ -168,33 +142,15 @@ typedef struct StdVideoH265VpsFlags {
uint32_t vps_poc_proportional_to_timing_flag : 1;
} StdVideoH265VpsFlags;
typedef struct StdVideoH265ProfileTierLevelFlags {
uint32_t general_tier_flag : 1;
uint32_t general_progressive_source_flag : 1;
uint32_t general_interlaced_source_flag : 1;
uint32_t general_non_packed_constraint_flag : 1;
uint32_t general_frame_only_constraint_flag : 1;
} StdVideoH265ProfileTierLevelFlags;
typedef struct StdVideoH265ProfileTierLevel {
StdVideoH265ProfileTierLevelFlags flags;
StdVideoH265ProfileIdc general_profile_idc;
StdVideoH265LevelIdc general_level_idc;
} StdVideoH265ProfileTierLevel;
typedef struct StdVideoH265VideoParameterSet {
StdVideoH265VpsFlags flags;
uint8_t vps_video_parameter_set_id;
uint8_t vps_max_sub_layers_minus1;
uint8_t reserved1;
uint8_t reserved2;
uint32_t vps_num_units_in_tick;
uint32_t vps_time_scale;
uint32_t vps_num_ticks_poc_diff_one_minus1;
uint32_t reserved3;
const StdVideoH265DecPicBufMgr* pDecPicBufMgr;
const StdVideoH265HrdParameters* pHrdParameters;
const StdVideoH265ProfileTierLevel* pProfileTierLevel;
uint8_t vps_video_parameter_set_id;
uint8_t vps_max_sub_layers_minus1;
uint32_t vps_num_units_in_tick;
uint32_t vps_time_scale;
uint32_t vps_num_ticks_poc_diff_one_minus1;
StdVideoH265DecPicBufMgr* pDecPicBufMgr;
StdVideoH265HrdParameters* pHrdParameters;
StdVideoH265VpsFlags flags;
} StdVideoH265VideoParameterSet;
typedef struct StdVideoH265ScalingLists {
@@ -228,32 +184,29 @@ typedef struct StdVideoH265SpsVuiFlags {
} StdVideoH265SpsVuiFlags;
typedef struct StdVideoH265SequenceParameterSetVui {
StdVideoH265SpsVuiFlags flags;
StdVideoH265AspectRatioIdc aspect_ratio_idc;
uint16_t sar_width;
uint16_t sar_height;
uint8_t video_format;
uint8_t colour_primaries;
uint8_t transfer_characteristics;
uint8_t matrix_coeffs;
uint8_t chroma_sample_loc_type_top_field;
uint8_t chroma_sample_loc_type_bottom_field;
uint8_t reserved1;
uint8_t reserved2;
uint16_t def_disp_win_left_offset;
uint16_t def_disp_win_right_offset;
uint16_t def_disp_win_top_offset;
uint16_t def_disp_win_bottom_offset;
uint32_t vui_num_units_in_tick;
uint32_t vui_time_scale;
uint32_t vui_num_ticks_poc_diff_one_minus1;
uint16_t min_spatial_segmentation_idc;
uint16_t reserved3;
uint8_t max_bytes_per_pic_denom;
uint8_t max_bits_per_min_cu_denom;
uint8_t log2_max_mv_length_horizontal;
uint8_t log2_max_mv_length_vertical;
const StdVideoH265HrdParameters* pHrdParameters;
uint8_t aspect_ratio_idc;
uint16_t sar_width;
uint16_t sar_height;
uint8_t video_format;
uint8_t colour_primaries;
uint8_t transfer_characteristics;
uint8_t matrix_coeffs;
uint8_t chroma_sample_loc_type_top_field;
uint8_t chroma_sample_loc_type_bottom_field;
uint16_t def_disp_win_left_offset;
uint16_t def_disp_win_right_offset;
uint16_t def_disp_win_top_offset;
uint16_t def_disp_win_bottom_offset;
uint32_t vui_num_units_in_tick;
uint32_t vui_time_scale;
uint32_t vui_num_ticks_poc_diff_one_minus1;
StdVideoH265HrdParameters* pHrdParameters;
uint16_t min_spatial_segmentation_idc;
uint8_t max_bytes_per_pic_denom;
uint8_t max_bits_per_min_cu_denom;
uint8_t log2_max_mv_length_horizontal;
uint8_t log2_max_mv_length_vertical;
StdVideoH265SpsVuiFlags flags;
} StdVideoH265SequenceParameterSetVui;
typedef struct StdVideoH265PredictorPaletteEntries {
@@ -263,8 +216,6 @@ typedef struct StdVideoH265PredictorPaletteEntries {
typedef struct StdVideoH265SpsFlags {
uint32_t sps_temporal_id_nesting_flag : 1;
uint32_t separate_colour_plane_flag : 1;
uint32_t conformance_window_flag : 1;
uint32_t sps_sub_layer_ordering_info_present_flag : 1;
uint32_t scaling_list_enabled_flag : 1;
uint32_t sps_scaling_list_data_present_flag : 1;
uint32_t amp_enabled_flag : 1;
@@ -286,80 +237,50 @@ typedef struct StdVideoH265SpsFlags {
uint32_t high_precision_offsets_enabled_flag : 1;
uint32_t persistent_rice_adaptation_enabled_flag : 1;
uint32_t cabac_bypass_alignment_enabled_flag : 1;
uint32_t sps_scc_extension_flag : 1;
uint32_t sps_curr_pic_ref_enabled_flag : 1;
uint32_t palette_mode_enabled_flag : 1;
uint32_t sps_palette_predictor_initializers_present_flag : 1;
uint32_t sps_palette_predictor_initializer_present_flag : 1;
uint32_t intra_boundary_filtering_disabled_flag : 1;
} StdVideoH265SpsFlags;
typedef struct StdVideoH265ShortTermRefPicSetFlags {
uint32_t inter_ref_pic_set_prediction_flag : 1;
uint32_t delta_rps_sign : 1;
} StdVideoH265ShortTermRefPicSetFlags;
typedef struct StdVideoH265ShortTermRefPicSet {
StdVideoH265ShortTermRefPicSetFlags flags;
uint32_t delta_idx_minus1;
uint16_t use_delta_flag;
uint16_t abs_delta_rps_minus1;
uint16_t used_by_curr_pic_flag;
uint16_t used_by_curr_pic_s0_flag;
uint16_t used_by_curr_pic_s1_flag;
uint16_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint8_t num_negative_pics;
uint8_t num_positive_pics;
uint16_t delta_poc_s0_minus1[STD_VIDEO_H265_MAX_DPB_SIZE];
uint16_t delta_poc_s1_minus1[STD_VIDEO_H265_MAX_DPB_SIZE];
} StdVideoH265ShortTermRefPicSet;
typedef struct StdVideoH265LongTermRefPicsSps {
uint32_t used_by_curr_pic_lt_sps_flag;
uint32_t lt_ref_pic_poc_lsb_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS];
} StdVideoH265LongTermRefPicsSps;
typedef struct StdVideoH265SequenceParameterSet {
StdVideoH265SpsFlags flags;
StdVideoH265ChromaFormatIdc chroma_format_idc;
uint32_t pic_width_in_luma_samples;
uint32_t pic_height_in_luma_samples;
uint8_t sps_video_parameter_set_id;
uint8_t sps_max_sub_layers_minus1;
uint8_t sps_seq_parameter_set_id;
uint8_t bit_depth_luma_minus8;
uint8_t bit_depth_chroma_minus8;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
uint8_t log2_min_luma_coding_block_size_minus3;
uint8_t log2_diff_max_min_luma_coding_block_size;
uint8_t log2_min_luma_transform_block_size_minus2;
uint8_t log2_diff_max_min_luma_transform_block_size;
uint8_t max_transform_hierarchy_depth_inter;
uint8_t max_transform_hierarchy_depth_intra;
uint8_t num_short_term_ref_pic_sets;
uint8_t num_long_term_ref_pics_sps;
uint8_t pcm_sample_bit_depth_luma_minus1;
uint8_t pcm_sample_bit_depth_chroma_minus1;
uint8_t log2_min_pcm_luma_coding_block_size_minus3;
uint8_t log2_diff_max_min_pcm_luma_coding_block_size;
uint8_t reserved1;
uint8_t reserved2;
uint8_t palette_max_size;
uint8_t delta_palette_max_predictor_size;
uint8_t motion_vector_resolution_control_idc;
uint8_t sps_num_palette_predictor_initializers_minus1;
uint32_t conf_win_left_offset;
uint32_t conf_win_right_offset;
uint32_t conf_win_top_offset;
uint32_t conf_win_bottom_offset;
const StdVideoH265ProfileTierLevel* pProfileTierLevel;
const StdVideoH265DecPicBufMgr* pDecPicBufMgr;
const StdVideoH265ScalingLists* pScalingLists;
const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet;
const StdVideoH265LongTermRefPicsSps* pLongTermRefPicsSps;
const StdVideoH265SequenceParameterSetVui* pSequenceParameterSetVui;
const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries;
StdVideoH265ProfileIdc profile_idc;
StdVideoH265Level level_idc;
uint32_t pic_width_in_luma_samples;
uint32_t pic_height_in_luma_samples;
uint8_t sps_video_parameter_set_id;
uint8_t sps_max_sub_layers_minus1;
uint8_t sps_seq_parameter_set_id;
uint8_t chroma_format_idc;
uint8_t bit_depth_luma_minus8;
uint8_t bit_depth_chroma_minus8;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
uint8_t sps_max_dec_pic_buffering_minus1;
uint8_t log2_min_luma_coding_block_size_minus3;
uint8_t log2_diff_max_min_luma_coding_block_size;
uint8_t log2_min_luma_transform_block_size_minus2;
uint8_t log2_diff_max_min_luma_transform_block_size;
uint8_t max_transform_hierarchy_depth_inter;
uint8_t max_transform_hierarchy_depth_intra;
uint8_t num_short_term_ref_pic_sets;
uint8_t num_long_term_ref_pics_sps;
uint8_t pcm_sample_bit_depth_luma_minus1;
uint8_t pcm_sample_bit_depth_chroma_minus1;
uint8_t log2_min_pcm_luma_coding_block_size_minus3;
uint8_t log2_diff_max_min_pcm_luma_coding_block_size;
uint32_t conf_win_left_offset;
uint32_t conf_win_right_offset;
uint32_t conf_win_top_offset;
uint32_t conf_win_bottom_offset;
StdVideoH265DecPicBufMgr* pDecPicBufMgr;
StdVideoH265SpsFlags flags;
StdVideoH265ScalingLists* pScalingLists;
StdVideoH265SequenceParameterSetVui* pSequenceParameterSetVui;
uint8_t palette_max_size;
uint8_t delta_palette_max_predictor_size;
uint8_t motion_vector_resolution_control_idc;
uint8_t sps_num_palette_predictor_initializer_minus1;
StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries;
} StdVideoH265SequenceParameterSet;
typedef struct StdVideoH265PpsFlags {
@@ -391,48 +312,44 @@ typedef struct StdVideoH265PpsFlags {
uint32_t pps_curr_pic_ref_enabled_flag : 1;
uint32_t residual_adaptive_colour_transform_enabled_flag : 1;
uint32_t pps_slice_act_qp_offsets_present_flag : 1;
uint32_t pps_palette_predictor_initializers_present_flag : 1;
uint32_t pps_palette_predictor_initializer_present_flag : 1;
uint32_t monochrome_palette_flag : 1;
uint32_t pps_range_extension_flag : 1;
} StdVideoH265PpsFlags;
typedef struct StdVideoH265PictureParameterSet {
StdVideoH265PpsFlags flags;
uint8_t pps_pic_parameter_set_id;
uint8_t pps_seq_parameter_set_id;
uint8_t sps_video_parameter_set_id;
uint8_t num_extra_slice_header_bits;
uint8_t num_ref_idx_l0_default_active_minus1;
uint8_t num_ref_idx_l1_default_active_minus1;
int8_t init_qp_minus26;
uint8_t diff_cu_qp_delta_depth;
int8_t pps_cb_qp_offset;
int8_t pps_cr_qp_offset;
int8_t pps_beta_offset_div2;
int8_t pps_tc_offset_div2;
uint8_t log2_parallel_merge_level_minus2;
uint8_t log2_max_transform_skip_block_size_minus2;
uint8_t diff_cu_chroma_qp_offset_depth;
uint8_t chroma_qp_offset_list_len_minus1;
int8_t cb_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE];
int8_t cr_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE];
uint8_t log2_sao_offset_scale_luma;
uint8_t log2_sao_offset_scale_chroma;
int8_t pps_act_y_qp_offset_plus5;
int8_t pps_act_cb_qp_offset_plus5;
int8_t pps_act_cr_qp_offset_plus3;
uint8_t pps_num_palette_predictor_initializers;
uint8_t luma_bit_depth_entry_minus8;
uint8_t chroma_bit_depth_entry_minus8;
uint8_t num_tile_columns_minus1;
uint8_t num_tile_rows_minus1;
uint8_t reserved1;
uint8_t reserved2;
uint16_t column_width_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE];
uint16_t row_height_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE];
uint32_t reserved3;
const StdVideoH265ScalingLists* pScalingLists;
const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries;
uint8_t pps_pic_parameter_set_id;
uint8_t pps_seq_parameter_set_id;
uint8_t num_extra_slice_header_bits;
uint8_t num_ref_idx_l0_default_active_minus1;
uint8_t num_ref_idx_l1_default_active_minus1;
int8_t init_qp_minus26;
uint8_t diff_cu_qp_delta_depth;
int8_t pps_cb_qp_offset;
int8_t pps_cr_qp_offset;
uint8_t num_tile_columns_minus1;
uint8_t num_tile_rows_minus1;
uint16_t column_width_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE];
uint16_t row_height_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE];
int8_t pps_beta_offset_div2;
int8_t pps_tc_offset_div2;
uint8_t log2_parallel_merge_level_minus2;
StdVideoH265PpsFlags flags;
StdVideoH265ScalingLists* pScalingLists;
uint8_t log2_max_transform_skip_block_size_minus2;
uint8_t diff_cu_chroma_qp_offset_depth;
uint8_t chroma_qp_offset_list_len_minus1;
int8_t cb_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE];
int8_t cr_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE];
uint8_t log2_sao_offset_scale_luma;
uint8_t log2_sao_offset_scale_chroma;
int8_t pps_act_y_qp_offset_plus5;
int8_t pps_act_cb_qp_offset_plus5;
int8_t pps_act_cr_qp_offset_plus5;
uint8_t pps_num_palette_predictor_initializer;
uint8_t luma_bit_depth_entry_minus8;
uint8_t chroma_bit_depth_entry_minus8;
StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries;
} StdVideoH265PictureParameterSet;
@@ -20,12 +20,7 @@ extern "C" {
#define vulkan_video_codec_h265std_decode 1
// Vulkan 0.9 provisional Vulkan video H.265 decode std specification version number
#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_0_9_9 VK_MAKE_VIDEO_STD_VERSION(0, 9, 9) // Patch version should always be set to 0
#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8
#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_0_9_9
#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode"
typedef struct StdVideoDecodeH265PictureInfoFlags {
uint32_t IrapPicFlag : 1;
uint32_t IdrPicFlag : 1;
@@ -34,27 +29,27 @@ typedef struct StdVideoDecodeH265PictureInfoFlags {
} StdVideoDecodeH265PictureInfoFlags;
typedef struct StdVideoDecodeH265PictureInfo {
StdVideoDecodeH265PictureInfoFlags flags;
uint8_t sps_video_parameter_set_id;
uint8_t pps_seq_parameter_set_id;
uint8_t vps_video_parameter_set_id;
uint8_t sps_seq_parameter_set_id;
uint8_t pps_pic_parameter_set_id;
uint8_t NumDeltaPocsOfRefRpsIdx;
uint8_t num_short_term_ref_pic_sets;
int32_t PicOrderCntVal;
uint16_t NumBitsForSTRefPicSetInSlice;
uint16_t reserved;
uint8_t NumDeltaPocsOfRefRpsIdx;
uint8_t RefPicSetStCurrBefore[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
uint8_t RefPicSetStCurrAfter[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
uint8_t RefPicSetLtCurr[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
StdVideoDecodeH265PictureInfoFlags flags;
} StdVideoDecodeH265PictureInfo;
typedef struct StdVideoDecodeH265ReferenceInfoFlags {
uint32_t used_for_long_term_reference : 1;
uint32_t unused_for_reference : 1;
uint32_t is_long_term : 1;
uint32_t is_non_existing : 1;
} StdVideoDecodeH265ReferenceInfoFlags;
typedef struct StdVideoDecodeH265ReferenceInfo {
StdVideoDecodeH265ReferenceInfoFlags flags;
int32_t PicOrderCntVal;
StdVideoDecodeH265ReferenceInfoFlags flags;
} StdVideoDecodeH265ReferenceInfo;
@@ -20,37 +20,13 @@ extern "C" {
#define vulkan_video_codec_h265std_encode 1
// Vulkan 0.9 provisional Vulkan video H.265 encode std specification version number
#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9 VK_MAKE_VIDEO_STD_VERSION(0, 9, 9) // Patch version should always be set to 0
#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9
#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode"
typedef struct StdVideoEncodeH265WeightTableFlags {
uint16_t luma_weight_l0_flag;
uint16_t chroma_weight_l0_flag;
uint16_t luma_weight_l1_flag;
uint16_t chroma_weight_l1_flag;
} StdVideoEncodeH265WeightTableFlags;
typedef struct StdVideoEncodeH265WeightTable {
StdVideoEncodeH265WeightTableFlags flags;
uint8_t luma_log2_weight_denom;
int8_t delta_chroma_log2_weight_denom;
int8_t delta_luma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
int8_t luma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
int8_t delta_chroma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
int8_t delta_chroma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
int8_t delta_luma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
int8_t luma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
int8_t delta_chroma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
int8_t delta_chroma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
} StdVideoEncodeH265WeightTable;
#define STD_VIDEO_ENCODE_H265_LUMA_LIST_SIZE 15
#define STD_VIDEO_ENCODE_H265_CHROMA_LIST_SIZE 15
#define STD_VIDEO_ENCODE_H265_CHROMA_LISTS_NUM 2
typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags {
uint32_t first_slice_segment_in_pic_flag : 1;
uint32_t no_output_of_prior_pics_flag : 1;
uint32_t dependent_slice_segment_flag : 1;
uint32_t pic_output_flag : 1;
uint32_t short_term_ref_pic_set_sps_flag : 1;
uint32_t slice_temporal_mvp_enable_flag : 1;
uint32_t slice_sao_luma_flag : 1;
@@ -58,42 +34,47 @@ typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags {
uint32_t num_ref_idx_active_override_flag : 1;
uint32_t mvd_l1_zero_flag : 1;
uint32_t cabac_init_flag : 1;
uint32_t cu_chroma_qp_offset_enabled_flag : 1;
uint32_t deblocking_filter_override_flag : 1;
uint32_t slice_deblocking_filter_disabled_flag : 1;
uint32_t slice_deblocking_filter_disable_flag : 1;
uint32_t collocated_from_l0_flag : 1;
uint32_t slice_loop_filter_across_slices_enabled_flag : 1;
uint32_t bLastSliceInPic : 1;
uint32_t reservedBits : 18;
uint16_t luma_weight_l0_flag;
uint16_t chroma_weight_l0_flag;
uint16_t luma_weight_l1_flag;
uint16_t chroma_weight_l1_flag;
} StdVideoEncodeH265SliceSegmentHeaderFlags;
typedef struct StdVideoEncodeH265SliceSegmentLongTermRefPics {
uint8_t num_long_term_sps;
uint8_t num_long_term_pics;
uint8_t lt_idx_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS];
uint8_t poc_lsb_lt[STD_VIDEO_H265_MAX_LONG_TERM_PICS];
uint16_t used_by_curr_pic_lt_flag;
uint8_t delta_poc_msb_present_flag[STD_VIDEO_H265_MAX_DELTA_POC];
uint8_t delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC];
} StdVideoEncodeH265SliceSegmentLongTermRefPics;
typedef struct StdVideoEncodeH265SliceSegmentHeader {
StdVideoEncodeH265SliceSegmentHeaderFlags flags;
StdVideoH265SliceType slice_type;
uint32_t slice_segment_address;
uint8_t short_term_ref_pic_set_idx;
uint8_t collocated_ref_idx;
uint8_t num_ref_idx_l0_active_minus1;
uint8_t num_ref_idx_l1_active_minus1;
uint8_t MaxNumMergeCand;
int8_t slice_cb_qp_offset;
int8_t slice_cr_qp_offset;
int8_t slice_beta_offset_div2;
int8_t slice_tc_offset_div2;
int8_t slice_act_y_qp_offset;
int8_t slice_act_cb_qp_offset;
int8_t slice_act_cr_qp_offset;
const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet;
const StdVideoEncodeH265SliceSegmentLongTermRefPics* pLongTermRefPics;
const StdVideoEncodeH265WeightTable* pWeightTable;
StdVideoH265SliceType slice_type;
uint8_t slice_pic_parameter_set_id;
uint8_t num_short_term_ref_pic_sets;
uint32_t slice_segment_address;
uint8_t short_term_ref_pic_set_idx;
uint8_t num_long_term_sps;
uint8_t num_long_term_pics;
uint8_t collocated_ref_idx;
uint8_t num_ref_idx_l0_active_minus1;
uint8_t num_ref_idx_l1_active_minus1;
uint8_t luma_log2_weight_denom;
int8_t delta_chroma_log2_weight_denom;
int8_t delta_luma_weight_l0[STD_VIDEO_ENCODE_H265_LUMA_LIST_SIZE];
int8_t luma_offset_l0[STD_VIDEO_ENCODE_H265_LUMA_LIST_SIZE];
int8_t delta_chroma_weight_l0[STD_VIDEO_ENCODE_H265_CHROMA_LIST_SIZE][STD_VIDEO_ENCODE_H265_CHROMA_LISTS_NUM];
int8_t delta_chroma_offset_l0[STD_VIDEO_ENCODE_H265_CHROMA_LIST_SIZE][STD_VIDEO_ENCODE_H265_CHROMA_LISTS_NUM];
int8_t delta_luma_weight_l1[STD_VIDEO_ENCODE_H265_LUMA_LIST_SIZE];
int8_t luma_offset_l1[STD_VIDEO_ENCODE_H265_LUMA_LIST_SIZE];
int8_t delta_chroma_weight_l1[STD_VIDEO_ENCODE_H265_CHROMA_LIST_SIZE][STD_VIDEO_ENCODE_H265_CHROMA_LISTS_NUM];
int8_t delta_chroma_offset_l1[STD_VIDEO_ENCODE_H265_CHROMA_LIST_SIZE][STD_VIDEO_ENCODE_H265_CHROMA_LISTS_NUM];
uint8_t MaxNumMergeCand;
int8_t slice_cb_qp_offset;
int8_t slice_cr_qp_offset;
int8_t slice_beta_offset_div2;
int8_t slice_tc_offset_div2;
int8_t slice_act_y_qp_offset;
int8_t slice_act_cb_qp_offset;
int8_t slice_act_cr_qp_offset;
StdVideoEncodeH265SliceSegmentHeaderFlags flags;
} StdVideoEncodeH265SliceSegmentHeader;
typedef struct StdVideoEncodeH265ReferenceModificationFlags {
@@ -104,38 +85,35 @@ typedef struct StdVideoEncodeH265ReferenceModificationFlags {
typedef struct StdVideoEncodeH265ReferenceModifications {
StdVideoEncodeH265ReferenceModificationFlags flags;
uint8_t referenceList0ModificationsCount;
const uint8_t* pReferenceList0Modifications;
uint8_t* pReferenceList0Modifications;
uint8_t referenceList1ModificationsCount;
const uint8_t* pReferenceList1Modifications;
uint8_t* pReferenceList1Modifications;
} StdVideoEncodeH265ReferenceModifications;
typedef struct StdVideoEncodeH265PictureInfoFlags {
uint32_t is_reference_flag : 1;
uint32_t IrapPicFlag : 1;
uint32_t long_term_flag : 1;
uint32_t discardable_flag : 1;
uint32_t cross_layer_bla_flag : 1;
} StdVideoEncodeH265PictureInfoFlags;
typedef struct StdVideoEncodeH265PictureInfo {
StdVideoEncodeH265PictureInfoFlags flags;
StdVideoH265PictureType PictureType;
uint8_t sps_video_parameter_set_id;
uint8_t pps_seq_parameter_set_id;
uint8_t pps_pic_parameter_set_id;
int32_t PicOrderCntVal;
uint8_t TemporalId;
StdVideoEncodeH265PictureInfoFlags flags;
} StdVideoEncodeH265PictureInfo;
typedef struct StdVideoEncodeH265ReferenceInfoFlags {
uint32_t used_for_long_term_reference : 1;
uint32_t unused_for_reference : 1;
uint32_t is_long_term : 1;
uint32_t isUsedFlag : 1;
} StdVideoEncodeH265ReferenceInfoFlags;
typedef struct StdVideoEncodeH265ReferenceInfo {
StdVideoEncodeH265ReferenceInfoFlags flags;
int32_t PicOrderCntVal;
uint8_t TemporalId;
StdVideoEncodeH265ReferenceInfoFlags flags;
} StdVideoEncodeH265ReferenceInfo;
+34 -6
View File
@@ -2,15 +2,45 @@
// File: vk_platform.h
//
/*
** Copyright 2014-2022 The Khronos Group Inc.
** Copyright (c) 2014-2017 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
** 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.
*/
#ifndef VK_PLATFORM_H_
#define VK_PLATFORM_H_
#if defined(__ANDROID__)
#define VK_USE_PLATFORM_ANDROID_KHR 1
#elif defined(IOS)
#define VK_USE_PLATFORM_IOS_MVK 1
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_XCB)
#define VK_USE_PLATFORM_XCB_KHR 1
#endif
#if defined(FILAMENT_SUPPORTS_XLIB)
#define VK_USE_PLATFORM_XLIB_KHR 1
#endif
#if defined(FILAMENT_SUPPORTS_WAYLAND)
#define VK_USE_PLATFORM_WAYLAND_KHR 1
#endif
#elif defined(__APPLE__)
#define VK_USE_PLATFORM_MACOS_MVK 1
#elif defined(WIN32)
#define VK_USE_PLATFORM_WIN32_KHR 1
#endif
#ifdef __cplusplus
extern "C"
{
@@ -42,7 +72,7 @@ extern "C"
#define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
#error "Vulkan is not supported for the 'armeabi' NDK ABI"
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
// calling convention, i.e. float parameters are passed in registers. This
@@ -58,9 +88,7 @@ extern "C"
#define VKAPI_PTR
#endif
#if !defined(VK_NO_STDDEF_H)
#include <stddef.h>
#endif // !defined(VK_NO_STDDEF_H)
#include <stddef.h>
#if !defined(VK_NO_STDINT_H)
#if defined(_MSC_VER) && (_MSC_VER < 1600)
+1
View File
@@ -38,6 +38,7 @@
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <wayland-client.h>
#include "vulkan_wayland.h"
#endif
+244 -268
View File
@@ -22,7 +22,7 @@ extern "C" {
#define VK_KHR_video_queue 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR)
#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 7
#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 3
#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue"
typedef enum VkQueryResultStatusKHR {
@@ -33,7 +33,7 @@ typedef enum VkQueryResultStatusKHR {
} VkQueryResultStatusKHR;
typedef enum VkVideoCodecOperationFlagBitsKHR {
VK_VIDEO_CODEC_OPERATION_NONE_KHR = 0,
VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR = 0,
#ifdef VK_ENABLE_BETA_EXTENSIONS
VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000,
#endif
@@ -51,7 +51,7 @@ typedef enum VkVideoCodecOperationFlagBitsKHR {
typedef VkFlags VkVideoCodecOperationFlagsKHR;
typedef enum VkVideoChromaSubsamplingFlagBitsKHR {
VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR = 0,
VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR = 0,
VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001,
VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002,
VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004,
@@ -77,136 +77,134 @@ typedef enum VkVideoCapabilityFlagBitsKHR {
typedef VkFlags VkVideoCapabilityFlagsKHR;
typedef enum VkVideoSessionCreateFlagBitsKHR {
VK_VIDEO_SESSION_CREATE_DEFAULT_KHR = 0,
VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001,
VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoSessionCreateFlagBitsKHR;
typedef VkFlags VkVideoSessionCreateFlagsKHR;
typedef VkFlags VkVideoSessionParametersCreateFlagsKHR;
typedef VkFlags VkVideoBeginCodingFlagsKHR;
typedef VkFlags VkVideoEndCodingFlagsKHR;
typedef enum VkVideoCodingControlFlagBitsKHR {
VK_VIDEO_CODING_CONTROL_DEFAULT_KHR = 0,
VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001,
#ifdef VK_ENABLE_BETA_EXTENSIONS
VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0x00000002,
#endif
#ifdef VK_ENABLE_BETA_EXTENSIONS
VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR = 0x00000004,
#endif
VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoCodingControlFlagBitsKHR;
typedef VkFlags VkVideoCodingControlFlagsKHR;
typedef struct VkQueueFamilyQueryResultStatusPropertiesKHR {
typedef enum VkVideoCodingQualityPresetFlagBitsKHR {
VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR = 0x00000001,
VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR = 0x00000002,
VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR = 0x00000004,
VK_VIDEO_CODING_QUALITY_PRESET_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoCodingQualityPresetFlagBitsKHR;
typedef VkFlags VkVideoCodingQualityPresetFlagsKHR;
typedef struct VkQueueFamilyQueryResultStatusProperties2KHR {
VkStructureType sType;
void* pNext;
VkBool32 queryResultStatusSupport;
} VkQueueFamilyQueryResultStatusPropertiesKHR;
VkBool32 supported;
} VkQueueFamilyQueryResultStatusProperties2KHR;
typedef struct VkQueueFamilyVideoPropertiesKHR {
typedef struct VkVideoQueueFamilyProperties2KHR {
VkStructureType sType;
void* pNext;
VkVideoCodecOperationFlagsKHR videoCodecOperations;
} VkQueueFamilyVideoPropertiesKHR;
} VkVideoQueueFamilyProperties2KHR;
typedef struct VkVideoProfileInfoKHR {
typedef struct VkVideoProfileKHR {
VkStructureType sType;
const void* pNext;
void* pNext;
VkVideoCodecOperationFlagBitsKHR videoCodecOperation;
VkVideoChromaSubsamplingFlagsKHR chromaSubsampling;
VkVideoComponentBitDepthFlagsKHR lumaBitDepth;
VkVideoComponentBitDepthFlagsKHR chromaBitDepth;
} VkVideoProfileInfoKHR;
} VkVideoProfileKHR;
typedef struct VkVideoProfileListInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t profileCount;
const VkVideoProfileInfoKHR* pProfiles;
} VkVideoProfileListInfoKHR;
typedef struct VkVideoProfilesKHR {
VkStructureType sType;
void* pNext;
uint32_t profileCount;
const VkVideoProfileKHR* pProfiles;
} VkVideoProfilesKHR;
typedef struct VkVideoCapabilitiesKHR {
VkStructureType sType;
void* pNext;
VkVideoCapabilityFlagsKHR flags;
VkVideoCapabilityFlagsKHR capabilityFlags;
VkDeviceSize minBitstreamBufferOffsetAlignment;
VkDeviceSize minBitstreamBufferSizeAlignment;
VkExtent2D pictureAccessGranularity;
VkExtent2D minCodedExtent;
VkExtent2D maxCodedExtent;
uint32_t maxDpbSlots;
uint32_t maxActiveReferencePictures;
VkExtent2D videoPictureExtentGranularity;
VkExtent2D minExtent;
VkExtent2D maxExtent;
uint32_t maxReferencePicturesSlotsCount;
uint32_t maxReferencePicturesActiveCount;
VkExtensionProperties stdHeaderVersion;
} VkVideoCapabilitiesKHR;
typedef struct VkPhysicalDeviceVideoFormatInfoKHR {
VkStructureType sType;
const void* pNext;
VkImageUsageFlags imageUsage;
VkStructureType sType;
void* pNext;
VkImageUsageFlags imageUsage;
const VkVideoProfilesKHR* pVideoProfiles;
} VkPhysicalDeviceVideoFormatInfoKHR;
typedef struct VkVideoFormatPropertiesKHR {
VkStructureType sType;
void* pNext;
VkFormat format;
VkComponentMapping componentMapping;
VkImageCreateFlags imageCreateFlags;
VkImageType imageType;
VkImageTiling imageTiling;
VkImageUsageFlags imageUsageFlags;
VkStructureType sType;
void* pNext;
VkFormat format;
} VkVideoFormatPropertiesKHR;
typedef struct VkVideoPictureResourceInfoKHR {
typedef struct VkVideoPictureResourceKHR {
VkStructureType sType;
const void* pNext;
VkOffset2D codedOffset;
VkExtent2D codedExtent;
uint32_t baseArrayLayer;
VkImageView imageViewBinding;
} VkVideoPictureResourceInfoKHR;
} VkVideoPictureResourceKHR;
typedef struct VkVideoReferenceSlotInfoKHR {
VkStructureType sType;
const void* pNext;
int32_t slotIndex;
const VkVideoPictureResourceInfoKHR* pPictureResource;
} VkVideoReferenceSlotInfoKHR;
typedef struct VkVideoReferenceSlotKHR {
VkStructureType sType;
const void* pNext;
int8_t slotIndex;
const VkVideoPictureResourceKHR* pPictureResource;
} VkVideoReferenceSlotKHR;
typedef struct VkVideoSessionMemoryRequirementsKHR {
VkStructureType sType;
void* pNext;
uint32_t memoryBindIndex;
VkMemoryRequirements memoryRequirements;
} VkVideoSessionMemoryRequirementsKHR;
typedef struct VkVideoGetMemoryPropertiesKHR {
VkStructureType sType;
const void* pNext;
uint32_t memoryBindIndex;
VkMemoryRequirements2* pMemoryRequirements;
} VkVideoGetMemoryPropertiesKHR;
typedef struct VkBindVideoSessionMemoryInfoKHR {
typedef struct VkVideoBindMemoryKHR {
VkStructureType sType;
const void* pNext;
uint32_t memoryBindIndex;
VkDeviceMemory memory;
VkDeviceSize memoryOffset;
VkDeviceSize memorySize;
} VkBindVideoSessionMemoryInfoKHR;
} VkVideoBindMemoryKHR;
typedef struct VkVideoSessionCreateInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t queueFamilyIndex;
VkVideoSessionCreateFlagsKHR flags;
const VkVideoProfileInfoKHR* pVideoProfile;
const VkVideoProfileKHR* pVideoProfile;
VkFormat pictureFormat;
VkExtent2D maxCodedExtent;
VkFormat referencePictureFormat;
uint32_t maxDpbSlots;
uint32_t maxActiveReferencePictures;
VkFormat referencePicturesFormat;
uint32_t maxReferencePicturesSlotsCount;
uint32_t maxReferencePicturesActiveCount;
const VkExtensionProperties* pStdHeaderVersion;
} VkVideoSessionCreateInfoKHR;
typedef struct VkVideoSessionParametersCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoSessionParametersCreateFlagsKHR flags;
VkVideoSessionParametersKHR videoSessionParametersTemplate;
VkVideoSessionKHR videoSession;
VkStructureType sType;
const void* pNext;
VkVideoSessionParametersKHR videoSessionParametersTemplate;
VkVideoSessionKHR videoSession;
} VkVideoSessionParametersCreateInfoKHR;
typedef struct VkVideoSessionParametersUpdateInfoKHR {
@@ -219,10 +217,11 @@ typedef struct VkVideoBeginCodingInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoBeginCodingFlagsKHR flags;
VkVideoCodingQualityPresetFlagsKHR codecQualityPreset;
VkVideoSessionKHR videoSession;
VkVideoSessionParametersKHR videoSessionParameters;
uint32_t referenceSlotCount;
const VkVideoReferenceSlotInfoKHR* pReferenceSlots;
const VkVideoReferenceSlotKHR* pReferenceSlots;
} VkVideoBeginCodingInfoKHR;
typedef struct VkVideoEndCodingInfoKHR {
@@ -237,12 +236,12 @@ typedef struct VkVideoCodingControlInfoKHR {
VkVideoCodingControlFlagsKHR flags;
} VkVideoCodingControlInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileInfoKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties);
typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession);
typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator);
typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pMemoryRequirementsCount, VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements);
typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t bindSessionMemoryInfoCount, const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos);
typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pVideoSessionMemoryRequirementsCount, VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements);
typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t videoSessionBindMemoryCount, const VkVideoBindMemoryKHR* pVideoSessionBindMemories);
typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters);
typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo);
typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator);
@@ -253,7 +252,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer command
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
const VkVideoProfileInfoKHR* pVideoProfile,
const VkVideoProfileKHR* pVideoProfile,
VkVideoCapabilitiesKHR* pCapabilities);
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR(
@@ -276,14 +275,14 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR(
VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR(
VkDevice device,
VkVideoSessionKHR videoSession,
uint32_t* pMemoryRequirementsCount,
VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements);
uint32_t* pVideoSessionMemoryRequirementsCount,
VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements);
VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR(
VkDevice device,
VkVideoSessionKHR videoSession,
uint32_t bindSessionMemoryInfoCount,
const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos);
uint32_t videoSessionBindMemoryCount,
const VkVideoBindMemoryKHR* pVideoSessionBindMemories);
VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR(
VkDevice device,
@@ -316,24 +315,22 @@ VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR(
#define VK_KHR_video_decode_queue 1
#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 6
#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 4
#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue"
typedef enum VkVideoDecodeCapabilityFlagBitsKHR {
VK_VIDEO_DECODE_CAPABILITY_DEFAULT_KHR = 0,
VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR = 0x00000001,
VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR = 0x00000002,
VK_VIDEO_DECODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoDecodeCapabilityFlagBitsKHR;
typedef VkFlags VkVideoDecodeCapabilityFlagsKHR;
typedef enum VkVideoDecodeUsageFlagBitsKHR {
VK_VIDEO_DECODE_USAGE_DEFAULT_KHR = 0,
VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001,
VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR = 0x00000002,
VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR = 0x00000004,
VK_VIDEO_DECODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoDecodeUsageFlagBitsKHR;
typedef VkFlags VkVideoDecodeUsageFlagsKHR;
typedef enum VkVideoDecodeFlagBitsKHR {
VK_VIDEO_DECODE_DEFAULT_KHR = 0,
VK_VIDEO_DECODE_RESERVED_0_BIT_KHR = 0x00000001,
VK_VIDEO_DECODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoDecodeFlagBitsKHR;
typedef VkFlags VkVideoDecodeFlagsKHR;
typedef struct VkVideoDecodeCapabilitiesKHR {
VkStructureType sType;
@@ -341,31 +338,25 @@ typedef struct VkVideoDecodeCapabilitiesKHR {
VkVideoDecodeCapabilityFlagsKHR flags;
} VkVideoDecodeCapabilitiesKHR;
typedef struct VkVideoDecodeUsageInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoDecodeUsageFlagsKHR videoUsageHints;
} VkVideoDecodeUsageInfoKHR;
typedef struct VkVideoDecodeInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoDecodeFlagsKHR flags;
VkBuffer srcBuffer;
VkDeviceSize srcBufferOffset;
VkDeviceSize srcBufferRange;
VkVideoPictureResourceInfoKHR dstPictureResource;
const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot;
uint32_t referenceSlotCount;
const VkVideoReferenceSlotInfoKHR* pReferenceSlots;
VkStructureType sType;
const void* pNext;
VkVideoDecodeFlagsKHR flags;
VkBuffer srcBuffer;
VkDeviceSize srcBufferOffset;
VkDeviceSize srcBufferRange;
VkVideoPictureResourceKHR dstPictureResource;
const VkVideoReferenceSlotKHR* pSetupReferenceSlot;
uint32_t referenceSlotCount;
const VkVideoReferenceSlotKHR* pReferenceSlots;
} VkVideoDecodeInfoKHR;
typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo);
typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pFrameInfo);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR(
VkCommandBuffer commandBuffer,
const VkVideoDecodeInfoKHR* pDecodeInfo);
const VkVideoDecodeInfoKHR* pFrameInfo);
#endif
@@ -401,20 +392,18 @@ typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR {
#define VK_KHR_video_encode_queue 1
#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 7
#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 5
#define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue"
typedef enum VkVideoEncodeTuningModeKHR {
VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR = 1,
VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR = 2,
VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR = 3,
VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR = 4,
VK_VIDEO_ENCODE_TUNING_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeTuningModeKHR;
typedef enum VkVideoEncodeFlagBitsKHR {
VK_VIDEO_ENCODE_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR = 0x00000001,
VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeFlagBitsKHR;
typedef VkFlags VkVideoEncodeFlagsKHR;
typedef enum VkVideoEncodeCapabilityFlagBitsKHR {
VK_VIDEO_ENCODE_CAPABILITY_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0x00000001,
VK_VIDEO_ENCODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeCapabilityFlagBitsKHR;
@@ -428,38 +417,25 @@ typedef enum VkVideoEncodeRateControlModeFlagBitsKHR {
} VkVideoEncodeRateControlModeFlagBitsKHR;
typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR;
typedef enum VkVideoEncodeUsageFlagBitsKHR {
VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001,
VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR = 0x00000002,
VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR = 0x00000004,
VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR = 0x00000008,
VK_VIDEO_ENCODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeUsageFlagBitsKHR;
typedef VkFlags VkVideoEncodeUsageFlagsKHR;
typedef enum VkVideoEncodeContentFlagBitsKHR {
VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR = 0x00000001,
VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR = 0x00000002,
VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR = 0x00000004,
VK_VIDEO_ENCODE_CONTENT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeContentFlagBitsKHR;
typedef VkFlags VkVideoEncodeContentFlagsKHR;
typedef enum VkVideoEncodeRateControlFlagBitsKHR {
VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR = 0,
VK_VIDEO_ENCODE_RATE_CONTROL_RESERVED_0_BIT_KHR = 0x00000001,
VK_VIDEO_ENCODE_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkVideoEncodeRateControlFlagBitsKHR;
typedef VkFlags VkVideoEncodeRateControlFlagsKHR;
typedef struct VkVideoEncodeInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoEncodeFlagsKHR flags;
uint32_t qualityLevel;
VkBuffer dstBitstreamBuffer;
VkDeviceSize dstBitstreamBufferOffset;
VkDeviceSize dstBitstreamBufferMaxRange;
VkVideoPictureResourceInfoKHR srcPictureResource;
const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot;
uint32_t referenceSlotCount;
const VkVideoReferenceSlotInfoKHR* pReferenceSlots;
uint32_t precedingExternallyEncodedBytes;
VkStructureType sType;
const void* pNext;
VkVideoEncodeFlagsKHR flags;
uint32_t qualityLevel;
VkBuffer dstBitstreamBuffer;
VkDeviceSize dstBitstreamBufferOffset;
VkDeviceSize dstBitstreamBufferMaxRange;
VkVideoPictureResourceKHR srcPictureResource;
const VkVideoReferenceSlotKHR* pSetupReferenceSlot;
uint32_t referenceSlotCount;
const VkVideoReferenceSlotKHR* pReferenceSlots;
uint32_t precedingExternallyEncodedBytes;
} VkVideoEncodeInfoKHR;
typedef struct VkVideoEncodeCapabilitiesKHR {
@@ -472,14 +448,6 @@ typedef struct VkVideoEncodeCapabilitiesKHR {
VkExtent2D inputImageDataFillAlignment;
} VkVideoEncodeCapabilitiesKHR;
typedef struct VkVideoEncodeUsageInfoKHR {
VkStructureType sType;
const void* pNext;
VkVideoEncodeUsageFlagsKHR videoUsageHints;
VkVideoEncodeContentFlagsKHR videoContentHints;
VkVideoEncodeTuningModeKHR tuningMode;
} VkVideoEncodeUsageInfoKHR;
typedef struct VkVideoEncodeRateControlLayerInfoKHR {
VkStructureType sType;
const void* pNext;
@@ -512,16 +480,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR(
#define VK_EXT_video_encode_h264 1
#include "vk_video/vulkan_video_codec_h264std.h"
#include "vk_video/vulkan_video_codec_h264std_encode.h"
#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 9
#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 7
#define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264"
typedef enum VkVideoEncodeH264RateControlStructureEXT {
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH264RateControlStructureEXT;
typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT {
VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT = 0x00000001,
VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT = 0x00000002,
@@ -567,6 +528,14 @@ typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT {
VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH264OutputModeFlagBitsEXT;
typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT;
typedef enum VkVideoEncodeH264RateControlStructureFlagBitsEXT {
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_BIT_EXT = 0x00000001,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_BIT_EXT = 0x00000002,
VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH264RateControlStructureFlagBitsEXT;
typedef VkFlags VkVideoEncodeH264RateControlStructureFlagsEXT;
typedef struct VkVideoEncodeH264CapabilitiesEXT {
VkStructureType sType;
void* pNext;
@@ -586,17 +555,17 @@ typedef struct VkVideoEncodeH264CapabilitiesEXT {
typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t stdSPSCount;
const StdVideoH264SequenceParameterSet* pStdSPSs;
uint32_t stdPPSCount;
const StdVideoH264PictureParameterSet* pStdPPSs;
uint32_t spsStdCount;
const StdVideoH264SequenceParameterSet* pSpsStd;
uint32_t ppsStdCount;
const StdVideoH264PictureParameterSet* pPpsStd;
} VkVideoEncodeH264SessionParametersAddInfoEXT;
typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxStdSPSCount;
uint32_t maxStdPPSCount;
uint32_t maxSpsStdCount;
uint32_t maxPpsStdCount;
const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo;
} VkVideoEncodeH264SessionParametersCreateInfoEXT;
@@ -607,7 +576,7 @@ typedef struct VkVideoEncodeH264DpbSlotInfoEXT {
const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo;
} VkVideoEncodeH264DpbSlotInfoEXT;
typedef struct VkVideoEncodeH264ReferenceListsInfoEXT {
typedef struct VkVideoEncodeH264ReferenceListsEXT {
VkStructureType sType;
const void* pNext;
uint8_t referenceList0EntryCount;
@@ -615,48 +584,48 @@ typedef struct VkVideoEncodeH264ReferenceListsInfoEXT {
uint8_t referenceList1EntryCount;
const VkVideoEncodeH264DpbSlotInfoEXT* pReferenceList1Entries;
const StdVideoEncodeH264RefMemMgmtCtrlOperations* pMemMgmtCtrlOperations;
} VkVideoEncodeH264ReferenceListsInfoEXT;
} VkVideoEncodeH264ReferenceListsEXT;
typedef struct VkVideoEncodeH264NaluSliceInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t mbCount;
const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists;
const StdVideoEncodeH264SliceHeader* pSliceHeaderStd;
} VkVideoEncodeH264NaluSliceInfoEXT;
typedef struct VkVideoEncodeH264NaluSliceEXT {
VkStructureType sType;
const void* pNext;
uint32_t mbCount;
const VkVideoEncodeH264ReferenceListsEXT* pReferenceFinalLists;
const StdVideoEncodeH264SliceHeader* pSliceHeaderStd;
} VkVideoEncodeH264NaluSliceEXT;
typedef struct VkVideoEncodeH264VclFrameInfoEXT {
VkStructureType sType;
const void* pNext;
const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists;
uint32_t naluSliceEntryCount;
const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries;
const StdVideoEncodeH264PictureInfo* pCurrentPictureInfo;
VkStructureType sType;
const void* pNext;
const VkVideoEncodeH264ReferenceListsEXT* pReferenceFinalLists;
uint32_t naluSliceEntryCount;
const VkVideoEncodeH264NaluSliceEXT* pNaluSliceEntries;
const StdVideoEncodeH264PictureInfo* pCurrentPictureInfo;
} VkVideoEncodeH264VclFrameInfoEXT;
typedef struct VkVideoEncodeH264EmitPictureParametersInfoEXT {
typedef struct VkVideoEncodeH264EmitPictureParametersEXT {
VkStructureType sType;
const void* pNext;
uint8_t spsId;
VkBool32 emitSpsEnable;
uint32_t ppsIdEntryCount;
const uint8_t* ppsIdEntries;
} VkVideoEncodeH264EmitPictureParametersInfoEXT;
} VkVideoEncodeH264EmitPictureParametersEXT;
typedef struct VkVideoEncodeH264ProfileInfoEXT {
typedef struct VkVideoEncodeH264ProfileEXT {
VkStructureType sType;
const void* pNext;
StdVideoH264ProfileIdc stdProfileIdc;
} VkVideoEncodeH264ProfileInfoEXT;
} VkVideoEncodeH264ProfileEXT;
typedef struct VkVideoEncodeH264RateControlInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t gopFrameCount;
uint32_t idrPeriod;
uint32_t consecutiveBFrameCount;
VkVideoEncodeH264RateControlStructureEXT rateControlStructure;
uint8_t temporalLayerCount;
VkStructureType sType;
const void* pNext;
uint32_t gopFrameCount;
uint32_t idrPeriod;
uint32_t consecutiveBFrameCount;
VkVideoEncodeH264RateControlStructureFlagBitsEXT rateControlStructure;
uint8_t temporalLayerCount;
} VkVideoEncodeH264RateControlInfoEXT;
typedef struct VkVideoEncodeH264QpEXT {
@@ -690,16 +659,9 @@ typedef struct VkVideoEncodeH264RateControlLayerInfoEXT {
#define VK_EXT_video_encode_h265 1
#include "vk_video/vulkan_video_codec_h265std.h"
#include "vk_video/vulkan_video_codec_h265std_encode.h"
#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 9
#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 7
#define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265"
typedef enum VkVideoEncodeH265RateControlStructureEXT {
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH265RateControlStructureEXT;
typedef enum VkVideoEncodeH265CapabilityFlagBitsEXT {
VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0x00000001,
VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT = 0x00000002,
@@ -763,6 +725,14 @@ typedef enum VkVideoEncodeH265TransformBlockSizeFlagBitsEXT {
VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH265TransformBlockSizeFlagBitsEXT;
typedef VkFlags VkVideoEncodeH265TransformBlockSizeFlagsEXT;
typedef enum VkVideoEncodeH265RateControlStructureFlagBitsEXT {
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_BIT_EXT = 0x00000001,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_BIT_EXT = 0x00000002,
VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoEncodeH265RateControlStructureFlagBitsEXT;
typedef VkFlags VkVideoEncodeH265RateControlStructureFlagsEXT;
typedef struct VkVideoEncodeH265CapabilitiesEXT {
VkStructureType sType;
void* pNext;
@@ -791,20 +761,20 @@ typedef struct VkVideoEncodeH265CapabilitiesEXT {
typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t stdVPSCount;
const StdVideoH265VideoParameterSet* pStdVPSs;
uint32_t stdSPSCount;
const StdVideoH265SequenceParameterSet* pStdSPSs;
uint32_t stdPPSCount;
const StdVideoH265PictureParameterSet* pStdPPSs;
uint32_t vpsStdCount;
const StdVideoH265VideoParameterSet* pVpsStd;
uint32_t spsStdCount;
const StdVideoH265SequenceParameterSet* pSpsStd;
uint32_t ppsStdCount;
const StdVideoH265PictureParameterSet* pPpsStd;
} VkVideoEncodeH265SessionParametersAddInfoEXT;
typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxStdVPSCount;
uint32_t maxStdSPSCount;
uint32_t maxStdPPSCount;
uint32_t maxVpsStdCount;
uint32_t maxSpsStdCount;
uint32_t maxPpsStdCount;
const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo;
} VkVideoEncodeH265SessionParametersCreateInfoEXT;
@@ -815,7 +785,7 @@ typedef struct VkVideoEncodeH265DpbSlotInfoEXT {
const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo;
} VkVideoEncodeH265DpbSlotInfoEXT;
typedef struct VkVideoEncodeH265ReferenceListsInfoEXT {
typedef struct VkVideoEncodeH265ReferenceListsEXT {
VkStructureType sType;
const void* pNext;
uint8_t referenceList0EntryCount;
@@ -823,26 +793,26 @@ typedef struct VkVideoEncodeH265ReferenceListsInfoEXT {
uint8_t referenceList1EntryCount;
const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries;
const StdVideoEncodeH265ReferenceModifications* pReferenceModifications;
} VkVideoEncodeH265ReferenceListsInfoEXT;
} VkVideoEncodeH265ReferenceListsEXT;
typedef struct VkVideoEncodeH265NaluSliceSegmentInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t ctbCount;
const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists;
const StdVideoEncodeH265SliceSegmentHeader* pSliceSegmentHeaderStd;
} VkVideoEncodeH265NaluSliceSegmentInfoEXT;
typedef struct VkVideoEncodeH265NaluSliceSegmentEXT {
VkStructureType sType;
const void* pNext;
uint32_t ctbCount;
const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists;
const StdVideoEncodeH265SliceSegmentHeader* pSliceSegmentHeaderStd;
} VkVideoEncodeH265NaluSliceSegmentEXT;
typedef struct VkVideoEncodeH265VclFrameInfoEXT {
VkStructureType sType;
const void* pNext;
const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists;
uint32_t naluSliceSegmentEntryCount;
const VkVideoEncodeH265NaluSliceSegmentInfoEXT* pNaluSliceSegmentEntries;
const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo;
VkStructureType sType;
const void* pNext;
const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists;
uint32_t naluSliceSegmentEntryCount;
const VkVideoEncodeH265NaluSliceSegmentEXT* pNaluSliceSegmentEntries;
const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo;
} VkVideoEncodeH265VclFrameInfoEXT;
typedef struct VkVideoEncodeH265EmitPictureParametersInfoEXT {
typedef struct VkVideoEncodeH265EmitPictureParametersEXT {
VkStructureType sType;
const void* pNext;
uint8_t vpsId;
@@ -851,22 +821,22 @@ typedef struct VkVideoEncodeH265EmitPictureParametersInfoEXT {
VkBool32 emitSpsEnable;
uint32_t ppsIdEntryCount;
const uint8_t* ppsIdEntries;
} VkVideoEncodeH265EmitPictureParametersInfoEXT;
} VkVideoEncodeH265EmitPictureParametersEXT;
typedef struct VkVideoEncodeH265ProfileInfoEXT {
typedef struct VkVideoEncodeH265ProfileEXT {
VkStructureType sType;
const void* pNext;
StdVideoH265ProfileIdc stdProfileIdc;
} VkVideoEncodeH265ProfileInfoEXT;
} VkVideoEncodeH265ProfileEXT;
typedef struct VkVideoEncodeH265RateControlInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t gopFrameCount;
uint32_t idrPeriod;
uint32_t consecutiveBFrameCount;
VkVideoEncodeH265RateControlStructureEXT rateControlStructure;
uint8_t subLayerCount;
VkStructureType sType;
const void* pNext;
uint32_t gopFrameCount;
uint32_t idrPeriod;
uint32_t consecutiveBFrameCount;
VkVideoEncodeH265RateControlStructureFlagBitsEXT rateControlStructure;
uint8_t subLayerCount;
} VkVideoEncodeH265RateControlInfoEXT;
typedef struct VkVideoEncodeH265QpEXT {
@@ -899,7 +869,7 @@ typedef struct VkVideoEncodeH265RateControlLayerInfoEXT {
#define VK_EXT_video_decode_h264 1
#include "vk_video/vulkan_video_codec_h264std_decode.h"
#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 7
#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 5
#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264"
typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT {
@@ -909,34 +879,34 @@ typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT {
VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkVideoDecodeH264PictureLayoutFlagBitsEXT;
typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsEXT;
typedef struct VkVideoDecodeH264ProfileInfoEXT {
VkStructureType sType;
const void* pNext;
StdVideoH264ProfileIdc stdProfileIdc;
VkVideoDecodeH264PictureLayoutFlagBitsEXT pictureLayout;
} VkVideoDecodeH264ProfileInfoEXT;
typedef struct VkVideoDecodeH264ProfileEXT {
VkStructureType sType;
const void* pNext;
StdVideoH264ProfileIdc stdProfileIdc;
VkVideoDecodeH264PictureLayoutFlagsEXT pictureLayout;
} VkVideoDecodeH264ProfileEXT;
typedef struct VkVideoDecodeH264CapabilitiesEXT {
VkStructureType sType;
void* pNext;
StdVideoH264LevelIdc maxLevelIdc;
VkOffset2D fieldOffsetGranularity;
VkStructureType sType;
void* pNext;
StdVideoH264Level maxLevel;
VkOffset2D fieldOffsetGranularity;
} VkVideoDecodeH264CapabilitiesEXT;
typedef struct VkVideoDecodeH264SessionParametersAddInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t stdSPSCount;
const StdVideoH264SequenceParameterSet* pStdSPSs;
uint32_t stdPPSCount;
const StdVideoH264PictureParameterSet* pStdPPSs;
uint32_t spsStdCount;
const StdVideoH264SequenceParameterSet* pSpsStd;
uint32_t ppsStdCount;
const StdVideoH264PictureParameterSet* pPpsStd;
} VkVideoDecodeH264SessionParametersAddInfoEXT;
typedef struct VkVideoDecodeH264SessionParametersCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxStdSPSCount;
uint32_t maxStdPPSCount;
uint32_t maxSpsStdCount;
uint32_t maxPpsStdCount;
const VkVideoDecodeH264SessionParametersAddInfoEXT* pParametersAddInfo;
} VkVideoDecodeH264SessionParametersCreateInfoEXT;
@@ -944,10 +914,16 @@ typedef struct VkVideoDecodeH264PictureInfoEXT {
VkStructureType sType;
const void* pNext;
const StdVideoDecodeH264PictureInfo* pStdPictureInfo;
uint32_t sliceCount;
const uint32_t* pSliceOffsets;
uint32_t slicesCount;
const uint32_t* pSlicesDataOffsets;
} VkVideoDecodeH264PictureInfoEXT;
typedef struct VkVideoDecodeH264MvcEXT {
VkStructureType sType;
const void* pNext;
const StdVideoDecodeH264Mvc* pStdMvc;
} VkVideoDecodeH264MvcEXT;
typedef struct VkVideoDecodeH264DpbSlotInfoEXT {
VkStructureType sType;
const void* pNext;
@@ -958,37 +934,37 @@ typedef struct VkVideoDecodeH264DpbSlotInfoEXT {
#define VK_EXT_video_decode_h265 1
#include "vk_video/vulkan_video_codec_h265std_decode.h"
#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 5
#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 3
#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265"
typedef struct VkVideoDecodeH265ProfileInfoEXT {
typedef struct VkVideoDecodeH265ProfileEXT {
VkStructureType sType;
const void* pNext;
StdVideoH265ProfileIdc stdProfileIdc;
} VkVideoDecodeH265ProfileInfoEXT;
} VkVideoDecodeH265ProfileEXT;
typedef struct VkVideoDecodeH265CapabilitiesEXT {
VkStructureType sType;
void* pNext;
StdVideoH265LevelIdc maxLevelIdc;
VkStructureType sType;
void* pNext;
StdVideoH265Level maxLevel;
} VkVideoDecodeH265CapabilitiesEXT;
typedef struct VkVideoDecodeH265SessionParametersAddInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t stdVPSCount;
const StdVideoH265VideoParameterSet* pStdVPSs;
uint32_t stdSPSCount;
const StdVideoH265SequenceParameterSet* pStdSPSs;
uint32_t stdPPSCount;
const StdVideoH265PictureParameterSet* pStdPPSs;
uint32_t vpsStdCount;
const StdVideoH265VideoParameterSet* pVpsStd;
uint32_t spsStdCount;
const StdVideoH265SequenceParameterSet* pSpsStd;
uint32_t ppsStdCount;
const StdVideoH265PictureParameterSet* pPpsStd;
} VkVideoDecodeH265SessionParametersAddInfoEXT;
typedef struct VkVideoDecodeH265SessionParametersCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxStdVPSCount;
uint32_t maxStdSPSCount;
uint32_t maxStdPPSCount;
uint32_t maxVpsStdCount;
uint32_t maxSpsStdCount;
uint32_t maxPpsStdCount;
const VkVideoDecodeH265SessionParametersAddInfoEXT* pParametersAddInfo;
} VkVideoDecodeH265SessionParametersCreateInfoEXT;
@@ -996,8 +972,8 @@ typedef struct VkVideoDecodeH265PictureInfoEXT {
VkStructureType sType;
const void* pNext;
StdVideoDecodeH265PictureInfo* pStdPictureInfo;
uint32_t sliceCount;
const uint32_t* pSliceOffsets;
uint32_t slicesCount;
const uint32_t* pSlicesDataOffsets;
} VkVideoDecodeH265PictureInfoEXT;
typedef struct VkVideoDecodeH265DpbSlotInfoEXT {
File diff suppressed because it is too large Load Diff
+65
View File
@@ -0,0 +1,65 @@
#ifndef VULKAN_MIR_H_
#define VULKAN_MIR_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2018 The Khronos Group Inc.
**
** 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.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_mir_surface 1
#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4
#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface"
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
typedef struct VkMirSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkMirSurfaceCreateFlagsKHR flags;
MirConnection* connection;
MirSurface* mirSurface;
} VkMirSurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
VkInstance instance,
const VkMirSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
MirConnection* connection);
#endif
#ifdef __cplusplus
}
#endif
#endif
+22
View File
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.19)
project(fgdbg)
set(TARGET fgdbg)
set(PUBLIC_HDR_DIR include)
# ==================================================================================================
# Sources and headers
# ==================================================================================================
set(PUBLIC_HDRS include/fgdbg/DebugServer.h include/fgdbg/Session.h)
set(SRCS src/DebugServer.cpp src/Session.cpp)
# ==================================================================================================
# Include and target definitions
# ==================================================================================================
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
target_link_libraries(${TARGET} PUBLIC civetweb utils)
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
include_directories(${PUBLIC_HDR_DIR})
+1
View File
@@ -0,0 +1 @@
# FrameGraph Debugger (WIP)
+9
View File
@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build
+46
View File
@@ -0,0 +1,46 @@
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.6.10"
id("org.jetbrains.compose") version "1.1.1"
}
group = "com.google.filament"
version = "1.0"
val ktorVersion: String by project
repositories {
google()
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven {
url = uri("https://maven.pkg.jetbrains.space/public/p/ktor/eap")
name = "ktor-eap"
}
}
dependencies {
implementation(compose.desktop.currentOs)
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-websockets:$ktorVersion")
}
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "fgdbg"
packageVersion = "1.0.0"
}
}
}
+2
View File
@@ -0,0 +1,2 @@
kotlin.code.style=official
ktorVersion=2.1.2
Binary file not shown.
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+234
View File
@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# 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/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# 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
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${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
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 ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
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
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
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
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
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 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" )
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
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# 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' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+89
View File
@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
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
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
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
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
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!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+9
View File
@@ -0,0 +1,9 @@
pluginManagement {
repositories {
google()
gradlePluginPortal()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
rootProject.name = "fgdbg"
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.compose.material.MaterialTheme
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import io.ktor.client.*
import io.ktor.client.plugins.websocket.*
import io.ktor.http.*
import io.ktor.websocket.Frame
import io.ktor.websocket.readText
import kotlinx.coroutines.delay
private enum class ConnectionState { UNKNOWN, CONNECTED, CONNECTING, ERROR }
private data class Connection(
val host: String = "localhost",
val port: Int = 8082,
val path: String = "/",
val state: MutableState<ConnectionState> = mutableStateOf(ConnectionState.UNKNOWN),
val reconnectDelay: Int = 5,
)
@Composable
@Preview
fun App() {
val connection = remember { Connection() }
val client = remember { HttpClient { install(WebSockets) } }
var message by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
while (true) {
connection.state.value = ConnectionState.CONNECTING
try {
client.webSocket(HttpMethod.Get,
connection.host,
connection.port,
connection.path) {
message = "Connected!"
connection.state.value = ConnectionState.CONNECTED
while (true) {
val frame = incoming.receive() as? Frame.Text ?: continue
message = frame.readText()
}
}
} catch (e: Exception) {
connection.state.value = ConnectionState.ERROR
repeat(connection.reconnectDelay) {
val remaining = connection.reconnectDelay - it
message = "Connection interrupted, will re-connect in $remaining seconds..."
delay(1000)
}
}
}
}
DisposableEffect(Unit) { onDispose { client.close() } }
MaterialTheme {
when (connection.state.value) {
ConnectionState.CONNECTED -> {
Row(Modifier.height(40.dp)) {
Text(modifier = Modifier.align(Alignment.CenterVertically),
text = "Listening on ${connection.host}:${connection.port} ")
Button(onClick = {}) { Text(message) }
}
}
ConnectionState.ERROR -> Text(text = message, color = Color.Red)
else -> Text(connection.state.value.name)
}
}
}
fun main() = application { Window(onCloseRequest = ::exitApplication) { App() } }
@@ -0,0 +1,2 @@
class NavRestore {
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef FGDBG_DEBUGSERVER_H
#define FGDBG_DEBUGSERVER_H
class CivetServer;
namespace filament::fgdbg {
class DebugServer {
public:
DebugServer();
~DebugServer();
void sendMessage(int number);
private:
CivetServer* mServer;
class RestRequestHandler *mRestRequestHandler = nullptr;
class WebSocketHandler* mWebSocketHandler = nullptr;
friend class RestRequestHandler;
friend class WebSocketHandler;
};
}
#endif // FGDBG_DEBUGSERVER_H
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef FGDBG_PASS_H
#define FGDBG_PASS_H
#include <string>
#include <vector>
namespace filament::fgdbg {
using ResourceId = int;
struct Pass {
std::string name;
int id;
std::vector<ResourceId> reads;
std::vector<ResourceId> writes;
};
}
#endif //FGDBG_PASS_H
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef FGDBG_RESOURCE_H
#define FGDBG_RESOURCE_H
#include <string>
namespace filament::fgdbg {
struct Resource {
std::string name;
int id;
int size;
};
}
#endif //FGDBG_RESOURCE_H
+28
View File
@@ -0,0 +1,28 @@
//
// Created by Fernando Raviola on 4/11/2022.
//
#ifndef FGDBG_SESSION_H
#define FGDBG_SESSION_H
#include "DebugServer.h"
#include "Resource.h"
#include "Pass.h"
#include <memory>
namespace filament::fgdbg {
class Session {
public:
Session(std::shared_ptr<DebugServer> server) : server{ server } {}
void addPasses(std::vector<Pass> passes);
void addResources(std::vector<Resource> resources);
void update();
private:
std::shared_ptr<DebugServer> server;
};
}
#endif //FGDBG_SESSION_H
+110
View File
@@ -0,0 +1,110 @@
/*
* Copyright (C) 2022 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 "fgdbg/DebugServer.h"
#include <CivetServer.h>
#include <utils/Log.h>
#include <tsl/robin_set.h>
namespace filament::fgdbg {
using namespace utils;
static const std::string_view kSuccessHeader =
"HTTP/1.1 200 OK\r\nContent-Type: %s\r\n"
"Connection: close\r\n\r\n";
class RestRequestHandler : public CivetHandler {
public:
RestRequestHandler() = default;
bool handleGet(CivetServer *server, struct mg_connection *conn) override {
mg_printf(conn, kSuccessHeader.data(), "application/json");
mg_printf(conn, "{ RestRequestHandler is working! }");
return true;
}
};
class WebSocketHandler : public CivetWebSocketHandler {
public:
WebSocketHandler() = default;
bool handleConnection(CivetServer *server, const struct mg_connection *conn) override {
return true;
}
void handleReadyState(CivetServer *server, struct mg_connection *conn) override {
mConnections.insert(conn);
}
void handleClose(CivetServer *server, const struct mg_connection *conn) override {
auto *key = const_cast<struct mg_connection *>(conn);
mConnections.erase(key);
}
void send(int number) {
auto string = std::to_string(number);
for (auto connection : mConnections) {
mg_websocket_write(connection,
MG_WEBSOCKET_OPCODE_TEXT,
string.c_str(),
string.length());
}
}
private:
tsl::robin_set<struct mg_connection*> mConnections;
};
DebugServer::DebugServer() {
slog.d << "FrameGraph debug server created" << io::endl;
//TODO (@feresr): Make port param customizable
const char* kServerOptions[] = {
"listening_ports", "8082",
"num_threads", "10",
"error_log_file", "civetweb.txt",
nullptr
};
mServer = new CivetServer(kServerOptions);
if (!mServer->getContext()) {
delete mServer;
mServer = nullptr;
slog.e << "Unable to start fgdbg DebugServer, see civetweb.txt for details." << io::endl;
return;
}
slog.i << "Server started successfully" << io::endl;
mRestRequestHandler = new RestRequestHandler();
mWebSocketHandler = new WebSocketHandler();
mServer->addHandler("", mRestRequestHandler);
mServer->addWebSocketHandler("", mWebSocketHandler);
}
void DebugServer::sendMessage(int number) {
mWebSocketHandler->send(number);
}
DebugServer::~DebugServer() {
slog.d << "FrameGraph debug server destroyed" << io::endl;
delete mRestRequestHandler;
delete mWebSocketHandler;
}
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 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 "Session.h"
namespace filament::fgdbg {
void Session::addPasses(std::vector <Pass> passes);
void Session::addResources(std::vector <Resource> resources);
void Session::update();
}
@@ -232,15 +232,14 @@ enum class Property : uint8_t {
// when adding new Properties, make sure to update MATERIAL_PROPERTIES_COUNT
};
// These flags should match the equivalents in Variant.h.
enum class UserVariantFilterBit : uint32_t {
DIRECTIONAL_LIGHTING = 0x01,
DYNAMIC_LIGHTING = 0x02,
SHADOW_RECEIVER = 0x04,
SKINNING = 0x08,
FOG = 0x20,
VSM = 0x40,
SSR = VSM | SHADOW_RECEIVER,
FOG = 0x10,
VSM = 0x20,
SSR = 0x40,
};
using UserVariantFilterMask = uint32_t;
@@ -49,7 +49,7 @@ public:
struct SamplerInfo { // NOLINT(cppcoreguidelines-pro-type-member-init)
utils::CString name; // name of this sampler
utils::CString uniformName; // name of the uniform holding this sampler (needed for glsl/MSL)
utils::CString uniformName; // name of the uniform holding this sampler (needed for glsl)
uint8_t offset; // offset in "Sampler" of this sampler in the buffer
Type type; // type of this sampler
Format format; // format of this sampler
-3
View File
@@ -57,7 +57,6 @@ set(PRIVATE_HDRS
src/eiff/DictionarySpirvChunk.h
src/eiff/MaterialSpirvChunk.h
src/GLSLPostProcessor.h
src/MetalArgumentBuffer.h
src/ShaderMinifier.h
src/sca/ASTHelpers.h
src/sca/GLSLTools.h
@@ -68,7 +67,6 @@ set(SRCS
src/eiff/BlobDictionary.cpp
src/eiff/DictionarySpirvChunk.cpp
src/eiff/MaterialSpirvChunk.cpp
src/MetalArgumentBuffer.cpp
src/sca/ASTHelpers.cpp
src/sca/GLSLTools.cpp
src/GLSLPostProcessor.cpp
@@ -165,7 +163,6 @@ project(test_filamat)
set(TARGET test_filamat)
set(SRCS
tests/test_filamat.cpp
tests/test_argBufferFixup.cpp
tests/test_includes.cpp)
add_executable(${TARGET} ${SRCS})
+21 -50
View File
@@ -28,8 +28,6 @@
#include "shaders/CodeGenerator.h"
#include "shaders/MaterialInfo.h"
#include "MetalArgumentBuffer.h"
#include <filament/MaterialEnums.h>
#include <private/filament/Variant.h>
#include "SibGenerator.h"
@@ -167,31 +165,8 @@ void GLSLPostProcessor::spirvToToMsl(const SpirvBlob *spirv, std::string *outMsl
mslOptions.argument_buffers = true;
// We're using argument buffers for texture resources, however, we cannot rely on spirv-cross to
// generate the argument buffer definitions.
//
// Consider a shader with 3 textures:
// layout (set = 0, binding = 0) uniform sampler2D texture1;
// layout (set = 0, binding = 1) uniform sampler2D texture2;
// layout (set = 0, binding = 2) uniform sampler2D texture3;
//
// If only texture1 and texture2 are used in the material, then texture3 will be optimized away.
// This results in an argument buffer like the following:
// struct spvDescriptorSetBuffer0 {
// texture2d<float> texture1 [[id(0)]];
// sampler texture1Smplr [[id(1)]];
// texture2d<float> texture2 [[id(2)]];
// sampler texture2Smplr [[id(3)]];
// };
// Note that this happens even if "pad_argument_buffer_resources" and
// "force_active_argument_buffer_resources" are true.
//
// This would be fine, except older Apple devices don't like it when the argument buffer in the
// shader doesn't precisely match the one generated at runtime.
//
// So, we use the MetalArgumentBuffer class to replace spirv-cross' argument buffer definitions
// with our own that contain all the textures/samples, even those optimized away.
std::vector<MetalArgumentBuffer*> argumentBuffers;
// Necessary to keep all argument buffers the same size across material variants.
mslOptions.pad_argument_buffer_resources = true;
mslCompiler.set_msl_options(mslOptions);
@@ -221,25 +196,28 @@ void GLSLPostProcessor::spirvToToMsl(const SpirvBlob *spirv, std::string *outMsl
//
// Which is then bound to the vertex/fragment functions:
// constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(27)]]
forEachSib(config,
[&executionModel, &mslCompiler, &argumentBuffers](
uint8_t bindingPoint, const SamplerInterfaceBlock* sib) {
forEachSib(config, [&executionModel, &mslCompiler](uint8_t bindingPoint, const SamplerInterfaceBlock* sib) {
const auto& infoList = sib->getSamplerInfoList();
// bindingPoint + 1, because the first descriptor set is for uniforms
auto argBufferBuilder = MetalArgumentBuffer::Builder()
.name("spvDescriptorSetBuffer" + std::to_string(int(bindingPoint + 1)));
for (const auto& info: infoList) {
const std::string name = info.uniformName.c_str();
argBufferBuilder
.texture(info.offset * 2, name, info.type, info.format)
.sampler(info.offset * 2 + 1, name + "Smplr");
// A MSLResourceBinding tells SPIRV-Cross how to map a sampler2D with a given set and
// binding to Metal resources.
// For example, textureB in the above example has:
// bindingPoint = 0 (it's the first sampler group)
// set = 1 (bindingPoint + 1, the first descriptor set is for uniforms)
// offset = 1 (it's the second sampler in the sampler group)
// The equivalent MSL texture argument is assigned the [[id(2)]] binding and its sampler
// resource assigned the [[id(3)]] binding (controlled via msl_texture and msl_sampler).
MSLResourceBinding newBinding;
newBinding.basetype = SPIRType::BaseType::SampledImage;
newBinding.stage = executionModel;
newBinding.desc_set = bindingPoint + 1;
newBinding.binding = info.offset;
newBinding.count = 1;
newBinding.msl_texture = info.offset * 2;
newBinding.msl_sampler = info.offset * 2 + 1;
mslCompiler.add_msl_resource_binding(newBinding);
}
argumentBuffers.push_back(argBufferBuilder.build());
// This MSLResourceBinding is how we control the [[buffer(n)]] binding of the argument
// This final MSLResourceBinding is how we control the [[buffer(n)]] binding of the argument
// buffer itself;
MSLResourceBinding argBufferBinding;
// the baseType doesn't matter, but can't be UNKNOWN
@@ -284,13 +262,6 @@ void GLSLPostProcessor::spirvToToMsl(const SpirvBlob *spirv, std::string *outMsl
*outMsl = mslCompiler.compile();
*outMsl = minifier.removeWhitespace(*outMsl);
// Replace spirv-cross' generated argument buffers with our own.
for (auto* argBuffer : argumentBuffers) {
auto argBufferMsl = argBuffer->getMsl();
MetalArgumentBuffer::replaceInShader(*outMsl, argBuffer->getName(), argBufferMsl);
MetalArgumentBuffer::destroy(&argBuffer);
}
}
bool GLSLPostProcessor::process(const std::string& inputShader, Config const& config,
-221
View File
@@ -1,221 +0,0 @@
/*
* Copyright (C) 2022 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 "MetalArgumentBuffer.h"
#include <sstream>
#include <utility>
namespace filamat {
MetalArgumentBuffer::Builder& filamat::MetalArgumentBuffer::Builder::name(
const std::string& name) noexcept {
mName = name;
return *this;
}
MetalArgumentBuffer::Builder& MetalArgumentBuffer::Builder::texture(size_t index,
const std::string& name, filament::backend::SamplerType type,
filament::backend::SamplerFormat format) noexcept {
// All combinations of SamplerType and SamplerFormat are valid except for SAMPLER_3D / SHADOW.
assert_invariant(type != filament::backend::SamplerType::SAMPLER_3D ||
format != filament::backend::SamplerFormat::SHADOW);
mArguments.emplace_back(TextureArgument { name, index, type, format });
return *this;
}
MetalArgumentBuffer::Builder& MetalArgumentBuffer::Builder::sampler(
size_t index, const std::string& name) noexcept {
mArguments.emplace_back(SamplerArgument { name , index });
return *this;
}
MetalArgumentBuffer* MetalArgumentBuffer::Builder::build() {
assert_invariant(!mName.empty());
return new MetalArgumentBuffer(*this);
}
std::ostream& MetalArgumentBuffer::Builder::TextureArgument::write(std::ostream& os) const {
switch (format) {
case filament::backend::SamplerFormat::INT:
case filament::backend::SamplerFormat::UINT:
case filament::backend::SamplerFormat::FLOAT:
os << "texture";
break;
case filament::backend::SamplerFormat::SHADOW:
os << "depth";
break;
}
switch (type) {
case filament::backend::SamplerType::SAMPLER_EXTERNAL:
case filament::backend::SamplerType::SAMPLER_2D:
os << "2d";
break;
case filament::backend::SamplerType::SAMPLER_2D_ARRAY:
os << "2d_array";
break;
case filament::backend::SamplerType::SAMPLER_CUBEMAP:
os << "cube";
break;
case filament::backend::SamplerType::SAMPLER_3D:
os << "3d";
break;
case filament::backend::SamplerType::SAMPLER_CUBEMAP_ARRAY:
os << "cube_array";
break;
}
switch (format) {
case filament::backend::SamplerFormat::INT:
os << "<int>";
break;
case filament::backend::SamplerFormat::UINT:
os << "<uint>";
break;
case filament::backend::SamplerFormat::FLOAT:
case filament::backend::SamplerFormat::SHADOW:
os << "<float>";
break;
}
os << " " << name << " [[id(" << index << ")]];" << std::endl;
return os;
}
std::ostream& MetalArgumentBuffer::Builder::SamplerArgument::write(std::ostream& os) const {
os << "sampler " << name << " [[id(" << index << ")]];" << std::endl;
return os;
}
MetalArgumentBuffer::MetalArgumentBuffer(Builder& builder) {
mName = builder.mName;
std::stringstream ss;
ss << "struct " << mName << " {" << std::endl;
auto& args = builder.mArguments;
// Sort the arguments by index.
std::sort(std::begin(args), std::end(args), [](auto const& lhs, auto const& rhs) {
return std::visit([](auto const& x, auto const& y) { return x.index < y.index; }, lhs, rhs);
});
// Check that all the indices are unique.
assert_invariant(
std::adjacent_find(args.begin(), args.end(), [](auto const& lhs, auto const& rhs) {
return std::visit(
[](auto const& x, auto const& y) { return x.index == y.index; }, lhs, rhs);
}) == args.end());
for (const auto& a : builder.mArguments) {
std::visit([&](auto&& arg) {
arg.write(ss);
}, a);
}
ss << "}";
mShaderText = ss.str();
}
void MetalArgumentBuffer::destroy(MetalArgumentBuffer** argumentBuffer) {
delete *argumentBuffer;
*argumentBuffer = nullptr;
}
static bool isWhitespace(char c) {
return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v');
}
bool MetalArgumentBuffer::replaceInShader(std::string& shader,
const std::string& targetArgBufferName, const std::string& replacement) noexcept {
// We make some assumptions here, e.g., that the MSL is well-formed and has no comments.
// This algorithm isn't a full-fledged parser, and isn't foolproof. In particular, we can't tell
// the difference between source code and comments. However, at this stage, the MSL should have
// all comments stripped.
// In order to do the replacement, we look for 4 key locations in the source shader.
// s: the beginning of the 'struct' token
// n: the beginning of the argument buffer name
// b: the beginning of the structure block
// e: the end of the argument buffer structure
//
// s n b e
// struct targetArgBuffer { }
// We only want to match the definition of the argument buffer, not any of its usages.
// For example:
// struct ArgBuffer { }; // this should match
// void aFunction(ArgBuffer& args); // this should not
const auto argBufferNameLength = targetArgBufferName.length();
// First, find n.
size_t n = shader.find(targetArgBufferName);
while (n != std::string::npos) {
// Now, find b, the opening curly brace {.
size_t b = shader.find('{', n);
if (b == std::string::npos) {
// If there's no { character in the rest of the shader, the arg buffer definition
// definitely doesn't exit.
return false;
}
// After the arg buffer name, ensure that only whitespace characters exist until b.
if (!std::all_of(shader.begin() + n + argBufferNameLength, shader.begin() + b,
isWhitespace)) {
// If there is a non-whitespace character, start over by looking for the next occurrence
// of the arg buffer name.
n = shader.find(targetArgBufferName, n + 1);
continue;
}
// Now, we find s.
size_t s = shader.rfind("struct", n);
if (s == std::string::npos) {
// If we can't find the "struct" keyword, it's not necessarily an error.
// Start over and Look for the next occurrence of the arg buffer name.
n = shader.find(targetArgBufferName, n + 1);
continue;
}
// After the struct keyword, ensure that only whitespace characters exist until n.
if (!std::all_of(shader.begin() + s + 6, shader.begin() + n, isWhitespace)) {
// Look for the next occurrence of the arg buffer name.
n = shader.find(targetArgBufferName, n + 1);
continue;
}
// Now, we find e.
size_t e = shader.find('}', n);
if (e == std::string::npos) {
// If there's no } character in the rest of the shader, the arg buffer definition
// definitely doesn't exit.
return false;
}
// Perform the replacement.
shader.replace(s, e - s + 1, replacement);
// Theoretically we could continue to find and replace other occurrences, but there should
// only ever be a single definition of the argument buffer structure.
return true;
}
return false;
}
} // namespace filamat
-117
View File
@@ -1,117 +0,0 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef TNT_METALARGUMENTBUFFER_H
#define TNT_METALARGUMENTBUFFER_H
#include <iostream>
#include <string>
#include <variant>
#include <vector>
#include <backend/DriverEnums.h>
namespace filamat {
class MetalArgumentBuffer {
public:
class Builder {
public:
/**
* Set the name of the argument buffer structure.
*/
Builder& name(const std::string& name) noexcept;
/**
* Add a texture argument to the argument buffer structure.
* All combinations of type/format are supported, except for SAMPLER_3D/SHADOW.
*
* @param index the [[id(n)]] index of the texture argument
* @param name the name of the texture argument
* @param type controls the texture data type, e.g., texture2d, texturecube, etc
* @param format controls the data format of the texture, e.g., int, float, etc
*/
Builder& texture(size_t index, const std::string& name,
filament::backend::SamplerType type,
filament::backend::SamplerFormat format) noexcept;
/**
* Add a sampler argument to the argument buffer structure.
* @param index the [[id(n)]] index of the texture argument
* @param name the name of the texture argument
*/
Builder& sampler(size_t index, const std::string& name) noexcept;
MetalArgumentBuffer* build();
friend class MetalArgumentBuffer;
private:
std::string mName;
struct TextureArgument {
std::string name;
size_t index;
filament::backend::SamplerType type;
filament::backend::SamplerFormat format;
std::ostream& write(std::ostream& os) const;
};
struct SamplerArgument {
std::string name;
size_t index;
std::ostream& write(std::ostream& os) const;
};
using ArgumentType = std::variant<TextureArgument, SamplerArgument>;
std::vector<ArgumentType> mArguments;
};
static void destroy(MetalArgumentBuffer** argumentBuffer);
const std::string& getName() const noexcept { return mName; }
/**
* Returns the generated MSL argument buffer definition.
*/
const std::string& getMsl() const noexcept { return mShaderText; }
/**
* Searches shader for the target argument buffer, and replaces it with the replacement string.
*
* @param shader the source MSL shader that contains the target argument buffer definition
* @param targetArgBufferName the name of the argument buffer definition to replace
* @param replacement the replacement argument buffer definition
* @return true if the target was found, false otherwise
*/
static bool replaceInShader(std::string& shader, const std::string& targetArgBufferName,
const std::string& replacement) noexcept;
private:
MetalArgumentBuffer(Builder& builder);
~MetalArgumentBuffer() = default;
std::string mName;
std::string mShaderText;
};
} // namespace filamat
#endif // TNT_METALARGUMENTBUFFER_H
-196
View File
@@ -1,196 +0,0 @@
/*
* Copyright (C) 2022 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 <gtest/gtest.h>
#include "MetalArgumentBuffer.h"
using namespace filamat;
using namespace filament::backend;
// -------------------------------------------------------------------------------------------------
TEST(ArgBufferFixup, Empty) {
auto argBuffer =
MetalArgumentBuffer::Builder()
.name("spvDescriptorSet0")
.build();
auto argBufferStr = argBuffer->getMsl();
const std::string expected =
"struct spvDescriptorSet0 {\n"
"}";
EXPECT_EQ(argBuffer->getMsl(), expected);
MetalArgumentBuffer::destroy(&argBuffer);
}
TEST(ArgBufferFixup, NoName) {
// A valid arg buffer name must be provided to MetalArgumentBuffer.
// This assertion is only fired in debug builds.
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
EXPECT_DEATH({
auto argBuffer = MetalArgumentBuffer::Builder().build();
MetalArgumentBuffer::destroy(&argBuffer);
}, "failed assertion");
EXPECT_DEATH({
auto argBuffer = MetalArgumentBuffer::Builder().name("").build();
MetalArgumentBuffer::destroy(&argBuffer);
}, "failed assertion");
#endif
}
TEST(ArgBufferFixup, DuplicateIndices) {
// Each index must be unique.
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
EXPECT_DEATH({
auto argBuffer = MetalArgumentBuffer::Builder()
.name("myArgumentBuffer")
.sampler(0, "samplerA")
.sampler(0, "samplerB")
.build();
MetalArgumentBuffer::destroy(&argBuffer);
}, "failed assertion");
#endif
}
TEST(ArgBufferFixup, TextureAndSampler) {
auto argBuffer =
MetalArgumentBuffer::Builder()
.name("myArgumentBuffer")
.texture(0, "textureA", SamplerType::SAMPLER_2D, SamplerFormat::FLOAT)
.sampler(1, "samplerA")
.build();
auto argBufferStr = argBuffer->getMsl();
const std::string expected =
"struct myArgumentBuffer {\n"
"texture2d<float> textureA [[id(0)]];\n"
"sampler samplerA [[id(1)]];\n"
"}";
EXPECT_EQ(argBuffer->getMsl(), expected);
MetalArgumentBuffer::destroy(&argBuffer);
}
TEST(ArgBufferFixup, Sorted) {
auto argBuffer =
MetalArgumentBuffer::Builder()
.name("myArgumentBuffer")
.sampler(3, "samplerB")
.texture(0, "textureA", SamplerType::SAMPLER_2D, SamplerFormat::FLOAT)
.texture(2, "textureB", SamplerType::SAMPLER_2D, SamplerFormat::FLOAT)
.sampler(1, "samplerA")
.build();
auto argBufferStr = argBuffer->getMsl();
const std::string expected =
"struct myArgumentBuffer {\n"
"texture2d<float> textureA [[id(0)]];\n"
"sampler samplerA [[id(1)]];\n"
"texture2d<float> textureB [[id(2)]];\n"
"sampler samplerB [[id(3)]];\n"
"}";
EXPECT_EQ(argBuffer->getMsl(), expected);
MetalArgumentBuffer::destroy(&argBuffer);
}
TEST(ArgBufferFixup, TextureTypes) {
auto argBuffer =
MetalArgumentBuffer::Builder()
.name("myArgumentBuffer")
.texture(0, "textureA", SamplerType::SAMPLER_2D, SamplerFormat::INT)
.texture(1, "textureB", SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::UINT)
.texture(2, "textureC", SamplerType::SAMPLER_CUBEMAP, SamplerFormat::FLOAT)
.texture(3, "textureD", SamplerType::SAMPLER_EXTERNAL, SamplerFormat::FLOAT)
.texture(4, "textureE", SamplerType::SAMPLER_3D, SamplerFormat::FLOAT)
.texture(5, "textureF", SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::SHADOW)
.build();
auto argBufferStr = argBuffer->getMsl();
const std::string expected =
"struct myArgumentBuffer {\n"
"texture2d<int> textureA [[id(0)]];\n"
"texture2d_array<uint> textureB [[id(1)]];\n"
"texturecube<float> textureC [[id(2)]];\n"
"texture2d<float> textureD [[id(3)]];\n"
"texture3d<float> textureE [[id(4)]];\n"
"depthcube_array<float> textureF [[id(5)]];\n"
"}";
EXPECT_EQ(argBuffer->getMsl(), expected);
MetalArgumentBuffer::destroy(&argBuffer);
}
TEST(ArgBufferFixup, InvalidType) {
// All combinations of SamplerType and SamplerFormat are valid except for SAMPLER_3D / SHADOW.
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
EXPECT_DEATH({
auto argBuffer =
MetalArgumentBuffer::Builder()
.name("myArgumentBuffer")
.texture(0, "textureA", SamplerType::SAMPLER_3D, SamplerFormat::SHADOW)
.build();
MetalArgumentBuffer::destroy(&argBuffer);
}, "failed assertion");
#endif
}
TEST(ArgBufferFixup, ReplaceInShader) {
{
std::string shader = "struct argBuffer {}"; // different name
EXPECT_FALSE(MetalArgumentBuffer::replaceInShader(shader, "argBufferX", "xyz"));
}
{
std::string shader = "argBuffer {} struct"; // no 'struct' keyword before
EXPECT_FALSE(MetalArgumentBuffer::replaceInShader(shader, "argBuffer", "xyz"));
}
{
std::string shader = "struct argBuffer"; // no braces
EXPECT_FALSE(MetalArgumentBuffer::replaceInShader(shader, "argBuffer", "xyz"));
}
{
std::string shader = "## struct argBuffer {} ###";
EXPECT_TRUE(MetalArgumentBuffer::replaceInShader(shader, "argBuffer", "replacement"));
EXPECT_EQ(shader, "## replacement ###");
}
{
std::string shader = "argBuffer {} struct argBuffer {} argBuffer";
EXPECT_TRUE(MetalArgumentBuffer::replaceInShader(shader, "argBuffer", "replacement"));
EXPECT_EQ(shader, "argBuffer {} replacement argBuffer");
}
{
std::string shader =
"struct FooBar {};\n"
"targetArgBuffer {};\n"
"struct targetArgBufferX {};\n"
"void someFunctionThatTakesAnArgBuffer(targetArgBuffer& arg);\n"
"struct targetArgBuffer{};\n";
std::string expected =
"struct FooBar {};\n"
"targetArgBuffer {};\n"
"struct targetArgBufferX {};\n"
"void someFunctionThatTakesAnArgBuffer(targetArgBuffer& arg);\n"
"replacement;\n";
EXPECT_TRUE(MetalArgumentBuffer::replaceInShader(shader, "targetArgBuffer", "replacement"));
EXPECT_EQ(shader, expected);
}
}
+3 -14
View File
@@ -645,7 +645,7 @@ void FAssetLoader::createPrimitives(const cgltf_data* srcAsset, const cgltf_node
// Expand the object-space bounding box.
aabb.min = min(outputPrim.aabb.min, aabb.min);
aabb.max = max(outputPrim.aabb.max, aabb.max);
}
}
mat4f worldTransform;
cgltf_node_transform_world(node, &worldTransform[0][0]);
@@ -964,7 +964,6 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, Primitive* out
targetsCount = MAX_MORPH_TARGETS;
}
const Aabb baseAabb(outPrim->aabb);
for (cgltf_size targetIndex = 0; targetIndex < targetsCount; targetIndex++) {
const cgltf_morph_target& morphTarget = inPrim.targets[targetIndex];
for (cgltf_size aindex = 0; aindex < morphTarget.attributes_count; aindex++) {
@@ -983,20 +982,10 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, Primitive* out
return false;
}
if (!accessor->has_min || !accessor->has_max) {
continue;
}
Aabb targetAabb(baseAabb);
const float* minp = &accessor->min[0];
const float* maxp = &accessor->max[0];
// We assume that the range of morph target weight is [0, 1].
targetAabb.min += float3(minp[0], minp[1], minp[2]);
targetAabb.max += float3(maxp[0], maxp[1], maxp[2]);
outPrim->aabb.min = min(outPrim->aabb.min, targetAabb.min);
outPrim->aabb.max = max(outPrim->aabb.max, targetAabb.max);
outPrim->aabb.min = min(outPrim->aabb.min, float3(minp[0], minp[1], minp[2]));
outPrim->aabb.max = max(outPrim->aabb.max, float3(maxp[0], maxp[1], maxp[2]));
VertexBuffer::AttributeType fatype;
VertexBuffer::AttributeType actualType;
-39
View File
@@ -130,45 +130,6 @@ void FFilamentInstance::recomputeBoundingBoxes() {
aabb.min = min(aabb.min, pt);
aabb.max = max(aabb.max, pt);
}
if (!prim->targets_count) {
break;
}
Aabb baseAabb(aabb);
for (cgltf_size targetIndex = 0; targetIndex < prim->targets_count; ++targetIndex) {
const cgltf_morph_target& target = prim->targets[targetIndex];
for (cgltf_size attribIndex = 0; attribIndex < target.attributes_count; ++attribIndex) {
const cgltf_attribute& targetAttribute = target.attributes[attribIndex];
if (targetAttribute.type != cgltf_attribute_type_position) {
continue;
}
const cgltf_accessor* targetAccessor = targetAttribute.data;
const cgltf_size targetCount = targetAccessor->count;
const cgltf_size targetDim = cgltf_num_components(targetAccessor->type);
assert_invariant(targetCount == accessor->count);
assert_invariant(targetDim == dim);
cgltf_accessor_unpack_floats(targetAccessor, unpacked.data(), unpacked.size());
Aabb targetAabb;
for (cgltf_size i = 0, j = 0, n = accessor->count; i < n; ++i, j += dim) {
float3 delta(unpacked[j + 0], unpacked[j + 1], unpacked[j + 2]);
targetAabb.min = min(targetAabb.min, delta);
targetAabb.max = max(targetAabb.max, delta);
}
targetAabb.min += baseAabb.min;
targetAabb.max += baseAabb.max;
aabb.min = min(aabb.min, targetAabb.min);
aabb.max = max(aabb.max, targetAabb.max);
break;
}
}
break;
}
}
+1 -1
View File
@@ -217,7 +217,7 @@ inline bool getElementType(cgltf_type type, cgltf_component_type ctype,
*actualType = filament::VertexBuffer::AttributeType::UBYTE3;
return true;
case cgltf_component_type_r_16:
*permitType = filament::VertexBuffer::AttributeType::SHORT3;
*permitType = filament::VertexBuffer::AttributeType::FLOAT3;
*actualType = filament::VertexBuffer::AttributeType::SHORT3;
return true;
case cgltf_component_type_r_16u:
+1 -1
View File
@@ -509,7 +509,7 @@ bool ResourceLoader::loadResources(FFilamentAsset* asset, bool async) {
data = bufferData + accessor->offset;
} else {
bufferData = (const uint8_t*) accessor->buffer_view->buffer->data;
data = computeBindingOffset(accessor) + bufferData;
data = computeBindingOffset(accessor) + bufferData + accessor->offset;
}
assert_invariant(bufferData);
const uint32_t size = computeBindingSize(accessor);
-1
View File
@@ -145,7 +145,6 @@ set(TEST_SRCS
test/test_FixedCapacityVector.cpp
test/test_Hash.cpp
test/test_JobSystem.cpp
test/test_QuadTreeArray.cpp
test/test_RangeMap.cpp
test/test_StructureOfArrays.cpp
test/test_sstream.cpp
-180
View File
@@ -1,180 +0,0 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef TNT_UTILS_QUADTREE_H
#define TNT_UTILS_QUADTREE_H
#include <utils/compiler.h>
#include <utils/debug.h>
#include <array>
#include <type_traits>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
namespace utils {
namespace QuadTreeUtils {
/**
* 16-bits morton encoding
* @param x 8-bits horizontal coordinate
* @param y 8-bits vertical coordinate
* @return morton encoding of (x,y)
*/
static inline constexpr uint16_t morton(uint8_t x, uint8_t y) noexcept {
uint32_t r = x | (uint32_t(y) << 16);
r = (r | (r << 4u)) & 0x0f0f0f0fu;
r = (r | (r << 2u)) & 0x33333333u;
r = (r | (r << 1u)) & 0x55555555u;
return uint16_t(r | (r >> 15u));
}
/**
* size of a quad-tree of height `height`
* @param height height of the Quad-tree
* @return the number of elements in the tree
*/
static inline constexpr size_t size(size_t height) noexcept {
return QuadTreeUtils::morton(uint8_t((1u << height) - 1u), 0u);
}
/**
* Index in the QuadTreeArray of a Quad-tree node referenced by its height and code
* @param l height of the node
* @param code morton code of the node
* @return index in the QuadTreeArray of this node
*/
static inline constexpr size_t index(size_t l, size_t code) noexcept {
return size(l) + code;
}
/**
* Index in the QuadTreeArray of the parent of the specified node
* @param l height of the node
* @param code morton code of the node
* @return index in the QuadTreeArray of this node's parent
*/
static inline constexpr size_t parent(size_t l, size_t code) noexcept {
assert_invariant(l > 0);
return index(l - 1u, code >> 2u);
}
// integrated unit-tests!
static_assert(size(0) == 0);
static_assert(size(1) == 1);
static_assert(size(2) == 5);
static_assert(size(3) == 21);
static_assert(size(4) == 85);
} // namespace QuadTreeUtils
/**
* A Quad-tree encoded as an array.
* @tparam T Type of the quad-tree nodes
* @tparam HEIGHT Height of the quad-tree, muse be <= 4
*/
template<typename T, size_t HEIGHT>
class QuadTreeArray : public std::array<T, QuadTreeUtils::size(HEIGHT)> {
static_assert(HEIGHT <= 4, "QuadTreeArray height must be <= 4");
// Simple fixed capacity stack
template<typename TYPE, size_t CAPACITY,
typename = typename std::enable_if<std::is_trivial<TYPE>::value>::type>
class stack {
TYPE mElements[CAPACITY];
size_t mSize = 0;
public:
bool empty() const noexcept { return mSize == 0; }
void push(TYPE const& v) noexcept {
assert_invariant(mSize < CAPACITY);
mElements[mSize++] = v;
}
void pop() noexcept {
assert_invariant(mSize > 0);
--mSize;
}
const TYPE& back() const noexcept {
return mElements[mSize - 1];
}
};
public:
using code_t = uint8_t;
struct NodeId {
int8_t l; // height of the node or -1 if invalid
code_t code; // morton code of the node
};
enum class TraversalResult {
EXIT, // end traversal
RECURSE, // proceed with the children
SKIP_CHILDREN // skip children
};
static inline constexpr size_t height() noexcept {
return HEIGHT;
}
/**
* non-recursive depth-first traversal
*
* @tparam Process closure to process each visited node
* @param l height of the node to start with
* @param code code of the node to start with
* @param h maximum height to visit, must be < height()
* @param process closure to process each visited node
*/
template<typename Process,
typename = typename std::enable_if<
std::is_invocable_r_v<TraversalResult, Process, NodeId>>::type>
static void traverse(int8_t l, code_t code, size_t maxHeight, Process&& process) noexcept {
assert_invariant(maxHeight < height());
const int8_t h = int8_t(maxHeight);
stack<NodeId, 4 * height()> stack;
stack.push({ l, code });
while (!stack.empty()) {
NodeId curr = stack.back();
stack.pop();
TraversalResult r = process(curr);
if (r == TraversalResult::EXIT) {
break;
}
if (r == TraversalResult::RECURSE && curr.l < h) {
for (size_t c = 0; c < 4; c++) {
stack.push({
int8_t(curr.l + 1u),
code_t((curr.code << 2u) | (3u - c))
});
}
}
}
}
template<typename Node,
typename = typename std::enable_if<
std::is_invocable_r_v<TraversalResult, Node, NodeId>>::type>
static void traverse(int8_t l, code_t code, Node&& process) noexcept {
traverse(l, code, height() - 1, std::forward<Node>(process));
}
};
} // namespace utils
#endif //TNT_UTILS_QUADTREE_H

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