Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
107f25ca75 | ||
|
|
46806735e4 | ||
|
|
c410acb69f | ||
|
|
cb9eba3b3e | ||
|
|
dcf51ba20e | ||
|
|
73e6ccad96 | ||
|
|
ad5c409317 | ||
|
|
db597af272 | ||
|
|
4a46955bfb | ||
|
|
864bc3c1c1 | ||
|
|
2da395caf8 |
+2
-9
@@ -525,14 +525,11 @@ else()
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
|
||||
endif()
|
||||
|
||||
# By default, link in matdbg/fgviewer for Desktop + Debug only since it pulls in filamat and a web server.
|
||||
# By default, link in matdbg for Desktop + Debug only since it pulls in filamat and a web server.
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND IS_HOST_PLATFORM)
|
||||
option(FILAMENT_ENABLE_MATDBG "Enable the material debugger" ON)
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" ON)
|
||||
else()
|
||||
option(FILAMENT_ENABLE_MATDBG "Enable the material debugger" OFF)
|
||||
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
|
||||
endif()
|
||||
|
||||
# Only optimize materials in Release mode (so error message lines match the source code)
|
||||
@@ -781,11 +778,6 @@ if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
|
||||
if (FILAMENT_ENABLE_MATDBG OR IS_HOST_PLATFORM)
|
||||
add_subdirectory(${LIBRARIES}/matdbg)
|
||||
endif()
|
||||
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# if (FILAMENT_ENABLE_FGVIEWER OR IS_HOST_PLATFORM)
|
||||
# add_subdirectory(${LIBRARIES}/fgviewer)
|
||||
# endif()
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
@@ -830,6 +822,7 @@ if (IS_HOST_PLATFORM)
|
||||
endif()
|
||||
add_subdirectory(${TOOLS}/mipgen)
|
||||
add_subdirectory(${TOOLS}/normal-blending)
|
||||
add_subdirectory(${TOOLS}/rainbowgen)
|
||||
add_subdirectory(${TOOLS}/resgen)
|
||||
add_subdirectory(${TOOLS}/rgb-to-lmsr)
|
||||
add_subdirectory(${TOOLS}/roughness-prefilter)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.56.6'
|
||||
implementation 'com.google.android.filament:filament-android:1.56.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.56.6'
|
||||
pod 'Filament', '~> 1.56.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,19 +7,6 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.56.6
|
||||
|
||||
fix crash: the 'target_node' of Animation Channel may be nullpointer.
|
||||
|
||||
## v1.56.5
|
||||
|
||||
|
||||
## v1.56.4
|
||||
|
||||
|
||||
## v1.56.3
|
||||
|
||||
|
||||
## v1.56.2
|
||||
|
||||
- vk: fix stage pool gc logic
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
// com.google.android.filament.exclude-vulkan
|
||||
// When set, support for Vulkan will be excluded.
|
||||
//
|
||||
// com.google.android.filament.fgviewer
|
||||
// When set, enables fgviewer
|
||||
//
|
||||
// com.google.android.filament.matdbg
|
||||
// When set, enables matdbg
|
||||
//
|
||||
@@ -64,11 +61,6 @@ buildscript {
|
||||
.gradleProperty("com.google.android.filament.exclude-vulkan")
|
||||
.isPresent()
|
||||
|
||||
// TODO: Uncomment below when fgviewer is ready
|
||||
// def fgviewer = providers
|
||||
// .gradleProperty("com.google.android.filament.fgviewer")
|
||||
// .isPresent()
|
||||
|
||||
def matdbg = providers
|
||||
.gradleProperty("com.google.android.filament.matdbg")
|
||||
.isPresent()
|
||||
@@ -123,8 +115,6 @@ buildscript {
|
||||
"-DANDROID_STL=c++_static",
|
||||
"-DFILAMENT_DIST_DIR=${filamentPath}".toString(),
|
||||
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString(),
|
||||
// TODO: Uncomment below when fgviewer is ready
|
||||
// "-DFILAMENT_ENABLE_FGVIEWER=${fgviewer ? 'ON' : 'OFF'}".toString(),
|
||||
"-DFILAMENT_ENABLE_MATDBG=${matdbg ? 'ON' : 'OFF'}".toString(),
|
||||
"-DFILAMENT_DISABLE_MATOPT=${matnopt ? 'ON' : 'OFF'}".toString()
|
||||
]
|
||||
|
||||
@@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.19)
|
||||
project(filament-android)
|
||||
|
||||
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# option(FILAMENT_ENABLE_FGVIEWER "Enables Frame Graph Viewer" OFF)
|
||||
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
|
||||
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
|
||||
|
||||
@@ -53,13 +51,6 @@ add_library(smol-v STATIC IMPORTED)
|
||||
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
|
||||
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# if (FILAMENT_ENABLE_FGVIEWER)
|
||||
# add_library(fgviewer STATIC IMPORTED)
|
||||
# set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
|
||||
# ${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfgviewer.a)
|
||||
# endif()
|
||||
|
||||
if (FILAMENT_ENABLE_MATDBG)
|
||||
add_library(matdbg STATIC IMPORTED)
|
||||
set_target_properties(matdbg PROPERTIES IMPORTED_LOCATION
|
||||
@@ -126,8 +117,6 @@ target_link_libraries(filament-jni
|
||||
# libgeometry is PUBLIC because gltfio uses it.
|
||||
PUBLIC geometry
|
||||
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# $<$<STREQUAL:${FILAMENT_ENABLE_FGVIEWER},ON>:fgviewer>
|
||||
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
|
||||
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
|
||||
|
||||
@@ -38,7 +38,7 @@ Java_com_google_android_filament_EntityManager_nCreateArray(JNIEnv* env, jclass,
|
||||
// (which it is), but still.
|
||||
em->create((size_t) n, reinterpret_cast<Entity *>(entities));
|
||||
|
||||
env->ReleaseIntArrayElements(entities_, entities, 0);
|
||||
env->ReleaseIntArrayElements(entities_, entities, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
|
||||
@@ -167,7 +167,7 @@ Java_com_google_android_filament_IndirectLight_nGetDirectionEstimateStatic(JNIEn
|
||||
jfloat *outDirection = env->GetFloatArrayElements(outDirection_, NULL);
|
||||
*reinterpret_cast<filament::math::float3*>(outDirection) = IndirectLight::getDirectionEstimate((filament::math::float3*)sh);
|
||||
env->ReleaseFloatArrayElements(outDirection_, outDirection, 0);
|
||||
env->ReleaseFloatArrayElements(sh_, sh, 0);
|
||||
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@@ -178,5 +178,5 @@ Java_com_google_android_filament_IndirectLight_nGetColorEstimateStatic(JNIEnv *e
|
||||
*reinterpret_cast<filament::math::float4*>(outColor) =
|
||||
IndirectLight::getColorEstimate((filament::math::float3*)sh, math::float3{x, y, z});
|
||||
env->ReleaseFloatArrayElements(outColor_, outColor, 0);
|
||||
env->ReleaseFloatArrayElements(sh_, sh, 0);
|
||||
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
|
||||
}
|
||||
|
||||
@@ -25,14 +25,13 @@ using namespace filament;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
|
||||
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount, jint shadowQuality) {
|
||||
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, buffer_, size);
|
||||
auto builder = Material::Builder();
|
||||
if (shBandCount) {
|
||||
builder.sphericalHarmonicsBandCount(shBandCount);
|
||||
}
|
||||
builder.shadowSamplingQuality((Material::Builder::ShadowSamplingQuality)shadowQuality);
|
||||
Material* material = builder
|
||||
.package(buffer.getData(), buffer.getSize())
|
||||
.build(*engine);
|
||||
|
||||
@@ -138,13 +138,6 @@ Java_com_google_android_filament_Texture_nBuilderImportTexture(JNIEnv*, jclass,
|
||||
builder->import((intptr_t)id);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Texture_nBuilderExternal(JNIEnv*, jclass, jlong nativeBuilder) {
|
||||
Texture::Builder *builder = (Texture::Builder *) nativeBuilder;
|
||||
builder->external();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Texture_nBuilderBuild(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jlong nativeEngine) {
|
||||
|
||||
@@ -344,18 +344,9 @@ public class Material {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
public enum ShadowSamplingQuality {
|
||||
/** 2x2 PCF */
|
||||
HARD,
|
||||
/** 3x3 gaussian filter */
|
||||
LOW,
|
||||
}
|
||||
|
||||
private Buffer mBuffer;
|
||||
private int mSize;
|
||||
private int mShBandCount = 0;
|
||||
private ShadowSamplingQuality mShadowSamplingQuality = ShadowSamplingQuality.LOW;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the material data. The material data is a binary blob produced by
|
||||
@@ -387,18 +378,6 @@ public class Material {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the quality of shadow sampling. This is only taken into account
|
||||
* if this material is lit and in the surface domain.
|
||||
* @param quality
|
||||
* @return Reference to this Builder for chaining calls.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder shadowSamplingQuality(ShadowSamplingQuality quality) {
|
||||
mShadowSamplingQuality = quality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the Material object.
|
||||
*
|
||||
@@ -411,7 +390,7 @@ public class Material {
|
||||
@NonNull
|
||||
public Material build(@NonNull Engine engine) {
|
||||
long nativeMaterial = nBuilderBuild(engine.getNativeObject(),
|
||||
mBuffer, mSize, mShBandCount, mShadowSamplingQuality.ordinal());
|
||||
mBuffer, mSize, mShBandCount);
|
||||
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
|
||||
return new Material(nativeMaterial);
|
||||
}
|
||||
@@ -1062,7 +1041,7 @@ public class Material {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount, int shadowQuality);
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount);
|
||||
private static native long nCreateInstance(long nativeMaterial);
|
||||
private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name);
|
||||
private static native long nGetDefaultInstance(long nativeMaterial);
|
||||
|
||||
@@ -800,19 +800,6 @@ public class Texture {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder external() {
|
||||
nBuilderExternal(mNativeBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Texture</code> instance.
|
||||
* @param engine The {@link Engine} to associate this <code>Texture</code> with.
|
||||
@@ -1274,7 +1261,6 @@ public class Texture {
|
||||
private static native void nBuilderUsage(long nativeBuilder, int flags);
|
||||
private static native void nBuilderSwizzle(long nativeBuilder, int r, int g, int b, int a);
|
||||
private static native void nBuilderImportTexture(long nativeBuilder, long id);
|
||||
private static native void nBuilderExternal(long nativeBuilder);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
|
||||
|
||||
private static native int nGetWidth(long nativeTexture, int level);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.56.6
|
||||
VERSION_NAME=1.56.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ function print_help {
|
||||
echo " This is sometimes needed instead of -c (which still misses some clean steps)."
|
||||
echo " -d"
|
||||
echo " Enable matdbg."
|
||||
echo " -t"
|
||||
echo " Enable fgviewer."
|
||||
echo " -f"
|
||||
echo " Always invoke CMake before incremental builds."
|
||||
echo " -g"
|
||||
@@ -127,27 +125,6 @@ function print_matdbg_help {
|
||||
echo ""
|
||||
}
|
||||
|
||||
function print_fgviewer_help {
|
||||
echo "fgviewer is enabled in the build, but some extra steps are needed."
|
||||
echo ""
|
||||
echo "FOR DESKTOP BUILDS:"
|
||||
echo ""
|
||||
echo "Please set the port environment variable before launching. e.g., on macOS do:"
|
||||
echo " export FILAMENT_FGVIEWER_PORT=8085"
|
||||
echo ""
|
||||
echo "FOR ANDROID BUILDS:"
|
||||
echo ""
|
||||
echo "1) For Android Studio builds, make sure to set:"
|
||||
echo " -Pcom.google.android.filament.fgviewer"
|
||||
echo " option in Preferences > Build > Compiler > Command line options."
|
||||
echo ""
|
||||
echo "2) The port number is hardcoded to 8085 so you will need to do:"
|
||||
echo " adb forward tcp:8085 tcp:8085"
|
||||
echo ""
|
||||
echo "3) Be sure to enable INTERNET permission in your app's manifest file."
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/android/ndk.version | cut -f 1 -d ".")}
|
||||
|
||||
@@ -195,7 +172,6 @@ VULKAN_ANDROID_GRADLE_OPTION=""
|
||||
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
|
||||
|
||||
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
|
||||
FGVIEWER_OPTION="-DFILAMENT_ENABLE_FGVIEWER=OFF"
|
||||
MATDBG_GRADLE_OPTION=""
|
||||
|
||||
MATOPT_OPTION=""
|
||||
@@ -264,7 +240,6 @@ function build_desktop_target {
|
||||
-DCMAKE_BUILD_TYPE="$1" \
|
||||
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
|
||||
${EGL_ON_LINUX_OPTION} \
|
||||
${FGVIEWER_OPTION} \
|
||||
${MATDBG_OPTION} \
|
||||
${MATOPT_OPTION} \
|
||||
${ASAN_UBSAN_OPTION} \
|
||||
@@ -401,7 +376,6 @@ function build_android_target {
|
||||
-DFILAMENT_NDK_VERSION="${FILAMENT_NDK_VERSION}" \
|
||||
-DCMAKE_INSTALL_PREFIX="../android-${lc_target}/filament" \
|
||||
-DCMAKE_TOOLCHAIN_FILE="../../build/toolchain-${arch}-linux-android.cmake" \
|
||||
${FGVIEWER_OPTION} \
|
||||
${MATDBG_OPTION} \
|
||||
${MATOPT_OPTION} \
|
||||
${VULKAN_ANDROID_OPTION} \
|
||||
@@ -639,7 +613,6 @@ function build_ios_target {
|
||||
-DPLATFORM_NAME="${platform}" \
|
||||
-DIOS=1 \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../../third_party/clang/iOS.cmake \
|
||||
${FGVIEWER_OPTION} \
|
||||
${MATDBG_OPTION} \
|
||||
${MATOPT_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
@@ -829,7 +802,7 @@ function check_debug_release_build {
|
||||
|
||||
pushd "$(dirname "$0")" > /dev/null
|
||||
|
||||
while getopts ":hacCfgijmp:q:uvslwedtk:bx:S:X:" opt; do
|
||||
while getopts ":hacCfgijmp:q:uvslwedk:bx:S:X:" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
@@ -850,12 +823,6 @@ while getopts ":hacCfgijmp:q:uvslwedtk:bx:S:X:" opt; do
|
||||
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_BUILD_FILAMAT=ON"
|
||||
MATDBG_GRADLE_OPTION="-Pcom.google.android.filament.matdbg"
|
||||
;;
|
||||
t)
|
||||
# TODO: Uncomment below when fgviewer is ready
|
||||
# PRINT_FGVIEWER_HELP=true
|
||||
# FGVIEWER_OPTION="-DFILAMENT_ENABLE_FGVIEWER=ON"
|
||||
#FGVIEWER_GRADLE_OPTION="-Pcom.google.android.filament.fgviewer"
|
||||
;;
|
||||
f)
|
||||
ISSUE_CMAKE_ALWAYS=true
|
||||
;;
|
||||
@@ -1060,7 +1027,3 @@ fi
|
||||
if [[ "${PRINT_MATDBG_HELP}" == "true" ]]; then
|
||||
print_matdbg_help
|
||||
fi
|
||||
|
||||
if [[ "${PRINT_FGVIEWER_HELP}" == "true" ]]; then
|
||||
print_fgviewer_help
|
||||
fi
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
-11
@@ -1787,12 +1787,7 @@ non-shader data.
|
||||
declare a variable called <code>eyeDirection</code> you can access it in the fragment shader using
|
||||
<code>variable_eyeDirection</code>. In the vertex shader, the interpolant name is simply a member of
|
||||
the <code>MaterialVertexInputs</code> structure (<code>material.eyeDirection</code> in your example). Each
|
||||
interpolant is of type <code>float4</code> (<code>vec4</code>) in the shaders. By default the precision of the
|
||||
interpolant is <code>highp</code> in <em class="asterisk">both</em> the vertex and fragment shaders.
|
||||
An alternate syntax can be used to specify both the name and precision of the interpolant.
|
||||
In this case the specified precision is used as-is in both fragment and vertex stages, in
|
||||
particular if <code>default</code> is specified the default precision is used is the fragment shader
|
||||
(<code>mediump</code>) and in the vertex shader (<code>highp</code>).
|
||||
interpolant is of type <code>float4</code> (<code>vec4</code>) in the shaders.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> name : Skybox,</span>
|
||||
@@ -1803,11 +1798,7 @@ non-shader data.
|
||||
<span class="line"> }</span>
|
||||
<span class="line"> ],</span>
|
||||
<span class="line"> variables : [</span>
|
||||
<span class="line"> eyeDirection,</span>
|
||||
<span class="line"> {</span>
|
||||
<span class="line"> name : eyeColor,</span>
|
||||
<span class="line"> precision : medium</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line"> eyeDirection</span>
|
||||
<span class="line"> ],</span>
|
||||
<span class="line"> vertexDomain : device,</span>
|
||||
<span class="line"> depthWrite : <span class="hljs-literal">false</span>,</span>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -561,13 +561,6 @@ target_link_libraries(${TARGET} PUBLIC filaflat)
|
||||
target_link_libraries(${TARGET} PUBLIC filabridge)
|
||||
target_link_libraries(${TARGET} PUBLIC ibl-lite)
|
||||
|
||||
if (FILAMENT_ENABLE_FGVIEWER)
|
||||
target_link_libraries(${TARGET} PUBLIC fgviewer)
|
||||
add_definitions(-DFILAMENT_ENABLE_FGVIEWER=1)
|
||||
else()
|
||||
add_definitions(-DFILAMENT_ENABLE_FGVIEWER=0)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_ENABLE_MATDBG)
|
||||
target_link_libraries(${TARGET} PUBLIC matdbg)
|
||||
add_definitions(-DFILAMENT_ENABLE_MATDBG=1)
|
||||
|
||||
@@ -226,12 +226,10 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
src/vulkan/VulkanUtility.cpp
|
||||
src/vulkan/VulkanUtility.h
|
||||
)
|
||||
if (LINUX OR WIN32)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformLinuxWindows.cpp)
|
||||
if (ANDROID OR LINUX OR WIN32)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformAndroidLinuxWindows.cpp)
|
||||
elseif (APPLE OR IOS)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformApple.mm)
|
||||
elseif (ANDROID)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformAndroid.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -292,64 +292,8 @@ public:
|
||||
*/
|
||||
VkQueue getProtectedGraphicsQueue() const noexcept;
|
||||
|
||||
struct ExternalImageMetadata {
|
||||
/**
|
||||
* The width of the external image
|
||||
*/
|
||||
uint32_t width;
|
||||
|
||||
/**
|
||||
* The height of the external image
|
||||
*/
|
||||
uint32_t height;
|
||||
|
||||
/**
|
||||
* The layer count of the external image
|
||||
*/
|
||||
uint32_t layers;
|
||||
|
||||
/**
|
||||
* The format of the external image
|
||||
*/
|
||||
VkFormat format;
|
||||
|
||||
/**
|
||||
* An external buffer can be protected. This tells you if it is.
|
||||
*/
|
||||
bool isProtected;
|
||||
|
||||
/**
|
||||
* The type of external format (opaque int) if used.
|
||||
*/
|
||||
uint64_t externalFormat;
|
||||
|
||||
/**
|
||||
* Image usage
|
||||
*/
|
||||
VkImageUsageFlags usage;
|
||||
|
||||
/**
|
||||
* Allocation size
|
||||
*/
|
||||
VkDeviceSize allocationSize;
|
||||
|
||||
/**
|
||||
* Heap information
|
||||
*/
|
||||
uint32_t memoryTypeBits;
|
||||
};
|
||||
virtual ExternalImageMetadata getExternalImageMetadata(void* externalImage);
|
||||
|
||||
using ImageData = std::pair<VkImage, VkDeviceMemory>;
|
||||
virtual ImageData createExternalImage(void* externalImage,
|
||||
const ExternalImageMetadata& metadata);
|
||||
|
||||
private:
|
||||
static ExtensionSet getSwapchainInstanceExtensions();
|
||||
static ExternalImageMetadata getExternalImageMetadataImpl(void* externalImage,
|
||||
VkDevice device);
|
||||
static ImageData createExternalImageImpl(void* externalImage, VkDevice device,
|
||||
const VkAllocationCallbacks* allocator, const ExternalImageMetadata& metadata);
|
||||
|
||||
// Platform dependent helper methods
|
||||
using SurfaceBundle = std::tuple<VkSurfaceKHR, VkExtent2D>;
|
||||
|
||||
@@ -214,7 +214,6 @@ DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
|
||||
backend::TextureSwizzle, a)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
@@ -400,6 +399,17 @@ DECL_DRIVER_API_N(update3DImage,
|
||||
DECL_DRIVER_API_N(generateMipmaps,
|
||||
backend::TextureHandle, th)
|
||||
|
||||
// Deprecated
|
||||
DECL_DRIVER_API_N(setExternalImage,
|
||||
backend::TextureHandle, th,
|
||||
void*, image)
|
||||
|
||||
// Deprecated
|
||||
DECL_DRIVER_API_N(setExternalImagePlane,
|
||||
backend::TextureHandle, th,
|
||||
void*, image,
|
||||
uint32_t, plane)
|
||||
|
||||
DECL_DRIVER_API_N(setExternalStream,
|
||||
backend::TextureHandle, th,
|
||||
backend::StreamHandle, sh)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
|
||||
#include "backend/platforms/PlatformEGLAndroid.h"
|
||||
#endif
|
||||
#elif defined(FILAMENT_IOS)
|
||||
#elif defined(IOS)
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
|
||||
#include "backend/platforms/PlatformCocoaTouchGL.h"
|
||||
#endif
|
||||
@@ -88,7 +88,7 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
|
||||
*backend = Backend::OPENGL;
|
||||
#elif defined(__ANDROID__)
|
||||
*backend = Backend::OPENGL;
|
||||
#elif defined(FILAMENT_IOS) || defined(__APPLE__)
|
||||
#elif defined(IOS) || defined(__APPLE__)
|
||||
*backend = Backend::METAL;
|
||||
#elif defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
*backend = Backend::VULKAN;
|
||||
@@ -119,7 +119,7 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
|
||||
return nullptr;
|
||||
#elif defined(__ANDROID__)
|
||||
return new PlatformEGLAndroid();
|
||||
#elif defined(FILAMENT_IOS)
|
||||
#elif defined(IOS)
|
||||
return new PlatformCocoaTouchGL();
|
||||
#elif defined(__APPLE__)
|
||||
return new PlatformCocoaGL();
|
||||
|
||||
@@ -250,7 +250,7 @@ public:
|
||||
// In practice, MetalRingBuffer is used for argument buffers, which are kept in the constant
|
||||
// address space. Constant buffers have specific alignment requirements when specifying an
|
||||
// offset.
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
#if TARGET_OS_SIMULATOR
|
||||
// The iOS simulator has differing alignment requirements.
|
||||
static constexpr auto METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 256;
|
||||
|
||||
@@ -135,7 +135,6 @@ struct MetalContext {
|
||||
bool supportsTextureSwizzling = false;
|
||||
bool supportsAutoDepthResolve = false;
|
||||
bool supportsMemorylessRenderTargets = false;
|
||||
bool supportsDepthClamp = false;
|
||||
uint8_t maxColorRenderTargets = 4;
|
||||
struct {
|
||||
uint8_t common;
|
||||
@@ -155,7 +154,6 @@ struct MetalContext {
|
||||
|
||||
RenderPassFlags currentRenderPassFlags;
|
||||
MetalRenderTarget* currentRenderTarget = nullptr;
|
||||
bool validPipelineBound = false;
|
||||
|
||||
// State trackers.
|
||||
PipelineStateTracker pipelineState;
|
||||
|
||||
@@ -151,11 +151,6 @@ MetalDriver::MetalDriver(
|
||||
mContext->highestSupportedGpuFamily.mac >= 2; // newer macOS GPUs
|
||||
}
|
||||
|
||||
mContext->supportsDepthClamp = false;
|
||||
if (@available(macOS 10.11, iOS 11.0, *)) {
|
||||
mContext->supportsDepthClamp = true;
|
||||
}
|
||||
|
||||
// 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).
|
||||
@@ -482,9 +477,7 @@ void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTextu
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* image) {
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(
|
||||
th, *mContext, format, width, height, usage, (CVPixelBufferRef)image));
|
||||
@@ -909,7 +902,7 @@ void MetalDriver::terminate() {
|
||||
}
|
||||
|
||||
ShaderModel MetalDriver::getShaderModel() const noexcept {
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
return ShaderModel::MOBILE;
|
||||
#else
|
||||
return ShaderModel::DESKTOP;
|
||||
@@ -983,7 +976,7 @@ bool MetalDriver::isTextureFormatMipmappable(TextureFormat format) {
|
||||
case MTLPixelFormatRGBA16Float:
|
||||
return true;
|
||||
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
// Mipmappable only on desktop:
|
||||
case MTLPixelFormatR32Float:
|
||||
case MTLPixelFormatRG32Float:
|
||||
@@ -991,7 +984,7 @@ bool MetalDriver::isTextureFormatMipmappable(TextureFormat format) {
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
// Mipmappable only on iOS:
|
||||
case MTLPixelFormatRGB9E5Float:
|
||||
return true;
|
||||
@@ -1070,7 +1063,7 @@ bool MetalDriver::isProtectedTexturesSupported() {
|
||||
}
|
||||
|
||||
bool MetalDriver::isDepthClampSupported() {
|
||||
return mContext->supportsDepthClamp;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
@@ -1193,6 +1186,10 @@ void MetalDriver::setupExternalImage(void* image) {
|
||||
CVPixelBufferRetain(pixelBuffer);
|
||||
}
|
||||
|
||||
void MetalDriver::setExternalImage(Handle<HwTexture> th, void* image) {}
|
||||
|
||||
void MetalDriver::setExternalImagePlane(Handle<HwTexture> th, void* image, uint32_t plane) {}
|
||||
|
||||
void MetalDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
|
||||
}
|
||||
|
||||
@@ -1261,7 +1258,6 @@ void MetalDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
||||
mContext->cullModeState.invalidate();
|
||||
mContext->windingState.invalidate();
|
||||
mContext->scissorRectState.invalidate();
|
||||
mContext->depthClampState.invalidate();
|
||||
mContext->currentPolygonOffset = {0.0f, 0.0f};
|
||||
|
||||
mContext->finalizedDescriptorSets.clear();
|
||||
@@ -1364,7 +1360,7 @@ void MetalDriver::startCapture(int) {
|
||||
if (@available(iOS 13, *)) {
|
||||
MTLCaptureDescriptor* descriptor = [MTLCaptureDescriptor new];
|
||||
descriptor.captureObject = mContext->device;
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
descriptor.destination = MTLCaptureDestinationDeveloperTools;
|
||||
#else
|
||||
descriptor.destination = MTLCaptureDestinationGPUTraceDocument;
|
||||
@@ -1428,7 +1424,7 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
|
||||
width:srcTextureSize.width
|
||||
height:srcTextureSize.height
|
||||
mipmapped:NO];
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
#else
|
||||
textureDescriptor.storageMode = MTLStorageModeManaged;
|
||||
@@ -1447,7 +1443,7 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
|
||||
|
||||
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "readPixels blit");
|
||||
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
// Managed textures on macOS require explicit synchronization between GPU / CPU.
|
||||
id <MTLBlitCommandEncoder> blitEncoder = [getPendingCommandBuffer(mContext) blitCommandEncoder];
|
||||
[blitEncoder synchronizeResource:readPixelsTexture];
|
||||
@@ -1655,7 +1651,6 @@ void MetalDriver::bindPipeline(PipelineState const& ps) {
|
||||
// during the draw call when the program is invalid. The shader compile error has already been
|
||||
// dumped to the console at this point, so it's fine to simply return early.
|
||||
if (FILAMENT_ENABLE_MATDBG && UTILS_UNLIKELY(!functions)) {
|
||||
mContext->validPipelineBound = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1734,12 +1729,10 @@ void MetalDriver::bindPipeline(PipelineState const& ps) {
|
||||
}
|
||||
|
||||
// depth clip mode
|
||||
if (mContext->supportsDepthClamp) {
|
||||
MTLDepthClipMode depthClipMode = rs.depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
|
||||
mContext->depthClampState.updateState(depthClipMode);
|
||||
if (mContext->depthClampState.stateChanged()) {
|
||||
[mContext->currentRenderPassEncoder setDepthClipMode:depthClipMode];
|
||||
}
|
||||
MTLDepthClipMode depthClipMode = rs.depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
|
||||
mContext->depthClampState.updateState(depthClipMode);
|
||||
if (mContext->depthClampState.stateChanged()) {
|
||||
[mContext->currentRenderPassEncoder setDepthClipMode:depthClipMode];
|
||||
}
|
||||
|
||||
// Set the depth-stencil state, if a state change is needed.
|
||||
@@ -1788,8 +1781,6 @@ void MetalDriver::bindPipeline(PipelineState const& ps) {
|
||||
clamp:0.0];
|
||||
mContext->currentPolygonOffset = ps.polygonOffset;
|
||||
}
|
||||
|
||||
mContext->validPipelineBound = true;
|
||||
}
|
||||
|
||||
void MetalDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
@@ -1887,10 +1878,6 @@ void MetalDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t inst
|
||||
<< "draw() without a valid command encoder.";
|
||||
DEBUG_LOG("draw2(...)\n");
|
||||
|
||||
if (FILAMENT_ENABLE_MATDBG && UTILS_UNLIKELY(!mContext->validPipelineBound)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind the offset data.
|
||||
if (mContext->dynamicOffsets.isDirty()) {
|
||||
const auto [size, data] = mContext->dynamicOffsets.getOffsets();
|
||||
|
||||
@@ -196,7 +196,7 @@ inline MTLPixelFormat getMetalFormatLinear(MTLPixelFormat format) {
|
||||
case MTLPixelFormatRG8Unorm_sRGB: return MTLPixelFormatRG8Unorm;
|
||||
case MTLPixelFormatRGBA8Unorm_sRGB: return MTLPixelFormatRGBA8Unorm;
|
||||
case MTLPixelFormatBGRA8Unorm_sRGB: return MTLPixelFormatBGRA8Unorm;
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
case MTLPixelFormatBC1_RGBA_sRGB: return MTLPixelFormatBC1_RGBA;
|
||||
case MTLPixelFormatBC2_RGBA_sRGB: return MTLPixelFormatBC2_RGBA;
|
||||
case MTLPixelFormatBC3_RGBA_sRGB: return MTLPixelFormatBC3_RGBA;
|
||||
@@ -268,7 +268,7 @@ constexpr inline bool isMetalFormatStencil(MTLPixelFormat format) {
|
||||
case MTLPixelFormatStencil8:
|
||||
case MTLPixelFormatDepth32Float_Stencil8:
|
||||
case MTLPixelFormatX32_Stencil8:
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
case MTLPixelFormatDepth24Unorm_Stencil8:
|
||||
case MTLPixelFormatX24_Stencil8:
|
||||
#endif
|
||||
|
||||
@@ -157,7 +157,7 @@ id<MTLTexture> MetalSwapChain::acquireDrawable() {
|
||||
textureDescriptor.height = headlessHeight;
|
||||
// Specify MTLTextureUsageShaderRead so the headless surface can be blitted from.
|
||||
textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
#else
|
||||
textureDescriptor.storageMode = MTLStorageModeManaged;
|
||||
@@ -520,7 +520,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
const BOOL mipmapped = levels > 1;
|
||||
const BOOL multisampled = samples > 1;
|
||||
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
const BOOL textureArray = target == SamplerType::SAMPLER_2D_ARRAY;
|
||||
FILAMENT_CHECK_PRECONDITION(!textureArray || !multisampled)
|
||||
<< "iOS does not support multisampled texture arrays.";
|
||||
@@ -533,7 +533,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return MTLTextureType2DMultisample;
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return MTLTextureType2DMultisampleArray;
|
||||
#endif
|
||||
@@ -856,7 +856,7 @@ void MetalTexture::loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region
|
||||
descriptor.height = region.size.height;
|
||||
descriptor.depth = region.size.depth;
|
||||
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
descriptor.storageMode = MTLStorageModeShared;
|
||||
#else
|
||||
descriptor.storageMode = MTLStorageModeManaged;
|
||||
|
||||
@@ -37,7 +37,7 @@ Driver* MetalPlatform::createDriver(void* /*sharedContext*/, const Platform::Dri
|
||||
id<MTLDevice> MetalPlatform::createDevice() noexcept {
|
||||
id<MTLDevice> result;
|
||||
|
||||
#if !defined(FILAMENT_IOS)
|
||||
#if !defined(IOS)
|
||||
const bool forceIntegrated =
|
||||
NSProcessInfo.processInfo.environment[@"FILAMENT_FORCE_INTEGRATED_GPU"] != nil;
|
||||
if (forceIntegrated) {
|
||||
|
||||
@@ -226,11 +226,9 @@ MetalShaderCompiler::program_token_t MetalShaderCompiler::createProgram(
|
||||
CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();
|
||||
mCompilerThreadPool.queue(priorityQueue, token,
|
||||
[this, name, device = mDevice, program = std::move(program), token]() {
|
||||
@autoreleasepool {
|
||||
MetalFunctionBundle compiledProgram = compileProgram(program, device);
|
||||
token->set(compiledProgram);
|
||||
mCallbackManager.put(token->handle);
|
||||
}
|
||||
MetalFunctionBundle compiledProgram = compileProgram(program, device);
|
||||
token->set(compiledProgram);
|
||||
mCallbackManager.put(token->handle);
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
@@ -150,7 +150,7 @@ id<MTLSamplerState> SamplerStateCreator::operator()(id<MTLDevice> device,
|
||||
MTLCompareFunctionNever : getCompareFunction(params.compareFunc);
|
||||
samplerDescriptor.supportArgumentBuffers = YES;
|
||||
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
// Older Apple devices (and the simulator) don't support setting a comparison function in
|
||||
// MTLSamplerDescriptor.
|
||||
// In practice, this means shadows are not supported when running in the simulator.
|
||||
|
||||
@@ -32,7 +32,7 @@ Dispatcher NoopDriver::getDispatcher() const noexcept {
|
||||
}
|
||||
|
||||
ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
#if defined(__ANDROID__) || defined(FILAMENT_IOS) || defined(__EMSCRIPTEN__)
|
||||
#if defined(__ANDROID__) || defined(IOS) || defined(__EMSCRIPTEN__)
|
||||
return ShaderModel::MOBILE;
|
||||
#else
|
||||
return ShaderModel::DESKTOP;
|
||||
@@ -265,6 +265,12 @@ TimerQueryResult NoopDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint64
|
||||
return TimerQueryResult::ERROR;
|
||||
}
|
||||
|
||||
void NoopDriver::setExternalImage(Handle<HwTexture> th, void* image) {
|
||||
}
|
||||
|
||||
void NoopDriver::setExternalImagePlane(Handle<HwTexture> th, void* image, uint32_t plane) {
|
||||
}
|
||||
|
||||
void NoopDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,6 @@ void GLDescriptorSet::update(OpenGLContext& gl,
|
||||
|
||||
arg.target = t ? t->gl.target : 0;
|
||||
arg.id = t ? t->gl.id : 0;
|
||||
arg.external = t ? t->gl.external : false;
|
||||
if constexpr (std::is_same_v<T, Sampler> ||
|
||||
std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||
if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||
@@ -286,7 +285,7 @@ void GLDescriptorSet::bind(
|
||||
} else if constexpr (std::is_same_v<T, Sampler>) {
|
||||
GLuint const unit = p.getTextureUnit(set, binding);
|
||||
if (arg.target) {
|
||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
||||
gl.bindTexture(unit, arg.target, arg.id);
|
||||
gl.bindSampler(unit, arg.sampler);
|
||||
if (UTILS_UNLIKELY(arg.ref)) {
|
||||
updateTextureView(gl, handleAllocator, unit, arg);
|
||||
@@ -297,7 +296,7 @@ void GLDescriptorSet::bind(
|
||||
} else if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||
GLuint const unit = p.getTextureUnit(set, binding);
|
||||
if (arg.target) {
|
||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
||||
gl.bindTexture(unit, arg.target, arg.id);
|
||||
gl.bindSampler(unit, arg.sampler);
|
||||
if (UTILS_UNLIKELY(arg.ref)) {
|
||||
updateTextureView(gl, handleAllocator, unit, arg);
|
||||
@@ -315,7 +314,7 @@ void GLDescriptorSet::bind(
|
||||
// in ES2 the sampler parameters need to be set on the texture itself
|
||||
GLuint const unit = p.getTextureUnit(set, binding);
|
||||
if (arg.target) {
|
||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
||||
gl.bindTexture(unit, arg.target, arg.id);
|
||||
SamplerParams const params = arg.params;
|
||||
glTexParameteri(arg.target, GL_TEXTURE_MIN_FILTER,
|
||||
(GLint)GLUtils::getTextureFilter(params.filterMin));
|
||||
|
||||
@@ -111,9 +111,7 @@ private:
|
||||
|
||||
// A sampler descriptor
|
||||
struct Sampler {
|
||||
uint16_t target; // 2 (GLenum)
|
||||
bool external = false; // 1
|
||||
bool reserved = false; // 1
|
||||
GLenum target = 0; // 4
|
||||
GLuint id = 0; // 4
|
||||
GLuint sampler = 0; // 4
|
||||
Handle<GLTextureRef> ref; // 4
|
||||
@@ -128,9 +126,7 @@ private:
|
||||
};
|
||||
|
||||
struct SamplerWithAnisotropyWorkaround {
|
||||
uint16_t target; // 2 (GLenum)
|
||||
bool external = false; // 1
|
||||
bool reserved = false; // 1
|
||||
GLenum target = 0; // 4
|
||||
GLuint id = 0; // 4
|
||||
GLuint sampler = 0; // 4
|
||||
Handle<GLTextureRef> ref; // 4
|
||||
@@ -147,9 +143,7 @@ private:
|
||||
|
||||
// A sampler descriptor for ES2
|
||||
struct SamplerGLES2 {
|
||||
uint16_t target; // 2 (GLenum)
|
||||
bool external = false; // 1
|
||||
bool reserved = false; // 1
|
||||
GLenum target = 0; // 4
|
||||
GLuint id = 0; // 4
|
||||
SamplerParams params{}; // 4
|
||||
float anisotropy = 1.0f; // 4
|
||||
|
||||
@@ -35,7 +35,7 @@ struct GLTextureRef {
|
||||
GLTextureRef() = default;
|
||||
// view reference counter
|
||||
uint16_t count = 1;
|
||||
// Current per-view values of the texture (in GL we can only have a single View active at
|
||||
// current per-view values of the texture (in GL we can only have a single View active at
|
||||
// a time, and this tracks that state). It's used to avoid unnecessarily change state.
|
||||
int8_t baseLevel = 127;
|
||||
int8_t maxLevel = -1;
|
||||
@@ -50,7 +50,7 @@ struct GLTextureRef {
|
||||
struct GLTexture : public HwTexture {
|
||||
using HwTexture::HwTexture;
|
||||
struct GL {
|
||||
GL() noexcept : imported(false), external(false), sidecarSamples(1), reserved1(0) {}
|
||||
GL() noexcept : imported(false), sidecarSamples(1), reserved1(0) {}
|
||||
GLuint id = 0; // texture or renderbuffer id
|
||||
GLenum target = 0;
|
||||
GLenum internalFormat = 0;
|
||||
@@ -62,8 +62,7 @@ struct GLTexture : public HwTexture {
|
||||
int8_t maxLevel = -1;
|
||||
uint8_t reserved0 = 0;
|
||||
bool imported : 1;
|
||||
bool external : 1;
|
||||
uint8_t sidecarSamples : 3;
|
||||
uint8_t sidecarSamples : 4;
|
||||
uint8_t reserved1 : 3;
|
||||
std::array<TextureSwizzle, 4> swizzle{
|
||||
TextureSwizzle::CHANNEL_0,
|
||||
|
||||
@@ -408,7 +408,7 @@ void OpenGLContext::initProcs(Procs* procs,
|
||||
procs->maxShaderCompilerThreadsKHR = +[](GLuint) {};
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
# ifndef FILAMENT_IOS // FILAMENT_IOS is guaranteed to have ES3.x
|
||||
# ifndef IOS // IOS is guaranteed to have ES3.x
|
||||
# ifndef __EMSCRIPTEN__
|
||||
if (UTILS_UNLIKELY(major == 2)) {
|
||||
// Runtime OpenGL version is ES 2.x
|
||||
@@ -438,7 +438,7 @@ void OpenGLContext::initProcs(Procs* procs,
|
||||
procs->maxShaderCompilerThreadsKHR = glMaxShaderCompilerThreadsKHR;
|
||||
}
|
||||
# endif // __EMSCRIPTEN__
|
||||
# endif // FILAMENT_IOS
|
||||
# endif // IOS
|
||||
#else
|
||||
procs->maxShaderCompilerThreadsKHR = glMaxShaderCompilerThreadsARB;
|
||||
#endif
|
||||
@@ -500,13 +500,11 @@ void OpenGLContext::initBugs(Bugs* bugs, Extensions const& exts,
|
||||
// qualcomm seems to have no problem with this (which is good for us)
|
||||
bugs->allow_read_only_ancillary_feedback_loop = true;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
// Older Adreno devices that support ES3.0 only tend to be extremely buggy, so we
|
||||
// fall back to ES2.0.
|
||||
if (major == 3 && minor == 0) {
|
||||
bugs->force_feature_level0 = true;
|
||||
}
|
||||
#endif
|
||||
} else if (strstr(renderer, "Mali")) {
|
||||
// ARM GPU
|
||||
bugs->vao_doesnt_store_element_array_buffer_binding = true;
|
||||
@@ -576,14 +574,14 @@ void OpenGLContext::initBugs(Bugs* bugs, Extensions const& exts,
|
||||
}
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
# ifndef FILAMENT_IOS // FILAMENT_IOS is guaranteed to have ES3.x
|
||||
# ifndef IOS // IOS is guaranteed to have ES3.x
|
||||
if (UTILS_UNLIKELY(major == 2)) {
|
||||
if (UTILS_UNLIKELY(!exts.OES_vertex_array_object)) {
|
||||
// we activate this workaround path, which does the reset of array buffer
|
||||
bugs->vao_doesnt_store_element_array_buffer_binding = true;
|
||||
}
|
||||
}
|
||||
# endif // FILAMENT_IOS
|
||||
# endif // IOS
|
||||
#else
|
||||
// feedback loops are allowed on GL desktop as long as writes are disabled
|
||||
bugs->allow_read_only_ancillary_feedback_loop = true;
|
||||
@@ -622,7 +620,7 @@ FeatureLevel OpenGLContext::resolveFeatureLevel(GLint major, GLint minor,
|
||||
}
|
||||
}
|
||||
}
|
||||
# ifndef FILAMENT_IOS // FILAMENT_IOS is guaranteed to have ES3.x
|
||||
# ifndef IOS // IOS is guaranteed to have ES3.x
|
||||
else if (UTILS_UNLIKELY(major == 2)) {
|
||||
// Runtime OpenGL version is ES 2.x
|
||||
// note: mandatory extensions (all supported by Mali-400 and Adreno 304)
|
||||
@@ -634,7 +632,7 @@ FeatureLevel OpenGLContext::resolveFeatureLevel(GLint major, GLint minor,
|
||||
// OES_texture_npot
|
||||
featureLevel = FeatureLevel::FEATURE_LEVEL_0;
|
||||
}
|
||||
# endif // FILAMENT_IOS
|
||||
# endif // IOS
|
||||
#else
|
||||
assert_invariant(gets.max_texture_image_units >= 16);
|
||||
assert_invariant(gets.max_combined_texture_image_units >= 32);
|
||||
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
}
|
||||
|
||||
inline bool isES2() const noexcept {
|
||||
#if defined(BACKEND_OPENGL_VERSION_GLES) && !defined(FILAMENT_IOS)
|
||||
#if defined(BACKEND_OPENGL_VERSION_GLES) && !defined(IOS)
|
||||
# ifndef BACKEND_OPENGL_LEVEL_GLES30
|
||||
return true;
|
||||
# else
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
|
||||
void pixelStore(GLenum, GLint) noexcept;
|
||||
inline void activeTexture(GLuint unit) noexcept;
|
||||
inline void bindTexture(GLuint unit, GLuint target, GLuint texId, bool external) noexcept;
|
||||
inline void bindTexture(GLuint unit, GLuint target, GLuint texId) noexcept;
|
||||
|
||||
void unbindTexture(GLenum target, GLuint id) noexcept;
|
||||
void unbindTextureUnit(GLuint unit) noexcept;
|
||||
@@ -761,9 +761,7 @@ void OpenGLContext::bindBufferRange(GLenum target, GLuint index, GLuint buffer,
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId, bool external) noexcept {
|
||||
// another texture is bound to the same unit with a different target,
|
||||
// unbind the texture from the current target
|
||||
void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId) noexcept {
|
||||
update_state(state.textures.units[unit].target, target, [&]() {
|
||||
activeTexture(unit);
|
||||
glBindTexture(state.textures.units[unit].target, 0);
|
||||
@@ -771,7 +769,7 @@ void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId, bool e
|
||||
update_state(state.textures.units[unit].id, texId, [&]() {
|
||||
activeTexture(unit);
|
||||
glBindTexture(target, texId);
|
||||
}, external);
|
||||
}, target == GL_TEXTURE_EXTERNAL_OES);
|
||||
}
|
||||
|
||||
void OpenGLContext::useProgram(GLuint program) noexcept {
|
||||
|
||||
@@ -402,7 +402,7 @@ void OpenGLDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
|
||||
void OpenGLDriver::bindTexture(GLuint unit, GLTexture const* t) noexcept {
|
||||
assert_invariant(t != nullptr);
|
||||
mContext.bindTexture(unit, t->gl.target, t->gl.id, t->gl.external);
|
||||
mContext.bindTexture(unit, t->gl.target, t->gl.id);
|
||||
}
|
||||
|
||||
bool OpenGLDriver::useProgram(OpenGLProgram* p) noexcept {
|
||||
@@ -1052,49 +1052,17 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
usage &= ~TextureUsage::UPLOADABLE;
|
||||
|
||||
auto& gl = mContext;
|
||||
GLenum internalFormat = getInternalFormat(format);
|
||||
if (UTILS_UNLIKELY(gl.isES2())) {
|
||||
// on ES2, format and internal format must match
|
||||
// FIXME: handle compressed texture format
|
||||
internalFormat = textureFormatToFormatAndType(format).first;
|
||||
}
|
||||
assert_invariant(internalFormat);
|
||||
|
||||
GLTexture* const t = construct<GLTexture>(th, target, 1, 1, width, height, 1, format, usage);
|
||||
assert_invariant(t);
|
||||
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
// because it's not used anywhere for anything important.
|
||||
t->gl.internalFormat = internalFormat;
|
||||
t->gl.baseLevel = 0;
|
||||
t->gl.maxLevel = 0;
|
||||
t->gl.external = true; // forces bindTexture() call (they're never cached)
|
||||
}
|
||||
|
||||
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
|
||||
if (mPlatform.setExternalImage(image, t->externalTexture)) {
|
||||
// the target and id can be reset each time
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
}
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* image) {
|
||||
createTextureR(th, SamplerType::SAMPLER_EXTERNAL, 1, format, 1, width, height, 1, usage);
|
||||
setExternalImage(th, image);
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane) {
|
||||
// not relevant for the OpenGL backend
|
||||
createTextureR(th, SamplerType::SAMPLER_EXTERNAL, 1, format, 1, width, height, 1, usage);
|
||||
setExternalImagePlane(th, image, plane);
|
||||
}
|
||||
|
||||
void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
@@ -1114,7 +1082,6 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
t->gl.target = GL_TEXTURE_EXTERNAL_OES;
|
||||
t->gl.external = true; // forces bindTexture() call (they're never cached)
|
||||
break;
|
||||
case SamplerType::SAMPLER_2D:
|
||||
t->gl.target = GL_TEXTURE_2D;
|
||||
@@ -1381,13 +1348,13 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
|
||||
// TODO: support multiview for iOS and WebGL
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(IOS)
|
||||
if (layerCount > 1) {
|
||||
// if layerCount > 1, it means we use the multiview extension.
|
||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, attachment,
|
||||
t->gl.id, 0, binfo.layer, layerCount);
|
||||
} else
|
||||
#endif // !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
||||
#endif // !defined(__EMSCRIPTEN__) && !defined(IOS)
|
||||
{
|
||||
// GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GLES
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment,
|
||||
@@ -2807,6 +2774,25 @@ void OpenGLDriver::setupExternalImage(void* image) {
|
||||
mPlatform.retainExternalImage(image);
|
||||
}
|
||||
|
||||
void OpenGLDriver::setExternalImage(Handle<HwTexture> th, void* image) {
|
||||
DEBUG_MARKER()
|
||||
GLTexture* t = handle_cast<GLTexture*>(th);
|
||||
assert_invariant(t);
|
||||
assert_invariant(t->target == SamplerType::SAMPLER_EXTERNAL);
|
||||
|
||||
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
|
||||
if (mPlatform.setExternalImage(image, t->externalTexture)) {
|
||||
// the target and id can be reset each time
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::setExternalImagePlane(Handle<HwTexture> th, void* image, uint32_t plane) {
|
||||
DEBUG_MARKER()
|
||||
}
|
||||
|
||||
void OpenGLDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
|
||||
auto& gl = mContext;
|
||||
if (gl.ext.OES_EGL_image_external_essl3) {
|
||||
@@ -3526,7 +3512,7 @@ void OpenGLDriver::endFrame(UTILS_UNUSED uint32_t frameId) {
|
||||
auto& gl = mContext;
|
||||
gl.bindVertexArray(nullptr);
|
||||
for (int unit = OpenGLContext::DUMMY_TEXTURE_BINDING; unit >= 0; unit--) {
|
||||
gl.bindTexture(unit, GL_TEXTURE_2D, 0, false);
|
||||
gl.bindTexture(unit, GL_TEXTURE_2D, 0);
|
||||
}
|
||||
gl.disable(GL_CULL_FACE);
|
||||
gl.depthFunc(GL_LESS);
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
# define FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
#endif
|
||||
|
||||
#elif defined(FILAMENT_IOS)
|
||||
#elif defined(IOS)
|
||||
|
||||
#define GLES_SILENCE_DEPRECATION
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
#if defined(GL_VERSION_4_5)
|
||||
#elif defined(GL_ES_VERSION_3_1)
|
||||
#elif defined(GL_ES_VERSION_3_0)
|
||||
# if !defined(FILAMENT_IOS) && !defined(__EMSCRIPTEN__)
|
||||
# if !defined(IOS) && !defined(__EMSCRIPTEN__)
|
||||
# error "GLES 3.0 headers only supported on iOS and WebGL2"
|
||||
# endif
|
||||
#elif defined(GL_ES_VERSION_2_0)
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
#if defined(GL_ES_VERSION_2_0) // this basically means all versions of GLES
|
||||
|
||||
#if defined(FILAMENT_IOS)
|
||||
#if defined(IOS)
|
||||
|
||||
// iOS headers only provide prototypes, nothing to do.
|
||||
|
||||
@@ -271,7 +271,7 @@ void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void *d
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES_VERSION_2_0
|
||||
# ifndef FILAMENT_IOS
|
||||
# ifndef IOS
|
||||
# ifndef GL_OES_vertex_array_object
|
||||
# error "Headers with GL_OES_vertex_array_object are mandatory unless on iOS"
|
||||
# endif
|
||||
|
||||
@@ -715,16 +715,14 @@ void PlatformEGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
|
||||
bool PlatformEGL::setExternalImage(void* externalImage,
|
||||
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
|
||||
|
||||
// OES_EGL_image_external_essl3 must be present if the target is TEXTURE_EXTERNAL_OES
|
||||
// GL_OES_EGL_image must be present if TEXTURE_2D is used
|
||||
|
||||
#if defined(GL_OES_EGL_image) || defined(GL_OES_EGL_image_external_essl3)
|
||||
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
|
||||
assert_invariant(texture->target == GL_TEXTURE_EXTERNAL_OES);
|
||||
// the texture is guaranteed to be bound here.
|
||||
glEGLImageTargetTexture2DOES(texture->target,
|
||||
#ifdef GL_OES_EGL_image
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
|
||||
static_cast<GLeglImageOES>(externalImage));
|
||||
#endif
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,14 +64,10 @@ public:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mLib) {
|
||||
OSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
|
||||
} else {
|
||||
OSMesaGetProcAddress = (GetProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
|
||||
}
|
||||
FILAMENT_CHECK_PRECONDITION(mLib)
|
||||
<< "Unable to dlopen libOSMesa to create a software GL context";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(OSMesaGetProcAddress)
|
||||
<< "Unable to against libOSMesa to create a software GL context";
|
||||
OSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
|
||||
|
||||
OSMesaCreateContext = (CreateContextFunc) OSMesaGetProcAddress("OSMesaCreateContext");
|
||||
OSMesaDestroyContext =
|
||||
@@ -80,9 +76,7 @@ public:
|
||||
}
|
||||
|
||||
~OSMesaAPI() {
|
||||
if (mLib) {
|
||||
dlclose(mLib);
|
||||
}
|
||||
dlclose(mLib);
|
||||
}
|
||||
private:
|
||||
void* mLib = nullptr;
|
||||
|
||||
@@ -288,7 +288,7 @@ Driver* VulkanDriver::create(VulkanPlatform* platform, VulkanContext const& cont
|
||||
}
|
||||
|
||||
ShaderModel VulkanDriver::getShaderModel() const noexcept {
|
||||
#if defined(__ANDROID__) || defined(FILAMENT_IOS)
|
||||
#if defined(__ANDROID__) || defined(IOS)
|
||||
return ShaderModel::MOBILE;
|
||||
#else
|
||||
return ShaderModel::DESKTOP;
|
||||
@@ -543,27 +543,8 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
texture.inc();
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
backend::SamplerType target, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
|
||||
if (metadata.isProtected) {
|
||||
usage |= backend::TextureUsage::PROTECTED;
|
||||
}
|
||||
|
||||
assert_invariant(width == metadata.width);
|
||||
assert_invariant(height == metadata.height);
|
||||
assert_invariant(getVkFormat(format) == metadata.format);
|
||||
|
||||
const auto& data = mPlatform->createExternalImage(externalImage, metadata);
|
||||
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format,
|
||||
1, metadata.width, metadata.height, usage, mStagePool);
|
||||
|
||||
texture.inc();
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* image) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
@@ -1190,6 +1171,12 @@ TimerQueryResult VulkanDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint
|
||||
return TimerQueryResult::AVAILABLE;
|
||||
}
|
||||
|
||||
void VulkanDriver::setExternalImage(Handle<HwTexture> th, void* image) {
|
||||
}
|
||||
|
||||
void VulkanDriver::setExternalImagePlane(Handle<HwTexture> th, void* image, uint32_t plane) {
|
||||
}
|
||||
|
||||
void VulkanDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
|
||||
}
|
||||
|
||||
|
||||
@@ -75,16 +75,15 @@ void VulkanSwapChain::update() {
|
||||
}
|
||||
for (auto const color: bundle.colors) {
|
||||
auto colorTexture = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager,
|
||||
device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE,
|
||||
bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height, colorUsage,
|
||||
device, mAllocator, mResourceManager, mCommands, color, bundle.colorFormat, 1,
|
||||
bundle.extent.width, bundle.extent.height, TextureUsage::COLOR_ATTACHMENT,
|
||||
mStagePool);
|
||||
mColors.push_back(colorTexture);
|
||||
}
|
||||
|
||||
mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, device,
|
||||
mAllocator, mResourceManager, mCommands, bundle.depth, VK_NULL_HANDLE,
|
||||
bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height, depthUsage,
|
||||
mStagePool);
|
||||
mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, device, mAllocator,
|
||||
mResourceManager, mCommands, bundle.depth, bundle.depthFormat, 1, bundle.extent.width,
|
||||
bundle.extent.height, TextureUsage::DEPTH_ATTACHMENT, mStagePool);
|
||||
|
||||
mExtent = bundle.extent;
|
||||
}
|
||||
|
||||
@@ -164,15 +164,14 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
|
||||
// Constructor for internally passed VkImage
|
||||
VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
|
||||
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
|
||||
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width,
|
||||
uint32_t height, TextureUsage tusage, VulkanStagePool& stagePool)
|
||||
VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage,
|
||||
VulkanStagePool& stagePool)
|
||||
: HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED,
|
||||
tusage),
|
||||
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
|
||||
allocator, commands, stagePool, format, imgutil::getViewType(SamplerType::SAMPLER_2D),
|
||||
1, 1, getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) {
|
||||
mState->mTextureImage = image;
|
||||
mState->mTextureImageMemory = memory;
|
||||
mPrimaryViewRange = mState->mFullViewRange;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,8 +94,8 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
|
||||
// The texture will never destroy the given VkImage, but it does manages its subresources.
|
||||
VulkanTexture(VkDevice device, VmaAllocator allocator,
|
||||
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
|
||||
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width, uint32_t height,
|
||||
TextureUsage tusage, VulkanStagePool& stagePool);
|
||||
VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage,
|
||||
VulkanStagePool& stagePool);
|
||||
|
||||
// Constructor for creating a texture view for wrt specific mip range
|
||||
VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context,
|
||||
|
||||
@@ -66,8 +66,7 @@ struct Resource {
|
||||
: resManager(nullptr),
|
||||
id(HandleBase::nullid),
|
||||
mCount(0),
|
||||
restype(ResourceType::UNDEFINED_TYPE),
|
||||
mHandleConsideredDestroyed(false) {}
|
||||
restype(ResourceType::UNDEFINED_TYPE) {}
|
||||
|
||||
private:
|
||||
inline void inc() noexcept {
|
||||
@@ -81,16 +80,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// To be able to detect use-after-free, we need a bit to signify if the handle should be
|
||||
// consider destroyed (from Filament's perspective).
|
||||
inline void setHandleConsiderDestroyed() noexcept {
|
||||
mHandleConsideredDestroyed = true;
|
||||
}
|
||||
|
||||
inline bool isHandleConsideredDestroyed() const {
|
||||
return mHandleConsideredDestroyed;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init(HandleId id, ResourceManager* resManager) {
|
||||
this->id = id;
|
||||
@@ -103,9 +92,7 @@ private:
|
||||
ResourceManager* resManager; // 8
|
||||
HandleId id; // 4
|
||||
uint32_t mCount : 24;
|
||||
ResourceType restype : 7;
|
||||
bool mHandleConsideredDestroyed : 1; // restype + mCount + mHandleConsideredDestroyed
|
||||
// is 4 bytes.
|
||||
ResourceType restype : 6; // restype + mCount is 4 bytes.
|
||||
|
||||
friend class ResourceManager;
|
||||
|
||||
@@ -118,8 +105,7 @@ struct ThreadSafeResource {
|
||||
: resManager(nullptr),
|
||||
id(HandleBase::nullid),
|
||||
mCount(0),
|
||||
restype(ResourceType::UNDEFINED_TYPE),
|
||||
mHandleConsideredDestroyed(false) {}
|
||||
restype(ResourceType::UNDEFINED_TYPE) {}
|
||||
|
||||
private:
|
||||
inline void inc() noexcept {
|
||||
@@ -132,16 +118,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// To be able to detect use-after-free, we need a bit to signify if the handle should be
|
||||
// consider destroyed (from Filament's perspective).
|
||||
inline void setHandleConsiderDestroyed() noexcept {
|
||||
mHandleConsideredDestroyed = true;
|
||||
}
|
||||
|
||||
inline bool isHandleConsideredDestroyed() const {
|
||||
return mHandleConsideredDestroyed;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init(HandleId id, ResourceManager* resManager) {
|
||||
this->id = id;
|
||||
@@ -154,8 +130,7 @@ private:
|
||||
ResourceManager* resManager; // 8
|
||||
HandleId id; // 4
|
||||
std::atomic<uint32_t> mCount; // 4
|
||||
ResourceType restype : 7;
|
||||
bool mHandleConsideredDestroyed : 1; // restype + mHandleConsideredDestroyed is 1 byte
|
||||
ResourceType restype; // 1
|
||||
|
||||
friend class ResourceManager;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "vulkan/memory/ResourceManager.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -60,10 +59,6 @@ public:
|
||||
static enabled_resource_ptr<B> cast(ResourceManager* resManager,
|
||||
Handle<B> const& handle) noexcept {
|
||||
D* ptr = resManager->handle_cast<D*, B>(handle);
|
||||
FILAMENT_CHECK_PRECONDITION(!ptr->isHandleConsideredDestroyed())
|
||||
<< "Handle id=" << ptr->id << " (" << getTypeStr(ptr->restype)
|
||||
<< ") is being used after it has been freed";
|
||||
|
||||
return {ptr};
|
||||
}
|
||||
|
||||
@@ -161,8 +156,6 @@ private:
|
||||
// only be used from VulkanDriver.
|
||||
inline void dec() {
|
||||
assert_invariant(mRef);
|
||||
assert_invariant(!mRef->isHandleConsideredDestroyed());
|
||||
mRef->setHandleConsiderDestroyed();
|
||||
mRef->dec();
|
||||
}
|
||||
|
||||
|
||||
@@ -194,15 +194,6 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
|
||||
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
|
||||
#endif
|
||||
// We only support external image for Android for now, but nothing bars us from
|
||||
// supporting other platforms.
|
||||
#if defined(__ANDROID__)
|
||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
|
||||
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
||||
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
|
||||
#endif
|
||||
|
||||
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE2_EXTENSION_NAME,
|
||||
@@ -954,16 +945,6 @@ VkQueue VulkanPlatform::getProtectedGraphicsQueue() const noexcept {
|
||||
return mImpl->mProtectedGraphicsQueue;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadata(
|
||||
void* externalImage) {
|
||||
return getExternalImageMetadataImpl(externalImage, mImpl->mDevice);
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImage(void* externalImage,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return createExternalImageImpl(externalImage, mImpl->mDevice, nullptr, metadata);
|
||||
}
|
||||
|
||||
#undef SWAPCHAIN_RET_FUNC
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <android/native_window.h>
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
void getVKFormatAndUsage(const AHardwareBuffer_Desc& desc, VkFormat& format,
|
||||
VkImageUsageFlags& usage, bool& isProtected) {
|
||||
// Refer to "11.2.17. External Memory Handle Types" in the spec, and
|
||||
// Tables 13/14 for how the following derivation works.
|
||||
bool isDepthFormat = false;
|
||||
isProtected = false;
|
||||
switch (desc.format) {
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
|
||||
format = VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
|
||||
format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
|
||||
format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_D16_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_D32_SFLOAT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_S8_UINT:
|
||||
isDepthFormat = true;
|
||||
format = VK_FORMAT_S8_UINT;
|
||||
break;
|
||||
default:
|
||||
format = VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
// The following only concern usage flags derived from Table 14.
|
||||
usage = 0;
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
|
||||
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
}
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
|
||||
if (isDepthFormat) {
|
||||
usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
} else {
|
||||
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) {
|
||||
usage = VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
}
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
|
||||
isProtected = true;
|
||||
}
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData allocateExternalImage(void* externalBuffer,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
VulkanPlatform::ExternalImageMetadata const& metadata) {
|
||||
VulkanPlatform::ImageData data;
|
||||
AHardwareBuffer* buffer = static_cast<AHardwareBuffer*>(externalBuffer);
|
||||
|
||||
// if external format we need to specifiy it in the allocation
|
||||
const bool useExternalFormat = metadata.format == VK_FORMAT_UNDEFINED;
|
||||
|
||||
const VkExternalFormatANDROID externalFormat = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
||||
.pNext = nullptr,
|
||||
.externalFormat = metadata
|
||||
.externalFormat,// pass down the format (external means we don't have it VK defined)
|
||||
};
|
||||
const VkExternalMemoryImageCreateInfo externalCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.pNext = useExternalFormat ? &externalFormat : nullptr,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
|
||||
};
|
||||
|
||||
VkImageCreateInfo imageInfo{.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
imageInfo.pNext = &externalCreateInfo;
|
||||
imageInfo.format = metadata.format;
|
||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.extent = {
|
||||
metadata.width,
|
||||
metadata.height,
|
||||
1u,
|
||||
};
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.arrayLayers = metadata.layers;
|
||||
imageInfo.usage = metadata.usage;
|
||||
// In the unprotected case add R/W capabilities
|
||||
if (metadata.isProtected == false)
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
VkResult result = vkCreateImage(device, &imageInfo, allocator, &data.first);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkCreateImage failed with error=" << result;
|
||||
|
||||
// Allocate the memory
|
||||
VkImportAndroidHardwareBufferInfoANDROID androidHardwareBufferInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
|
||||
.pNext = nullptr,
|
||||
.buffer = buffer,
|
||||
};
|
||||
VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||
.pNext = &androidHardwareBufferInfo,
|
||||
.image = data.first,
|
||||
.buffer = VK_NULL_HANDLE,
|
||||
};
|
||||
VkMemoryAllocateInfo allocInfo = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &memoryDedicatedAllocateInfo,
|
||||
.allocationSize = metadata.allocationSize,
|
||||
.memoryTypeIndex = metadata.memoryTypeBits};
|
||||
result = vkAllocateMemory(device, &allocInfo, allocator, &data.second);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkAllocateMemory failed with error=" << result;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}// namespace
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(void* externalImage,
|
||||
VkDevice device) {
|
||||
ExternalImageMetadata metadata;
|
||||
AHardwareBuffer* buffer = static_cast<AHardwareBuffer*>(externalImage);
|
||||
if (__builtin_available(android 26, *)) {
|
||||
AHardwareBuffer_Desc bufferDesc;
|
||||
AHardwareBuffer_describe(buffer, &bufferDesc);
|
||||
metadata.width = bufferDesc.width;
|
||||
metadata.height = bufferDesc.height;
|
||||
metadata.layers = bufferDesc.layers;
|
||||
|
||||
getVKFormatAndUsage(bufferDesc, metadata.format, metadata.usage, metadata.isProtected);
|
||||
}
|
||||
// In the unprotected case add R/W capabilities
|
||||
if (metadata.isProtected == false) {
|
||||
metadata.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
|
||||
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
|
||||
.pNext = nullptr,
|
||||
};
|
||||
VkAndroidHardwareBufferPropertiesANDROID properties = {
|
||||
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
|
||||
.pNext = &formatInfo,
|
||||
};
|
||||
VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID(device, buffer, &properties);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkGetAndroidHardwareBufferProperties failed with error=" << result;
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(metadata.format == formatInfo.format);
|
||||
metadata.externalFormat = formatInfo.externalFormat;
|
||||
metadata.allocationSize = properties.allocationSize;
|
||||
metadata.memoryTypeBits = properties.memoryTypeBits;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
ImageData data = allocateExternalImage(externalImage, device, allocator, metadata);
|
||||
VkResult result = vkBindImageMemory(device, data.first, data.second, 0);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkBindImageMemory error=" << result << ".";
|
||||
return data;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
return {
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
}
|
||||
|
||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
|
||||
VkInstance instance, uint64_t flags) noexcept {
|
||||
VkSurfaceKHR surface;
|
||||
VkExtent2D extent;
|
||||
|
||||
VkAndroidSurfaceCreateInfoKHR const createInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
|
||||
.window = (ANativeWindow*) nativeWindow,
|
||||
};
|
||||
VkResult const result =
|
||||
vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC, (VkSurfaceKHR*) &surface);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkCreateAndroidSurfaceKHR with error=" << result;
|
||||
return {surface, extent};
|
||||
}
|
||||
}
|
||||
+15
-14
@@ -34,7 +34,9 @@
|
||||
#endif
|
||||
|
||||
// Platform specific includes and defines
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/native_window.h>
|
||||
#elif defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#include <dlfcn.h>
|
||||
namespace {
|
||||
typedef struct _wl {
|
||||
@@ -84,20 +86,11 @@ using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
||||
void* externalImage, VkDevice device) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
VulkanPlatform::ExtensionSet const ret = {
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined(__ANDROID__)
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
|
||||
#elif defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
|
||||
#elif defined(LINUX_OR_FREEBSD) && defined(FILAMENT_SUPPORTS_X11)
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
@@ -123,7 +116,15 @@ VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWin
|
||||
// swap chain extent.
|
||||
VkExtent2D extent;
|
||||
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined(__ANDROID__)
|
||||
VkAndroidSurfaceCreateInfoKHR const createInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
|
||||
.window = (ANativeWindow*) nativeWindow,
|
||||
};
|
||||
VkResult const result = vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC,
|
||||
(VkSurfaceKHR*) &surface);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "vkCreateAndroidSurfaceKHR error.";
|
||||
#elif defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
wl* ptrval = reinterpret_cast<wl*>(nativeWindow);
|
||||
extent.width = ptrval->width;
|
||||
extent.height = ptrval->height;
|
||||
@@ -32,7 +32,7 @@
|
||||
#ifndef VK_MVK_macos_surface
|
||||
#error VK_MVK_macos_surface is not defined
|
||||
#endif
|
||||
#elif defined(FILAMENT_IOS)
|
||||
#elif defined(IOS)
|
||||
// Metal is not available when building for the iOS simulator on Desktop.
|
||||
#define METAL_AVAILABLE __has_include(<QuartzCore/CAMetalLayer.h>)
|
||||
#if METAL_AVAILABLE
|
||||
@@ -56,24 +56,13 @@ VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
ExtensionSet const ret = {
|
||||
#if defined(__APPLE__)
|
||||
VK_MVK_MACOS_SURFACE_EXTENSION_NAME, // TODO: replace with VK_EXT_metal_surface
|
||||
#elif defined(FILAMENT_IOS) && defined(METAL_AVAILABLE)
|
||||
#elif defined(IOS) && defined(METAL_AVAILABLE)
|
||||
VK_MVK_IOS_SURFACE_EXTENSION_NAME,
|
||||
#endif
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
||||
void* externalImage, VkDevice device) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
|
||||
VkInstance instance, uint64_t flags) noexcept {
|
||||
VkSurfaceKHR surface;
|
||||
@@ -90,7 +79,7 @@ VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWin
|
||||
VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC,
|
||||
(VkSurfaceKHR*) &surface);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "vkCreateMacOSSurfaceMVK error.";
|
||||
#elif defined(FILAMENT_IOS) && defined(METAL_AVAILABLE)
|
||||
#elif defined(IOS) && defined(METAL_AVAILABLE)
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow;
|
||||
// Create the VkSurface.
|
||||
FILAMENT_CHECK_POSTCONDITION(vkCreateIOSSurfaceMVK)
|
||||
|
||||
@@ -33,7 +33,7 @@ static constexpr size_t CONFIG_COMMAND_BUFFERS_SIZE = 3 * CONFIG_MIN_COMMAND
|
||||
using namespace filament;
|
||||
using namespace filament::backend;
|
||||
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
#include <imageio/ImageEncoder.h>
|
||||
#include <image/ColorTransform.h>
|
||||
|
||||
@@ -177,7 +177,7 @@ void BackendTest::readPixelsAndAssertHash(const char* testName, size_t width, si
|
||||
|
||||
// Export a screenshot, if requested.
|
||||
if (c->exportScreenshot) {
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
LinearImage image(c->width, c->height, 4);
|
||||
image = toLinearWithAlpha<uint8_t>(c->width, c->height, c->width * 4,
|
||||
(uint8_t*) buffer);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
#include <imageio/ImageEncoder.h>
|
||||
#include <image/ColorTransform.h>
|
||||
#endif
|
||||
@@ -67,7 +67,7 @@ struct ScreenshotParams {
|
||||
uint32_t pixelHashResult;
|
||||
};
|
||||
|
||||
#ifdef FILAMENT_IOS
|
||||
#ifdef IOS
|
||||
static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt, ScreenshotParams* params) {}
|
||||
#else
|
||||
static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt, ScreenshotParams* params) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
#include <imageio/ImageEncoder.h>
|
||||
#include <image/ColorTransform.h>
|
||||
|
||||
@@ -112,7 +112,7 @@ static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt) {
|
||||
int w = kTexWidth, h = kTexHeight;
|
||||
const uint32_t* texels = (uint32_t*) buffer;
|
||||
sPixelHashResult = utils::hash::murmur3(texels, size / 4, 0);
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
LinearImage image(w, h, 4);
|
||||
image = toLinearWithAlpha<uint8_t>(w, h, w * 4, (uint8_t*) buffer);
|
||||
std::ofstream pngstrm("feedback.png", std::ios::binary | std::ios::trunc);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
using namespace filament;
|
||||
using namespace filament::backend;
|
||||
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
#include <imageio/ImageEncoder.h>
|
||||
#include <image/ColorTransform.h>
|
||||
|
||||
@@ -137,7 +137,7 @@ TEST_F(ReadPixelsTest, ReadPixels) {
|
||||
}
|
||||
|
||||
void exportScreenshot(void* pixelData) const {
|
||||
#ifndef FILAMENT_IOS
|
||||
#ifndef IOS
|
||||
const size_t width = readRect.width, height = readRect.height;
|
||||
LinearImage image(width, height, 4);
|
||||
if (format == PixelDataFormat::RGBA && type == PixelDataType::UBYTE) {
|
||||
|
||||
@@ -227,8 +227,7 @@ TEST_F(BackendTest, RenderExternalImage) {
|
||||
|
||||
api.setupExternalImage(pixBuffer);
|
||||
backend::Handle<HwTexture> texture =
|
||||
api.createTextureExternalImage(SamplerType::SAMPLER_EXTERNAL,
|
||||
TextureFormat::RGBA8, 1024, 1024, usage, pixBuffer);
|
||||
api.createTextureExternalImage(TextureFormat::RGBA8, 1024, 1024, usage, pixBuffer);
|
||||
|
||||
// We're now free to release the buffer.
|
||||
CVBufferRelease(pixBuffer);
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace filament {
|
||||
* filament::Camera* myCamera = engine->createCamera(myCameraEntity);
|
||||
* myCamera->setProjection(45, 16.0/9.0, 0.1, 1.0);
|
||||
* myCamera->lookAt({0, 1.60, 1}, {0, 0, 0});
|
||||
* engine->destroyCameraComponent(myCameraEntity);
|
||||
* engine->destroyCameraComponent(myCamera);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
|
||||
@@ -103,11 +103,6 @@ public:
|
||||
Builder& operator=(Builder const& rhs) noexcept;
|
||||
Builder& operator=(Builder&& rhs) noexcept;
|
||||
|
||||
enum class ShadowSamplingQuality : uint8_t {
|
||||
HARD, // 2x2 PCF
|
||||
LOW // 3x3 gaussian filter
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the material data. The material data is a binary blob produced by
|
||||
* libfilamat or by matc.
|
||||
@@ -157,14 +152,6 @@ public:
|
||||
*/
|
||||
Builder& sphericalHarmonicsBandCount(size_t shBandCount) noexcept;
|
||||
|
||||
/**
|
||||
* Set the quality of shadow sampling. This is only taken into account
|
||||
* if this material is lit and in the surface domain.
|
||||
* @param quality
|
||||
* @return
|
||||
*/
|
||||
Builder& shadowSamplingQuality(ShadowSamplingQuality quality) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Material object and returns a pointer to it.
|
||||
*
|
||||
|
||||
@@ -438,7 +438,7 @@ struct MultiSampleAntiAliasingOptions {
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
struct TemporalAntiAliasingOptions {
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 1 (sharper) and 2 (smoother)
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
|
||||
float feedback = 0.12f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
float lodBias = -1.0f; //!< texturing lod bias (typically -1 or -2)
|
||||
float sharpness = 0.0f; //!< post-TAA sharpen, especially useful when upscaling is true.
|
||||
|
||||
@@ -261,18 +261,6 @@ public:
|
||||
*/
|
||||
Builder& import(intptr_t id) noexcept;
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
*
|
||||
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Builder& external() noexcept;
|
||||
|
||||
private:
|
||||
friend class FTexture;
|
||||
};
|
||||
@@ -407,7 +395,7 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically, the external
|
||||
* Specify the external image to associate with this Texture. Typically the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
* There are many restrictions when using an external image as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
@@ -432,7 +420,7 @@ public:
|
||||
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external image and plane to associate with this Texture. Typically, the external
|
||||
* Specify the external image and plane to associate with this Texture. Typically the external
|
||||
* image is OS specific, and can be a video or camera frame. When using this method, the
|
||||
* external image must be a planar type (such as a YUV camera frame). The plane parameter
|
||||
* selects which image plane is bound to this texture.
|
||||
|
||||
@@ -2622,7 +2622,7 @@ void PostProcessManager::TaaJitterCamera(
|
||||
current.projection = inoutCameraInfo->projection * inoutCameraInfo->getUserViewMatrix();
|
||||
current.frameId = previous.frameId + 1;
|
||||
|
||||
auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t frameIndex) -> float2 {
|
||||
auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t frameIndex){
|
||||
using JitterPattern = TemporalAntiAliasingOptions::JitterPattern;
|
||||
switch (pattern) {
|
||||
case JitterPattern::RGSS_X4:
|
||||
@@ -2636,7 +2636,6 @@ void PostProcessManager::TaaJitterCamera(
|
||||
case JitterPattern::HALTON_23_X32:
|
||||
return sHaltonSamples(frameIndex);
|
||||
}
|
||||
return { 0.0f, 0.0f };
|
||||
};
|
||||
|
||||
// sample position within a pixel [-0.5, 0.5]
|
||||
@@ -2760,31 +2759,15 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
}};
|
||||
|
||||
constexpr float2 sampleOffsets[9] = {
|
||||
{ -1.0f, -1.0f }, { 0.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f }, { -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f }, { 0.0f, -1.0f }, { 1.0f, -1.0f },
|
||||
{ -1.0f, 0.0f }, { 0.0f, 0.0f }, { 1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
|
||||
};
|
||||
|
||||
constexpr float2 subSampleOffsets[4] = {
|
||||
{ -0.25f, 0.25f },
|
||||
{ 0.25f, 0.25f },
|
||||
{ 0.25f, -0.25f },
|
||||
{ -0.25f, -0.25f }
|
||||
{ -0.25f, 0.25f }, { 0.25f, 0.25f }, { 0.25f, -0.25f }, { -0.25f, -0.25f }
|
||||
};
|
||||
|
||||
UTILS_UNUSED
|
||||
auto const lanczos = [](float x, float a) -> float {
|
||||
if (x <= std::numeric_limits<float>::epsilon()) {
|
||||
return 1.0f;
|
||||
}
|
||||
if (std::abs(x) <= a) {
|
||||
return (a * std::sin(f::PI * x) * std::sin(f::PI * x / a))
|
||||
/ ((f::PI * f::PI) * (x * x));
|
||||
}
|
||||
return 0.0f;
|
||||
};
|
||||
|
||||
float const filterWidth = std::clamp(taaOptions.filterWidth, 1.0f, 2.0f);
|
||||
float4 sum = 0.0;
|
||||
float4 weights[9];
|
||||
|
||||
@@ -2794,9 +2777,11 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
float2 const o = sampleOffsets[i];
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
float2 const subPixelOffset = taaOptions.upscaling ? subSampleOffsets[j] : float2{ 0 };
|
||||
float2 const d = (o - (current.jitter - subPixelOffset)) / filterWidth;
|
||||
weights[i][j] = lanczos(length(d), filterWidth);
|
||||
float2 const s = taaOptions.upscaling ? subSampleOffsets[j] : float2{ 0 };
|
||||
float2 const d = (o - current.jitter - s) / taaOptions.filterWidth;
|
||||
// This is a gaussian fit of a 3.3-wide Blackman-Harris window
|
||||
// see: "High Quality Temporal Supersampling" by Brian Karis
|
||||
weights[i][j] = std::exp(-2.29f * (d.x * d.x + d.y * d.y));
|
||||
}
|
||||
sum += weights[i];
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private:
|
||||
|
||||
template<size_t SIZE>
|
||||
struct JitterSequence {
|
||||
math::float2 operator()(size_t i) const noexcept { return positions[i % SIZE] - 0.5f; }
|
||||
auto operator()(size_t i) const noexcept { return positions[i % SIZE] - 0.5f; }
|
||||
const std::array<math::float2, SIZE> positions;
|
||||
};
|
||||
|
||||
|
||||
+17
-38
@@ -680,6 +680,8 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
cmd.info.hasMorphing = (bool)morphing.handle;
|
||||
cmd.info.hasSkinning = (bool)skinning.handle;
|
||||
|
||||
assert_invariant(cmd.info.hasHybridInstancing || cmd.info.instanceCount <= 1);
|
||||
|
||||
// soaInstanceInfo[i].count is the number of instances the user has requested, either for
|
||||
// manual or hybrid instancing. Instanced stereo multiplies the number of instances by the
|
||||
// eye count.
|
||||
@@ -862,44 +864,21 @@ backend::Viewport RenderPass::Executor::applyScissorViewport(
|
||||
backend::Viewport const& scissorViewport, backend::Viewport const& scissor) noexcept {
|
||||
// scissor is set, we need to apply the offset/clip
|
||||
// clang vectorizes this!
|
||||
constexpr int64_t maxvali = std::numeric_limits<int32_t>::max();
|
||||
|
||||
// we do all the offsetting/clipping math in 64 bits below to avoid overflows
|
||||
struct {
|
||||
int64_t l;
|
||||
int64_t b;
|
||||
int64_t r;
|
||||
int64_t t;
|
||||
} svp, s;
|
||||
|
||||
// convert scissorViewport to {left,bottom,right,top} format
|
||||
svp.l = scissorViewport.left;
|
||||
svp.b = scissorViewport.bottom;
|
||||
svp.r = svp.l + scissorViewport.width;
|
||||
svp.t = svp.b + scissorViewport.height;
|
||||
|
||||
// convert scissor to {left,bottom,right,top} format and offset by scissorViewport's left,bottom
|
||||
s.l = svp.l + scissor.left;
|
||||
s.b = svp.b + scissor.bottom;
|
||||
s.r = s.l + scissor.width;
|
||||
s.t = s.b + scissor.height;
|
||||
|
||||
// clip to the scissorViewport
|
||||
s.l = std::max(s.l, svp.l);
|
||||
s.b = std::max(s.b, svp.b);
|
||||
s.r = std::min(s.r, svp.r);
|
||||
s.t = std::min(s.t, svp.t);
|
||||
|
||||
// clip to positive int32_t
|
||||
s.l = std::max(s.l, int64_t(0));
|
||||
s.b = std::max(s.b, int64_t(0));
|
||||
s.r = std::min(s.r, maxvali);
|
||||
s.t = std::min(s.t, maxvali);
|
||||
|
||||
assert_invariant(s.r >= s.l && s.t >= s.b);
|
||||
|
||||
// convert back to Viewport format
|
||||
return { int32_t(s.l), int32_t(s.b), uint32_t(s.r - s.l), uint32_t(s.t - s.b) };
|
||||
constexpr int32_t maxvali = std::numeric_limits<int32_t>::max();
|
||||
// compute new left/bottom, assume no overflow
|
||||
int32_t const l = scissor.left + scissorViewport.left;
|
||||
int32_t const b = scissor.bottom + scissorViewport.bottom;
|
||||
// compute right/top without overflowing, scissor.width/height guaranteed
|
||||
// to convert to int32
|
||||
int32_t r = (l > maxvali - int32_t(scissor.width)) ? maxvali : l + int32_t(scissor.width);
|
||||
int32_t t = (b > maxvali - int32_t(scissor.height)) ? maxvali : b + int32_t(scissor.height);
|
||||
// clip to the viewport
|
||||
assert_invariant(l == std::max(l, scissorViewport.left));
|
||||
assert_invariant(b == std::max(b, scissorViewport.bottom));
|
||||
r = std::min(r, scissorViewport.left + int32_t(scissorViewport.width));
|
||||
t = std::min(t, scissorViewport.bottom + int32_t(scissorViewport.height));
|
||||
assert_invariant(r >= l && t >= b);
|
||||
return { l, b, uint32_t(r - l), uint32_t(t - b) };
|
||||
}
|
||||
|
||||
UTILS_NOINLINE // no need to be inlined
|
||||
|
||||
@@ -427,7 +427,7 @@ float FLightManager::getSpotLightInnerCone(Instance i) const noexcept {
|
||||
|
||||
void LightManager::ShadowCascades::computeUniformSplits(float splitPositions[3], uint8_t cascades) {
|
||||
size_t s = 0;
|
||||
cascades = min(cascades, (uint8_t) 4u);
|
||||
cascades = max(cascades, (uint8_t) 4u);
|
||||
for (size_t c = 1; c < cascades; c++) {
|
||||
splitPositions[s++] = float(c) / float(cascades);
|
||||
}
|
||||
@@ -436,7 +436,7 @@ void LightManager::ShadowCascades::computeUniformSplits(float splitPositions[3],
|
||||
void LightManager::ShadowCascades::computeLogSplits(float splitPositions[3], uint8_t cascades,
|
||||
float near, float far) {
|
||||
size_t s = 0;
|
||||
cascades = min(cascades, (uint8_t) 4u);
|
||||
cascades = max(cascades, (uint8_t) 4u);
|
||||
for (size_t c = 1; c < cascades; c++) {
|
||||
splitPositions[s++] =
|
||||
(near * std::pow(far / near, float(c) / float(cascades)) - near) / (far - near);
|
||||
@@ -447,7 +447,7 @@ void LightManager::ShadowCascades::computePracticalSplits(float splitPositions[3
|
||||
float near, float far, float lambda) {
|
||||
float uniformSplits[3];
|
||||
float logSplits[3];
|
||||
cascades = min(cascades, (uint8_t) 4u);
|
||||
cascades = max(cascades, (uint8_t) 4u);
|
||||
computeUniformSplits(uniformSplits, cascades);
|
||||
computeLogSplits(logSplits, cascades, near, far);
|
||||
size_t s = 0;
|
||||
|
||||
@@ -1159,13 +1159,8 @@ bool FEngine::destroy(const FMaterial* ptr) {
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(pos->second.empty(),
|
||||
"destroying material \"%s\" but %u instances still alive",
|
||||
ptr->getName().c_str(), (*pos).second.size())) {
|
||||
// We return true here, because the material has been destroyed. However, this
|
||||
// leaks this material's ResourceList<FMaterialInstance> until the engine
|
||||
// is shut down. Note that it's still possible for the MaterialInstances to be
|
||||
// destroyed manually.
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
mMaterialInstances.erase(pos);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
|
||||
@@ -123,7 +123,6 @@ struct Material::BuilderDetails {
|
||||
size_t mSize = 0;
|
||||
bool mDefaultMaterial = false;
|
||||
int32_t mShBandsCount = 3;
|
||||
Builder::ShadowSamplingQuality mShadowSamplingQuality = Builder::ShadowSamplingQuality::LOW;
|
||||
std::unordered_map<
|
||||
utils::CString,
|
||||
std::variant<int32_t, float, bool>,
|
||||
@@ -153,11 +152,6 @@ Material::Builder& Material::Builder::sphericalHarmonicsBandCount(size_t shBandC
|
||||
return *this;
|
||||
}
|
||||
|
||||
Material::Builder& Material::Builder::shadowSamplingQuality(ShadowSamplingQuality quality) noexcept {
|
||||
mImpl->mShadowSamplingQuality = quality;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
Material::Builder& Material::Builder::constant(const char* name, size_t nameLength, T value) {
|
||||
FILAMENT_CHECK_PRECONDITION(name != nullptr) << "name cannot be null";
|
||||
@@ -556,7 +550,7 @@ Program FMaterial::getProgramWithVariants(
|
||||
<< "The material '" << mName.c_str()
|
||||
<< "' has not been compiled to include the required GLSL or SPIR-V chunks for the "
|
||||
"vertex shader (variant="
|
||||
<< +variant.key << ", filtered=" << +vertexVariant.key << ").";
|
||||
<< variant.key << ", filtered=" << vertexVariant.key << ").";
|
||||
|
||||
/*
|
||||
* Fragment shader
|
||||
@@ -571,7 +565,7 @@ Program FMaterial::getProgramWithVariants(
|
||||
<< "The material '" << mName.c_str()
|
||||
<< "' has not been compiled to include the required GLSL or SPIR-V chunks for the "
|
||||
"fragment shader (variant="
|
||||
<< +variant.key << ", filtered=" << +fragmentVariant.key << ").";
|
||||
<< variant.key << ", filtered=" << ").";
|
||||
|
||||
Program program;
|
||||
program.shader(ShaderStage::VERTEX, vsBuilder.data(), vsBuilder.size())
|
||||
@@ -611,10 +605,10 @@ void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexce
|
||||
FEngine const& engine = mEngine;
|
||||
DriverApi& driverApi = mEngine.getDriverApi();
|
||||
|
||||
bool const isShared = isSharedVariant(variant);
|
||||
|
||||
// Check if the default material has this program cached
|
||||
if (isShared) {
|
||||
if (mMaterialDomain == MaterialDomain::SURFACE &&
|
||||
!mIsDefaultMaterial && !mHasCustomDepthShader &&
|
||||
Variant::isValidDepthVariant(variant)) {
|
||||
FMaterial const* const pDefaultMaterial = engine.getDefaultMaterial();
|
||||
if (pDefaultMaterial) {
|
||||
auto program = pDefaultMaterial->mCachedPrograms[variant.key];
|
||||
@@ -633,7 +627,9 @@ void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexce
|
||||
// If the default material doesn't already have this program cached, and all caching conditions
|
||||
// are met (Surface Domain and no custom depth shader), cache it now.
|
||||
// New Materials will inherit these program automatically.
|
||||
if (isShared) {
|
||||
if (mMaterialDomain == MaterialDomain::SURFACE &&
|
||||
!mIsDefaultMaterial && !mHasCustomDepthShader &&
|
||||
Variant::isValidDepthVariant(variant)) {
|
||||
FMaterial const* const pDefaultMaterial = engine.getDefaultMaterial();
|
||||
if (pDefaultMaterial && !pDefaultMaterial->mCachedPrograms[variant.key]) {
|
||||
// set the tag to the default material name
|
||||
@@ -1002,11 +998,7 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde
|
||||
+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT,
|
||||
(int)engine.getConfig().stereoscopicEyeCount });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT,
|
||||
builder->mShBandsCount });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_SHADOW_SAMPLING_METHOD,
|
||||
(int32_t)builder->mShadowSamplingQuality });
|
||||
+ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT, builder->mShBandsCount });
|
||||
if (UTILS_UNLIKELY(parser->getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
// The actual value of this spec-constant is set in the OpenGLDriver backend.
|
||||
mSpecializationConstants.push_back({
|
||||
@@ -1084,21 +1076,6 @@ void FMaterial::processPushConstants(FEngine& engine, MaterialParser const* pars
|
||||
}
|
||||
|
||||
void FMaterial::precacheDepthVariants(FEngine& engine) {
|
||||
// pre-cache all depth variants inside the default material. Note that this should be
|
||||
// entirely optional; if we remove this pre-caching, these variants will be populated
|
||||
// later, when/if needed by createAndCacheProgram(). Doing it now potentially uses more
|
||||
// memory and increases init time, but reduces hiccups during the first frame.
|
||||
if (UTILS_UNLIKELY(mIsDefaultMaterial)) {
|
||||
auto const allDepthVariants = VariantUtils::getDepthVariants();
|
||||
for (auto const variant: allDepthVariants) {
|
||||
assert_invariant(Variant::isValidDepthVariant(variant));
|
||||
if (hasVariant(variant)) {
|
||||
prepareProgram(variant);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if possible pre-cache all depth variants from the default material
|
||||
if (mMaterialDomain == MaterialDomain::SURFACE &&
|
||||
!mIsDefaultMaterial &&
|
||||
|
||||
@@ -156,13 +156,6 @@ public:
|
||||
std::unique_lock<utils::Mutex> lock(mActiveProgramsLock);
|
||||
mActivePrograms.set(variant.key);
|
||||
lock.unlock();
|
||||
|
||||
if (isSharedVariant(variant)) {
|
||||
FMaterial const* const pDefaultMaterial = mEngine.getDefaultMaterial();
|
||||
if (pDefaultMaterial && pDefaultMaterial->mCachedPrograms[variant.key]) {
|
||||
return pDefaultMaterial->getProgram(variant);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
assert_invariant(mCachedPrograms[variant.key]);
|
||||
return mCachedPrograms[variant.key];
|
||||
@@ -297,11 +290,6 @@ private:
|
||||
|
||||
void createAndCacheProgram(backend::Program&& p, Variant variant) const noexcept;
|
||||
|
||||
inline bool isSharedVariant(Variant variant) const {
|
||||
return (mMaterialDomain == MaterialDomain::SURFACE) && !mIsDefaultMaterial &&
|
||||
!mHasCustomDepthShader && Variant::isValidDepthVariant(variant);
|
||||
}
|
||||
|
||||
// try to order by frequency of use
|
||||
mutable std::array<backend::Handle<backend::HwProgram>, VARIANT_COUNT> mCachedPrograms;
|
||||
DescriptorSetLayout mPerViewDescriptorSetLayout;
|
||||
|
||||
@@ -963,11 +963,6 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
uint32_t(float(xvp.width ) * aoOptions.resolution),
|
||||
uint32_t(float(xvp.height) * aoOptions.resolution)});
|
||||
|
||||
// this needs to reset the sampler that are only set in RendererUtils::colorPass(), because
|
||||
// this descriptor-set is also used for ssr/picking/structure and these could be stale
|
||||
// it would be better to use a separate desriptor-set for those two cases so that we don't
|
||||
// have to do this
|
||||
view.unbindSamplers(driver);
|
||||
view.commitUniformsAndSamplers(driver);
|
||||
});
|
||||
|
||||
|
||||
@@ -81,7 +81,6 @@ struct Texture::BuilderDetails {
|
||||
Usage mUsage = Usage::NONE;
|
||||
bool mHasBlitSrc = false;
|
||||
bool mTextureIsSwizzled = false;
|
||||
bool mExternal = false;
|
||||
std::array<Swizzle, 4> mSwizzle = {
|
||||
Swizzle::CHANNEL_0, Swizzle::CHANNEL_1,
|
||||
Swizzle::CHANNEL_2, Swizzle::CHANNEL_3 };
|
||||
@@ -137,11 +136,6 @@ Texture::Builder& Texture::Builder::import(intptr_t id) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Texture::Builder& Texture::Builder::external() noexcept {
|
||||
mImpl->mExternal = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Texture::Builder& Texture::Builder::swizzle(Swizzle r, Swizzle g, Swizzle b, Swizzle a) noexcept {
|
||||
mImpl->mTextureIsSwizzled = true;
|
||||
mImpl->mSwizzle = { r, g, b, a };
|
||||
@@ -160,11 +154,6 @@ Texture* Texture::Builder::build(Engine& engine) {
|
||||
(isProtectedTexturesSupported && useProtectedMemory) || !useProtectedMemory)
|
||||
<< "Texture is PROTECTED but protected textures are not supported";
|
||||
|
||||
// SAMPLER_EXTERNAL implies imported.
|
||||
if (mImpl->mTarget == SamplerType::SAMPLER_EXTERNAL) {
|
||||
mImpl->mExternal = true;
|
||||
}
|
||||
|
||||
uint8_t maxLevelCount;
|
||||
switch (mImpl->mTarget) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
@@ -185,7 +174,7 @@ Texture* Texture::Builder::build(Engine& engine) {
|
||||
mImpl->mUsage = TextureUsage::DEFAULT;
|
||||
if (mImpl->mLevels > 1 &&
|
||||
(mImpl->mWidth > 1 || mImpl->mHeight > 1) &&
|
||||
!mImpl->mExternal) {
|
||||
mImpl->mTarget != SamplerType::SAMPLER_EXTERNAL) {
|
||||
const bool formatMipmappable =
|
||||
downcast(engine).getDriverApi().isTextureFormatMipmappable(mImpl->mFormat);
|
||||
if (formatMipmappable) {
|
||||
@@ -254,10 +243,9 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) {
|
||||
mSwizzle = builder->mSwizzle;
|
||||
mTextureIsSwizzled = builder->mTextureIsSwizzled;
|
||||
mHasBlitSrc = builder->mHasBlitSrc;
|
||||
mExternal = builder->mExternal;
|
||||
|
||||
bool const isImported = builder->mImportedId != 0;
|
||||
if (mExternal && !isImported) {
|
||||
if (mTarget == SamplerType::SAMPLER_EXTERNAL && !isImported) {
|
||||
// mHandle and mHandleForSampling will be created in setExternalImage()
|
||||
// If this Texture is used for sampling before setExternalImage() is called,
|
||||
// we'll lazily create a 1x1 placeholder texture.
|
||||
@@ -330,8 +318,8 @@ void FTexture::setImage(FEngine& engine, size_t level,
|
||||
<< "level=" << unsigned(level) << " is >= to levelCount=" << unsigned(mLevelCount)
|
||||
<< ".";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(!mExternal)
|
||||
<< "External Texture not supported for this operation.";
|
||||
FILAMENT_CHECK_PRECONDITION(mTarget != SamplerType::SAMPLER_EXTERNAL)
|
||||
<< "Texture SamplerType::SAMPLER_EXTERNAL not supported for this operation.";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(mSampleCount <= 1) << "Operation not supported with multisample ("
|
||||
<< unsigned(mSampleCount) << ") texture.";
|
||||
@@ -466,14 +454,15 @@ void FTexture::setImage(FEngine& engine, size_t level,
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, void* image) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
if (mTarget != Sampler::SAMPLER_EXTERNAL) {
|
||||
return;
|
||||
}
|
||||
// The call to setupExternalImage is synchronous, and allows the driver to take ownership of the
|
||||
// external image on this thread, if necessary.
|
||||
auto& api = engine.getDriverApi();
|
||||
api.setupExternalImage(image);
|
||||
|
||||
auto texture = api.createTextureExternalImage(mTarget, mFormat, mWidth, mHeight, mUsage, image);
|
||||
auto texture = api.createTextureExternalImage(mFormat, mWidth, mHeight, mUsage, image);
|
||||
|
||||
if (mTextureIsSwizzled) {
|
||||
auto const& s = mSwizzle;
|
||||
@@ -486,8 +475,9 @@ void FTexture::setExternalImage(FEngine& engine, void* image) noexcept {
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, void* image, size_t plane) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
if (mTarget != Sampler::SAMPLER_EXTERNAL) {
|
||||
return;
|
||||
}
|
||||
// The call to setupExternalImage is synchronous, and allows the driver to take ownership of
|
||||
// the external image on this thread, if necessary.
|
||||
auto& api = engine.getDriverApi();
|
||||
@@ -507,7 +497,9 @@ void FTexture::setExternalImage(FEngine& engine, void* image, size_t plane) noex
|
||||
}
|
||||
|
||||
void FTexture::setExternalStream(FEngine& engine, FStream* stream) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
if (mTarget != Sampler::SAMPLER_EXTERNAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& api = engine.getDriverApi();
|
||||
auto texture = api.createTexture(
|
||||
@@ -532,7 +524,7 @@ void FTexture::setExternalStream(FEngine& engine, FStream* stream) noexcept {
|
||||
}
|
||||
|
||||
void FTexture::generateMipmaps(FEngine& engine) const noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(!mExternal)
|
||||
FILAMENT_CHECK_PRECONDITION(mTarget != SamplerType::SAMPLER_EXTERNAL)
|
||||
<< "External Textures are not mipmappable.";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(mTarget != SamplerType::SAMPLER_3D)
|
||||
@@ -552,11 +544,12 @@ void FTexture::generateMipmaps(FEngine& engine) const noexcept {
|
||||
}
|
||||
|
||||
bool FTexture::textureHandleCanMutate() const noexcept {
|
||||
return (any(mUsage & Usage::SAMPLEABLE) && mLevelCount > 1) || mExternal;
|
||||
return (any(mUsage & Usage::SAMPLEABLE) && mLevelCount > 1) ||
|
||||
mTarget == SamplerType::SAMPLER_EXTERNAL;
|
||||
}
|
||||
|
||||
void FTexture::updateLodRange(uint8_t baseLevel, uint8_t levelCount) noexcept {
|
||||
assert_invariant(!mExternal);
|
||||
assert_invariant(mTarget != SamplerType::SAMPLER_EXTERNAL);
|
||||
if (any(mUsage & Usage::SAMPLEABLE) && mLevelCount > 1) {
|
||||
auto& range = mLodRange;
|
||||
uint8_t const last = int8_t(baseLevel + levelCount);
|
||||
@@ -608,7 +601,7 @@ backend::Handle<backend::HwTexture> FTexture::createPlaceholderTexture(
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> FTexture::getHwHandleForSampling() const noexcept {
|
||||
if (UTILS_UNLIKELY(mExternal && !mHandleForSampling)) {
|
||||
if (UTILS_UNLIKELY(mTarget == SamplerType::SAMPLER_EXTERNAL && !mHandleForSampling)) {
|
||||
return setHandleForSampling(createPlaceholderTexture(*mDriver));
|
||||
}
|
||||
auto const& range = mLodRange;
|
||||
@@ -617,10 +610,9 @@ backend::Handle<backend::HwTexture> FTexture::getHwHandleForSampling() const noe
|
||||
if (UTILS_UNLIKELY(lodRangeChanged)) {
|
||||
activeRange = range;
|
||||
if (range.empty() || hasAllLods(range)) {
|
||||
std::ignore = setHandleForSampling(mHandle);
|
||||
setHandleForSampling(mHandle);
|
||||
} else {
|
||||
std::ignore = setHandleForSampling(mDriver->createTextureView(
|
||||
mHandle, range.first, range.size()));
|
||||
setHandleForSampling(mDriver->createTextureView(mHandle, range.first, range.size()));
|
||||
}
|
||||
}
|
||||
return mHandleForSampling;
|
||||
|
||||
@@ -173,8 +173,7 @@ private:
|
||||
// Indicates whether the user has set the TextureUsage::BLIT_SRC usage. This will be used to
|
||||
// temporarily validate whether this texture can be used for readPixels.
|
||||
bool mHasBlitSrc = false;
|
||||
bool mExternal = false;
|
||||
// there is 4 bytes of padding here
|
||||
// there is 5 bytes of padding here
|
||||
|
||||
FStream* mStream = nullptr; // only needed for streaming textures
|
||||
};
|
||||
|
||||
@@ -912,10 +912,6 @@ void FView::commitUniformsAndSamplers(DriverApi& driver) const noexcept {
|
||||
mColorPassDescriptorSet.commit(driver);
|
||||
}
|
||||
|
||||
void FView::unbindSamplers(DriverApi& driver) noexcept {
|
||||
mColorPassDescriptorSet.unbindSamplers(driver);
|
||||
}
|
||||
|
||||
void FView::commitFroxels(DriverApi& driverApi) const noexcept {
|
||||
if (mHasDynamicLighting) {
|
||||
mFroxelizer.commit(driverApi);
|
||||
|
||||
@@ -174,7 +174,6 @@ public:
|
||||
|
||||
void commitFroxels(backend::DriverApi& driverApi) const noexcept;
|
||||
void commitUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
|
||||
void unbindSamplers(backend::DriverApi& driver) noexcept;
|
||||
|
||||
utils::JobSystem::Job* getFroxelizerSync() const noexcept { return mFroxelizerSync; }
|
||||
void setFroxelizerSync(utils::JobSystem::Job* sync) noexcept { mFroxelizerSync = sync; }
|
||||
|
||||
@@ -541,17 +541,6 @@ void ColorPassDescriptorSet::commit(backend::DriverApi& driver) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void ColorPassDescriptorSet::unbindSamplers(DriverApi&) noexcept {
|
||||
// this needs to reset the sampler that are only set in RendererUtils::colorPass(), because
|
||||
// this descriptor-set is also used for ssr/picking/structure and these could be stale
|
||||
// it would be better to use a separate descriptor-set for those two cases so that we don't
|
||||
// have to do this
|
||||
setSampler(+PerViewBindingPoints::STRUCTURE, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SHADOW_MAP, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SSAO, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SSR, {}, {});
|
||||
}
|
||||
|
||||
void ColorPassDescriptorSet::setSampler(backend::descriptor_binding_t binding,
|
||||
TextureHandle th, SamplerParams params) noexcept {
|
||||
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
|
||||
|
||||
@@ -158,8 +158,6 @@ public:
|
||||
// update local data into GPU UBO
|
||||
void commit(backend::DriverApi& driver) noexcept;
|
||||
|
||||
void unbindSamplers(backend::DriverApi& driver) noexcept;
|
||||
|
||||
// bind this UBO
|
||||
void bind(backend::DriverApi& driver, uint8_t index) const noexcept {
|
||||
mDescriptorSet[index].bind(driver, DescriptorSetBindingPoints::PER_VIEW);
|
||||
|
||||
@@ -149,7 +149,7 @@ void DescriptorSet::setSampler(
|
||||
|
||||
DescriptorSet DescriptorSet::duplicate(DescriptorSetLayout const& layout) const noexcept {
|
||||
DescriptorSet set{layout};
|
||||
set.mDescriptors = mDescriptors; // Use the vector's assignment operator
|
||||
memcpy(set.mDescriptors.data(), mDescriptors.data(), mDescriptors.size() * sizeof(Desc));
|
||||
set.mDirty = mDirty;
|
||||
set.mValid = mValid;
|
||||
return set;
|
||||
|
||||
@@ -127,8 +127,7 @@ float lumaYCoCg(const vec3 c) {
|
||||
}
|
||||
|
||||
float luma(const vec3 c) {
|
||||
return (materialConstants_useYCoCg && materialConstants_boxClipping != BOX_CLIPPING_NONE) ?
|
||||
lumaYCoCg(c) : lumaRGB(c);
|
||||
return materialConstants_useYCoCg ? lumaYCoCg(c) : lumaRGB(c);
|
||||
}
|
||||
|
||||
vec3 tonemap(const vec3 c) {
|
||||
@@ -279,6 +278,10 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
history = textureLod(materialParams_history, uv.zw, 0.0);
|
||||
}
|
||||
|
||||
if (materialConstants_useYCoCg) {
|
||||
history.rgb = RGB_YCoCg(history.rgb);
|
||||
}
|
||||
|
||||
highp vec2 size = vec2(textureSize(materialParams_color, 0));
|
||||
highp vec2 p = (floor(uv.xy * size) + 0.5) / size;
|
||||
vec4 filtered = textureLod(materialParams_color, p, 0.0);
|
||||
@@ -294,46 +297,47 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
s[6] = textureLodOffset(materialParams_color, p, 0.0, ivec2(-1, 1)).rgb;
|
||||
s[7] = textureLodOffset(materialParams_color, p, 0.0, ivec2( 0, 1)).rgb;
|
||||
s[8] = textureLodOffset(materialParams_color, p, 0.0, ivec2( 1, 1)).rgb;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
float confidence = 1.0;
|
||||
if (materialConstants_upscaling) {
|
||||
highp vec2 subPixelOffset = (p - uv.xy) * size; // +/- [0.25, 0.25]
|
||||
|
||||
// we reduce the contribution of a sample based on the distance
|
||||
// to the high resolution pixel center
|
||||
const float cutoff = 0.5;
|
||||
highp float l = length(materialParams.jitter - subPixelOffset) / cutoff;
|
||||
confidence = saturate(1.0 - l * l);
|
||||
|
||||
if (materialConstants_filterInput) {
|
||||
int jxp = subPixelOffset.y > 0.0 ? 1 : 2;
|
||||
int jxn = subPixelOffset.y > 0.0 ? 0 : 3;
|
||||
j = subPixelOffset.x > 0.0 ? jxp : jxn;
|
||||
}
|
||||
}
|
||||
|
||||
if (materialConstants_filterInput) {
|
||||
// unjitter/filter input
|
||||
filtered = vec4(vec3(0), filtered.a);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
float w = materialParams.filterWeights[i][j];
|
||||
filtered.rgb += s[i] * w;
|
||||
}
|
||||
filtered.rgb = max(filtered.rgb, vec3(0));
|
||||
}
|
||||
|
||||
// build the history clamping box
|
||||
if (materialConstants_boxClipping != BOX_CLIPPING_NONE) {
|
||||
if (materialConstants_useYCoCg) {
|
||||
history.rgb = RGB_YCoCg(history.rgb);
|
||||
filtered.rgb = RGB_YCoCg(filtered.rgb);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
s[i] = RGB_YCoCg(s[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec2 subPixelOffset = p - uv.xy; // +/- [0.25, 0.25]
|
||||
float confidence = materialConstants_upscaling ? 0.0 : 1.0;
|
||||
|
||||
if (materialConstants_filterInput) {
|
||||
// unjitter/filter input
|
||||
// figure out which set of coeficients to use
|
||||
filtered = vec4(0, 0, 0, filtered.a);
|
||||
if (materialConstants_upscaling) {
|
||||
int jxp = subPixelOffset.y > 0.0 ? 3 : 0;
|
||||
int jxn = subPixelOffset.y > 0.0 ? 2 : 1;
|
||||
int j = subPixelOffset.x > 0.0 ? jxp : jxn;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
float w = materialParams.filterWeights[i][j];
|
||||
filtered.rgb += s[i] * w;
|
||||
confidence = max(confidence, w);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
float w = materialParams.filterWeights[i][0];
|
||||
filtered.rgb += s[i] * w;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (materialConstants_useYCoCg) {
|
||||
filtered.rgb = RGB_YCoCg(filtered.rgb);
|
||||
}
|
||||
if (materialConstants_upscaling) {
|
||||
confidence = float(materialParams.jitter.x * subPixelOffset.x > 0.0 &&
|
||||
materialParams.jitter.y * subPixelOffset.y > 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// build the history clamping box
|
||||
if (materialConstants_boxClipping != BOX_CLIPPING_NONE) {
|
||||
vec3 boxmin;
|
||||
vec3 boxmax;
|
||||
if (materialConstants_boxType == BOX_TYPE_AABB ||
|
||||
@@ -342,7 +346,7 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
boxmax = max(s[4], max(max(s[1], s[3]), max(s[5], s[7])));
|
||||
vec3 box9min = min(boxmin, min(min(s[0], s[2]), min(s[6], s[8])));
|
||||
vec3 box9max = max(boxmax, max(max(s[0], s[2]), max(s[6], s[8])));
|
||||
// round the corners of the 3x3 box, giving less importance to the corner samples
|
||||
// round the corners of the 3x3 box
|
||||
boxmin = (boxmin + box9min) * 0.5;
|
||||
boxmax = (boxmax + box9max) * 0.5;
|
||||
}
|
||||
@@ -384,11 +388,9 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
}
|
||||
|
||||
// go back to RGB space before tonemapping
|
||||
if (materialConstants_boxClipping != BOX_CLIPPING_NONE) {
|
||||
if (materialConstants_useYCoCg) {
|
||||
filtered.rgb = YCoCg_RGB(filtered.rgb);
|
||||
history.rgb = YCoCg_RGB(history.rgb);
|
||||
}
|
||||
if (materialConstants_useYCoCg) {
|
||||
filtered.rgb = YCoCg_RGB(filtered.rgb);
|
||||
history.rgb = YCoCg_RGB(history.rgb);
|
||||
}
|
||||
|
||||
// tonemap before mixing
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.56.6"
|
||||
spec.version = "1.56.1"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.6/filament-v1.56.6-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.1/filament-v1.56.1-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -38,13 +38,12 @@ bool initBinder() {
|
||||
}
|
||||
}
|
||||
if (!g_driver.library) {
|
||||
// The library has been linked explicitly during compile.
|
||||
g_driver.OSMesaGetProcAddress = (ProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
|
||||
} else {
|
||||
g_driver.OSMesaGetProcAddress =
|
||||
(ProcAddressFunc) dlsym(g_driver.library, "OSMesaGetProcAddress");
|
||||
return false;
|
||||
}
|
||||
|
||||
g_driver.OSMesaGetProcAddress = (ProcAddressFunc)
|
||||
dlsym(g_driver.library, "OSMesaGetProcAddress");
|
||||
|
||||
return g_driver.OSMesaGetProcAddress;
|
||||
}
|
||||
|
||||
@@ -53,9 +52,7 @@ void* loadFunction(const char* name) {
|
||||
}
|
||||
|
||||
void shutdownBinder() {
|
||||
if (g_driver.library) {
|
||||
dlclose(g_driver.library);
|
||||
}
|
||||
dlclose(g_driver.library);
|
||||
memset(&g_driver, 0, sizeof(g_driver));
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR 1
|
||||
#elif defined(FILAMENT_IOS)
|
||||
#elif defined(IOS)
|
||||
#define VK_USE_PLATFORM_IOS_MVK 1
|
||||
#elif defined(__linux__)
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(fgviewer C ASM)
|
||||
|
||||
set(TARGET fgviewer)
|
||||
set(PUBLIC_HDR_DIR include)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
include(${IMPORT_EXECUTABLES})
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Sources and headers
|
||||
# ==================================================================================================
|
||||
|
||||
set(PUBLIC_HDRS
|
||||
include/fgviewer/DebugServer.h
|
||||
include/fgviewer/JsonWriter.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
src/ApiHandler.cpp
|
||||
src/ApiHandler.h
|
||||
src/DebugServer.cpp
|
||||
)
|
||||
|
||||
# ==================================================================================================
|
||||
# Include and target definitions
|
||||
# ==================================================================================================
|
||||
|
||||
include_directories(${PUBLIC_HDR_DIR})
|
||||
|
||||
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
|
||||
|
||||
target_link_libraries(${TARGET} PUBLIC
|
||||
civetweb
|
||||
utils
|
||||
)
|
||||
|
||||
target_include_directories(${TARGET} PRIVATE ${filamat_SOURCE_DIR}/src)
|
||||
|
||||
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
|
||||
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
|
||||
|
||||
# ==================================================================================================
|
||||
# Compiler flags
|
||||
# ==================================================================================================
|
||||
|
||||
if (MSVC)
|
||||
else()
|
||||
target_compile_options(${TARGET} PRIVATE -Wno-deprecated-register)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Installation
|
||||
# ==================================================================================================
|
||||
|
||||
# matdbg has dependencies on non-installed libraries. Here we bundle them all together into a single
|
||||
# library that gets copied into the installation folder so users are only required to link against
|
||||
# matdbg.
|
||||
set(FGVIEWER_DEPS
|
||||
fgviewer
|
||||
civetweb
|
||||
)
|
||||
|
||||
set(FGVIEWER_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libfgviewer_combined.a")
|
||||
combine_static_libs(fgviewer "${FGVIEWER_COMBINED_OUTPUT}" "${FGVIEWER_DEPS}")
|
||||
|
||||
set(FGVIEWER_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}fgviewer${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
install(FILES "${FGVIEWER_COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR} RENAME ${FGVIEWER_LIB_NAME})
|
||||
# We do not need fgviewer headers in the install directory
|
||||
# install(DIRECTORY ${PUBLIC_HDR_DIR}/fgviewer DESTINATION include)
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 FGVIEWER_DEBUGSERVER_H
|
||||
#define FGVIEWER_DEBUGSERVER_H
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class CivetServer;
|
||||
|
||||
namespace filament::fgviewer {
|
||||
|
||||
using FrameGraphInfoKey = uint32_t;
|
||||
|
||||
struct FrameGraphPassInfo {
|
||||
utils::CString pass_name;
|
||||
// TODO: Add struct detail properties
|
||||
};
|
||||
|
||||
struct FrameGraphInfo {
|
||||
utils::CString view_name;
|
||||
std::vector<FrameGraphPassInfo> passes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Server-side frame graph debugger.
|
||||
*
|
||||
* This class manages an HTTP server. It receives frame graph packages from the Filament C++ engine or
|
||||
* from a standalone tool such as fginfo.
|
||||
*/
|
||||
class DebugServer {
|
||||
public:
|
||||
static std::string_view const kSuccessHeader;
|
||||
static std::string_view const kErrorHeader;
|
||||
|
||||
DebugServer(int port);
|
||||
~DebugServer();
|
||||
|
||||
/**
|
||||
* Notifies the debugger that a new view has been added.
|
||||
*/
|
||||
void addView(const utils::CString& name, FrameGraphInfo info);
|
||||
|
||||
/**
|
||||
* Notifies the debugger that the given view has been deleted.
|
||||
*/
|
||||
void removeView(const utils::CString& name);
|
||||
|
||||
/**
|
||||
* Updates the information for a given view.
|
||||
*/
|
||||
void updateView(const utils::CString& name, FrameGraphInfo info);
|
||||
|
||||
bool isReady() const { return mServer; }
|
||||
|
||||
private:
|
||||
CivetServer* mServer;
|
||||
|
||||
std::unordered_map<FrameGraphInfoKey, FrameGraphInfo> mViews;
|
||||
mutable utils::Mutex mViewsMutex;
|
||||
|
||||
class FileRequestHandler* mFileHandler = nullptr;
|
||||
class ApiHandler* mApiHandler = nullptr;
|
||||
|
||||
friend class FileRequestHandler;
|
||||
friend class ApiHandler;
|
||||
};
|
||||
|
||||
} // namespace filament::fgviewer
|
||||
|
||||
#endif // FGVIEWER_DEBUGSERVER_H
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 FGVIEWER_JSONWRITER_H
|
||||
#define FGVIEWER_JSONWRITER_H
|
||||
|
||||
#include <utils/CString.h>
|
||||
|
||||
namespace filament::fgviewer {
|
||||
|
||||
struct FrameGraphInfo;
|
||||
|
||||
// This class generates portions of JSON messages that are sent to the web client.
|
||||
// Note that some portions of these JSON strings are generated by directly in DebugServer,
|
||||
// as well as CommonWriter.
|
||||
class JsonWriter {
|
||||
public:
|
||||
|
||||
// Retrieves the most recently generated string.
|
||||
const char* getJsonString() const;
|
||||
size_t getJsonSize() const;
|
||||
|
||||
// Generates a JSON string describing the given FrameGraphInfo.
|
||||
bool writeFrameGraphInfo(const FrameGraphInfo& frameGraph);
|
||||
|
||||
private:
|
||||
utils::CString mJsonString;
|
||||
};
|
||||
|
||||
} // namespace filament::fgviewer
|
||||
|
||||
#endif // FGVIEWER_JSONWRITER_H
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 "ApiHandler.h"
|
||||
|
||||
#include <fgviewer/DebugServer.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <CivetServer.h>
|
||||
|
||||
namespace filament::fgviewer {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
|
||||
auto const& kSuccessHeader = DebugServer::kSuccessHeader;
|
||||
auto const& kErrorHeader = DebugServer::kErrorHeader;
|
||||
|
||||
auto const error = [](int line, std::string const& uri) {
|
||||
utils::slog.e << "[fgviewer] DebugServer: 404 at line " << line << ": " << uri << utils::io::endl;
|
||||
return false;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
bool ApiHandler::handleGetApiFgInfo(struct mg_connection* conn,
|
||||
struct mg_request_info const* request) {
|
||||
auto const softError = [conn, request](char const* msg) {
|
||||
utils::slog.e << "[fgviewer] DebugServer: " << msg << ": " << request->query_string << utils::io::endl;
|
||||
mg_printf(conn, kErrorHeader.data(), "application/txt");
|
||||
mg_write(conn, msg, strlen(msg));
|
||||
return true;
|
||||
};
|
||||
|
||||
// TODO: Implement the method
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApiHandler::addFrameGraph(FrameGraphInfo const* framegraph) {
|
||||
// TODO: Implement the method
|
||||
}
|
||||
|
||||
|
||||
bool ApiHandler::handleGet(CivetServer* server, struct mg_connection* conn) {
|
||||
struct mg_request_info const* request = mg_get_request_info(conn);
|
||||
std::string const& uri = request->local_uri;
|
||||
|
||||
// TODO: Implement the method
|
||||
return true;
|
||||
}
|
||||
|
||||
} // filament::fgviewer
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 FGVIEWER_APIHANDLER_H
|
||||
#define FGVIEWER_APIHANDLER_H
|
||||
|
||||
#include <CivetServer.h>
|
||||
|
||||
namespace filament::fgviewer {
|
||||
|
||||
class DebugServer;
|
||||
struct FrameGraphInfo;
|
||||
|
||||
// Handles the following REST requests, where {id} is an 8-digit hex string.
|
||||
//
|
||||
// GET /api/framegraphs
|
||||
// GET /api/framegraph?fg={viewname}
|
||||
//
|
||||
class ApiHandler : public CivetHandler {
|
||||
public:
|
||||
explicit ApiHandler(DebugServer* server)
|
||||
: mServer(server) {}
|
||||
~ApiHandler() = default;
|
||||
|
||||
bool handleGet(CivetServer* server, struct mg_connection* conn);
|
||||
void addFrameGraph(FrameGraphInfo const* frameGraph);
|
||||
|
||||
private:
|
||||
bool handleGetApiFgInfo(struct mg_connection* conn, struct mg_request_info const* request);
|
||||
|
||||
DebugServer* mServer;
|
||||
};
|
||||
|
||||
} // filament::fgviewer
|
||||
|
||||
#endif // FGVIEWER_APIHANDLER_H
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <fgviewer/DebugServer.h>
|
||||
|
||||
#include "ApiHandler.h"
|
||||
|
||||
#include <CivetServer.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace filament::fgviewer {
|
||||
|
||||
namespace {
|
||||
std::string const BASE_URL = "libs/fgviewer/web";
|
||||
|
||||
FrameGraphInfoKey getKeybyString(const utils::CString &input,
|
||||
uint32_t seed) {
|
||||
return utils::hash::murmurSlow(reinterpret_cast<uint8_t const*>(
|
||||
input.c_str()), input.size(), 0);
|
||||
}
|
||||
} // anonymous
|
||||
|
||||
using namespace utils;
|
||||
|
||||
std::string_view const DebugServer::kSuccessHeader =
|
||||
"HTTP/1.1 200 OK\r\nContent-Type: %s\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
|
||||
std::string_view const DebugServer::kErrorHeader =
|
||||
"HTTP/1.1 404 Not Found\r\nContent-Type: %s\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
|
||||
class FileRequestHandler : public CivetHandler {
|
||||
public:
|
||||
FileRequestHandler(DebugServer* server) : mServer(server) {}
|
||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
||||
auto const& kSuccessHeader = DebugServer::kSuccessHeader;
|
||||
struct mg_request_info const* request = mg_get_request_info(conn);
|
||||
std::string uri(request->request_uri);
|
||||
if (uri == "/") {
|
||||
uri = "/index.html";
|
||||
}
|
||||
|
||||
if (uri == "/index.html" || uri == "/app.js" || uri == "/api.js") {
|
||||
mg_send_file(conn, (BASE_URL + uri).c_str());
|
||||
return true;
|
||||
}
|
||||
slog.e << "[fgviewer] DebugServer: bad request at line " << __LINE__ << ": " << uri << io::endl;
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
DebugServer* mServer;
|
||||
};
|
||||
|
||||
DebugServer::DebugServer(int port) {
|
||||
// By default the server spawns 50 threads so we override this to 10. According to the civetweb
|
||||
// documentation, "it is recommended to use num_threads of at least 5, since browsers often
|
||||
/// establish multiple connections to load a single web page, including all linked documents
|
||||
// (CSS, JavaScript, images, ...)." If this count is too small, the web app basically hangs.
|
||||
const char* kServerOptions[] = {
|
||||
"listening_ports", "8085",
|
||||
"num_threads", "10",
|
||||
"error_log_file", "civetweb.txt",
|
||||
nullptr
|
||||
};
|
||||
std::string portString = std::to_string(port);
|
||||
kServerOptions[1] = portString.c_str();
|
||||
|
||||
mServer = new CivetServer(kServerOptions);
|
||||
if (!mServer->getContext()) {
|
||||
delete mServer;
|
||||
mServer = nullptr;
|
||||
slog.e << "[fgviewer] Unable to start DebugServer, see civetweb.txt for details." << io::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
mFileHandler = new FileRequestHandler(this);
|
||||
mApiHandler = new ApiHandler(this);
|
||||
|
||||
mServer->addHandler("/api", mApiHandler);
|
||||
mServer->addHandler("", mFileHandler);
|
||||
|
||||
slog.i << "[fgviewer] DebugServer listening at http://localhost:" << port << io::endl;
|
||||
}
|
||||
|
||||
DebugServer::~DebugServer() {
|
||||
mServer->close();
|
||||
|
||||
delete mFileHandler;
|
||||
delete mApiHandler;
|
||||
delete mServer;
|
||||
}
|
||||
|
||||
void DebugServer::addView(const utils::CString &name, FrameGraphInfo info) {
|
||||
std::unique_lock<utils::Mutex> lock(mViewsMutex);
|
||||
const FrameGraphInfoKey key = getKeybyString(name, 0);
|
||||
mViews.insert({key, info});
|
||||
}
|
||||
|
||||
void DebugServer::removeView(const utils::CString& name) {
|
||||
std::unique_lock<utils::Mutex> lock(mViewsMutex);
|
||||
const FrameGraphInfoKey key = getKeybyString(name, 0);
|
||||
mViews.erase(key);
|
||||
}
|
||||
|
||||
void DebugServer::updateView(const utils::CString& name, FrameGraphInfo info) {
|
||||
std::unique_lock<utils::Mutex> lock(mViewsMutex);
|
||||
const FrameGraphInfoKey key = getKeybyString(name, 0);
|
||||
mViews[key] = info;
|
||||
}
|
||||
|
||||
} // namespace filament::fgviewer
|
||||
@@ -81,9 +81,7 @@ enum class ReservedSpecializationConstants : uint8_t {
|
||||
CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP = 6,
|
||||
CONFIG_DEBUG_FROXEL_VISUALIZATION = 7,
|
||||
CONFIG_STEREO_EYE_COUNT = 8, // don't change (hardcoded in ShaderCompilerService.cpp)
|
||||
CONFIG_SH_BANDS_COUNT = 9,
|
||||
CONFIG_SHADOW_SAMPLING_METHOD = 10
|
||||
// check CONFIG_MAX_RESERVED_SPEC_CONSTANTS below
|
||||
CONFIG_SH_BANDS_COUNT = 9
|
||||
};
|
||||
|
||||
enum class PushConstantIds : uint8_t {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user