Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84cecd334b | ||
|
|
bb6ebd3aea |
@@ -8,7 +8,7 @@ runs:
|
||||
uses: actions/cache@v3
|
||||
id: cache-vulkan-sdk
|
||||
with:
|
||||
path: ~/VulkanSDK
|
||||
path: ${{ runner.homedir }}/VulkanSDK
|
||||
key: vulkansdk-${{ env.GITHUB_VULKANSDK_VERSION }}-2-${{ runner.os }}
|
||||
- name: Download Vulkan SDK
|
||||
if: steps.cache-vulkan-sdk.outputs.cache-hit != 'true'
|
||||
@@ -21,9 +21,6 @@ runs:
|
||||
run: |
|
||||
source ${{ github.workspace }}/build/common/get-vulkan-sdk.sh
|
||||
unpack_vulkan_installer
|
||||
shell: bash
|
||||
- name: Run Vulkan SDK setup
|
||||
run: |
|
||||
pushd .
|
||||
cd ~/VulkanSDK/${GITHUB_VULKANSDK_VERSION}
|
||||
sudo ./install_vulkan.py
|
||||
|
||||
@@ -14,7 +14,7 @@ runs:
|
||||
id: brew-cache
|
||||
uses: actions/cache@v4 # Use a specific version
|
||||
with:
|
||||
path: ~/Library/Caches/Homebrew
|
||||
path: $HOME/Library/Caches/Homebrew
|
||||
key: ${{ runner.os }}-brew-20250424
|
||||
- name: Install Mac Prerequisites
|
||||
shell: bash
|
||||
|
||||
+1
-10
@@ -532,15 +532,6 @@ if (FILAMENT_SUPPORTS_OPENGL)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_OPENGL)
|
||||
endif()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||
option(FILAMENT_ENABLE_PERFETTO "Enable perfetto SDK on Android" OFF)
|
||||
else()
|
||||
option(FILAMENT_ENABLE_PERFETTO "Enable perfetto SDK on Android" ON)
|
||||
endif()
|
||||
if (FILAMENT_ENABLE_PERFETTO)
|
||||
add_definitions(-DFILAMENT_ENABLE_PERFETTO)
|
||||
endif()
|
||||
|
||||
# By default, build with Vulkan support on desktop platforms, although clients must request to use
|
||||
# it at run time.
|
||||
if (WIN32 OR WEBGL OR IOS)
|
||||
@@ -642,7 +633,7 @@ endif()
|
||||
# With WebGPU, Tint does not support ClipDistance which is used in Stereo. Mentioned in comment
|
||||
# https://github.com/google/dawn/blob/855d17b08abdf02f9142bf5a8f14d0ea088810a4/src/tint/lang/spirv/reader/ast_parser/function.cc#L4434
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=stereo)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=skinning,stereo)
|
||||
endif()
|
||||
|
||||
# Disable ESSL 1.0 code generation.
|
||||
|
||||
@@ -7,3 +7,6 @@ We are chaning the way Vulkan buffers are handled. We need to switch over to a m
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- Rename `sampler` parameter `unfilterable` to `filterable` [⚠️ **New Material Version**]
|
||||
- materials: new mutable specialization constants feature. See the [materials documentation](https://google.github.io/filament/Materials.html) for details. [⚠️ **New Material Version**]
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.65.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.64.0'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.65.0'
|
||||
pod 'Filament', '~> 1.64.0'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,18 +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.65.1
|
||||
|
||||
- `setFrameScheduledCallback` now works on all backends (frame presentation scheduling is still only
|
||||
available on Metal). Non-Metal backends can use the callback to be notified when Filament has
|
||||
finished processing a frame on the CPU.
|
||||
- materials: added `getEyeFromViewMatrix()` for vertex shader [⚠️ **Recompile Materials**]
|
||||
- matc: make `--workarounds=none` the default [**Recompile Materials to take effect**]
|
||||
|
||||
## v1.65.0
|
||||
|
||||
lighting: the intermediate froxel record buffer is now dynamically sized [⚠️ **New Material Version**]
|
||||
|
||||
## v1.64.1
|
||||
|
||||
- Update CMake minimum version to 3.22.1
|
||||
|
||||
@@ -178,8 +178,6 @@ nexusPublishing {
|
||||
repositories {
|
||||
sonatype {
|
||||
stagingProfileId = '9a75a224a4f17b'
|
||||
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
|
||||
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ abstract class MaterialCompiler extends TaskWithBinary {
|
||||
.gradleProperty("com.google.android.filament.include-webgpu")
|
||||
.forUseAtConfigurationTime().present
|
||||
if (include_webgpu) {
|
||||
matcArgs += ['-a', 'webgpu', '--variant-filter=stereo']
|
||||
matcArgs += ['-a', 'webgpu', '--variant-filter=skinning,stereo']
|
||||
}
|
||||
|
||||
def mat_no_opt = providers
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(filamat-android)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
@@ -7,8 +7,6 @@ option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
|
||||
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
|
||||
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
add_library(filament STATIC IMPORTED)
|
||||
@@ -132,14 +130,6 @@ add_library(filament-jni SHARED
|
||||
../common/NioUtils.cpp
|
||||
)
|
||||
|
||||
target_include_directories(filament-jni PRIVATE
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
../../filament/backend/include
|
||||
../../third_party/robin-map
|
||||
../../third_party/perfetto
|
||||
../../libs/utils/include)
|
||||
|
||||
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
|
||||
target_link_libraries(filament-jni
|
||||
PRIVATE filament-generatePrefilterMipmap
|
||||
@@ -154,21 +144,29 @@ target_link_libraries(filament-jni
|
||||
PRIVATE android
|
||||
PRIVATE jnigraphics
|
||||
PRIVATE utils
|
||||
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
|
||||
PRIVATE abseil # needed only when FILAMENT_USE_ABSEIL_LOGGING is defined
|
||||
PRIVATE perfetto
|
||||
PRIVATE abseil
|
||||
PRIVATE zstd
|
||||
|
||||
# libgeometry is PUBLIC because gltfio uses it.
|
||||
PUBLIC geometry
|
||||
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_FGVIEWER},ON>:fgviewer>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:smol-v>
|
||||
PRIVATE $<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:webgpu_dawn>
|
||||
$<$<STREQUAL:${FILAMENT_ENABLE_FGVIEWER},ON>:fgviewer>
|
||||
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
|
||||
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:filamat>
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:webgpu_dawn>
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:smol-v>
|
||||
)
|
||||
|
||||
target_include_directories(filament-jni PRIVATE
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
../../filament/backend/include
|
||||
../../third_party/robin-map
|
||||
../../third_party/perfetto
|
||||
../../libs/utils/include)
|
||||
|
||||
# Force a relink when the version script is changed:
|
||||
set_target_properties(filament-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
||||
|
||||
@@ -60,6 +60,14 @@ static void setParameter(JNIEnv* env, jlong nativeMaterialInstance, jstring name
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void setConstant(JNIEnv* env, jlong nativeMaterialInstance, jstring name_, T v) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
instance->setConstant(name, v);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterBool(JNIEnv *env, jclass,
|
||||
@@ -264,6 +272,13 @@ Java_com_google_android_filament_MaterialInstance_nSetParameterTexture(
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetConstantBool(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jboolean x) {
|
||||
setConstant(env, nativeMaterialInstance, name_, bool(x));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetScissor(
|
||||
|
||||
@@ -450,13 +450,6 @@ Java_com_google_android_filament_RenderableManager_nGetPrimitiveCount(JNIEnv*, j
|
||||
return (jint) rm->getPrimitiveCount((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetInstanceCount(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jint) rm->getInstanceCount((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex, jlong nativeMaterialInstance) {
|
||||
|
||||
@@ -40,13 +40,6 @@ Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported(
|
||||
return (jboolean)SwapChain::isSRGBSwapChainSupported(*engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_SwapChain_nIsMSAASwapChainSupported(
|
||||
JNIEnv *, jclass, jlong nativeEngine, jint samples) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jboolean)SwapChain::isMSAASwapChainSupported(*engine, samples);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_SwapChain_nIsProtectedContentSupported(
|
||||
JNIEnv *, jclass, jlong nativeEngine) {
|
||||
|
||||
+13
@@ -402,6 +402,16 @@ public class MaterialInstance {
|
||||
nSetParameterFloat4(getNativeObject(), name, color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a bool constant.
|
||||
*
|
||||
* @param name the name of the material constant
|
||||
* @param x the value of the material constant
|
||||
*/
|
||||
public void setConstant(@NonNull String name, boolean x) {
|
||||
nSetConstantBool(getNativeObject(), name, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set-up a custom scissor rectangle; by default it is disabled.
|
||||
*
|
||||
@@ -921,6 +931,9 @@ public class MaterialInstance {
|
||||
@NonNull String name, int element, @NonNull @Size(min = 1) float[] v,
|
||||
@IntRange(from = 0) int offset, @IntRange(from = 1) int count);
|
||||
|
||||
private static native void nSetConstantBool(long nativeMaterialInstance,
|
||||
@NonNull String name, boolean x);
|
||||
|
||||
private static native void nSetParameterTexture(long nativeMaterialInstance,
|
||||
@NonNull String name, long nativeTexture, long sampler);
|
||||
|
||||
|
||||
-9
@@ -851,14 +851,6 @@ public class RenderableManager {
|
||||
return nGetPrimitiveCount(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the immutable number of instances in the given renderable.
|
||||
*/
|
||||
@IntRange(from = 0)
|
||||
public int getInstanceCount(@EntityInstance int i) {
|
||||
return nGetInstanceCount(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the material instance binding for the given primitive.
|
||||
*
|
||||
@@ -1026,7 +1018,6 @@ public class RenderableManager {
|
||||
private static native boolean nIsShadowReceiver(long nativeRenderableManager, int i);
|
||||
private static native void nGetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float[] center, float[] halfExtent);
|
||||
private static native int nGetPrimitiveCount(long nativeRenderableManager, int i);
|
||||
private static native int nGetInstanceCount(long nativeRenderableManager, int i);
|
||||
private static native void nSetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex, long nativeMaterialInstance);
|
||||
private static native void nClearMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native long nGetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
|
||||
@@ -97,19 +97,6 @@ public class SwapChain {
|
||||
return nIsSRGBSwapChainSupported(engine.getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether createSwapChain supports the CONFIG_MSAA_*_SAMPLES flag.
|
||||
* The default implementation returns false.
|
||||
*
|
||||
* @param engine A reference to the filament Engine
|
||||
* @param samples The number of samples
|
||||
* @return true if CONFIG_MSAA_*_SAMPLES is supported, false otherwise.
|
||||
* @see SwapChainFlags#CONFIG_MSAA_*_SAMPLES
|
||||
*/
|
||||
public static boolean isMSAASwapChainSupported(@NonNull Engine engine, int samples) {
|
||||
return nIsMSAASwapChainSupported(engine.getNativeObject(), samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the native <code>Object</code> this <code>SwapChain</code> was created from or null
|
||||
* for a headless SwapChain.
|
||||
@@ -152,6 +139,5 @@ public class SwapChain {
|
||||
|
||||
private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback);
|
||||
private static native boolean nIsSRGBSwapChainSupported(long nativeEngine);
|
||||
private static native boolean nIsMSAASwapChainSupported(long nativeEngine, int samples);
|
||||
private static native boolean nIsProtectedContentSupported(long nativeEngine);
|
||||
}
|
||||
|
||||
+2
-11
@@ -92,15 +92,6 @@ public final class SwapChainFlags {
|
||||
* The SwapChain contains protected content. Only supported when isProtectedContentSupported()
|
||||
* is true.
|
||||
*/
|
||||
public static final long CONFIG_PROTECTED_CONTENT = 0x40;
|
||||
|
||||
/**
|
||||
* Indicates that the SwapChain is configured to use Multi-Sample Anti-Aliasing (MSAA) with the
|
||||
* given sample points within each pixel. Only supported when isMSAASwapChainSupported(4) is
|
||||
* true.
|
||||
*
|
||||
* This is only supported by EGL(Android). Other GL platforms (GLX, WGL, etc) don't support it
|
||||
* because the swapchain MSAA settings must be configured before window creation.
|
||||
*/
|
||||
public static final long CONFIG_MSAA_4_SAMPLES = 0x80;
|
||||
public static final long CONFIG_PROTECTED_CONTENT = 0x40;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ public class View {
|
||||
*
|
||||
* <p>
|
||||
* The View does not take ownership of the Scene pointer. Before destroying a Camera, be sure
|
||||
* to remove it from all associated Views. If the camera isn't set, Renderer::render() will result in a no-op.
|
||||
* to remove it from all assoicated Views.
|
||||
* </p>
|
||||
*
|
||||
* @see #getCamera
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(filament-utils-android)
|
||||
|
||||
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
|
||||
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)
|
||||
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
set(IMAGEIO_DIR ../../libs/imageio)
|
||||
|
||||
@@ -38,16 +30,7 @@ add_library(iblprefilter STATIC IMPORTED)
|
||||
set_target_properties(iblprefilter PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament-iblprefilter.a)
|
||||
|
||||
add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
|
||||
add_library(perfetto STATIC IMPORTED)
|
||||
set_target_properties(perfetto PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libperfetto.a)
|
||||
|
||||
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
||||
|
||||
add_library(filament-utils-jni SHARED
|
||||
@@ -70,25 +53,22 @@ add_library(filament-utils-jni SHARED
|
||||
target_compile_definitions(filament-utils-jni PUBLIC IMAGEIO_LITE=1)
|
||||
|
||||
target_include_directories(filament-utils-jni PRIVATE
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
..
|
||||
../../filament/backend/include
|
||||
${IMAGEIO_DIR}/include
|
||||
../../libs/utils/include)
|
||||
|
||||
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
||||
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.symbols)
|
||||
|
||||
# The ordering in the following list is important because CMake does not have dependency information.
|
||||
target_link_libraries(filament-utils-jni
|
||||
PRIVATE gltfio-jni
|
||||
PRIVATE civetweb
|
||||
PRIVATE camutils
|
||||
PRIVATE iblprefilter
|
||||
PRIVATE image
|
||||
PRIVATE filament-jni
|
||||
PRIVATE ktxreader
|
||||
PRIVATE viewer
|
||||
PRIVATE log
|
||||
PRIVATE utils
|
||||
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
|
||||
gltfio-jni
|
||||
civetweb
|
||||
camutils
|
||||
iblprefilter
|
||||
image
|
||||
ktxreader
|
||||
viewer
|
||||
)
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(gltfio-android)
|
||||
|
||||
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
|
||||
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)
|
||||
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
set(GLTFIO_DIR ../../libs/gltfio)
|
||||
set(DRACO_DIR ../../third_party/draco)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../filament-android ${CMAKE_CURRENT_BINARY_DIR}/filament-android)
|
||||
|
||||
add_library(gltfio_core STATIC IMPORTED)
|
||||
set_target_properties(gltfio_core PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
|
||||
|
||||
add_library(dracodec STATIC IMPORTED)
|
||||
set_target_properties(dracodec PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libdracodec.a)
|
||||
|
||||
add_library(meshoptimizer STATIC IMPORTED)
|
||||
set_target_properties(meshoptimizer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libmeshoptimizer.a)
|
||||
|
||||
add_library(ktxreader STATIC IMPORTED)
|
||||
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
|
||||
@@ -34,6 +27,10 @@ add_library(basis_transcoder STATIC IMPORTED)
|
||||
set_target_properties(basis_transcoder PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbasis_transcoder.a)
|
||||
|
||||
add_library(zstd STATIC IMPORTED)
|
||||
set_target_properties(zstd PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libzstd.a)
|
||||
|
||||
add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
@@ -50,11 +47,60 @@ add_library(uberarchive STATIC IMPORTED)
|
||||
set_target_properties(uberarchive PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libuberarchive.a)
|
||||
|
||||
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
||||
|
||||
set(GLTFIO_SRCS
|
||||
${GLTFIO_DIR}/include/gltfio/Animator.h
|
||||
${GLTFIO_DIR}/include/gltfio/AssetLoader.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
|
||||
${GLTFIO_DIR}/include/gltfio/MaterialProvider.h
|
||||
${GLTFIO_DIR}/include/gltfio/NodeManager.h
|
||||
${GLTFIO_DIR}/include/gltfio/TrsTransformManager.h
|
||||
${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
|
||||
${GLTFIO_DIR}/include/gltfio/TextureProvider.h
|
||||
${GLTFIO_DIR}/include/gltfio/math.h
|
||||
|
||||
${GLTFIO_DIR}/src/ArchiveCache.cpp
|
||||
${GLTFIO_DIR}/src/ArchiveCache.h
|
||||
${GLTFIO_DIR}/src/Animator.cpp
|
||||
${GLTFIO_DIR}/src/AssetLoader.cpp
|
||||
${GLTFIO_DIR}/src/DependencyGraph.cpp
|
||||
${GLTFIO_DIR}/src/DependencyGraph.h
|
||||
${GLTFIO_DIR}/src/DracoCache.cpp
|
||||
${GLTFIO_DIR}/src/DracoCache.h
|
||||
${GLTFIO_DIR}/src/FFilamentAsset.h
|
||||
${GLTFIO_DIR}/src/FFilamentInstance.h
|
||||
${GLTFIO_DIR}/src/FilamentAsset.cpp
|
||||
${GLTFIO_DIR}/src/FilamentInstance.cpp
|
||||
${GLTFIO_DIR}/src/FNodeManager.h
|
||||
${GLTFIO_DIR}/src/FTrsTransformManager.h
|
||||
${GLTFIO_DIR}/src/GltfEnums.h
|
||||
${GLTFIO_DIR}/src/Ktx2Provider.cpp
|
||||
${GLTFIO_DIR}/src/MaterialProvider.cpp
|
||||
${GLTFIO_DIR}/src/NodeManager.cpp
|
||||
${GLTFIO_DIR}/src/TrsTransformManager.cpp
|
||||
${GLTFIO_DIR}/src/ResourceLoader.cpp
|
||||
${GLTFIO_DIR}/src/StbProvider.cpp
|
||||
${GLTFIO_DIR}/src/TangentsJob.cpp
|
||||
${GLTFIO_DIR}/src/TangentsJob.h
|
||||
${GLTFIO_DIR}/src/UbershaderProvider.cpp
|
||||
${GLTFIO_DIR}/src/Utility.cpp
|
||||
${GLTFIO_DIR}/src/Utility.h
|
||||
${GLTFIO_DIR}/src/Wireframe.cpp
|
||||
${GLTFIO_DIR}/src/Wireframe.h
|
||||
${GLTFIO_DIR}/src/downcast.h
|
||||
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.cpp
|
||||
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.h
|
||||
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.cpp
|
||||
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.h
|
||||
${GLTFIO_DIR}/src/extended/TangentsJobExtended.cpp
|
||||
${GLTFIO_DIR}/src/extended/TangentsJobExtended.h
|
||||
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.cpp
|
||||
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.h
|
||||
|
||||
|
||||
src/main/cpp/Animator.cpp
|
||||
src/main/cpp/AssetLoader.cpp
|
||||
src/main/cpp/FilamentAsset.cpp
|
||||
@@ -72,38 +118,24 @@ set(GLTFIO_SRCS
|
||||
set(GLTFIO_INCLUDE_DIRS
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
${FILAMENT_DIR}/backend/include
|
||||
../../filament/backend/include
|
||||
../../libs/gltfio/include
|
||||
../../third_party/zstd/lib
|
||||
../../third_party/cgltf
|
||||
../../third_party/meshoptimizer/src
|
||||
../../third_party/robin-map
|
||||
../../third_party/stb
|
||||
../../third_party/perfetto
|
||||
../../libs/utils/include
|
||||
../../libs/ktxreader/include
|
||||
)
|
||||
|
||||
add_library(gltfio-jni SHARED ${GLTFIO_SRCS})
|
||||
|
||||
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
|
||||
|
||||
target_include_directories(gltfio-jni PRIVATE ${GLTFIO_INCLUDE_DIRS})
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols)
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map)
|
||||
target_link_libraries(gltfio-jni filament-jni utils perfetto uberzlib log stb ktxreader basis_transcoder zstd uberarchive)
|
||||
target_link_libraries(gltfio-jni dracodec meshoptimizer)
|
||||
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
|
||||
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/src)
|
||||
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/tnt)
|
||||
|
||||
# Force a relink when the version script is changed:
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols;${VERSION_SCRIPT}")
|
||||
|
||||
# The ordering in the following list is important because CMake does not have dependency information.
|
||||
target_link_libraries(gltfio-jni
|
||||
PRIVATE gltfio_core
|
||||
PRIVATE ktxreader
|
||||
PUBLIC filament-jni
|
||||
PRIVATE stb
|
||||
PRIVATE basis_transcoder
|
||||
PRIVATE uberarchive
|
||||
PRIVATE dracodec
|
||||
PRIVATE utils
|
||||
PRIVATE uberzlib
|
||||
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
|
||||
PRIVATE log # needed only when perfetto above is used
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.65.0
|
||||
VERSION_NAME=1.64.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -75,8 +75,6 @@ function print_help {
|
||||
echo " -S type"
|
||||
echo " Enable stereoscopic rendering where type is one of [instanced|multiview]. This is only"
|
||||
echo " meant for building the samples."
|
||||
echo " -P"
|
||||
echo " Enable perfetto traces on Android. Disabled by default on the Release build, enabled otherwise."
|
||||
echo ""
|
||||
echo "Build types:"
|
||||
echo " release"
|
||||
@@ -206,7 +204,6 @@ MATOPT_GRADLE_OPTION=""
|
||||
|
||||
ASAN_UBSAN_OPTION=""
|
||||
COVERAGE_OPTION=""
|
||||
ENABLE_PERFETTO=""
|
||||
|
||||
BACKEND_DEBUG_FLAG_OPTION=""
|
||||
|
||||
@@ -416,7 +413,6 @@ function build_android_target {
|
||||
${WEBGPU_OPTION} \
|
||||
${BACKEND_DEBUG_FLAG_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
${ENABLE_PERFETTO} \
|
||||
../..
|
||||
ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \
|
||||
../../compile_commands.json
|
||||
@@ -810,7 +806,7 @@ function check_debug_release_build {
|
||||
|
||||
pushd "$(dirname "$0")" > /dev/null
|
||||
|
||||
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
|
||||
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
@@ -958,9 +954,6 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:P" opt; do
|
||||
V) COVERAGE_OPTION="-DFILAMENT_ENABLE_COVERAGE=ON"
|
||||
echo "Enabled coverage"
|
||||
;;
|
||||
P) ENABLE_PERFETTO="-DFILAMENT_ENABLE_PERFETTO=ON"
|
||||
echo "Enabled perfetto"
|
||||
;;
|
||||
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
|
||||
;;
|
||||
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2025 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""
|
||||
This script automates the process of closing a Sonatype OSSRH staging repository.
|
||||
|
||||
To run the script:
|
||||
python3 ./close-sonatype-staging-repository.py
|
||||
|
||||
To run the embedded unit tests:
|
||||
python3 ./close-sonatype-staging-repository.py test
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import base64
|
||||
import json
|
||||
import pathlib
|
||||
import unittest
|
||||
import io
|
||||
from unittest import mock
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
PROPERTIES_PATH = pathlib.Path.home() / ".gradle" / "gradle.properties"
|
||||
API_BASE_URL = "https://ossrh-staging-api.central.sonatype.com/manual"
|
||||
|
||||
def get_gradle_credentials(file_path: pathlib.Path) -> (str, str):
|
||||
"""
|
||||
Reads sonatypeUsername and sonatypePassword from the properties file.
|
||||
"""
|
||||
if not file_path.exists():
|
||||
print(f"Error: Properties file not found at {file_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
username = None
|
||||
password = None
|
||||
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
|
||||
# Ignore blank lines and comments
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
|
||||
if line.startswith("sonatypeUsername="):
|
||||
username = line.split("=", 1)[1].strip()
|
||||
elif line.startswith("sonatypePassword="):
|
||||
password = line.split("=", 1)[1].strip()
|
||||
|
||||
if not username or not password:
|
||||
print(f"Error: 'sonatypeUsername' or 'sonatypePassword' not found in {file_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
return username, password
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error reading properties file: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def generate_auth_token(username: str, password: str) -> str:
|
||||
"""
|
||||
Generates a Base64 encoded auth token from username and password.
|
||||
"""
|
||||
auth_string = f"{username}:{password}"
|
||||
auth_bytes = auth_string.encode('utf-8')
|
||||
token_bytes = base64.b64encode(auth_bytes)
|
||||
return token_bytes.decode('utf-8')
|
||||
|
||||
|
||||
def find_staging_repository(token: str) -> str:
|
||||
"""
|
||||
Finds the 'open' staging repository key from the Sonatype API.
|
||||
"""
|
||||
print("Searching for staging repository...")
|
||||
|
||||
url = f"{API_BASE_URL}/search/repositories"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
req = urllib.request.Request(url, headers=headers, method="GET")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req) as response:
|
||||
response_body = response.read().decode('utf-8')
|
||||
data = json.loads(response_body)
|
||||
|
||||
repositories = data.get("repositories", [])
|
||||
|
||||
open_repositories = list(filter(lambda repo: repo.get("state") == "open", repositories))
|
||||
|
||||
if len(open_repositories) == 0:
|
||||
print("Error: No 'open' staging repositories found.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if len(open_repositories) > 1:
|
||||
print(f"Error: Expected 1 'open' repository, but found {len(repositories)}.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
repo_key = open_repositories[0].get("key")
|
||||
if not repo_key:
|
||||
print("Error: Repository found, but it has no 'key'.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
return repo_key
|
||||
|
||||
except urllib.error.HTTPError as e:
|
||||
# Handle HTTP errors (e.g., 401 Unauthorized, 404 Not Found, 500 Server Error)
|
||||
print(f"Error during repository search: HTTP {e.code} {e.reason}", file=sys.stderr)
|
||||
try:
|
||||
# Try to read the error response body for more context
|
||||
error_body = e.read().decode('utf-8')
|
||||
print(f"Response body: {error_body}", file=sys.stderr)
|
||||
except Exception:
|
||||
pass # Ignore if we can't read the body
|
||||
sys.exit(1)
|
||||
except urllib.error.URLError as e:
|
||||
# Handle network errors (e.g., connection refused)
|
||||
print(f"Error during repository search: {e.reason}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except json.JSONDecodeError:
|
||||
print("Error: Failed to decode JSON response from server.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def close_staging_repository(token: str, repo_key: str):
|
||||
"""
|
||||
Closes (promotes) the staging repository with the given key.
|
||||
"""
|
||||
print(f"Attempting to close staging repository: {repo_key}")
|
||||
|
||||
url = f"{API_BASE_URL}/upload/repository/{repo_key}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
req = urllib.request.Request(url, headers=headers, method="POST")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req) as response:
|
||||
print(f"Successfully submitted request. Server responded with: {response.status} {response.reason}")
|
||||
print("It may take a few moments to process.")
|
||||
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f"Error closing repository: HTTP {e.code} {e.reason}", file=sys.stderr)
|
||||
try:
|
||||
error_body = e.read().decode('utf-8')
|
||||
print(f"Response body: {error_body}", file=sys.stderr)
|
||||
except Exception:
|
||||
pass
|
||||
sys.exit(1)
|
||||
except urllib.error.URLError as e:
|
||||
print(f"Error closing repository: {e.reason}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
username, password = get_gradle_credentials(PROPERTIES_PATH)
|
||||
token = generate_auth_token(username, password)
|
||||
print("Successfully generated auth token.")
|
||||
|
||||
repo_key = find_staging_repository(token)
|
||||
print(f"Found staging repository: {repo_key}")
|
||||
|
||||
close_staging_repository(token, repo_key)
|
||||
|
||||
print("\nScript completed successfully.")
|
||||
|
||||
|
||||
# --- Unit Tests ---
|
||||
|
||||
class TestSonatypeScript(unittest.TestCase):
|
||||
|
||||
@mock.patch('pathlib.Path.exists', return_value=True)
|
||||
@mock.patch('builtins.open', new_callable=mock.mock_open,
|
||||
read_data="# This is a comment\nsonatypeUsername=testuser\n\nsonatypePassword=testpass\nother=data")
|
||||
def test_get_gradle_credentials_success(self, mock_file, mock_exists):
|
||||
"""Tests successful credential parsing, ignoring comments."""
|
||||
user, pw = get_gradle_credentials(pathlib.Path("/fake/path"))
|
||||
self.assertEqual(user, "testuser")
|
||||
self.assertEqual(pw, "testpass")
|
||||
|
||||
@mock.patch('pathlib.Path.exists', return_value=False)
|
||||
def test_get_gradle_credentials_no_file(self, mock_exists):
|
||||
"""Tests error exit when file is missing."""
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
get_gradle_credentials(pathlib.Path("/fake/path"))
|
||||
|
||||
@mock.patch('pathlib.Path.exists', return_value=True)
|
||||
@mock.patch('builtins.open', new_callable=mock.mock_open, read_data="# Only comments\nsonatypeUsername=testuser")
|
||||
def test_get_gradle_credentials_missing_key(self, mock_file, mock_exists):
|
||||
"""Tests error exit when a key is missing."""
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
get_gradle_credentials(pathlib.Path("/fake/path"))
|
||||
|
||||
def test_generate_auth_token(self):
|
||||
"""Tests the Base64 token encoding."""
|
||||
token = generate_auth_token("foobar", "abc123")
|
||||
# echo -n "foobar:abc123" | base64
|
||||
self.assertEqual(token, "Zm9vYmFyOmFiYzEyMw==")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_success(self, mock_urlopen):
|
||||
"""Tests finding exactly one open repository."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 200
|
||||
mock_response.reason = "OK"
|
||||
mock_response.read.return_value = json.dumps({
|
||||
"repositories": [{"key": "test-repo-key-123", "state": "open"}]
|
||||
}).encode('utf-8')
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
key = find_staging_repository("fake-token")
|
||||
self.assertEqual(key, "test-repo-key-123")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_success(self, mock_urlopen):
|
||||
"""Tests finding exactly one open repository."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 200
|
||||
mock_response.reason = "OK"
|
||||
mock_response.read.return_value = json.dumps({
|
||||
"repositories": [{"key": "test-repo-key-123", "state": "open"}, {"key": "test-repo-key-456", "state": "closed"}]
|
||||
}).encode('utf-8')
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
key = find_staging_repository("fake-token")
|
||||
self.assertEqual(key, "test-repo-key-123")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_success(self, mock_urlopen):
|
||||
"""Tests error exit when only a closed repository is found."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 200
|
||||
mock_response.reason = "OK"
|
||||
mock_response.read.return_value = json.dumps({
|
||||
"repositories": [{"key": "test-repo-key-123", "state": "closed"}]
|
||||
}).encode('utf-8')
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
key = find_staging_repository("fake-token")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_not_found(self, mock_urlopen):
|
||||
"""Tests error exit when zero repositories are found."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 200
|
||||
mock_response.read.return_value = json.dumps({"repositories": []}).encode('utf-8')
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
find_staging_repository("fake-token")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_too_many(self, mock_urlopen):
|
||||
"""Tests error exit when multiple open repositories are found."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 200
|
||||
mock_response.read.return_value = json.dumps({
|
||||
"repositories": [{"key": "key1", "state": "open"}, {"key": "key2", "state": "open"}]
|
||||
}).encode('utf-8')
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
find_staging_repository("fake-token")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_find_repository_http_error(self, mock_urlopen):
|
||||
"""Tests error exit on a network HTTP error."""
|
||||
# Mock an HTTPError
|
||||
mock_urlopen.side_effect = urllib.error.HTTPError(
|
||||
url='http://fake.com',
|
||||
code=401,
|
||||
msg="Unauthorized",
|
||||
hdrs={},
|
||||
fp=io.BytesIO(b'{"error":"bad token"}')
|
||||
)
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
find_staging_repository("fake-token")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_close_repository_success(self, mock_urlopen):
|
||||
"""Tests successful repository close."""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status = 202 # 202 Accepted is a common response for POST
|
||||
mock_response.reason = "Accepted"
|
||||
mock_urlopen.return_value.__enter__.return_value = mock_response
|
||||
|
||||
close_staging_repository("fake-token", "test-repo-key")
|
||||
|
||||
# Check that the request object was created correctly
|
||||
called_request = mock_urlopen.call_args[0][0]
|
||||
self.assertEqual(called_request.full_url, f"{API_BASE_URL}/upload/repository/test-repo-key")
|
||||
self.assertEqual(called_request.method, "POST")
|
||||
self.assertEqual(called_request.headers["Authorization"], "Bearer fake-token")
|
||||
|
||||
@mock.patch('urllib.request.urlopen')
|
||||
def test_close_repository_http_error(self, mock_urlopen):
|
||||
"""Tests error exit on close network failure."""
|
||||
mock_urlopen.side_effect = urllib.error.HTTPError(
|
||||
url='http://fake.com',
|
||||
code=500,
|
||||
msg="Server Error",
|
||||
hdrs={},
|
||||
fp=io.BytesIO(b'{"error":"failed to close"}')
|
||||
)
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
close_staging_repository("fake-token", "test-repo-key")
|
||||
|
||||
|
||||
def run_unit_tests():
|
||||
"""
|
||||
Configures and runs the unit tests.
|
||||
"""
|
||||
print("Running unit tests...")
|
||||
# We replace sys.argv to prevent unittest.main from
|
||||
# trying to parse the 'test' argument.
|
||||
original_argv = sys.argv
|
||||
sys.argv = [original_argv[0]] # Keep only the script name
|
||||
unittest.main()
|
||||
sys.argv = original_argv # Restore original args
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check if the user wants to run tests
|
||||
if len(sys.argv) > 1 and sys.argv[1].lower() == 'test':
|
||||
run_unit_tests()
|
||||
else:
|
||||
# Run the main script logic
|
||||
main()
|
||||
+22
-25
@@ -212,7 +212,7 @@ when using textures.
|
||||
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
|
||||
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
|
||||
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
|
||||
(reflected light takes on the color of the surfaced as defined by `baseColor`).
|
||||
(reflected light takes on the color of the surfaced as defined by `baseColor`).
|
||||
|
||||
The effect of `metallic` is shown in figure [metallicProperty] (click on the image to see a
|
||||
larger version).
|
||||
@@ -248,7 +248,7 @@ The effect of `roughness` on metallic surfaces is shown in figure [roughnessCond
|
||||
When refraction through an object is enabled (using a `refractonType` of `thin` or `solid`), the
|
||||
`roughness` property will also affect the refractions, as shown in figure
|
||||
[roughnessRefractionProperty] (click on the image to see a larger version).
|
||||
|
||||
|
||||
![Figure [roughnessRefractionProperty]: Refractive sphere with `roughness` varying from 0.0
|
||||
(left) to 1.0 (right)](images/materials/refraction_roughness.png)
|
||||
|
||||
@@ -307,7 +307,7 @@ The sheen color controls the color appearance and strength of an optional sheen
|
||||
base layer described by the properties above. The sheen layer always sits below the clear coat layer
|
||||
if such a layer is present.
|
||||
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
section [Cloth model] for more information about cloth and fabric materials.
|
||||
|
||||
The effect of `sheenColor` is shown in figure [materialSheenColor]
|
||||
@@ -520,14 +520,14 @@ light to bend further away from the initial path.
|
||||
|
||||
Table [commonMatIOR] describes acceptable refractive indices for various types of materials.
|
||||
|
||||
Material | IOR
|
||||
Material | IOR
|
||||
--------------------------:|:-----------------
|
||||
Air | 1.0
|
||||
Water | 1.33
|
||||
Common liquids | 1.33 to 1.5
|
||||
Common gemstones | 1.58 to 2.33
|
||||
Plastics, glass | 1.5 to 1.58
|
||||
Other dielectric materials | 1.33 to 1.58
|
||||
Water | 1.33
|
||||
Common liquids | 1.33 to 1.5
|
||||
Common gemstones | 1.58 to 2.33
|
||||
Plastics, glass | 1.5 to 1.58
|
||||
Other dielectric materials | 1.33 to 1.58
|
||||
[Table [commonMatIOR]: Index of refraction of common materials]
|
||||
|
||||
The appearance of a refractive material will greatly depend on the `refractionType` and
|
||||
@@ -995,10 +995,10 @@ Value
|
||||
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
|
||||
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
|
||||
mobile), `low`, `medium`, `high`. The type must be one of the types described in
|
||||
table [materialParamsTypes]. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
table [materialParamsTypes]. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
|
||||
this will always be identity.
|
||||
this will always be identity.
|
||||
|
||||
Type | Description
|
||||
:----------------------|:---------------------------------
|
||||
@@ -2476,17 +2476,14 @@ type aliases:
|
||||
|
||||
### Matrices
|
||||
|
||||
Name | Type | Description
|
||||
:-----------------------------------------|:--------:|:------------------------------------
|
||||
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
|
||||
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
|
||||
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
|
||||
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
|
||||
**getEyeFromViewMatrix()** | float4x4 | Matrix that converts from view space to eye space
|
||||
**getEyeFromViewMatrix(int eyeIndex)** | float4x4 | Matrix that converts from view space to eye space for the eye referred to by eyeIndex
|
||||
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
|
||||
**getClipFromWorldMatrix(int eyeIndex)** | float4x4 | Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex
|
||||
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
|
||||
Name | Type | Description
|
||||
:-----------------------------------|:--------:|:------------------------------------
|
||||
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
|
||||
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
|
||||
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
|
||||
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
|
||||
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
|
||||
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
|
||||
|
||||
### Frame constants
|
||||
|
||||
@@ -2642,7 +2639,7 @@ standard skybox material. It produces a list of 2 parameters, named `showSun` an
|
||||
respectively a boolean and a cubemap texture.
|
||||
|
||||
```text
|
||||
$ matc --reflect parameters filament/src/materials/skybox.mat
|
||||
$ matc --reflect parameters filament/src/materials/skybox.mat
|
||||
{
|
||||
"parameters": [
|
||||
{
|
||||
@@ -2658,7 +2655,7 @@ $ matc --reflect parameters filament/src/materials/skybox.mat
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### --variant-filter
|
||||
|
||||
|
||||
Vendored
-267
@@ -1,267 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>Maven Release - Filament</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link rel="shortcut icon" href="../favicon.png">
|
||||
<link rel="stylesheet" href="../css/variables.css">
|
||||
<link rel="stylesheet" href="../css/general.css">
|
||||
<link rel="stylesheet" href="../css/chrome.css">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
||||
<link rel="stylesheet" href="../fonts/fonts.css">
|
||||
|
||||
<!-- Highlight.js Stylesheets -->
|
||||
<link rel="stylesheet" href="../highlight.css">
|
||||
<link rel="stylesheet" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
|
||||
<!-- MathJax -->
|
||||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
|
||||
<!-- Provide site root to javascript -->
|
||||
<script>
|
||||
var path_to_root = "../";
|
||||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
var theme = localStorage.getItem('mdbook-theme');
|
||||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||
|
||||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||
}
|
||||
|
||||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
|
||||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||
<script>
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
var sidebar = null;
|
||||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div style="display:flex;align-items:center;justify-content:center">
|
||||
<img class="flogo" src="../images/filament_logo_small.png"></img>
|
||||
</div>
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
||||
<div class="page">
|
||||
<div id="menu-bar-hover-placeholder"></div>
|
||||
<div id="menu-bar" class="menu-bar sticky">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
|
||||
<!--
|
||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</button>
|
||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||||
</ul>
|
||||
-->
|
||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">Filament</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="search-wrapper" class="hidden">
|
||||
<form id="searchbar-outer" class="searchbar-outer">
|
||||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||
</form>
|
||||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||
<div id="searchresults-header" class="searchresults-header"></div>
|
||||
<ul id="searchresults">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||
<script>
|
||||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h1 id="maven-release"><a class="header" href="#maven-release">Maven Release</a></h1>
|
||||
<h2 id="register-for-a-sonatype-account"><a class="header" href="#register-for-a-sonatype-account">Register for a Sonatype Account</a></h2>
|
||||
<p>First, you'll need to register for a Sonatype account at the <a href="https://central.sonatype.org/register/central-portal/">Central
|
||||
Portal</a>.</p>
|
||||
<p>To publish under the <code>com.google.android</code> namespace, you'll also need to email
|
||||
<code>central-support@sonatype.com</code> with your account information to request access.</p>
|
||||
<p>Then, generate a user token through the Sonatype website. Navigate to
|
||||
<a href="https://central.sonatype.com/account">https://central.sonatype.com/account</a> and select <strong>Generate
|
||||
User Token</strong>.</p>
|
||||
<p>Finally, add the generated token credentials to <code>~/.gradle/gradle.properties</code>. (Note: these are
|
||||
different from the credentials used to log into your Sonatype account):</p>
|
||||
<pre><code class="language-gradle"># Generated Sonatype token
|
||||
sonatypeUsername=<username>
|
||||
sonatypePassword=<password>
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="signing-key"><a class="header" href="#signing-key">Signing Key</a></h2>
|
||||
<p>All release artifacts must be signed. You'll need to create an OpenPGP key pair. See Gradle's
|
||||
documentation on <a href="https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials">Signatory
|
||||
credentials</a>
|
||||
for instructions.</p>
|
||||
<p>Update <code>~/.gradle/gradle.properties</code> with your new key's credentials:</p>
|
||||
<pre><code class="language-gradle">signing.keyId=<key id>
|
||||
signing.password=<key password>
|
||||
signing.secretKeyRingFile=<secret key ring file>
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="build-the-android-release"><a class="header" href="#build-the-android-release">Build the Android Release</a></h2>
|
||||
<p>Make sure <code>JAVA_HOME</code> is set correctly. For example:</p>
|
||||
<pre><code class="language-bash">export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
|
||||
./build.sh -C -i -p android release
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="publish-to-sonatype"><a class="header" href="#publish-to-sonatype">Publish to Sonatype</a></h2>
|
||||
<h3 id="a-note-on-the-legacy-staging-service"><a class="header" href="#a-note-on-the-legacy-staging-service">A Note on the Legacy Staging Service</a></h3>
|
||||
<p>Previously, Filament was published to Maven via OSSRH (Open Source Software Repository Hosting). In
|
||||
2025, this service was <a href="https://central.sonatype.org/pages/ossrh-eol/">sunsetted</a>. Now, we use
|
||||
Sonatype's <a href="https://central.sonatype.org/">Central Publisher Portal</a>.</p>
|
||||
<p>The new Central Publisher Portal does not officially support Gradle. However, Sonatype provides a
|
||||
staging API compatibility service, which works with Filament's Gradle setup.</p>
|
||||
<hr />
|
||||
<h3 id="1-upload-to-the-staging-api-compatibility-service"><a class="header" href="#1-upload-to-the-staging-api-compatibility-service">1. Upload to the Staging API Compatibility Service</a></h3>
|
||||
<pre><code class="language-bash">cd android
|
||||
./gradlew publishToSonatype
|
||||
</code></pre>
|
||||
<h3 id="2-move-the-repository-to-the-central-publisher-portal"><a class="header" href="#2-move-the-repository-to-the-central-publisher-portal">2. Move the Repository to the Central Publisher Portal</a></h3>
|
||||
<p>We have a script to automate this. It reads the <code>sonatypeUsername</code> and <code>sonatypePassword</code> from your
|
||||
<code>~/.gradle/gradle.properties</code> file.</p>
|
||||
<pre><code class="language-bash">python3 build/common/close-sonatype-staging-repository.py
|
||||
</code></pre>
|
||||
<h3 id="3-publish-the-release-on-sonatype"><a class="header" href="#3-publish-the-release-on-sonatype">3. Publish the Release on Sonatype</a></h3>
|
||||
<p>Navigate to <a href="https://central.sonatype.com/publishing/deployments">Maven Central Repository Deployments</a>.</p>
|
||||
<p>Here, you should see a new deployment with a <strong>Validated</strong> status and all your artifacts listed. Click
|
||||
the <strong>Publish</strong> button to publish the artifacts. It typically takes around 5 minutes after clicking
|
||||
<strong>Publish</strong> for the artifacts to go live.</p>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../build/windows_android.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../build/windows_android.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+2
-2
@@ -273,7 +273,7 @@ copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../build/maven_release.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
@@ -287,7 +287,7 @@ copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../build/maven_release.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
@@ -209,7 +209,7 @@ as possible. The current external dependencies of the runtime library include:</
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../build/maven_release.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../build/windows_android.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
@@ -223,7 +223,7 @@ as possible. The current external dependencies of the runtime library include:</
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../build/maven_release.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../build/windows_android.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
+2
-2
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.65.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.64.0'
|
||||
}
|
||||
</code></pre>
|
||||
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
|
||||
@@ -196,7 +196,7 @@ dependencies {
|
||||
</div>
|
||||
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
|
||||
<p>iOS projects can use CocoaPods to install the latest release:</p>
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.65.0'
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.64.0'
|
||||
</code></pre>
|
||||
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
|
||||
<ul>
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
<p>This tool makes it easy to analyze the composition of Android applications that use Filament.</p>
|
||||
<ul>
|
||||
<li>Filament materials are shown in the treemap if <code>resgen --json</code> was used in the build.</li>
|
||||
<li>The input path can be a <code>.so</code> or <code>.a</code> file, a folder, or a zip archive (apk or aar).</li>
|
||||
<li>The input path can be a so file, folder, or zip archive (apk or aar).</li>
|
||||
<li>If the path is a zip or folder, interactively finds the file to analyze.</li>
|
||||
<li>The generated web report is a self-contained HTML file.</li>
|
||||
<li>Reports the gzipped size of all Filament materials.</li>
|
||||
|
||||
@@ -178,9 +178,9 @@ content:counter(h1) "."counter(h2) "."counter(h3) "."counter(h4) "."counter(h5)
|
||||
counter-increment: h6;margin-right:10px}
|
||||
</style><style>.hljs{display:block;overflow-x:auto;padding:0.5em;background:#fff;color:#000;-webkit-text-size-adjust:none}.hljs-comment{color:#006a00}.hljs-keyword{color:#02E}.hljs-literal,.nginx .hljs-title{color:#aa0d91}.method,.hljs-list .hljs-title,.hljs-tag .hljs-title,.setting .hljs-value,.hljs-winutils,.tex .hljs-command,.http .hljs-title,.hljs-request,.hljs-status,.hljs-name{color:#008}.hljs-envvar,.tex .hljs-special{color:#660}.hljs-string{color:#c41a16}.hljs-tag .hljs-value,.hljs-cdata,.hljs-filter .hljs-argument,.hljs-attr_selector,.apache .hljs-cbracket,.hljs-date,.hljs-regexp{color:#080}.hljs-sub .hljs-identifier,.hljs-pi,.hljs-tag,.hljs-tag .hljs-keyword,.hljs-decorator,.ini .hljs-title,.hljs-shebang,.hljs-prompt,.hljs-hexcolor,.hljs-rule .hljs-value,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-number,.css .hljs-function,.hljs-function .hljs-title,.coffeescript .hljs-attribute{color:#A0C}.hljs-function .hljs-title{font-weight:bold;color:#000}.hljs-class .hljs-title,.smalltalk .hljs-class,.hljs-type,.hljs-typename,.hljs-tag .hljs-attribute,.hljs-doctype,.hljs-class .hljs-id,.hljs-built_in,.setting,.hljs-params,.clojure .hljs-attribute{color:#5c2699}.hljs-variable{color:#3f6e74}.css .hljs-tag,.hljs-rule .hljs-property,.hljs-pseudo,.hljs-subst{color:#000}.css .hljs-class,.css .hljs-id{color:#9b703f}.hljs-value .hljs-important{color:#ff7700;font-weight:bold}.hljs-rule .hljs-keyword{color:#c5af75}.hljs-annotation,.apache .hljs-sqbracket,.nginx .hljs-built_in{color:#9b859d}.hljs-preprocessor,.hljs-preprocessor *,.hljs-pragma{color:#643820}.tex .hljs-formula{background-color:#eee;font-style:italic}.diff .hljs-header,.hljs-chunk{color:#808080;font-weight:bold}.diff .hljs-change{background-color:#bccff9}.hljs-addition{background-color:#baeeba}.hljs-deletion{background-color:#ffc8bd}.hljs-comment .hljs-doctag{font-weight:bold}.method .hljs-id{color:#000}</style><style>div.title { padding-top: 40px; } div.afterTitles { height: 15px; }</style><meta charset="utf-8"></p>
|
||||
<style>img { max-width: 100%; }</style>
|
||||
<p><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{,\mathrm{#1}}$$
|
||||
<script type="text/x-mathjax-config">MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });</script><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{\,\mathrm{#1}}$$
|
||||
</span>
|
||||
<span class="md"><p><title>Physically Based Rendering in Filament</title><div class="title"> Physically Based Rendering in Filament </div></p>
|
||||
<span class="md"><p><title>Physically Based Rendering in Filament</title><div class="title"> Physically Based Rendering in Filament </div>
|
||||
<div class="afterTitles"></div>
|
||||
</p><p>
|
||||
</p>
|
||||
@@ -2060,7 +2060,7 @@ In practice only 4 or 9 coefficients (i.e.: 2 or 3 bands) are enough for \(\cosT
|
||||
In practice we pre-convolve \(\Lt\) with \(\cosTheta\) and pre-scale these coefficients by the basis scaling factors \(K_l^m\) so that the reconstruction code is as simple as possible in the shader:
|
||||
</p><a class="target" name="listing_irradiancesh"> </a><pre class="listing tilde"><code><span class="line"></span>vec3 irradianceSH(vec3 n) {
|
||||
<span class="line"></span> // uniform vec3 sphericalHarmonics<span class="hljs-selector-attr">[9]</span>
|
||||
<span class="line"></span> // We can <span class="hljs-selector-tag">use</span> only the first <span class="hljs-number">2</span> bands for better performance
|
||||
<span class="line"></span> // We can use only the first <span class="hljs-number">2</span> bands for better performance
|
||||
<span class="line"></span> return
|
||||
<span class="line"></span> sphericalHarmonics<span class="hljs-selector-attr">[0]</span>
|
||||
<span class="line"></span> + sphericalHarmonics<span class="hljs-selector-attr">[1]</span> * (n<span class="hljs-selector-class">.y</span>)
|
||||
@@ -4395,7 +4395,7 @@ For Fast Realistic Image Display. <em class="asterisk">SIGGRAPH '00 Proceedings
|
||||
</div><div class="bib">[<a class="target" name="citation-schlick94"> </a><b>Schlick94</b>] Christophe Schlick. 1994. An Inexpensive BRDF Model for Physically-Based Rendering. <em class="asterisk">Computer Graphics Forum</em>, 13 (3), 233–246.
|
||||
</div><div class="bib">[<a class="target" name="citation-walter07"> </a><b>Walter07</b>] Bruce Walter et al. 2007. Microfacet Models for Refraction through Rough Surfaces. <em class="asterisk">Proceedings of the Eurographics Symposium on Rendering</em>.
|
||||
</div>
|
||||
</sample></float></sample></float></float></p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep 1.18 </a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">✒</div></div><script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
|
||||
</sample></float></sample></float></float></p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep 1.18 </a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">✒</div></div><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
|
||||
@@ -178,9 +178,9 @@ content:counter(h1) "."counter(h2) "."counter(h3) "."counter(h4) "."counter(h5)
|
||||
counter-increment: h6;margin-right:10px}
|
||||
</style><style>.hljs{display:block;overflow-x:auto;padding:0.5em;background:#fff;color:#000;-webkit-text-size-adjust:none}.hljs-comment{color:#006a00}.hljs-keyword{color:#02E}.hljs-literal,.nginx .hljs-title{color:#aa0d91}.method,.hljs-list .hljs-title,.hljs-tag .hljs-title,.setting .hljs-value,.hljs-winutils,.tex .hljs-command,.http .hljs-title,.hljs-request,.hljs-status,.hljs-name{color:#008}.hljs-envvar,.tex .hljs-special{color:#660}.hljs-string{color:#c41a16}.hljs-tag .hljs-value,.hljs-cdata,.hljs-filter .hljs-argument,.hljs-attr_selector,.apache .hljs-cbracket,.hljs-date,.hljs-regexp{color:#080}.hljs-sub .hljs-identifier,.hljs-pi,.hljs-tag,.hljs-tag .hljs-keyword,.hljs-decorator,.ini .hljs-title,.hljs-shebang,.hljs-prompt,.hljs-hexcolor,.hljs-rule .hljs-value,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-number,.css .hljs-function,.hljs-function .hljs-title,.coffeescript .hljs-attribute{color:#A0C}.hljs-function .hljs-title{font-weight:bold;color:#000}.hljs-class .hljs-title,.smalltalk .hljs-class,.hljs-type,.hljs-typename,.hljs-tag .hljs-attribute,.hljs-doctype,.hljs-class .hljs-id,.hljs-built_in,.setting,.hljs-params,.clojure .hljs-attribute{color:#5c2699}.hljs-variable{color:#3f6e74}.css .hljs-tag,.hljs-rule .hljs-property,.hljs-pseudo,.hljs-subst{color:#000}.css .hljs-class,.css .hljs-id{color:#9b703f}.hljs-value .hljs-important{color:#ff7700;font-weight:bold}.hljs-rule .hljs-keyword{color:#c5af75}.hljs-annotation,.apache .hljs-sqbracket,.nginx .hljs-built_in{color:#9b859d}.hljs-preprocessor,.hljs-preprocessor *,.hljs-pragma{color:#643820}.tex .hljs-formula{background-color:#eee;font-style:italic}.diff .hljs-header,.hljs-chunk{color:#808080;font-weight:bold}.diff .hljs-change{background-color:#bccff9}.hljs-addition{background-color:#baeeba}.hljs-deletion{background-color:#ffc8bd}.hljs-comment .hljs-doctag{font-weight:bold}.method .hljs-id{color:#000}</style><style>div.title { padding-top: 40px; } div.afterTitles { height: 15px; }</style><meta charset="utf-8"></p>
|
||||
<style>img { max-width: 100%; }</style>
|
||||
<p><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{,\mathrm{#1}}$$
|
||||
<script type="text/x-mathjax-config">MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });</script><span style="display:none">$$\newcommand{\n}{\hat{n}}\newcommand{\thetai}{\theta_\mathrm{i}}\newcommand{\thetao}{\theta_\mathrm{o}}\newcommand{\d}[1]{\mathrm{d}#1}\newcommand{\w}{\hat{\omega}}\newcommand{\wi}{\w_\mathrm{i}}\newcommand{\wo}{\w_\mathrm{o}}\newcommand{\wh}{\w_\mathrm{h}}\newcommand{\Li}{L_\mathrm{i}}\newcommand{\Lo}{L_\mathrm{o}}\newcommand{\Le}{L_\mathrm{e}}\newcommand{\Lr}{L_\mathrm{r}}\newcommand{\Lt}{L_\mathrm{t}}\newcommand{\O}{\mathrm{O}}\newcommand{\degrees}{{^{\large\circ}}}\newcommand{\T}{\mathsf{T}}\newcommand{\mathset}[1]{\mathbb{#1}}\newcommand{\Real}{\mathset{R}}\newcommand{\Integer}{\mathset{Z}}\newcommand{\Boolean}{\mathset{B}}\newcommand{\Complex}{\mathset{C}}\newcommand{\un}[1]{\,\mathrm{#1}}$$
|
||||
</span>
|
||||
<span class="md"><p><title>Filament Materials Guide</title><div class="title"> Filament Materials Guide </div></p>
|
||||
<span class="md"><p><title>Filament Materials Guide</title><div class="title"> Filament Materials Guide </div>
|
||||
<div class="afterTitles"></div>
|
||||
</p><p>
|
||||
</p>
|
||||
@@ -504,7 +504,7 @@ when using textures.</p>
|
||||
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
|
||||
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
|
||||
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
|
||||
(reflected light takes on the color of the surfaced as defined by <code>baseColor</code>).
|
||||
(reflected light takes on the color of the surfaced as defined by <code>baseColor</code>).
|
||||
</p><p>
|
||||
The effect of <code>metallic</code> is shown in <a href="#figure_metallicproperty" target="_self">figure 1</a> (click on the image to see a
|
||||
larger version).
|
||||
@@ -597,7 +597,7 @@ indices.
|
||||
base layer described by the properties above. The sheen layer always sits below the clear coat layer
|
||||
if such a layer is present.</p>
|
||||
</p><p>
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
section <a href="#toc3.3" target="_self">3.3</a> for more information about cloth and fabric materials.
|
||||
</p><p>
|
||||
The effect of <code>sheenColor</code> is shown in <a href="#figure_materialsheencolor" target="_self">figure 7</a>
|
||||
@@ -1220,10 +1220,10 @@ non-shader data.</p>
|
||||
name must be a valid GLSL identifier. Entries have an optional <code>precision</code>, which can be
|
||||
one of <code>default</code> (best precision for the platform, typically <code>high</code> on desktop, <code>medium</code> on
|
||||
mobile), <code>low</code>, <code>medium</code>, <code>high</code>. The type must be one of the types described in
|
||||
<a href="#table_materialparamstypes" target="_self">table 14</a>. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
<a href="#table_materialparamstypes" target="_self">table 14</a>. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
|
||||
this will always be identity.
|
||||
this will always be identity.
|
||||
</p></dd></dl><div class='table'>
|
||||
<a class="target" name="table_materialparamstypes"> </a><table class="table longtable"><tr><th style="text-align:left"> Type </th><th style="text-align:left"> Description </th></tr>
|
||||
<tr><td style="text-align:left"> bool </td><td style="text-align:left"> Single boolean </td></tr>
|
||||
@@ -2361,10 +2361,7 @@ type aliases:</p>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getWorldFromViewMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from view/eye space to world space </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromViewMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from view/eye space to clip (NDC) space </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getViewFromClipMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from clip (NDC) space to view/eye space </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getEyeFromViewMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from view space to eye space </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getEyeFromViewMatrix(int eyeIndex)</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from view space to eye space for the eye referred to by eyeIndex </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromWorldMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from world to clip (NDC) space </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getClipFromWorldMatrix(int eyeIndex)</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getWorldFromClipMatrix()</strong> </td><td style="text-align:center"> float4×4 </td><td style="text-align:left"> Matrix that converts from clip (NDC) space to world space </td></tr>
|
||||
</table></div>
|
||||
</p>
|
||||
@@ -2504,7 +2501,7 @@ a good compromise between runtime performance and size.</p>
|
||||
metadata in JSON format. The example below prints out the list of parameters defined in Filament's
|
||||
standard skybox material. It produces a list of 2 parameters, named <code>showSun</code> and <code>skybox</code>,
|
||||
respectively a boolean and a cubemap texture.</p>
|
||||
</p><pre class="listing backtick"><code><span class="line"></span>$ matc --reflect parameters filament/src/materials/skybox.mat
|
||||
</p><pre class="listing backtick"><code><span class="line"></span>$ matc --reflect parameters filament/src/materials/skybox.mat
|
||||
<span class="line"></span>{
|
||||
<span class="line"></span> "parameters": [
|
||||
<span class="line"></span> {
|
||||
@@ -2603,7 +2600,7 @@ Finally if <code>variantFilter</code> contains the <code>fog</code> filter, an e
|
||||
</p><p>
|
||||
Be aware that <code>external</code> samplers account for 2 regular samplers.</div>
|
||||
</p><p>
|
||||
</p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep 1.18 </a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">✒</div></div><script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
|
||||
</p></span><div id="mdContextMenu" style="visibility:hidden"></div><div class="markdeepFooter"><i>formatted by <a href="https://casual-effects.com/markdeep" style="color:#999">Markdeep 1.18 </a></i><div style="display:inline-block;font-size:13px;font-family:'Times New Roman',serif;vertical-align:middle;transform:translate(-3px,-1px)rotate(135deg);">✒</div></div><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
|
||||
@@ -250,7 +250,7 @@ execution profile data.</p>
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../notes/performance_analysis.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../notes/framegraph.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
@@ -264,7 +264,7 @@ execution profile data.</p>
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../notes/performance_analysis.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../notes/framegraph.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
@@ -331,7 +331,7 @@ nodes</li>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../notes/performance_analysis.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../notes/coverage.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
@@ -345,7 +345,7 @@ nodes</li>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../notes/performance_analysis.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../notes/coverage.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>Performance analysis - Filament</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link rel="shortcut icon" href="../favicon.png">
|
||||
<link rel="stylesheet" href="../css/variables.css">
|
||||
<link rel="stylesheet" href="../css/general.css">
|
||||
<link rel="stylesheet" href="../css/chrome.css">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
||||
<link rel="stylesheet" href="../fonts/fonts.css">
|
||||
|
||||
<!-- Highlight.js Stylesheets -->
|
||||
<link rel="stylesheet" href="../highlight.css">
|
||||
<link rel="stylesheet" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
|
||||
<!-- MathJax -->
|
||||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
|
||||
<!-- Provide site root to javascript -->
|
||||
<script>
|
||||
var path_to_root = "../";
|
||||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
var theme = localStorage.getItem('mdbook-theme');
|
||||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||
|
||||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||
}
|
||||
|
||||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
|
||||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||
<script>
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
var sidebar = null;
|
||||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div style="display:flex;align-items:center;justify-content:center">
|
||||
<img class="flogo" src="../images/filament_logo_small.png"></img>
|
||||
</div>
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
||||
<div class="page">
|
||||
<div id="menu-bar-hover-placeholder"></div>
|
||||
<div id="menu-bar" class="menu-bar sticky">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
|
||||
<!--
|
||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</button>
|
||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||||
</ul>
|
||||
-->
|
||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">Filament</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="search-wrapper" class="hidden">
|
||||
<form id="searchbar-outer" class="searchbar-outer">
|
||||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||
</form>
|
||||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||
<div id="searchresults-header" class="searchresults-header"></div>
|
||||
<ul id="searchresults">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||
<script>
|
||||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h1 id="performance-analysis"><a class="header" href="#performance-analysis">Performance Analysis</a></h1>
|
||||
<h2 id="android"><a class="header" href="#android">Android</a></h2>
|
||||
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
|
||||
<ul>
|
||||
<li>Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h4 id="profiling"><a class="header" href="#profiling">Profiling</a></h4>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Before profiling the application or analyzing the performance in a consistent way, ideally
|
||||
the <strong>GPU frequency on the target hardware should get locked</strong>. In order to do this, you need to do the following:</p>
|
||||
<ol>
|
||||
<li>Ensure your device is OEM unlocked. If your phone is carrier-locked, you may need
|
||||
to wait a period, such as 60 or 90 days after activation to be eligible for unlocking.
|
||||
Some phones don't support this at all. You will need to enable developer options
|
||||
(e.g. Settings > About Phone and tap the Build number 7 times). You need to go to
|
||||
Settings > System > Developer options and toggle on "OEM unlocking".</li>
|
||||
<li>Next, you need to unlock the phone. You will need to install Android SDK Platform
|
||||
Tools on you computer, enable "USB debugging" in your phone's Settings > System > Developer options.</li>
|
||||
<li>Connect the phone to the computer via a USB cable and run from the command line:
|
||||
<pre><code class="language-shell">adb reboot bootloader
|
||||
# once the phone is in bootloader mode, run the following to begin the unlocking
|
||||
# process:
|
||||
fastboot flashing unlock
|
||||
</code></pre>
|
||||
A warning will appear on your phone's screen. Use the volume buttons to navigate and
|
||||
the power button to select the "Unlock the bootloader" option. The phone will perform
|
||||
a factory data reset and reboot with an unlocked bootloader.</li>
|
||||
<li>You would need to flash an image to the phone with root permissions, such as a *-userdebug or *-eng
|
||||
build. One way to do this is with the <a href="https://flash.android.com/">Android Flash Tool</a>. Connect the
|
||||
tool to your device and find a build to flash ending in <code>-userdebug</code> or <code>-eng</code>. Once you have that
|
||||
selected run <code>Install build</code>.</li>
|
||||
<li>Shell into your device as root and configure the gpu frequency to be locked, e.g.:
|
||||
<pre><code class="language-shell">adb shell
|
||||
su
|
||||
# navigate to the system GPU directory. this varies on different phones. One phone might have
|
||||
# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with "mali" instead
|
||||
# of "kgsl". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali
|
||||
cd /sys/devices/platform/1f000000.mali
|
||||
# get the current available GPU governors and frequencies.
|
||||
# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but
|
||||
# the system at the time of writing this had available_governors and available_frequences
|
||||
cat available_governors
|
||||
cat available_frequencies
|
||||
# depending on the governors, you may want to set it prioritize performance over other things like
|
||||
# battery. Some systems allow you to do this with something like (although, for the device used at the
|
||||
# time of writing this did not have an equivalent option):
|
||||
echo performance > gpu_governor
|
||||
# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you
|
||||
# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:
|
||||
echo 940000 > hint_min_freq
|
||||
echo 940000 > hint_max_freq
|
||||
# you can typically verify the GPU is running at that frequency consistently by running something like
|
||||
# the following a few times over time, which should show the frequency you want to lock the device to:
|
||||
cat cur_freq
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>You may need to re-apply the <code>hint_min_freq</code> just before starting the profiling trace and check before and after
|
||||
that the frequency remained at the value expected. Some systems may adjust the frequency on you, but you
|
||||
may want to ensure the frequency remains the same through the analysis.</li>
|
||||
<li>The GPU frequency settings should be undone after restarting the device, but after you have done your app profiling,
|
||||
you can revert the state of the device, such as the OS build image, back to the way you had it
|
||||
initially, as needed.</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<p>Build a release build of Filament with the applicable backend(s) enabled
|
||||
<em>(+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from
|
||||
building a release build with no flags)</em> <em>(debug builds for this are useless)</em></p>
|
||||
<pre><code class="language-shell"># the following command assumes you are in the root filament directory
|
||||
# and ANDROID_HOME is exported (and possibly also CC and CXX on linux as needed)
|
||||
#
|
||||
# NOTE: to build with WebGPU support you need to explicitly include the -W flag
|
||||
# (it doesn't get compiled in by default), e.g.:
|
||||
# ./build.sh -W -p android,desktop -i release
|
||||
#
|
||||
# Note that you can speed this up a bit (and reduce disk space usage) by limiting the target to just
|
||||
# the ABI you plan on testing with the -q flag, e.g. -q arm64-v8a. If you do this, you
|
||||
# will need to update the android/gradle.properties file to specify the ABI(s) you are targeting
|
||||
# with the com.google.android.filament.abis property.
|
||||
# Thus, a build command that would target BOTH Vulkan AND WebGPU AND only target the ARM64 ABI would look something
|
||||
# like:
|
||||
# ./build.sh -W -q arm64-v8a -p android,desktop -i release
|
||||
./build.sh -p android,desktop -i release
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Connect your Android device to your computer via a USB cord with USB debugging enabled and configure
|
||||
the system property to default to the desired backend, e.g.
|
||||
<em>(to determine how these numbers map to the backends, see the <code>enum class Backend</code>
|
||||
definition in <a href="../../../../filament/backend/include/backend/DriverEnums.h">filament/filament/backend/include/backend/DriverEnums.h</a>)</em>:</p>
|
||||
<pre><code class="language-shell"># to set the backend to Vulkan:
|
||||
adb shell setprop debug.filament.backend 2
|
||||
# to set the backend to WebGPU:
|
||||
adb shell setprop debug.filament.backend 4
|
||||
# to view the current property:
|
||||
adb shell getprop debug.filament.backend
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Build and run a sample, e.g. sample-gltf-viewer, on your Android device
|
||||
<em>(<a href="https://developer.android.com/studio">Android Studio</a> recommended)</em>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Run <a href="https://developer.android.com/agi">AGI</a> and follow instructions to profile the app/system
|
||||
with trace capture(s). See https://developer.android.com/agi/start for more details to
|
||||
get started.</p>
|
||||
<ul>
|
||||
<li>We typically only run "Capture System Profiler trace" <em>(not necessarily "Capture Frame Profiler trace")</em></li>
|
||||
<li>When configuring the trace:
|
||||
<ul>
|
||||
<li>For both the WebGPU and Vulkan backends configure the profiler for the Vulkan API
|
||||
<em>(since WebGPU should be using Vulkan under the hood as well)</em></li>
|
||||
<li>Running for ~1 seconds should suffice</li>
|
||||
<li>Hit the "Configure" button in Trace objects, select "Switch to advanced mode" and add:
|
||||
<pre><code>data_sources {
|
||||
config {
|
||||
name: "track_event"
|
||||
track_event_config {
|
||||
disabled_categories: "*"
|
||||
enabled_categories: "filament/filament"
|
||||
enabled_categories: "filament/jobsystem"
|
||||
enabled_categories: "filament/gltfio"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>One you open the trace, zoom into a series of frames to get a sense of generally how long they typically take
|
||||
<em>(use <code>W</code>, <code>S</code>, <code>A</code> and <code>D</code> keys and mouse wheel for navigation)</em> and find a representative one.
|
||||
We are most interested in the performance of the
|
||||
<code>FEngine::loop</code> thread, how long it takes, overlap in activities/processes/commands, reduction in queue submissions,
|
||||
etc. Similarly, we can view GPU timeline as it relates to that. We want to see overlapping
|
||||
shader invocations and non-interrupted fragment shader runs.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../notes/coverage.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../notes/framegraph.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../notes/coverage.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../notes/framegraph.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -995,10 +995,10 @@ Value
|
||||
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
|
||||
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
|
||||
mobile), `low`, `medium`, `high`. The type must be one of the types described in
|
||||
table [materialParamsTypes]. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
table [materialParamsTypes]. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
|
||||
this will always be identity.
|
||||
this will always be identity.
|
||||
|
||||
Type | Description
|
||||
:----------------------|:---------------------------------
|
||||
@@ -1096,30 +1096,37 @@ Value
|
||||
`bool` or `number`, depending on the `type` of the constant. The type must be one of the types
|
||||
described in table [materialConstantsTypes].
|
||||
|
||||
Type | Description | Default
|
||||
:----------------------|:-----------------------------------------|:------------------
|
||||
int | A signed, 32 bit GLSL int | 0
|
||||
float | A single-precision GLSL float | 0.0
|
||||
bool | A GLSL bool | false
|
||||
Constants may also be specified as mutable by setting the `mutable` property to `true`. Only
|
||||
`bool` spec constants may be specified as mutable.
|
||||
|
||||
| Type | Description | Default | May be mutable? |
|
||||
|:------|:------------------------------|:--------|-----------------|
|
||||
| int | A signed, 32 bit GLSL int | | no |
|
||||
| float | A single-precision GLSL float | 0.0 | no |
|
||||
| bool | A GLSL bool | false | yes |
|
||||
[Table [materialConstantsTypes]: Material constants types]
|
||||
|
||||
Description
|
||||
: Lists the constant parameters accepted by your material. These constants can be set, or
|
||||
"specialized", at runtime when loading a material package. Multiple materials can be loaded from
|
||||
the same material package with differing constant parameter specializations. Once a material is
|
||||
loaded from a material package, its constant parameters cannot be changed. Compared to regular
|
||||
parameters, constant parameters allow the compiler to generate more efficient code. Access
|
||||
constant parameters from the shader by prefixing the name with `materialConstant_`. For example,
|
||||
a constant parameter named `myConstant` is accessed in the shader as
|
||||
`materialConstant_myConstant`. If a constant parameter is not set at runtime, the default is
|
||||
used.
|
||||
the same material package with differing constant parameter specializations. If a constant
|
||||
parameter is specialized as mutable, it may be changed at any time on a per-instance basis via
|
||||
`MaterialInstance::setConstant(name, value)`. Otherwise, once a material is loaded from a
|
||||
material package, its constant parameters cannot be changed.
|
||||
|
||||
Compared to regular parameters, constant parameters allow the compiler to generate more
|
||||
efficient code. Access constant parameters from the shader by prefixing the name with
|
||||
`materialConstant_`. For example, a constant parameter named `myConstant` is accessed in the
|
||||
shader as `materialConstant_myConstant`. If a constant parameter is not set at runtime, the
|
||||
default is used.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
constants : [
|
||||
{
|
||||
name : overrideAlpha,
|
||||
type : bool
|
||||
type : bool,
|
||||
mutable : true,
|
||||
},
|
||||
{
|
||||
name : customAlpha,
|
||||
@@ -2476,17 +2483,14 @@ type aliases:
|
||||
|
||||
### Matrices
|
||||
|
||||
Name | Type | Description
|
||||
:-----------------------------------------|:--------:|:------------------------------------
|
||||
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
|
||||
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
|
||||
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
|
||||
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
|
||||
**getEyeFromViewMatrix()** | float4x4 | Matrix that converts from view space to eye space
|
||||
**getEyeFromViewMatrix(int eyeIndex)** | float4x4 | Matrix that converts from view space to eye space for the eye referred to by eyeIndex
|
||||
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
|
||||
**getClipFromWorldMatrix(int eyeIndex)** | float4x4 | Matrix that converts from world to clip (NDC) space for the eye referred to by eyeIndex
|
||||
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
|
||||
Name | Type | Description
|
||||
:-----------------------------------|:--------:|:------------------------------------
|
||||
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
|
||||
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
|
||||
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
|
||||
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
|
||||
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
|
||||
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
|
||||
|
||||
### Frame constants
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
- [Introduction](./dup/intro.md)
|
||||
- [Build](./dup/building.md)
|
||||
- [Build for Android on Windows](./build/windows_android.md)
|
||||
- [Maven Release](./build/maven_release.md)
|
||||
- [Contribute](./dup/contributing.md)
|
||||
- [Coding Style](./dup/code_style.md)
|
||||
- [Core Concepts](./main/README.md)
|
||||
@@ -25,7 +24,6 @@
|
||||
- [Running with ASAN and UBSAN](./notes/asan_ubsan.md)
|
||||
- [Using Instruments on macOS](./notes/instruments.md)
|
||||
- [Code coverage analysis](./notes/coverage.md)
|
||||
- [Performance analysis](./notes/performance_analysis.md)
|
||||
- [Framegraph](./notes/framegraph.md)
|
||||
- [Libraries](./notes/libs.md)
|
||||
- [bluegl](./dup/bluegl.md)
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# Maven Release
|
||||
|
||||
## Register for a Sonatype Account
|
||||
|
||||
First, you'll need to register for a Sonatype account at the [Central
|
||||
Portal](https://central.sonatype.org/register/central-portal/).
|
||||
|
||||
To publish under the `com.google.android` namespace, you'll also need to email
|
||||
`central-support@sonatype.com` with your account information to request access.
|
||||
|
||||
Then, generate a user token through the Sonatype website. Navigate to
|
||||
[https://central.sonatype.com/account](https://central.sonatype.com/account) and select **Generate
|
||||
User Token**.
|
||||
|
||||
Finally, add the generated token credentials to `~/.gradle/gradle.properties`. (Note: these are
|
||||
different from the credentials used to log into your Sonatype account):
|
||||
|
||||
```gradle
|
||||
# Generated Sonatype token
|
||||
sonatypeUsername=<username>
|
||||
sonatypePassword=<password>
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
## Signing Key
|
||||
|
||||
All release artifacts must be signed. You'll need to create an OpenPGP key pair. See Gradle's
|
||||
documentation on [Signatory
|
||||
credentials](https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials)
|
||||
for instructions.
|
||||
|
||||
Update `~/.gradle/gradle.properties` with your new key's credentials:
|
||||
|
||||
```gradle
|
||||
signing.keyId=<key id>
|
||||
signing.password=<key password>
|
||||
signing.secretKeyRingFile=<secret key ring file>
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
## Build the Android Release
|
||||
|
||||
Make sure `JAVA_HOME` is set correctly. For example:
|
||||
|
||||
```bash
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
|
||||
./build.sh -C -i -p android release
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
## Publish to Sonatype
|
||||
|
||||
### A Note on the Legacy Staging Service
|
||||
|
||||
Previously, Filament was published to Maven via OSSRH (Open Source Software Repository Hosting). In
|
||||
2025, this service was [sunsetted](https://central.sonatype.org/pages/ossrh-eol/). Now, we use
|
||||
Sonatype's [Central Publisher Portal](https://central.sonatype.org/).
|
||||
|
||||
The new Central Publisher Portal does not officially support Gradle. However, Sonatype provides a
|
||||
staging API compatibility service, which works with Filament's Gradle setup.
|
||||
|
||||
-----
|
||||
|
||||
### 1\. Upload to the Staging API Compatibility Service
|
||||
|
||||
```bash
|
||||
cd android
|
||||
./gradlew publishToSonatype
|
||||
```
|
||||
|
||||
### 2\. Move the Repository to the Central Publisher Portal
|
||||
|
||||
We have a script to automate this. It reads the `sonatypeUsername` and `sonatypePassword` from your
|
||||
`~/.gradle/gradle.properties` file.
|
||||
|
||||
```bash
|
||||
python3 build/common/close-sonatype-staging-repository.py
|
||||
```
|
||||
|
||||
### 3\. Publish the Release on Sonatype
|
||||
|
||||
Navigate to [Maven Central Repository Deployments](https://central.sonatype.com/publishing/deployments).
|
||||
|
||||
Here, you should see a new deployment with a **Validated** status and all your artifacts listed. Click
|
||||
the **Publish** button to publish the artifacts. It typically takes around 5 minutes after clicking
|
||||
**Publish** for the artifacts to go live.
|
||||
@@ -6,64 +6,12 @@
|
||||
|
||||
- Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi.
|
||||
|
||||
### Android with the Vulkan Backend
|
||||
|
||||
---
|
||||
|
||||
#### Profiling
|
||||
|
||||
1. Before profiling the application or analyzing the performance in a consistent way, ideally
|
||||
the **GPU frequency on the target hardware should get locked**. In order to do this, you need to do the following:
|
||||
1. Ensure your device is OEM unlocked. If your phone is carrier-locked, you may need
|
||||
to wait a period, such as 60 or 90 days after activation to be eligible for unlocking.
|
||||
Some phones don't support this at all. You will need to enable developer options
|
||||
(e.g. Settings > About Phone and tap the Build number 7 times). You need to go to
|
||||
Settings > System > Developer options and toggle on "OEM unlocking".
|
||||
1. Next, you need to unlock the phone. You will need to install Android SDK Platform
|
||||
Tools on you computer, enable "USB debugging" in your phone's Settings > System > Developer options.
|
||||
1. Connect the phone to the computer via a USB cable and run from the command line:
|
||||
```shell
|
||||
adb reboot bootloader
|
||||
# once the phone is in bootloader mode, run the following to begin the unlocking
|
||||
# process:
|
||||
fastboot flashing unlock
|
||||
```
|
||||
A warning will appear on your phone's screen. Use the volume buttons to navigate and
|
||||
the power button to select the "Unlock the bootloader" option. The phone will perform
|
||||
a factory data reset and reboot with an unlocked bootloader.
|
||||
1. You would need to flash an image to the phone with root permissions, such as a *-userdebug or *-eng
|
||||
build. One way to do this is with the [Android Flash Tool](https://flash.android.com/). Connect the
|
||||
tool to your device and find a build to flash ending in `-userdebug` or `-eng`. Once you have that
|
||||
selected run `Install build`.
|
||||
1. Shell into your device as root and configure the gpu frequency to be locked, e.g.:
|
||||
```shell
|
||||
adb shell
|
||||
su
|
||||
# navigate to the system GPU directory. this varies on different phones. One phone might have
|
||||
# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with "mali" instead
|
||||
# of "kgsl". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali
|
||||
cd /sys/devices/platform/1f000000.mali
|
||||
# get the current available GPU governors and frequencies.
|
||||
# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but
|
||||
# the system at the time of writing this had available_governors and available_frequences
|
||||
cat available_governors
|
||||
cat available_frequencies
|
||||
# depending on the governors, you may want to set it prioritize performance over other things like
|
||||
# battery. Some systems allow you to do this with something like (although, for the device used at the
|
||||
# time of writing this did not have an equivalent option):
|
||||
echo performance > gpu_governor
|
||||
# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you
|
||||
# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:
|
||||
echo 940000 > hint_min_freq
|
||||
echo 940000 > hint_max_freq
|
||||
# you can typically verify the GPU is running at that frequency consistently by running something like
|
||||
# the following a few times over time, which should show the frequency you want to lock the device to:
|
||||
cat cur_freq
|
||||
```
|
||||
1. You may need to re-apply the `hint_min_freq` just before starting the profiling trace and check before and after
|
||||
that the frequency remained at the value expected. Some systems may adjust the frequency on you, but you
|
||||
may want to ensure the frequency remains the same through the analysis.
|
||||
1. The GPU frequency settings should be undone after restarting the device, but after you have done your app profiling,
|
||||
you can revert the state of the device, such as the OS build image, back to the way you had it
|
||||
initially, as needed.
|
||||
1. Build a release build of Filament with the applicable backend(s) enabled
|
||||
_(+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from
|
||||
building a release build with no flags)_ _(debug builds for this are useless)_
|
||||
|
||||
@@ -40,7 +40,6 @@ set(PUBLIC_HDRS
|
||||
include/filament/Skybox.h
|
||||
include/filament/Stream.h
|
||||
include/filament/SwapChain.h
|
||||
include/filament/Sync.h
|
||||
include/filament/Texture.h
|
||||
include/filament/TextureSampler.h
|
||||
include/filament/ToneMapper.h
|
||||
@@ -104,7 +103,6 @@ set(SRCS
|
||||
src/Skybox.cpp
|
||||
src/Stream.cpp
|
||||
src/SwapChain.cpp
|
||||
src/Sync.cpp
|
||||
src/Texture.cpp
|
||||
src/ToneMapper.cpp
|
||||
src/TransformManager.cpp
|
||||
@@ -134,7 +132,6 @@ set(SRCS
|
||||
src/details/Skybox.cpp
|
||||
src/details/Stream.cpp
|
||||
src/details/SwapChain.cpp
|
||||
src/details/Sync.cpp
|
||||
src/details/Texture.cpp
|
||||
src/details/VertexBuffer.cpp
|
||||
src/details/View.cpp
|
||||
|
||||
@@ -295,7 +295,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
src/webgpu/WebGPUStrings.h
|
||||
src/webgpu/WebGPUSwapChain.cpp
|
||||
src/webgpu/WebGPUSwapChain.h
|
||||
src/webgpu/WebGPUSync.h
|
||||
src/webgpu/WebGPUTexture.cpp
|
||||
src/webgpu/WebGPUTexture.h
|
||||
src/webgpu/WebGPUTextureHelpers.h
|
||||
@@ -495,6 +494,9 @@ else()
|
||||
-Wover-aligned -Wreorder-init-list
|
||||
-Werror
|
||||
)
|
||||
if (CMAKE_CXX_STANDARD EQUAL 20)
|
||||
list(APPEND FILAMENT_WARNINGS -Wno-deprecated-this-capture)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
@@ -578,9 +580,7 @@ if (APPLE OR LINUX)
|
||||
test/test_Template.cpp
|
||||
)
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
list(APPEND BACKEND_TEST_SRC
|
||||
test/test_WebGPUAsyncTaskCounter.cpp
|
||||
test/test_WebGPUComposeSwizzle.cpp)
|
||||
list(APPEND BACKEND_TEST_SRC test/test_WebGPUAsyncTaskCounter.cpp)
|
||||
endif()
|
||||
if (APPLE)
|
||||
# Metal-specific tests
|
||||
@@ -629,10 +629,6 @@ if (APPLE AND NOT IOS)
|
||||
target_link_libraries(backend_test PRIVATE image imageio)
|
||||
list(APPEND BACKEND_TEST_DEPS image)
|
||||
endif()
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
target_link_libraries(backend_test PRIVATE webgpu_dawn dawncpp_headers)
|
||||
list(APPEND BACKEND_TEST_DEPS webgpu_dawn dawncpp_headers)
|
||||
endif()
|
||||
|
||||
set(BACKEND_TEST_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libbackendtest_combined.a")
|
||||
combine_static_libs(backend_test "${BACKEND_TEST_COMBINED_OUTPUT}" "${BACKEND_TEST_DEPS}")
|
||||
@@ -664,9 +660,6 @@ if (LINUX)
|
||||
add_executable(backend_test_linux test/linux_runner.cpp ${BACKEND_TEST_SRC})
|
||||
target_link_libraries(backend_test_linux PRIVATE ${BACKEND_TEST_LIBS})
|
||||
set_target_properties(backend_test_linux PROPERTIES FOLDER Tests)
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
target_link_libraries(backend_test_linux PRIVATE webgpu_dawn dawncpp_headers)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -101,16 +101,6 @@ static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = SWAP_CHAIN_CON
|
||||
*/
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_PROTECTED_CONTENT = 0x40;
|
||||
|
||||
/**
|
||||
* Indicates that the SwapChain is configured to use Multi-Sample Anti-Aliasing (MSAA) with the
|
||||
* given sample points within each pixel. Only supported when isMSAASwapChainSupported(4) is
|
||||
* true.
|
||||
*
|
||||
* This is only supported by EGL(Android). Other GL platforms (GLX, WGL, etc) don't support it
|
||||
* because the swapchain MSAA settings must be configured before window creation.
|
||||
*/
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES = 0x80;
|
||||
|
||||
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
|
||||
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
|
||||
@@ -639,18 +629,6 @@ enum class PrimitiveType : uint8_t {
|
||||
TRIANGLE_STRIP = 5 //!< triangle strip
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr bool isStripPrimitiveType(const PrimitiveType type) {
|
||||
switch (type) {
|
||||
case PrimitiveType::POINTS:
|
||||
case PrimitiveType::LINES:
|
||||
case PrimitiveType::TRIANGLES:
|
||||
return false;
|
||||
case PrimitiveType::LINE_STRIP:
|
||||
case PrimitiveType::TRIANGLE_STRIP:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported uniform types
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,6 @@ struct HwRenderPrimitive;
|
||||
struct HwRenderTarget;
|
||||
struct HwStream;
|
||||
struct HwSwapChain;
|
||||
struct HwSync;
|
||||
struct HwTexture;
|
||||
struct HwTimerQuery;
|
||||
struct HwVertexBufferInfo;
|
||||
@@ -152,7 +151,6 @@ using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
|
||||
using RenderTargetHandle = Handle<HwRenderTarget>;
|
||||
using StreamHandle = Handle<HwStream>;
|
||||
using SwapChainHandle = Handle<HwSwapChain>;
|
||||
using SyncHandle = Handle<HwSync>;
|
||||
using TextureHandle = Handle<HwTexture>;
|
||||
using TimerQueryHandle = Handle<HwTimerQuery>;
|
||||
using VertexBufferHandle = Handle<HwVertexBuffer>;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class CallbackHandler;
|
||||
class Driver;
|
||||
|
||||
/**
|
||||
@@ -43,9 +42,6 @@ public:
|
||||
struct SwapChain {};
|
||||
struct Fence {};
|
||||
struct Stream {};
|
||||
struct Sync {};
|
||||
|
||||
using SyncCallback = void(*)(Sync* UTILS_NONNULL sync, void* UTILS_NULLABLE userData);
|
||||
|
||||
class ExternalImageHandle;
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ namespace filament::backend {
|
||||
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
|
||||
* a SwapChain.
|
||||
*
|
||||
* Typically, Filament's backend is responsible for scheduling a frame's presentation. However,
|
||||
* there are certain cases where the application might want to control when a frame is scheduled for
|
||||
* Typically, Filament's backend is responsible scheduling a frame's presentation. However, there
|
||||
* are certain cases where the application might want to control when a frame is scheduled for
|
||||
* presentation.
|
||||
*
|
||||
* For example, on iOS, UIKit elements can be synchronized to 3D content by scheduling a present
|
||||
* within a CATransaction:
|
||||
* within a CATransation:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* void myFrameScheduledCallback(PresentCallable presentCallable, void* user) {
|
||||
@@ -55,13 +55,12 @@ namespace filament::backend {
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @remark The PresentCallable mechanism for user-controlled presentation is only supported by
|
||||
* Filament's Metal backend. On other backends, the FrameScheduledCallback is still invoked, but the
|
||||
* PresentCallable passed to it is a no-op and calling it has no effect.
|
||||
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
|
||||
* backends ignore the callback (which will never be called) and proceed normally.
|
||||
*
|
||||
* When using the Metal backend, applications *must* call each PresentCallable they receive. Each
|
||||
* PresentCallable represents a frame that is waiting to be presented, and failing to call it
|
||||
* will result in a memory leak. To "cancel" the presentation of a frame, pass false to the
|
||||
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
|
||||
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
|
||||
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
|
||||
* PresentCallable, which will cancel the presentation of the frame and release associated memory.
|
||||
*
|
||||
* @see Renderer, SwapChain::setFrameScheduledCallback
|
||||
@@ -70,7 +69,6 @@ class UTILS_PUBLIC PresentCallable {
|
||||
public:
|
||||
|
||||
using PresentFn = void(*)(bool presentFrame, void* user);
|
||||
static void noopPresent(bool, void*) {}
|
||||
|
||||
PresentCallable(PresentFn fn, void* user) noexcept;
|
||||
~PresentCallable() noexcept = default;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/bitset.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
@@ -66,6 +67,7 @@ public:
|
||||
using DescriptorBindingsInfo = utils::FixedCapacityVector<Descriptor>;
|
||||
using DescriptorSetInfo = std::array<DescriptorBindingsInfo, MAX_DESCRIPTOR_SET_COUNT>;
|
||||
using SpecializationConstantsInfo = utils::FixedCapacityVector<SpecializationConstant>;
|
||||
using MutableSpecConstantsInfo = utils::bitset8;
|
||||
using ShaderBlob = utils::FixedCapacityVector<uint8_t>;
|
||||
using ShaderSource = std::array<ShaderBlob, SHADER_TYPE_COUNT>;
|
||||
|
||||
@@ -103,7 +105,8 @@ public:
|
||||
Program& descriptorBindings(backend::descriptor_set_t set,
|
||||
DescriptorBindingsInfo descriptorBindings) noexcept;
|
||||
|
||||
Program& specializationConstants(SpecializationConstantsInfo specConstants) noexcept;
|
||||
Program& specializationConstants(SpecializationConstantsInfo specConstants,
|
||||
uint32_t firstMutableId, MutableSpecConstantsInfo mutableSpecConstants) noexcept;
|
||||
|
||||
struct PushConstant {
|
||||
utils::CString name;
|
||||
|
||||
@@ -85,15 +85,6 @@ public:
|
||||
*/
|
||||
virtual bool isSRGBSwapChainSupported() const noexcept;
|
||||
|
||||
/**
|
||||
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_MSAA_*_SAMPLES flag.
|
||||
* The default implementation returns false.
|
||||
*
|
||||
* @param samples The number of samples
|
||||
* @return true if SWAP_CHAIN_CONFIG_MSAA_*_SAMPLES is supported, false otherwise.
|
||||
*/
|
||||
virtual bool isMSAASwapChainSupported(uint32_t samples) const noexcept;
|
||||
|
||||
/**
|
||||
* Return whether protected contexts are supported by this backend.
|
||||
* If protected context are supported, the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag can be
|
||||
@@ -285,26 +276,6 @@ public:
|
||||
*/
|
||||
virtual backend::FenceStatus waitFence(Fence* UTILS_NONNULL fence, uint64_t timeout) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Sync support
|
||||
|
||||
/**
|
||||
* Creates a Sync. These can be used for frame synchronization externally
|
||||
* (certain platform implementations can be exported to handles that can
|
||||
* be used in other processes).
|
||||
*
|
||||
* @return A Sync object.
|
||||
*/
|
||||
virtual Platform::Sync* UTILS_NONNULL createSync() noexcept;
|
||||
|
||||
/**
|
||||
* Destroys a sync. If called with a sync not created by this platform
|
||||
* object, this will lead to undefined behavior.
|
||||
*
|
||||
* @param sync The sync to destroy, that was created by this platform
|
||||
* instance.
|
||||
*/
|
||||
virtual void destroySync(Platform::Sync* UTILS_NONNULL sync) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Streaming support
|
||||
|
||||
@@ -98,9 +98,8 @@ protected:
|
||||
void terminate() noexcept override;
|
||||
|
||||
bool isProtectedContextSupported() const noexcept override;
|
||||
bool isSRGBSwapChainSupported() const noexcept override;
|
||||
bool isMSAASwapChainSupported(uint32_t samples) const noexcept override;
|
||||
|
||||
bool isSRGBSwapChainSupported() const noexcept override;
|
||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||
|
||||
@@ -58,17 +58,6 @@ public:
|
||||
|
||||
ExternalImageDescAndroid UTILS_PUBLIC getExternalImageDesc(ExternalImageHandle externalImage) noexcept;
|
||||
|
||||
/**
|
||||
* Converts a sync to an external file descriptor, if possible. Accepts an
|
||||
* opaque handle to a sync, as well as a pointer to where the fd should be
|
||||
* stored.
|
||||
* @param sync The sync to be converted to a file descriptor.
|
||||
* @param fd A pointer to where the file descriptor should be stored.
|
||||
* @return `true` on success, `false` on failure. The default implementation
|
||||
* returns `false`.
|
||||
*/
|
||||
bool convertSyncToFd(Platform::Sync* sync, int* fd) noexcept;
|
||||
|
||||
protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
@@ -85,10 +74,6 @@ protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// OpenGLPlatform Interface
|
||||
|
||||
struct SyncEGLAndroid : public Platform::Sync {
|
||||
EGLSyncKHR sync;
|
||||
};
|
||||
|
||||
void terminate() noexcept override;
|
||||
|
||||
void beginFrame(
|
||||
@@ -104,10 +89,9 @@ protected:
|
||||
*/
|
||||
void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept override;
|
||||
|
||||
|
||||
Stream* createStream(void* nativeStream) noexcept override;
|
||||
void destroyStream(Stream* stream) noexcept override;
|
||||
Platform::Sync* createSync() noexcept override;
|
||||
void destroySync(Platform::Sync* sync) noexcept override;
|
||||
void attach(Stream* stream, intptr_t tname) noexcept override;
|
||||
void detach(Stream* stream) noexcept override;
|
||||
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept override;
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
|
||||
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
@@ -30,9 +29,9 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -46,10 +45,6 @@ using SwapChain = Platform::SwapChain;
|
||||
*/
|
||||
struct VulkanPlatformPrivate;
|
||||
|
||||
// Forward declare the fence status that will be maintained by the command
|
||||
// buffer manager.
|
||||
struct VulkanCmdFence;
|
||||
|
||||
/**
|
||||
* A Platform interface that creates a Vulkan backend.
|
||||
*/
|
||||
@@ -234,25 +229,6 @@ public:
|
||||
virtual SwapChainPtr createSwapChain(void* nativeWindow, uint64_t flags = 0,
|
||||
VkExtent2D extent = {0, 0});
|
||||
|
||||
/**
|
||||
* Creates a Platform::Sync object, which tracks a fence and its status,
|
||||
* and allows conversion to an external sync.
|
||||
* @param fence The underlying VkFence to use for synchronization.
|
||||
* @param fenceStatus An object tracking the fence's state
|
||||
* @return A Platform::Sync object tracking the provided fence.
|
||||
*/
|
||||
virtual Platform::Sync* createSync(VkFence fence,
|
||||
std::shared_ptr<VulkanCmdFence> fenceStatus) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys a sync. If called with a sync not created by this platform
|
||||
* object, this will lead to undefined behavior.
|
||||
*
|
||||
* @param sync The sync to destroy, which was created by this platform
|
||||
* instance.
|
||||
*/
|
||||
virtual void destroySync(Platform::Sync* sync) noexcept;
|
||||
|
||||
/**
|
||||
* Allows implementers to provide instance extensions that they'd like to include in the
|
||||
* instance creation.
|
||||
@@ -432,19 +408,12 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
struct VulkanSync : public Platform::Sync {
|
||||
VkFence fence;
|
||||
std::shared_ptr<VulkanCmdFence> fenceStatus;
|
||||
};
|
||||
|
||||
virtual ExtensionSet getSwapchainInstanceExtensions() const;
|
||||
|
||||
using SurfaceBundle = std::tuple<VkSurfaceKHR, VkExtent2D>;
|
||||
virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
|
||||
uint64_t flags) const noexcept;
|
||||
|
||||
virtual VkExternalFenceHandleTypeFlagBits getFenceExportFlags() const noexcept;
|
||||
|
||||
private:
|
||||
// Platform dependent helper methods
|
||||
static ExtensionSet getSwapchainInstanceExtensionsImpl();
|
||||
|
||||
@@ -44,17 +44,6 @@ public:
|
||||
|
||||
virtual ImageData createVkImageFromExternal(ExternalImageHandleRef image) const override;
|
||||
|
||||
/**
|
||||
* Converts a sync to an external file descriptor, if possible. Accepts an
|
||||
* opaque handle to a sync, as well as a pointer to where the fd should be
|
||||
* stored.
|
||||
* @param sync The sync to be converted to a file descriptor.
|
||||
* @param fd A pointer to where the file descriptor should be stored.
|
||||
* @return `true` on success, `false` on failure. The default implementation
|
||||
* returns `false`.
|
||||
*/
|
||||
bool convertSyncToFd(Platform::Sync* sync, int* fd) const noexcept;
|
||||
|
||||
protected:
|
||||
virtual ExtensionSet getSwapchainInstanceExtensions() const override;
|
||||
|
||||
@@ -62,8 +51,6 @@ protected:
|
||||
virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
|
||||
uint64_t flags) const noexcept override;
|
||||
|
||||
virtual VkExternalFenceHandleTypeFlagBits getFenceExportFlags() const noexcept override;
|
||||
|
||||
private:
|
||||
struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
|
||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||
|
||||
@@ -19,16 +19,6 @@
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_X11)
|
||||
// Resolve the conflicts between webgpu_cpp.h and X11 defines
|
||||
#undef Always
|
||||
#undef Success
|
||||
#undef None
|
||||
#undef True
|
||||
#undef False
|
||||
#undef Status
|
||||
#undef Bool
|
||||
#endif
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -107,10 +107,6 @@
|
||||
#define DECL_DRIVER_API_R_N(R, N, ...) \
|
||||
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
|
||||
|
||||
#define DECL_DRIVER_API_TAGGED_R_N(R, N, ...) \
|
||||
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString, tag = {}), \
|
||||
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString, tag))
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS_N(R, N, ...) \
|
||||
DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
|
||||
|
||||
@@ -169,31 +165,35 @@ DECL_DRIVER_API_0(finish)
|
||||
// reset state tracking, if the driver does any state tracking (e.g. GL)
|
||||
DECL_DRIVER_API_0(resetState)
|
||||
|
||||
DECL_DRIVER_API_N(setDebugTag,
|
||||
backend::HandleBase::HandleId, handleId,
|
||||
utils::CString, tag)
|
||||
|
||||
/*
|
||||
* Creating driver objects
|
||||
* -----------------------
|
||||
*/
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::VertexBufferInfoHandle, createVertexBufferInfo,
|
||||
DECL_DRIVER_API_R_N(backend::VertexBufferInfoHandle, createVertexBufferInfo,
|
||||
uint8_t, bufferCount,
|
||||
uint8_t, attributeCount,
|
||||
backend::AttributeArray, attributes)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::VertexBufferHandle, createVertexBuffer,
|
||||
DECL_DRIVER_API_R_N(backend::VertexBufferHandle, createVertexBuffer,
|
||||
uint32_t, vertexCount,
|
||||
backend::VertexBufferInfoHandle, vbih)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::IndexBufferHandle, createIndexBuffer,
|
||||
DECL_DRIVER_API_R_N(backend::IndexBufferHandle, createIndexBuffer,
|
||||
backend::ElementType, elementType,
|
||||
uint32_t, indexCount,
|
||||
backend::BufferUsage, usage)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::BufferObjectHandle, createBufferObject,
|
||||
DECL_DRIVER_API_R_N(backend::BufferObjectHandle, createBufferObject,
|
||||
uint32_t, byteCount,
|
||||
backend::BufferObjectBinding, bindingType,
|
||||
backend::BufferUsage, usage)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTexture,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTexture,
|
||||
backend::SamplerType, target,
|
||||
uint8_t, levels,
|
||||
backend::TextureFormat, format,
|
||||
@@ -203,19 +203,19 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTexture,
|
||||
uint32_t, depth,
|
||||
backend::TextureUsage, usage)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureView,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureView,
|
||||
backend::TextureHandle, texture,
|
||||
uint8_t, baseLevel,
|
||||
uint8_t, levelCount)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureViewSwizzle,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
|
||||
backend::TextureHandle, texture,
|
||||
backend::TextureSwizzle, r,
|
||||
backend::TextureSwizzle, g,
|
||||
backend::TextureSwizzle, b,
|
||||
backend::TextureSwizzle, a)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage2,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage2,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
@@ -223,7 +223,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage2,
|
||||
backend::TextureUsage, usage,
|
||||
backend::Platform::ExternalImageHandleRef, image)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
@@ -231,7 +231,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
backend::TextureUsage, usage,
|
||||
void*, image)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImagePlane,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImagePlane,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
@@ -239,7 +239,7 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, createTextureExternalImagePla
|
||||
void*, image,
|
||||
uint32_t, plane)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, importTexture,
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, importTexture,
|
||||
intptr_t, id,
|
||||
backend::SamplerType, target,
|
||||
uint8_t, levels,
|
||||
@@ -250,17 +250,17 @@ DECL_DRIVER_API_TAGGED_R_N(backend::TextureHandle, importTexture,
|
||||
uint32_t, depth,
|
||||
backend::TextureUsage, usage)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::RenderPrimitiveHandle, createRenderPrimitive,
|
||||
DECL_DRIVER_API_R_N(backend::RenderPrimitiveHandle, createRenderPrimitive,
|
||||
backend::VertexBufferHandle, vbh,
|
||||
backend::IndexBufferHandle, ibh,
|
||||
backend::PrimitiveType, pt)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::ProgramHandle, createProgram,
|
||||
DECL_DRIVER_API_R_N(backend::ProgramHandle, createProgram,
|
||||
backend::Program&&, program)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createDefaultRenderTarget)
|
||||
DECL_DRIVER_API_R_0(backend::RenderTargetHandle, createDefaultRenderTarget)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createRenderTarget,
|
||||
DECL_DRIVER_API_R_N(backend::RenderTargetHandle, createRenderTarget,
|
||||
backend::TargetBufferFlags, targetBufferFlags,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
@@ -270,25 +270,23 @@ DECL_DRIVER_API_TAGGED_R_N(backend::RenderTargetHandle, createRenderTarget,
|
||||
backend::TargetBufferInfo, depth,
|
||||
backend::TargetBufferInfo, stencil)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::FenceHandle, createFence)
|
||||
DECL_DRIVER_API_R_0(backend::FenceHandle, createFence)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::SyncHandle, createSync)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::SwapChainHandle, createSwapChain,
|
||||
DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChain,
|
||||
void*, nativeWindow,
|
||||
uint64_t, flags)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::SwapChainHandle, createSwapChainHeadless,
|
||||
DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChainHeadless,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
uint64_t, flags)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::TimerQueryHandle, createTimerQuery)
|
||||
DECL_DRIVER_API_R_0(backend::TimerQueryHandle, createTimerQuery)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::DescriptorSetLayoutHandle, createDescriptorSetLayout,
|
||||
DECL_DRIVER_API_R_N(backend::DescriptorSetLayoutHandle, createDescriptorSetLayout,
|
||||
backend::DescriptorSetLayout&&, info)
|
||||
|
||||
DECL_DRIVER_API_TAGGED_R_N(backend::DescriptorSetHandle, createDescriptorSet,
|
||||
DECL_DRIVER_API_R_N(backend::DescriptorSetHandle, createDescriptorSet,
|
||||
backend::DescriptorSetLayoutHandle, dslh)
|
||||
|
||||
DECL_DRIVER_API_N(updateDescriptorSetBuffer,
|
||||
@@ -330,7 +328,6 @@ DECL_DRIVER_API_N(destroySwapChain, backend::SwapChainHandle, sch)
|
||||
DECL_DRIVER_API_N(destroyStream, backend::StreamHandle, sh)
|
||||
DECL_DRIVER_API_N(destroyTimerQuery, backend::TimerQueryHandle, sh)
|
||||
DECL_DRIVER_API_N(destroyFence, backend::FenceHandle, fh)
|
||||
DECL_DRIVER_API_N(destroySync, backend::SyncHandle, sh)
|
||||
DECL_DRIVER_API_N(destroyDescriptorSetLayout, backend::DescriptorSetLayoutHandle, dslh)
|
||||
DECL_DRIVER_API_N(destroyDescriptorSet, backend::DescriptorSetHandle, dsh)
|
||||
|
||||
@@ -340,15 +337,13 @@ DECL_DRIVER_API_N(destroyDescriptorSet, backend::DescriptorSetHandle, ds
|
||||
*/
|
||||
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(void, terminate)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream, utils::CString, tag)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamAcquired, utils::CString, tag)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(backend::StreamHandle, createStreamAcquired)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, const math::mat3f&, transform, backend::CallbackHandler*, handler, backend::StreamCallback, cb, void*, userData)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setStreamDimensions, backend::StreamHandle, stream, uint32_t, width, uint32_t, height)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(int64_t, getStreamTimestamp, backend::StreamHandle, stream)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, updateStreams, backend::DriverApi*, driver)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::FenceStatus, getFenceStatus, backend::FenceHandle, fh)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, getPlatformSync, backend::SyncHandle, sh,
|
||||
backend::CallbackHandler*, handler, backend::Platform::SyncCallback, cb, void*, userData)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isTextureFormatSupported, backend::TextureFormat, format)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isTextureSwizzleSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isTextureFormatMipmappable, backend::TextureFormat, format)
|
||||
@@ -358,7 +353,6 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchMultiSampleSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isAutoDepthResolveSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isSRGBSwapChainSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isMSAASwapChainSupported, uint32_t, samples)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedContentSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isStereoSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported)
|
||||
|
||||
@@ -249,9 +249,8 @@ public:
|
||||
}
|
||||
|
||||
void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
|
||||
if (tag.empty()) {
|
||||
return;
|
||||
}
|
||||
// TODO: for now, only pool handles check for use-after-free, so we only keep tags for
|
||||
// those
|
||||
uint32_t key = id;
|
||||
if (UTILS_LIKELY(isPoolHandle(id))) {
|
||||
// Truncate the age to get the debug tag
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
# include <windows.h> // for VirtualAlloc, VirtualProtect, VirtualFree
|
||||
# include <utils/unwindows.h>
|
||||
#endif
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament::backend {
|
||||
@@ -139,21 +134,6 @@ void* CircularBuffer::alloc(size_t size) {
|
||||
mprotect(guard, BLOCK_SIZE, PROT_NONE);
|
||||
}
|
||||
return data;
|
||||
#elif defined(WIN32)
|
||||
size_t const BLOCK_SIZE = getBlockSize();
|
||||
// On Windows, use VirtualAlloc instead of malloc to allocate virtual memory.
|
||||
// This allows us to set page protection by VirtualProtect.
|
||||
void* data = VirtualAlloc(nullptr, size * 2 + BLOCK_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
FILAMENT_CHECK_POSTCONDITION(data != nullptr)
|
||||
<< "couldn't allocate " << (size * 2 / 1024)
|
||||
<< " KiB of virtual address space for the command buffer";
|
||||
|
||||
// guard page at the end
|
||||
void* guard = (void*)(uintptr_t(data) + size * 2);
|
||||
DWORD oldProtect = 0;
|
||||
BOOL ok = VirtualProtect(guard, BLOCK_SIZE, PAGE_NOACCESS, &oldProtect);
|
||||
FILAMENT_CHECK_POSTCONDITION(ok) << "VirtualProtect failed to set guard page";
|
||||
return data;
|
||||
#else
|
||||
return ::malloc(2 * size);
|
||||
#endif
|
||||
@@ -170,10 +150,6 @@ void CircularBuffer::dealloc() noexcept {
|
||||
mAshmemFd = -1;
|
||||
}
|
||||
}
|
||||
#elif defined(WIN32)
|
||||
if (mData) {
|
||||
VirtualFree(mData, 0, MEM_RELEASE);
|
||||
}
|
||||
#else
|
||||
::free(mData);
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,7 @@ static void printParameterPack(io::ostream& out, const FIRST& first, const REMAI
|
||||
printParameterPack(out, rest...);
|
||||
}
|
||||
|
||||
static UTILS_NOINLINE UTILS_UNUSED std::string_view extractMethodName(std::string_view command) noexcept {
|
||||
static UTILS_NOINLINE UTILS_UNUSED std::string extractMethodName(std::string& command) noexcept {
|
||||
constexpr const char startPattern[] = "::Command<&filament::backend::Driver::";
|
||||
auto pos = command.rfind(startPattern);
|
||||
auto end = command.rfind('(');
|
||||
@@ -133,9 +133,9 @@ template<std::size_t... I>
|
||||
void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log(std::index_sequence<I...>) noexcept {
|
||||
#if DEBUG_COMMAND_STREAM
|
||||
static_assert(UTILS_HAS_RTTI, "DEBUG_COMMAND_STREAM can only be used with RTTI");
|
||||
CString command = CallStack::demangleTypeName(typeid(Command).name());
|
||||
DLOG(INFO) << extractMethodName({command.data(), command.size()}) << " : size=" << sizeof(Command);
|
||||
io::sstream parameterPack;
|
||||
std::string command = utils::CallStack::demangleTypeName(typeid(Command).name()).c_str();
|
||||
DLOG(INFO) << extractMethodName(command) << " : size=" << sizeof(Command);
|
||||
utils::io::sstream parameterPack;
|
||||
printParameterPack(parameterPack, std::get<I>(mArgs)...);
|
||||
DLOG(INFO) << "\t" << parameterPack.c_str();
|
||||
#endif
|
||||
@@ -164,7 +164,7 @@ void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log() noexcept {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void CustomCommand::execute(Driver&, CommandBase* base, intptr_t* next) {
|
||||
*next = align(sizeof(CustomCommand));
|
||||
*next = CustomCommand::align(sizeof(CustomCommand));
|
||||
static_cast<CustomCommand*>(base)->mCommand();
|
||||
static_cast<CustomCommand*>(base)->~CustomCommand();
|
||||
}
|
||||
|
||||
@@ -140,10 +140,6 @@ struct HwFence : public HwBase {
|
||||
Platform::Fence* fence = nullptr;
|
||||
};
|
||||
|
||||
struct HwSync : public HwBase {
|
||||
Platform::Sync* sync = nullptr;
|
||||
};
|
||||
|
||||
struct HwSwapChain : public HwBase {
|
||||
Platform::SwapChain* swapChain = nullptr;
|
||||
};
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
# include <utils/CString.h>
|
||||
# include <string_view>
|
||||
# include <string>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -37,11 +36,11 @@ static char const * const kOurNamespace = "filament::backend::";
|
||||
|
||||
// removes all occurrences of "what" from "str"
|
||||
UTILS_NOINLINE
|
||||
static CString& removeAll(CString& str, const std::string_view what) noexcept {
|
||||
static std::string& removeAll(std::string& str, const std::string& what) noexcept {
|
||||
if (!what.empty()) {
|
||||
const CString empty;
|
||||
const std::string empty;
|
||||
size_t pos = 0;
|
||||
while ((pos = std::string_view{ str.data(), str.size() }.find(what, pos)) != std::string_view::npos) {
|
||||
while ((pos = str.find(what, pos)) != std::string::npos) {
|
||||
str.replace(pos, what.length(), empty);
|
||||
}
|
||||
}
|
||||
@@ -50,13 +49,13 @@ static CString& removeAll(CString& str, const std::string_view what) noexcept {
|
||||
|
||||
template <typename T>
|
||||
UTILS_NOINLINE
|
||||
static io::ostream& logHandle(io::ostream& out, CString& typeName, T id) noexcept {
|
||||
static io::ostream& logHandle(io::ostream& out, std::string& typeName, T id) noexcept {
|
||||
return out << removeAll(typeName, kOurNamespace) << " @ " << id;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
io::ostream& operator<<(io::ostream& out, const Handle<T>& h) noexcept {
|
||||
CString s{ CallStack::typeName<Handle<T>>() };
|
||||
std::string s(CallStack::typeName<Handle<T>>().c_str());
|
||||
return logHandle(out, s, h.getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +82,19 @@ Program& Program::attributes(AttributesInfo attributes) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::specializationConstants(SpecializationConstantsInfo specConstants) noexcept {
|
||||
mSpecializationConstants = std::move(specConstants);
|
||||
Program& Program::specializationConstants(SpecializationConstantsInfo specConstants,
|
||||
uint32_t firstMutableId, MutableSpecConstantsInfo mutableSpecConstants) noexcept {
|
||||
// String the two lists together.
|
||||
mSpecializationConstants = SpecializationConstantsInfo(
|
||||
specConstants.size() + mutableSpecConstants.size());
|
||||
std::uninitialized_move(specConstants.begin(), specConstants.end(),
|
||||
mSpecializationConstants.begin());
|
||||
for (uint32_t i = 0; i < mutableSpecConstants.size(); i++) {
|
||||
mSpecializationConstants[i + specConstants.size()] = SpecializationConstant {
|
||||
.id = i + firstMutableId,
|
||||
.value = mutableSpecConstants[i],
|
||||
};
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
Type mType = Type::NONE;
|
||||
|
||||
static PlatformMetal* platform;
|
||||
static std::array<std::atomic<uint64_t>, TypeCount> aliveBuffers;
|
||||
static std::array<uint64_t, TypeCount> aliveBuffers;
|
||||
};
|
||||
|
||||
class MetalBuffer {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
std::array<std::atomic<uint64_t>, TrackedMetalBuffer::TypeCount> TrackedMetalBuffer::aliveBuffers = { 0 };
|
||||
std::array<uint64_t, TrackedMetalBuffer::TypeCount> TrackedMetalBuffer::aliveBuffers = { 0 };
|
||||
PlatformMetal* TrackedMetalBuffer::platform = nullptr;
|
||||
PlatformMetal* ScopedAllocationTimer::platform = nullptr;
|
||||
|
||||
|
||||
@@ -418,40 +418,49 @@ void MetalDriver::finish(int) {
|
||||
}
|
||||
|
||||
void MetalDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::CString tag) {
|
||||
uint8_t attributeCount, AttributeArray attributes) {
|
||||
construct_handle<MetalVertexBufferInfo>(vbih, *mContext,
|
||||
bufferCount, attributeCount, attributes);
|
||||
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh,
|
||||
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih, utils::CString tag) {
|
||||
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih) {
|
||||
MetalVertexBufferInfo const* const vbi = handle_cast<const MetalVertexBufferInfo>(vbih);
|
||||
construct_handle<MetalVertexBuffer>(vbh, *mContext, vertexCount, vbi->bufferCount, vbih);
|
||||
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
|
||||
// No actual GPU memory is allocated here, so no need to check for allocation success.
|
||||
}
|
||||
|
||||
void MetalDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage, utils::CString tag) {
|
||||
uint32_t indexCount, BufferUsage usage) {
|
||||
auto elementSize = (uint8_t)getElementTypeSize(elementType);
|
||||
auto* indexBuffer =
|
||||
construct_handle<MetalIndexBuffer>(ibh, *mContext, usage, elementSize, indexCount);
|
||||
auto& buffer = indexBuffer->buffer;
|
||||
FILAMENT_CHECK_POSTCONDITION(buffer.wasAllocationSuccessful())
|
||||
<< "Could not allocate Metal index buffer of size " << buffer.getSize()
|
||||
<< ", tag=" << tag.c_str_safe();
|
||||
mHandleAllocator.associateTagToHandle(ibh.getId(), std::move(tag));
|
||||
// If the allocation was not successful, postpone the error message until the next tick, to give
|
||||
// Filament a chance to call setDebugTag on the handle; this way we get a nicer error message.
|
||||
if (UTILS_UNLIKELY(!buffer.wasAllocationSuccessful())) {
|
||||
const size_t byteCount = buffer.getSize();
|
||||
runAtNextTick([byteCount, this, ibh]() {
|
||||
FILAMENT_CHECK_POSTCONDITION(false)
|
||||
<< "Could not allocate Metal index buffer of size " << byteCount
|
||||
<< ", tag=" << mHandleAllocator.getHandleTag(ibh.getId()).c_str_safe();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MetalDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
|
||||
BufferObjectBinding bindingType, BufferUsage usage) {
|
||||
auto* bufferObject =
|
||||
construct_handle<MetalBufferObject>(boh, *mContext, bindingType, usage, byteCount);
|
||||
FILAMENT_CHECK_POSTCONDITION(bufferObject->getBuffer()->wasAllocationSuccessful())
|
||||
<< "Could not allocate Metal buffer of size " << byteCount
|
||||
<< ", tag=" << tag.c_str_safe();
|
||||
mHandleAllocator.associateTagToHandle(boh.getId(), std::move(tag));
|
||||
// If the allocation was not successful, postpone the error message until the next tick, to give
|
||||
// Filament a chance to call setDebugTag on the handle; this way we get a nicer error message.
|
||||
if (UTILS_UNLIKELY(!bufferObject->getBuffer()->wasAllocationSuccessful())) {
|
||||
runAtNextTick([byteCount, this, boh]() {
|
||||
FILAMENT_CHECK_POSTCONDITION(false)
|
||||
<< "Could not allocate Metal buffer of size " << byteCount
|
||||
<< ", tag=" << mHandleAllocator.getHandleTag(boh.getId()).c_str_safe();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// fixme: TextureUsage is a bitfield
|
||||
@@ -486,7 +495,7 @@ inline const char* stringify(SamplerType samplerType) {
|
||||
|
||||
void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
|
||||
uint32_t depth, TextureUsage usage, utils::CString tag) {
|
||||
uint32_t depth, TextureUsage usage) {
|
||||
// Clamp sample count to what the device supports.
|
||||
auto& sc = mContext->sampleCountLookup;
|
||||
samples = sc[std::min(MAX_SAMPLE_COUNT, samples)];
|
||||
@@ -498,60 +507,55 @@ void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8
|
||||
"createTextureR(th = %d, target = %s, levels = %d, format = ?, samples = %d, width = "
|
||||
"%d, height = %d, depth = %d, usage = %s)\n",
|
||||
th.getId(), stringify(target), levels, samples, width, height, depth, stringify(usage));
|
||||
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
|
||||
void MetalDriver::createTextureViewR(
|
||||
Handle<HwTexture> th, Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
|
||||
MetalTexture const* src = handle_cast<MetalTexture>(srch);
|
||||
mContext->textures.insert(
|
||||
construct_handle<MetalTexture>(th, *mContext, src, baseLevel, levelCount));
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a, utils::CString tag) {
|
||||
backend::TextureSwizzle a) {
|
||||
MetalTexture const* src = handle_cast<MetalTexture>(srch);
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image, utils::CString tag) {
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, utils::CString tag) {
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
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));
|
||||
// This release matches the retain call in setupExternalImage. The MetalTexture will have
|
||||
// retained the buffer by now.
|
||||
CVPixelBufferRelease((CVPixelBufferRef)image);
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane, utils::CString tag) {
|
||||
void* image, uint32_t plane) {
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(
|
||||
th, *mContext, format, width, height, usage, (CVPixelBufferRef)image, plane));
|
||||
// This release matches the retain call in setupExternalImage. The MetalTexture will have
|
||||
// retained the buffer by now.
|
||||
CVPixelBufferRelease((CVPixelBufferRef)image);
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
|
||||
SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
|
||||
uint32_t depth, TextureUsage usage, utils::CString tag) {
|
||||
uint32_t depth, TextureUsage usage) {
|
||||
id<MTLTexture> metalTexture = (id<MTLTexture>) CFBridgingRelease((void*) i);
|
||||
FILAMENT_CHECK_PRECONDITION(metalTexture.width == width)
|
||||
<< "Imported id<MTLTexture> width (" << metalTexture.width
|
||||
@@ -568,36 +572,32 @@ void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
|
||||
<< ") != Filament texture type (" << filamentMetalType << ")";
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext,
|
||||
target, levels, format, samples, width, height, depth, usage, metalTexture));
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType pt, utils::CString tag) {
|
||||
PrimitiveType pt) {
|
||||
construct_handle<MetalRenderPrimitive>(rph);
|
||||
MetalDriver::setRenderPrimitiveBuffer(rph, pt, vbh, ibh);
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program, utils::CString tag) {
|
||||
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program) {
|
||||
#if FILAMENT_METAL_DEBUG_LOG
|
||||
auto handleId = rph.getId();
|
||||
DEBUG_LOG("createProgramR(rph = %d, program = ", handleId);
|
||||
DLOG(INFO) << program;
|
||||
#endif
|
||||
construct_handle<MetalProgram>(rph, *mContext, std::move(program));
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString tag) {
|
||||
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int dummy) {
|
||||
construct_handle<MetalRenderTarget>(rth, mContext);
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
|
||||
uint8_t samples, uint8_t layerCount, MRT color,
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil, utils::CString tag) {
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil) {
|
||||
FILAMENT_CHECK_PRECONDITION(!isInRenderPass(mContext))
|
||||
<< "createRenderTarget must be called outside of a render pass.";
|
||||
// Clamp sample count to what the device supports.
|
||||
@@ -640,20 +640,14 @@ void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
|
||||
construct_handle<MetalRenderTarget>(rth, mContext, width, height, samples,
|
||||
colorAttachments, depthAttachment, stencilAttachment);
|
||||
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
|
||||
void MetalDriver::createFenceR(Handle<HwFence> fh, int dummy) {
|
||||
auto* fence = handle_cast<MetalFence>(fh);
|
||||
fence->encode();
|
||||
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
|
||||
utils::CString tag) {
|
||||
// TODO: support MSAA swapchain
|
||||
|
||||
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
|
||||
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) nativeWindow;
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, pixelBuffer, flags);
|
||||
@@ -664,24 +658,15 @@ void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
auto* metalLayer = (__bridge CAMetalLayer*) nativeWindow;
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, metalLayer, flags);
|
||||
}
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
uint32_t width, uint32_t height, uint64_t flags, utils::CString tag) {
|
||||
uint32_t width, uint32_t height, uint64_t flags) {
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, width, height, flags);
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createSyncR(Handle<HwSync> sh, utils::CString tag) {
|
||||
// TODO: Ensure sync is active, and then invoke and clear all pending
|
||||
// callbacks.
|
||||
mHandleAllocator.associateTagToHandle(sh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
UTILS_UNUSED
|
||||
@@ -718,7 +703,7 @@ const char* toString(DescriptorFlags flags) {
|
||||
}
|
||||
|
||||
void MetalDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info, utils::CString tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info) {
|
||||
#if FILAMENT_METAL_DEBUG_LOG == 1
|
||||
const char* labelStr = "";
|
||||
std::visit([&labelStr](auto&& arg) {
|
||||
@@ -739,15 +724,13 @@ void MetalDriver::createDescriptorSetLayoutR(
|
||||
DEBUG_LOG("})\n");
|
||||
#endif
|
||||
construct_handle<MetalDescriptorSetLayout>(dslh, std::move(info));
|
||||
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createDescriptorSetR(
|
||||
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
|
||||
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh) {
|
||||
DEBUG_LOG("createDescriptorSetR(dsh = %d, dslh = %d)\n", dsh.getId(), dslh.getId());
|
||||
MetalDescriptorSetLayout* layout = handle_cast<MetalDescriptorSetLayout>(dslh);
|
||||
construct_handle<MetalDescriptorSet>(dsh, layout);
|
||||
mHandleAllocator.associateTagToHandle(dsh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
Handle<HwVertexBufferInfo> MetalDriver::createVertexBufferInfoS() noexcept {
|
||||
@@ -824,10 +807,6 @@ Handle<HwSwapChain> MetalDriver::createSwapChainHeadlessS() noexcept {
|
||||
return alloc_handle<MetalSwapChain>();
|
||||
}
|
||||
|
||||
Handle<HwSync> MetalDriver::createSyncS() noexcept {
|
||||
return alloc_handle<MetalSync>();
|
||||
}
|
||||
|
||||
Handle<HwTimerQuery> MetalDriver::createTimerQueryS() noexcept {
|
||||
// The handle must be constructed here, as a synchronous call to getTimerQueryValue might happen
|
||||
// before createTimerQueryR is executed.
|
||||
@@ -990,11 +969,11 @@ ShaderLanguage MetalDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::MSL;
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream, utils::CString tag) {
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> MetalDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1029,19 +1008,6 @@ FenceStatus MetalDriver::getFenceStatus(Handle<HwFence> fh) {
|
||||
return fence->wait(0);
|
||||
}
|
||||
|
||||
void MetalDriver::destroySync(Handle<HwSync> sh) {
|
||||
if (sh) {
|
||||
destruct_handle<MetalSync>(sh);
|
||||
}
|
||||
}
|
||||
|
||||
void MetalDriver::getPlatformSync(Handle<HwSync> sh, CallbackHandler* handler,
|
||||
Platform::SyncCallback cb, void* userData) {
|
||||
// TODO: If the sync has been inserted into the command stream, execute
|
||||
// the callback. Otherwise, enqueue it.
|
||||
}
|
||||
|
||||
|
||||
bool MetalDriver::isTextureFormatSupported(TextureFormat format) {
|
||||
return MetalTexture::decidePixelFormat(mContext, format) != MTLPixelFormatInvalid;
|
||||
}
|
||||
@@ -1123,11 +1089,6 @@ bool MetalDriver::isSRGBSwapChainSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetalDriver::isMSAASwapChainSupported(uint32_t) {
|
||||
// TODO: support MSAA swapchain
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetalDriver::isProtectedContentSupported() {
|
||||
// the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag is not supported
|
||||
return false;
|
||||
@@ -2174,6 +2135,10 @@ void MetalDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
void MetalDriver::resetState(int) {
|
||||
}
|
||||
|
||||
void MetalDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::runAtNextTick(const std::function<void()>& fn) noexcept {
|
||||
mTickOps.push_back(fn);
|
||||
}
|
||||
|
||||
@@ -437,10 +437,6 @@ private:
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
// TODO: Provide implementation for MetalSync.
|
||||
class MetalSync : public HwSync {
|
||||
};
|
||||
|
||||
struct MetalTimerQuery : public HwTimerQuery {
|
||||
MetalTimerQuery() : status(std::make_shared<Status>()) {}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include "noop/NoopDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
@@ -115,9 +116,6 @@ void NoopDriver::destroySwapChain(Handle<HwSwapChain> sch) {
|
||||
void NoopDriver::destroyStream(Handle<HwStream> sh) {
|
||||
}
|
||||
|
||||
void NoopDriver::destroySync(Handle<HwSync> sh) {
|
||||
}
|
||||
|
||||
void NoopDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
@@ -127,11 +125,11 @@ void NoopDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> tqh) {
|
||||
void NoopDriver::destroyDescriptorSet(Handle<HwDescriptorSet> tqh) {
|
||||
}
|
||||
|
||||
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> NoopDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> NoopDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -149,10 +147,6 @@ int64_t NoopDriver::getStreamTimestamp(Handle<HwStream> sh) {
|
||||
void NoopDriver::updateStreams(CommandStream* driver) {
|
||||
}
|
||||
|
||||
void NoopDriver::getPlatformSync(Handle<HwSync> sh, CallbackHandler* handler,
|
||||
Platform::SyncCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void NoopDriver::destroyFence(Handle<HwFence> fh) {
|
||||
}
|
||||
|
||||
@@ -198,10 +192,6 @@ bool NoopDriver::isSRGBSwapChainSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isMSAASwapChainSupported(uint32_t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isProtectedContentSupported() {
|
||||
return false;
|
||||
}
|
||||
@@ -425,4 +415,7 @@ void NoopDriver::bindDescriptorSet(
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
}
|
||||
|
||||
void NoopDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -149,18 +149,6 @@ using namespace utils;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
|
||||
static CallbackHandler::Callback syncCallbackWrapper = [](void* userData) {
|
||||
std::unique_ptr<OpenGLDriver::GLSyncFence::CallbackData> cbData(
|
||||
static_cast<OpenGLDriver::GLSyncFence::CallbackData*>(userData));
|
||||
// This assumes the sync has not yet been destroyed. If it has, this will be
|
||||
// undefined behavior.
|
||||
cbData->cb(cbData->sync, cbData->userData);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Driver* OpenGLDriverFactory::create(
|
||||
OpenGLPlatform* platform,
|
||||
void* sharedGLContext,
|
||||
@@ -627,10 +615,6 @@ Handle<HwFence> OpenGLDriver::createFenceS() noexcept {
|
||||
return initHandle<GLFence>();
|
||||
}
|
||||
|
||||
Handle<HwSync> OpenGLDriver::createSyncS() noexcept {
|
||||
return initHandle<GLSyncFence>();
|
||||
}
|
||||
|
||||
Handle<HwSwapChain> OpenGLDriver::createSwapChainS() noexcept {
|
||||
return initHandle<GLSwapChain>();
|
||||
}
|
||||
@@ -655,29 +639,24 @@ void OpenGLDriver::createVertexBufferInfoR(
|
||||
Handle<HwVertexBufferInfo> vbih,
|
||||
uint8_t bufferCount,
|
||||
uint8_t attributeCount,
|
||||
AttributeArray attributes,
|
||||
utils::CString tag) {
|
||||
AttributeArray attributes) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLVertexBufferInfo>(vbih, bufferCount, attributeCount, attributes);
|
||||
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createVertexBufferR(
|
||||
Handle<HwVertexBuffer> vbh,
|
||||
uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih,
|
||||
utils::CString tag) {
|
||||
Handle<HwVertexBufferInfo> vbih) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLVertexBuffer>(vbh, vertexCount, vbih);
|
||||
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createIndexBufferR(
|
||||
Handle<HwIndexBuffer> ibh,
|
||||
ElementType elementType,
|
||||
uint32_t indexCount,
|
||||
BufferUsage usage,
|
||||
utils::CString tag) {
|
||||
BufferUsage usage) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -689,11 +668,10 @@ void OpenGLDriver::createIndexBufferR(
|
||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, nullptr, getBufferUsage(usage));
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(ibh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
|
||||
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
|
||||
uint32_t byteCount, BufferObjectBinding bindingType, BufferUsage usage) {
|
||||
DEBUG_MARKER()
|
||||
assert_invariant(byteCount > 0);
|
||||
|
||||
@@ -715,12 +693,11 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byte
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(boh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType pt, utils::CString tag) {
|
||||
PrimitiveType pt) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -753,10 +730,9 @@ void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::CString tag) {
|
||||
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
|
||||
@@ -784,7 +760,6 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils
|
||||
|
||||
construct<OpenGLProgram>(ph, *this, std::move(program));
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(ph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
@@ -889,7 +864,7 @@ void OpenGLDriver::textureStorage(GLTexture* t,
|
||||
|
||||
void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage, utils::CString tag) {
|
||||
TextureUsage usage) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLenum internalFormat = getInternalFormat(format);
|
||||
@@ -978,11 +953,10 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
|
||||
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
|
||||
@@ -1025,12 +999,10 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
ref->count++;
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a,
|
||||
utils::CString tag) {
|
||||
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
|
||||
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
@@ -1090,12 +1062,11 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
ref->count++;
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image, utils::CString tag) {
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
@@ -1142,12 +1113,10 @@ void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerTyp
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
}
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image,
|
||||
utils::CString tag) {
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
@@ -1193,18 +1162,17 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
}
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
void* image, uint32_t plane, utils::CString tag) {
|
||||
void* image, uint32_t plane) {
|
||||
// not relevant for the OpenGL backend
|
||||
}
|
||||
|
||||
void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
|
||||
uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage, utils::CString tag) {
|
||||
uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -1257,7 +1225,6 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::updateVertexArrayObject(GLRenderPrimitive* rp, GLVertexBuffer const* vb) {
|
||||
@@ -1659,7 +1626,7 @@ void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDefaultRenderTargetR(
|
||||
Handle<HwRenderTarget> rth, utils::CString tag) {
|
||||
Handle<HwRenderTarget> rth, int) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
construct<GLRenderTarget>(rth, 0, 0); // FIXME: we don't know the width/height
|
||||
@@ -1670,7 +1637,6 @@ void OpenGLDriver::createDefaultRenderTargetR(
|
||||
rt->gl.samples = 1;
|
||||
// FIXME: these flags should reflect the actual attachments present
|
||||
rt->targets = TargetBufferFlags::COLOR0 | TargetBufferFlags::DEPTH;
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
@@ -1681,8 +1647,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
uint8_t layerCount,
|
||||
MRT color,
|
||||
TargetBufferInfo depth,
|
||||
TargetBufferInfo stencil,
|
||||
utils::CString tag) {
|
||||
TargetBufferInfo stencil) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLRenderTarget* rt = construct<GLRenderTarget>(rth, width, height);
|
||||
@@ -1795,10 +1760,9 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
assert_invariant(tmin == tmax);
|
||||
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
|
||||
void OpenGLDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLFence* f = handle_cast<GLFence*>(fh);
|
||||
@@ -1820,29 +1784,9 @@ void OpenGLDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
|
||||
});
|
||||
}
|
||||
#endif
|
||||
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSyncR(Handle<HwSync> sh, utils::CString tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSyncFence* s = handle_cast<GLSyncFence*>(sh);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s->lock);
|
||||
s->sync = mPlatform.createSync();
|
||||
}
|
||||
|
||||
for (auto& cbData : s->conversionCallbacks) {
|
||||
cbData->sync = s->sync;
|
||||
scheduleCallback(cbData->handler, cbData.release(), syncCallbackWrapper);
|
||||
}
|
||||
|
||||
s->conversionCallbacks.clear();
|
||||
mHandleAllocator.associateTagToHandle(sh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
|
||||
utils::CString tag) {
|
||||
void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
@@ -1859,12 +1803,10 @@ void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
sc->rec709 = ((flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) &&
|
||||
!mPlatform.isSRGBSwapChainSupported());
|
||||
}
|
||||
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
uint32_t width, uint32_t height, uint64_t flags, utils::CString tag) {
|
||||
uint32_t width, uint32_t height, uint64_t flags) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
@@ -1882,30 +1824,25 @@ void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
sc->rec709 = (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE &&
|
||||
!mPlatform.isSRGBSwapChainSupported());
|
||||
}
|
||||
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
|
||||
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
DEBUG_MARKER()
|
||||
GLTimerQuery* tq = handle_cast<GLTimerQuery*>(tqh);
|
||||
mContext.createTimerQuery(tq);
|
||||
mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
DescriptorSetLayout&& info, utils::CString tag) {
|
||||
DescriptorSetLayout&& info) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLDescriptorSetLayout>(dslh, std::move(info));
|
||||
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh) {
|
||||
DEBUG_MARKER()
|
||||
GLDescriptorSetLayout const* dsl = handle_cast<GLDescriptorSetLayout*>(dslh);
|
||||
construct<GLDescriptorSet>(dsh, mContext, dslh, dsl);
|
||||
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -2011,7 +1948,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
if (UTILS_UNLIKELY(t->hwStream)) {
|
||||
detachStream(t);
|
||||
}
|
||||
if (UTILS_UNLIKELY(t->externalTexture)) {
|
||||
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
|
||||
mPlatform.destroyExternalImageTexture(t->externalTexture);
|
||||
} else {
|
||||
glDeleteTextures(1, &t->gl.id);
|
||||
@@ -2114,16 +2051,6 @@ void OpenGLDriver::destroyStream(Handle<HwStream> sh) {
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::destroySync(Handle<HwSync> sh) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
if (sh) {
|
||||
GLSyncFence* s = handle_cast<GLSyncFence*>(sh);
|
||||
mPlatform.destroySync(s->sync);
|
||||
destruct(sh, s);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
@@ -2161,17 +2088,13 @@ void OpenGLDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
|
||||
// These are called on the application's thread
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream) {
|
||||
Platform::Stream* stream = mPlatform.createStream(nativeStream);
|
||||
auto handle = initHandle<GLStream>(stream);
|
||||
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
|
||||
return handle;
|
||||
return initHandle<GLStream>(stream);
|
||||
}
|
||||
|
||||
Handle<HwStream> OpenGLDriver::createStreamAcquired(utils::CString tag) {
|
||||
auto handle = initHandle<GLStream>();
|
||||
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
|
||||
return handle;
|
||||
Handle<HwStream> OpenGLDriver::createStreamAcquired() {
|
||||
return initHandle<GLStream>();
|
||||
}
|
||||
|
||||
// Stashes an acquired external image and a release callback. The image is not bound to OpenGL until
|
||||
@@ -2312,33 +2235,6 @@ FenceStatus OpenGLDriver::getFenceStatus(Handle<HwFence> fh) {
|
||||
return FenceStatus::ERROR;
|
||||
}
|
||||
|
||||
void OpenGLDriver::getPlatformSync(Handle<HwSync> sh, CallbackHandler* handler,
|
||||
Platform::SyncCallback cb, void* userData) {
|
||||
if (!sh) {
|
||||
return;
|
||||
}
|
||||
|
||||
GLSyncFence* s = handle_cast<GLSyncFence*>(sh);
|
||||
auto cbData = std::make_unique<GLSyncFence::CallbackData>();
|
||||
cbData->handler = handler;
|
||||
cbData->cb = cb;
|
||||
cbData->userData = userData;
|
||||
|
||||
// If we haven't already set the handle, toss the conversion callback in the
|
||||
// back of the list.
|
||||
{
|
||||
std::lock_guard guard(s->lock);
|
||||
if (s->sync == nullptr) {
|
||||
s->conversionCallbacks.push_back(std::move(cbData));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, go ahead and schedule the callback now.
|
||||
cbData->sync = s->sync;
|
||||
scheduleCallback(cbData->handler, cbData.release(), syncCallbackWrapper);
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isTextureFormatSupported(TextureFormat format) {
|
||||
const auto& ext = mContext.ext;
|
||||
if (isETC2Compression(format)) {
|
||||
@@ -2504,10 +2400,6 @@ bool OpenGLDriver::isSRGBSwapChainSupported() {
|
||||
return mPlatform.isSRGBSwapChainSupported();
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isMSAASwapChainSupported(uint32_t samples) {
|
||||
return mPlatform.isMSAASwapChainSupported(samples);
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isProtectedContentSupported() {
|
||||
return mPlatform.isProtectedContextSupported();
|
||||
}
|
||||
@@ -2622,20 +2514,13 @@ size_t OpenGLDriver::getMaxArrayTextureLayers() {
|
||||
// Swap chains
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
void OpenGLDriver::commit(Handle<HwSwapChain> sch) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
mPlatform.commit(sc->swapChain);
|
||||
|
||||
auto& fs = sc->frameScheduled;
|
||||
if (fs.callback) {
|
||||
scheduleCallback(fs.handler, [callback = std::move(fs.callback)]() {
|
||||
PresentCallable noop = PresentCallable(PresentCallable::noopPresent, nullptr);
|
||||
callback(noop);
|
||||
});
|
||||
}
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
if (UTILS_UNLIKELY(!mFrameCompleteOps.empty())) {
|
||||
whenGpuCommandsComplete([ops = std::move(mFrameCompleteOps)]() {
|
||||
@@ -2701,6 +2586,10 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
|
||||
// Updating driver objects
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, CString tag) {
|
||||
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh,
|
||||
uint32_t index, Handle<HwBufferObject> boh) {
|
||||
DEBUG_MARKER()
|
||||
@@ -3828,12 +3717,9 @@ void OpenGLDriver::beginFrame(
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
|
||||
FrameScheduledCallback&& callback, uint64_t /*flags*/) {
|
||||
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain>, CallbackHandler*,
|
||||
FrameScheduledCallback&& /*callback*/, uint64_t /*flags*/) {
|
||||
DEBUG_MARKER()
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
sc->frameScheduled.handler = handler;
|
||||
sc->frameScheduled.callback = std::move(callback);
|
||||
}
|
||||
|
||||
void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain>,
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "ShaderCompilerService.h"
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
@@ -100,10 +99,6 @@ public:
|
||||
struct GLSwapChain : public HwSwapChain {
|
||||
using HwSwapChain::HwSwapChain;
|
||||
bool rec709 = false;
|
||||
struct {
|
||||
CallbackHandler* handler = nullptr;
|
||||
FrameScheduledCallback callback;
|
||||
} frameScheduled;
|
||||
};
|
||||
|
||||
struct GLVertexBufferInfo : public HwVertexBufferInfo {
|
||||
@@ -198,19 +193,6 @@ public:
|
||||
std::shared_ptr<State> state{ std::make_shared<State>() };
|
||||
};
|
||||
|
||||
// Note: named "GLSyncFence" to avoid confusion with the GL handle,
|
||||
// "GLsync" (lowercase S)
|
||||
struct GLSyncFence : public HwSync {
|
||||
struct CallbackData {
|
||||
CallbackHandler* handler;
|
||||
Platform::SyncCallback cb;
|
||||
Platform::Sync* sync;
|
||||
void* userData;
|
||||
};
|
||||
std::mutex lock;
|
||||
std::vector<std::unique_ptr<CallbackData>> conversionCallbacks;
|
||||
};
|
||||
|
||||
OpenGLDriver(OpenGLDriver const&) = delete;
|
||||
OpenGLDriver& operator=(OpenGLDriver const&) = delete;
|
||||
|
||||
|
||||
@@ -76,10 +76,6 @@ bool OpenGLPlatform::isSRGBSwapChainSupported() const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenGLPlatform::isMSAASwapChainSupported(uint32_t) const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t OpenGLPlatform::getDefaultFramebufferObject() noexcept {
|
||||
return 0;
|
||||
}
|
||||
@@ -121,15 +117,6 @@ FenceStatus OpenGLPlatform::waitFence(
|
||||
return FenceStatus::ERROR;
|
||||
}
|
||||
|
||||
Platform::Sync* OpenGLPlatform::createSync() noexcept {
|
||||
return new Platform::Sync();
|
||||
}
|
||||
|
||||
void OpenGLPlatform::destroySync(Platform::Sync* sync) noexcept {
|
||||
// sync must be a Platform::Sync, since it was created by this platform
|
||||
// object.
|
||||
delete sync;
|
||||
}
|
||||
|
||||
Platform::Stream* OpenGLPlatform::createStream(
|
||||
UTILS_UNUSED void* nativeStream) noexcept {
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <cctype>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
@@ -66,9 +67,9 @@ constexpr uint32_t MAX_NUM_SYNCHRONOUS_PROGRAMS_PER_FRAME = 1;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
static CString to_string(bool const b) { return CString{ b ? "true" : "false" }; }
|
||||
static CString to_string(int const i) { return utils::to_string(i); }
|
||||
static CString to_string(float const f) { return "float(" + utils::to_string(f) + ")"; }
|
||||
static std::string to_string(bool const b) { return b ? "true" : "false"; }
|
||||
static std::string to_string(int const i) { return std::to_string(i); }
|
||||
static std::string to_string(float const f) { return "float(" + std::to_string(f) + ")"; }
|
||||
|
||||
static void logCompilationError(ShaderStage shaderType, const char* name, GLuint shaderId,
|
||||
Program::ShaderBlob const& sourceCode) noexcept;
|
||||
@@ -695,14 +696,14 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
bool multiview, program_token_t const& token) noexcept {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
auto const appendSpecConstantString = +[](CString& s, Program::SpecializationConstant const& sc) {
|
||||
s += "#define SPIRV_CROSS_CONSTANT_ID_" + utils::to_string(sc.id) + ' ';
|
||||
auto const appendSpecConstantString = +[](std::string& s, Program::SpecializationConstant const& sc) {
|
||||
s += "#define SPIRV_CROSS_CONSTANT_ID_" + std::to_string(sc.id) + ' ';
|
||||
s += std::visit([](auto&& arg) { return to_string(arg); }, sc.value);
|
||||
s += '\n';
|
||||
return s;
|
||||
};
|
||||
|
||||
CString specializationConstantString;
|
||||
std::string specializationConstantString;
|
||||
int32_t numViews = 2;
|
||||
for (auto const& sc: specializationConstants) {
|
||||
appendSpecConstantString(specializationConstantString, sc);
|
||||
@@ -765,10 +766,8 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
}
|
||||
|
||||
std::array<std::string_view, 5> sources = {
|
||||
version, prolog,
|
||||
{ specializationConstantString.data(), specializationConstantString.size() },
|
||||
packingFunctions,
|
||||
{ body.data(), body.size() - 1 } // null-terminated
|
||||
version, prolog, specializationConstantString, packingFunctions,
|
||||
{ body.data(), body.size() - 1 }// null-terminated
|
||||
};
|
||||
|
||||
// Some of the sources may be zero-length. Remove them as to avoid passing lengths of
|
||||
@@ -967,18 +966,16 @@ UTILS_NOINLINE
|
||||
sourceCode.size() };
|
||||
size_t lc = 1;
|
||||
size_t start = 0;
|
||||
CString line;
|
||||
std::string line;
|
||||
while (true) {
|
||||
size_t const end = shader.find('\n', start);
|
||||
if (end == std::string_view::npos) {
|
||||
auto sv = shader.substr(start);
|
||||
line = { sv.data(), sv.size() };
|
||||
if (end == std::string::npos) {
|
||||
line = shader.substr(start);
|
||||
} else {
|
||||
auto sv = shader.substr(start, end - start);
|
||||
line = { sv.data(), sv.size() };
|
||||
line = shader.substr(start, end - start);
|
||||
}
|
||||
LOG(ERROR) << lc++ << ": " << line.c_str();
|
||||
if (end == std::string_view::npos) {
|
||||
if (end == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
start = end + 1;
|
||||
|
||||
@@ -448,11 +448,6 @@ EGLConfig PlatformEGL::findSwapChainConfig(uint64_t flags, bool window, bool pbu
|
||||
configAttribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (flags & SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES) {
|
||||
configAttribs[EGL_SAMPLE_BUFFERS] = 1;
|
||||
configAttribs[EGL_SAMPLES] = 4;
|
||||
}
|
||||
|
||||
if (UTILS_UNLIKELY(
|
||||
!eglChooseConfig(mEGLDisplay, configAttribs.data(), &config, 1, &configsCount))) {
|
||||
logEglError("eglChooseConfig");
|
||||
@@ -486,48 +481,11 @@ bool PlatformEGL::isSRGBSwapChainSupported() const noexcept {
|
||||
return ext.egl.KHR_gl_colorspace;
|
||||
}
|
||||
|
||||
bool PlatformEGL::isMSAASwapChainSupported(uint32_t samples) const noexcept {
|
||||
if (samples <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Config configAttribs = {
|
||||
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT },
|
||||
{ EGL_RED_SIZE, 8 },
|
||||
{ EGL_GREEN_SIZE, 8 },
|
||||
{ EGL_BLUE_SIZE, 8 },
|
||||
{ EGL_DEPTH_SIZE, 24 },
|
||||
{ EGL_SAMPLE_BUFFERS, 1 },
|
||||
{ EGL_SAMPLES, samples },
|
||||
};
|
||||
|
||||
if (!ext.egl.KHR_no_config_context) {
|
||||
if (isOpenGL()) {
|
||||
configAttribs[EGL_RENDERABLE_TYPE] = EGL_OPENGL_BIT;
|
||||
} else {
|
||||
configAttribs[EGL_RENDERABLE_TYPE] = EGL_OPENGL_ES2_BIT;
|
||||
if (ext.egl.KHR_create_context) {
|
||||
configAttribs[EGL_RENDERABLE_TYPE] |= EGL_OPENGL_ES3_BIT_KHR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EGLConfig config = EGL_NO_CONFIG_KHR;
|
||||
EGLint configsCount;
|
||||
if (!eglChooseConfig(mEGLDisplay, configAttribs.data(), &config, 1, &configsCount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return configsCount > 0;
|
||||
}
|
||||
|
||||
Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
void* nativeWindow, uint64_t flags) noexcept {
|
||||
|
||||
Config attribs;
|
||||
|
||||
// Remove flags for unsupported features.
|
||||
if (isSRGBSwapChainSupported()) {
|
||||
if (ext.egl.KHR_gl_colorspace) {
|
||||
if (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) {
|
||||
attribs[EGL_GL_COLORSPACE_KHR] = EGL_GL_COLORSPACE_SRGB_KHR;
|
||||
}
|
||||
@@ -535,7 +493,7 @@ Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
flags &= ~SWAP_CHAIN_CONFIG_SRGB_COLORSPACE;
|
||||
}
|
||||
|
||||
if (isProtectedContextSupported()) {
|
||||
if (ext.egl.EXT_protected_content) {
|
||||
if (flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
|
||||
attribs[EGL_PROTECTED_CONTENT_EXT] = EGL_TRUE;
|
||||
}
|
||||
@@ -543,13 +501,6 @@ Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
flags &= ~SWAP_CHAIN_CONFIG_PROTECTED_CONTENT;
|
||||
}
|
||||
|
||||
if (flags & SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES) {
|
||||
if (!isMSAASwapChainSupported(4)) {
|
||||
flags &= ~SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve a config for the given flags.
|
||||
EGLConfig config = EGL_NO_CONFIG_KHR;
|
||||
if (UTILS_LIKELY(ext.egl.KHR_no_config_context)) {
|
||||
config = findSwapChainConfig(flags, true, false);
|
||||
|
||||
@@ -83,7 +83,6 @@ UTILS_PRIVATE PFNEGLGETCOMPOSITORTIMINGANDROIDPROC eglGetCompositorTimingANDROID
|
||||
UTILS_PRIVATE PFNEGLGETNEXTFRAMEIDANDROIDPROC eglGetNextFrameIdANDROID = {};
|
||||
UTILS_PRIVATE PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROIDPROC eglGetFrameTimestampSupportedANDROID = {};
|
||||
UTILS_PRIVATE PFNEGLGETFRAMETIMESTAMPSANDROIDPROC eglGetFrameTimestampsANDROID = {};
|
||||
UTILS_PRIVATE PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = {};
|
||||
}
|
||||
using namespace glext;
|
||||
|
||||
@@ -227,8 +226,6 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
|
||||
"eglGetFrameTimestampSupportedANDROID");
|
||||
eglGetFrameTimestampsANDROID = (PFNEGLGETFRAMETIMESTAMPSANDROIDPROC)eglGetProcAddress(
|
||||
"eglGetFrameTimestampsANDROID");
|
||||
eglDupNativeFenceFDANDROID =
|
||||
(PFNEGLDUPNATIVEFENCEFDANDROIDPROC) eglGetProcAddress("eglDupNativeFenceFDANDROID");
|
||||
}
|
||||
|
||||
mAssertNativeWindowIsValid = driverConfig.assertNativeWindowIsValid;
|
||||
@@ -398,31 +395,6 @@ void PlatformEGLAndroid::destroyStream(Platform::Stream* stream) noexcept {
|
||||
mExternalStreamManager.release(stream);
|
||||
}
|
||||
|
||||
Platform::Sync* PlatformEGLAndroid::createSync() noexcept {
|
||||
auto sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||
return new SyncEGLAndroid{.sync = sync};
|
||||
}
|
||||
|
||||
bool PlatformEGLAndroid::convertSyncToFd(Platform::Sync* sync, int* fd) noexcept {
|
||||
assert_invariant(sync && fd);
|
||||
SyncEGLAndroid& eglSync = static_cast<SyncEGLAndroid&>(*sync);
|
||||
*fd = eglDupNativeFenceFDANDROID(mEGLDisplay, eglSync.sync);
|
||||
// In the case where there was no native FD, -1 is returned. Return false
|
||||
// to indicate there was an error in this case.
|
||||
if (*fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
|
||||
LOG(ERROR) << "Failed to convert sync to fd: " << eglGetError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlatformEGLAndroid::destroySync(Platform::Sync* sync) noexcept {
|
||||
assert_invariant(sync);
|
||||
SyncEGLAndroid& eglSync = static_cast<SyncEGLAndroid&>(*sync);
|
||||
eglDestroySyncKHR(mEGLDisplay, eglSync.sync);
|
||||
delete sync;
|
||||
}
|
||||
|
||||
void PlatformEGLAndroid::attach(Stream* stream, intptr_t tname) noexcept {
|
||||
mExternalStreamManager.attach(stream, tname);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include "backend/Platform.h"
|
||||
|
||||
#include "vulkan/memory/Resource.h"
|
||||
|
||||
@@ -53,19 +52,6 @@ struct VulkanFence : public HwFence, fvkmemory::ThreadSafeResource {
|
||||
std::shared_ptr<VulkanCmdFence> fence;
|
||||
};
|
||||
|
||||
struct VulkanSync : fvkmemory::ThreadSafeResource, public HwSync {
|
||||
struct CallbackData {
|
||||
CallbackHandler* handler;
|
||||
Platform::SyncCallback cb;
|
||||
Platform::Sync* sync;
|
||||
void* userData;
|
||||
};
|
||||
|
||||
VulkanSync() {}
|
||||
std::mutex lock;
|
||||
std::vector<std::unique_ptr<CallbackData>> conversionCallbacks;
|
||||
};
|
||||
|
||||
struct VulkanTimerQuery : public HwTimerQuery, fvkmemory::ThreadSafeResource {
|
||||
VulkanTimerQuery(uint32_t startingIndex, uint32_t stoppingIndex)
|
||||
: mStartingQueryIndex(startingIndex),
|
||||
|
||||
@@ -96,6 +96,7 @@ inline void resolveFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect
|
||||
VulkanLayout oldSrcLayout = src.getLayout();
|
||||
VulkanLayout oldDstLayout = dst.getLayout();
|
||||
|
||||
src.texture->transitionLayout(commands, srcRange, VulkanLayout::TRANSFER_SRC);
|
||||
dst.texture->transitionLayout(commands, dstRange, VulkanLayout::TRANSFER_DST);
|
||||
|
||||
assert_invariant(
|
||||
@@ -108,9 +109,10 @@ inline void resolveFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect
|
||||
.extent = { src.getExtent2D().width, src.getExtent2D().height, 1 },
|
||||
}};
|
||||
vkCmdResolveImage(cmdbuffer,
|
||||
src.getImage(), fvkutils::getVkLayout(src.getLayout()),
|
||||
src.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
dst.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST),
|
||||
1, resolveRegions);
|
||||
|
||||
if (oldSrcLayout == VulkanLayout::UNDEFINED) {
|
||||
oldSrcLayout = src.texture->getDefaultLayout();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanContext.h"
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/debug.h>
|
||||
@@ -58,26 +57,26 @@ VkCommandBuffer createCommandBuffer(VkDevice device, VkCommandPool pool) {
|
||||
} // anonymous namespace
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
|
||||
void VulkanGroupMarkers::push(CString const& marker, Timestamp start) noexcept {
|
||||
void VulkanGroupMarkers::push(std::string const& marker, Timestamp start) noexcept {
|
||||
mMarkers.push_back({marker,
|
||||
start.time_since_epoch().count() > 0.0
|
||||
? start
|
||||
: std::chrono::high_resolution_clock::now()});
|
||||
}
|
||||
|
||||
std::pair<CString, Timestamp> VulkanGroupMarkers::pop() noexcept {
|
||||
std::pair<std::string, Timestamp> VulkanGroupMarkers::pop() noexcept {
|
||||
auto ret = mMarkers.back();
|
||||
mMarkers.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<CString, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
|
||||
std::pair<std::string, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
|
||||
auto ret = mMarkers.front();
|
||||
mMarkers.pop_front();
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<CString, Timestamp> const& VulkanGroupMarkers::top() const {
|
||||
std::pair<std::string, Timestamp> const& VulkanGroupMarkers::top() const {
|
||||
assert_invariant(!empty());
|
||||
return mMarkers.back();
|
||||
}
|
||||
@@ -103,12 +102,6 @@ VulkanCommandBuffer::VulkanCommandBuffer(VulkanContext const& context, VkDevice
|
||||
vkCreateSemaphore(mDevice, &sci, VKALLOC, &mSubmission);
|
||||
|
||||
VkFenceCreateInfo fenceCreateInfo{.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
||||
VkExportFenceCreateInfo exportFenceCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
|
||||
.handleTypes = context.getFenceExportFlags()
|
||||
};
|
||||
fenceCreateInfo.pNext = &exportFenceCreateInfo;
|
||||
|
||||
vkCreateFence(device, &fenceCreateInfo, VKALLOC, &mFence);
|
||||
}
|
||||
|
||||
@@ -218,9 +211,7 @@ VkSemaphore VulkanCommandBuffer::submit() {
|
||||
FVK_LOGI << "Submitting cmdbuffer=" << mBuffer
|
||||
<< " wait=(";
|
||||
for (size_t s = 0, count = mWaitSemaphores.size(); s < count; ++s) {
|
||||
FVK_LOGI << "\tsemaphore=" << mWaitSemaphores[s] << "|stage="
|
||||
<< mWaitSemaphoreStages[s]
|
||||
<< (s < mWaitSemaphores.size() - 1 ? "\n" : "");
|
||||
FVK_LOGI << mWaitSemaphores[s] << " ";
|
||||
}
|
||||
FVK_LOGI << ") "
|
||||
<< " signal=" << mSubmission
|
||||
@@ -360,7 +351,7 @@ void CommandBufferPool::waitFor(VkSemaphore previousAction, VkPipelineStageFlags
|
||||
}
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
|
||||
CString CommandBufferPool::topMarker() const {
|
||||
std::string CommandBufferPool::topMarker() const {
|
||||
if (!mGroupMarkers || mGroupMarkers->empty()) {
|
||||
return "";
|
||||
}
|
||||
@@ -371,11 +362,11 @@ void CommandBufferPool::pushMarker(char const* marker, VulkanGroupMarkers::Times
|
||||
if (!mGroupMarkers) {
|
||||
mGroupMarkers = std::make_unique<VulkanGroupMarkers>();
|
||||
}
|
||||
mGroupMarkers->push(CString{ marker }, timestamp);
|
||||
mGroupMarkers->push(marker, timestamp);
|
||||
getRecording().pushMarker(marker);
|
||||
}
|
||||
|
||||
std::pair<CString, VulkanGroupMarkers::Timestamp> CommandBufferPool::popMarker() {
|
||||
std::pair<std::string, VulkanGroupMarkers::Timestamp> CommandBufferPool::popMarker() {
|
||||
assert_invariant(mGroupMarkers && !mGroupMarkers->empty());
|
||||
auto ret = mGroupMarkers->pop();
|
||||
|
||||
@@ -431,9 +422,6 @@ bool VulkanCommands::flush() {
|
||||
VkSemaphore lastSubmit = mLastSubmit;
|
||||
bool hasFlushed = false;
|
||||
|
||||
VkFence flushedFence = VK_NULL_HANDLE;
|
||||
std::shared_ptr<VulkanCmdFence> flushedFenceStatus;
|
||||
|
||||
// Note that we've ordered it so that the non-protected commands are followed by the protected
|
||||
// commands. This assumes that the protected commands will be that one doing the rendering into
|
||||
// the protected memory (i.e. protected render target).
|
||||
@@ -446,17 +434,12 @@ bool VulkanCommands::flush() {
|
||||
}
|
||||
if (lastSubmit != VK_NULL_HANDLE) {
|
||||
// Note that the stage we're waiting on is the fragment shader stage. This assumes
|
||||
// that the subsequent command buffer will only depend on
|
||||
// 1) fragment output of the previous command buffer
|
||||
// 2) reading/writing of buffers (i.e. UBO) of the previous command buffer
|
||||
// Restricting the wait stages will allow for vertex work to proceed (more overlapping
|
||||
// that the subsequent command buffer will only dependent on the fragment output of the
|
||||
// previous buffer, allowing for vertex work to proceed (more overlapping
|
||||
// vertex/fragment work).
|
||||
pool->waitFor(lastSubmit,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
pool->waitFor(lastSubmit, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
lastSubmit = VK_NULL_HANDLE;
|
||||
}
|
||||
flushedFence = pool->getRecording().getVkFence();
|
||||
flushedFenceStatus = pool->getRecording().getFenceStatus();
|
||||
dependency = pool->flush();
|
||||
hasFlushed = true;
|
||||
}
|
||||
@@ -464,8 +447,6 @@ bool VulkanCommands::flush() {
|
||||
if (hasFlushed) {
|
||||
mInjectedDependency = VK_NULL_HANDLE;
|
||||
mLastSubmit = dependency;
|
||||
mLastFence = flushedFence;
|
||||
mLastFenceStatus = flushedFenceStatus;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -542,7 +523,7 @@ void VulkanCommands::insertEventMarker(char const* str, uint32_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
CString VulkanCommands::getTopGroupMarker() const {
|
||||
std::string VulkanCommands::getTopGroupMarker() const {
|
||||
if (mProtectedPool) {
|
||||
return mProtectedPool->topMarker();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "vulkan/utils/StaticVector.h"
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
@@ -36,6 +35,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace filament::backend {
|
||||
@@ -47,14 +47,14 @@ class VulkanGroupMarkers {
|
||||
public:
|
||||
using Timestamp = std::chrono::time_point<std::chrono::high_resolution_clock>;
|
||||
|
||||
void push(utils::CString const& marker, Timestamp start = {}) noexcept;
|
||||
std::pair<utils::CString, Timestamp> pop() noexcept;
|
||||
std::pair<utils::CString, Timestamp> pop_bottom() noexcept;
|
||||
std::pair<utils::CString, Timestamp> const& top() const;
|
||||
void push(std::string const& marker, Timestamp start = {}) noexcept;
|
||||
std::pair<std::string, Timestamp> pop() noexcept;
|
||||
std::pair<std::string, Timestamp> pop_bottom() noexcept;
|
||||
std::pair<std::string, Timestamp> const& top() const;
|
||||
bool empty() const noexcept;
|
||||
|
||||
private:
|
||||
std::list<std::pair<utils::CString, Timestamp>> mMarkers;
|
||||
std::list<std::pair<std::string, Timestamp>> mMarkers;
|
||||
};
|
||||
|
||||
#endif // FVK_DEBUG_GROUP_MARKERS
|
||||
@@ -148,9 +148,9 @@ struct CommandBufferPool {
|
||||
void waitFor(VkSemaphore previousAction, VkPipelineStageFlags waitStage);
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
|
||||
utils::CString topMarker() const;
|
||||
std::string topMarker() const;
|
||||
void pushMarker(char const* marker, VulkanGroupMarkers::Timestamp timestamp);
|
||||
std::pair<utils::CString, VulkanGroupMarkers::Timestamp> popMarker();
|
||||
std::pair<std::string, VulkanGroupMarkers::Timestamp> popMarker();
|
||||
void insertEvent(char const* marker);
|
||||
#endif
|
||||
|
||||
@@ -223,19 +223,11 @@ public:
|
||||
// it from the existing dependency chain. This is especially useful for setting up
|
||||
// vkQueuePresentKHR.
|
||||
VkSemaphore acquireFinishedSignal() {
|
||||
VkSemaphore ret = mLastSubmit;
|
||||
VkSemaphore ret= mLastSubmit;
|
||||
mLastSubmit = VK_NULL_HANDLE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
VkFence getMostRecentFence() {
|
||||
return mLastFence;
|
||||
}
|
||||
|
||||
std::shared_ptr<VulkanCmdFence> getMostRecentFenceStatus() {
|
||||
return mLastFenceStatus;
|
||||
}
|
||||
|
||||
// Takes a semaphore that signals when the next flush can occur. Only one injected
|
||||
// semaphore is allowed per flush. Useful after calling vkAcquireNextImageKHR.
|
||||
// waitStage
|
||||
@@ -257,7 +249,7 @@ public:
|
||||
void pushGroupMarker(char const* str, VulkanGroupMarkers::Timestamp timestamp = {});
|
||||
void popGroupMarker();
|
||||
void insertEventMarker(char const* string, uint32_t len);
|
||||
utils::CString getTopGroupMarker() const;
|
||||
std::string getTopGroupMarker() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -273,9 +265,6 @@ private:
|
||||
VkSemaphore mInjectedDependency = VK_NULL_HANDLE;
|
||||
VkSemaphore mLastSubmit = VK_NULL_HANDLE;
|
||||
|
||||
VkFence mLastFence = VK_NULL_HANDLE;
|
||||
std::shared_ptr<VulkanCmdFence> mLastFenceStatus;
|
||||
|
||||
VkPipelineStageFlags mInjectedDependencyWaitStage = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -106,10 +106,6 @@ public:
|
||||
return mPhysicalDeviceProperties.properties.vendorID;
|
||||
}
|
||||
|
||||
inline VkExternalFenceHandleTypeFlags getFenceExportFlags() const noexcept {
|
||||
return mFenceExportFlags;
|
||||
}
|
||||
|
||||
inline bool isImageCubeArraySupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.features.imageCubeArray == VK_TRUE;
|
||||
}
|
||||
@@ -172,9 +168,6 @@ private:
|
||||
// non-conformant vulkan implementation).
|
||||
.imageView2DOn3DImage = VK_TRUE,
|
||||
};
|
||||
|
||||
VkExternalFenceHandleTypeFlags mFenceExportFlags = {};
|
||||
|
||||
bool mDebugMarkersSupported = false;
|
||||
bool mDebugUtilsSupported = false;
|
||||
bool mLazilyAllocatedMemorySupported = false;
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
@@ -137,13 +136,6 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsCallback(VkDebugUtilsMessageSeverityFla
|
||||
}
|
||||
#endif // FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||
|
||||
static CallbackHandler::Callback syncCallbackWrapper = [](void* userData) {
|
||||
std::unique_ptr<VulkanSync::CallbackData> cbData(
|
||||
static_cast<VulkanSync::CallbackData*>(userData));
|
||||
// This assumes the sync has not yet been destroyed. If it has, this will be
|
||||
// undefined behavior.
|
||||
cbData->cb(cbData->sync, cbData->userData);
|
||||
};
|
||||
|
||||
}// anonymous namespace
|
||||
|
||||
@@ -240,7 +232,6 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context,
|
||||
mExternalImageManager(platform, &mSamplerCache, &mYcbcrConversionCache, &mDescriptorSetCache,
|
||||
&mDescriptorSetLayoutCache),
|
||||
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported),
|
||||
mIsMSAASwapChainSupported(false), // TODO: support MSAA swapchain
|
||||
mStereoscopicType(driverConfig.stereoscopicType) {
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||
@@ -425,8 +416,6 @@ void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||
|
||||
void VulkanDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
|
||||
FrameScheduledCallback&& callback, uint64_t flags) {
|
||||
auto swapChain = resource_ptr<VulkanSwapChain>::cast(&mResourceManager, sch);
|
||||
swapChain->setFrameScheduledCallback(handler, std::move(callback));
|
||||
}
|
||||
|
||||
void VulkanDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
|
||||
@@ -485,16 +474,6 @@ void VulkanDriver::finish(int dummy) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
endCommandRecording();
|
||||
|
||||
// It's not enough to wait on the fences of the buffers submitted. Present calls are
|
||||
// submitted to this same queue, so the more correct option is to call vkQueueWaitIdle.
|
||||
vkQueueWaitIdle(mPlatform->getGraphicsQueue());
|
||||
if (auto protectedQueue = mPlatform->getProtectedGraphicsQueue();
|
||||
UTILS_UNLIKELY(protectedQueue != VK_NULL_HANDLE)) {
|
||||
vkQueueWaitIdle(protectedQueue);
|
||||
}
|
||||
|
||||
// This wait() is still necessary to update the fence status.
|
||||
mCommands.wait();
|
||||
|
||||
mReadPixels.runUntilComplete();
|
||||
@@ -502,13 +481,12 @@ void VulkanDriver::finish(int dummy) {
|
||||
|
||||
void VulkanDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType pt, utils::CString tag) {
|
||||
PrimitiveType pt) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vb = resource_ptr<VulkanVertexBuffer>::cast(&mResourceManager, vbh);
|
||||
auto ib = resource_ptr<VulkanIndexBuffer>::cast(&mResourceManager, ibh);
|
||||
auto ptr = resource_ptr<VulkanRenderPrimitive>::make(&mResourceManager, rph, pt, vb, ib);
|
||||
ptr.inc();
|
||||
mResourceManager.associateHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
@@ -521,12 +499,11 @@ void VulkanDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::CString tag) {
|
||||
uint8_t attributeCount, AttributeArray attributes) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vbi = resource_ptr<VulkanVertexBufferInfo>::make(&mResourceManager, vbih, bufferCount,
|
||||
attributeCount, attributes);
|
||||
vbi.inc();
|
||||
mResourceManager.associateHandle(vbih.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyVertexBufferInfo(Handle<HwVertexBufferInfo> vbih) {
|
||||
@@ -539,13 +516,12 @@ void VulkanDriver::destroyVertexBufferInfo(Handle<HwVertexBufferInfo> vbih) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh, uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih, utils::CString tag) {
|
||||
Handle<HwVertexBufferInfo> vbih) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vbi = resource_ptr<VulkanVertexBufferInfo>::cast(&mResourceManager, vbih);
|
||||
auto vb = resource_ptr<VulkanVertexBuffer>::make(&mResourceManager, vbh, mContext, mStagePool,
|
||||
vertexCount, vbi);
|
||||
vb.inc();
|
||||
mResourceManager.associateHandle(vbh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
|
||||
@@ -558,13 +534,12 @@ void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage, utils::CString tag) {
|
||||
uint32_t indexCount, BufferUsage usage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto elementSize = (uint8_t) getElementTypeSize(elementType);
|
||||
auto ib = resource_ptr<VulkanIndexBuffer>::make(&mResourceManager, ibh, mContext, mAllocator,
|
||||
mStagePool, mBufferCache, elementSize, indexCount);
|
||||
ib.inc();
|
||||
mResourceManager.associateHandle(ibh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
|
||||
@@ -577,12 +552,11 @@ void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::CString tag) {
|
||||
BufferObjectBinding bindingType, BufferUsage usage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto bo = resource_ptr<VulkanBufferObject>::make(&mResourceManager, boh, mContext, mAllocator,
|
||||
mStagePool, mBufferCache, byteCount, bindingType);
|
||||
bo.inc();
|
||||
mResourceManager.associateHandle(boh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyBufferObject(Handle<HwBufferObject> boh) {
|
||||
@@ -596,7 +570,7 @@ void VulkanDriver::destroyBufferObject(Handle<HwBufferObject> boh) {
|
||||
|
||||
void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage, utils::CString tag) {
|
||||
TextureUsage usage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mResourceManager, &mCommands,
|
||||
@@ -609,34 +583,31 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
texture->transitionLayout(&commandsBuf, primaryViewRange, defaultLayout);
|
||||
|
||||
texture.inc();
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::CString tag) {
|
||||
uint8_t baseLevel, uint8_t levelCount) {
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, baseLevel,
|
||||
levelCount);
|
||||
texture.inc();
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a, utils::CString tag) {
|
||||
TextureSwizzle const swizzleArray[] = { r, g, b, a };
|
||||
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
|
||||
texture.inc();
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
backend::TextureSwizzle a) {
|
||||
TextureSwizzle const swizzleArray[] = {r, g, b, a};
|
||||
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
|
||||
texture.inc();
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage, utils::CString tag) {
|
||||
Platform::ExternalImageHandleRef externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto metadata = mPlatform->extractExternalImageMetadata(externalImage);
|
||||
|
||||
@@ -682,12 +653,11 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
|
||||
}
|
||||
|
||||
texture.inc();
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* externalImage, utils::CString tag) {
|
||||
void* externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
// not supported in this backend
|
||||
@@ -695,17 +665,16 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
|
||||
|
||||
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane, utils::CString tag) {
|
||||
void* image, uint32_t plane) {
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
}
|
||||
|
||||
void VulkanDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage, utils::CString tag) {
|
||||
TextureUsage usage) {
|
||||
// not supported in this backend
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
@@ -718,12 +687,11 @@ void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
mExternalImageManager.removeExternallySampledTexture(texture);
|
||||
}
|
||||
|
||||
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::CString tag) {
|
||||
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vprogram = resource_ptr<VulkanProgram>::make(&mResourceManager, ph, mPlatform->getDevice(),
|
||||
program);
|
||||
vprogram.inc();
|
||||
mResourceManager.associateHandle(ph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
|
||||
@@ -734,20 +702,18 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
|
||||
vprogram.dec();
|
||||
}
|
||||
|
||||
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString tag) {
|
||||
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
||||
assert_invariant(mDefaultRenderTarget); // Default render target should already exist.
|
||||
|
||||
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth,
|
||||
std::move(std::move(*mDefaultRenderTarget.get())));
|
||||
|
||||
mDefaultRenderTarget = renderTarget;
|
||||
mResourceManager.associateHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
TargetBufferFlags targets, uint32_t width, uint32_t height, uint8_t samples,
|
||||
uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil,
|
||||
utils::CString tag) {
|
||||
uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil) {
|
||||
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
@@ -808,8 +774,6 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
mPlatform->getPhysicalDevice(), mContext, &mResourceManager, mAllocator, &mCommands,
|
||||
width, height, samples, colorTargets, depthStencil, mStagePool, layerCount);
|
||||
rt.inc();
|
||||
|
||||
mResourceManager.associateHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
|
||||
@@ -818,13 +782,15 @@ void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
|
||||
}
|
||||
|
||||
auto rt = resource_ptr<VulkanRenderTarget>::cast(&mResourceManager, rth);
|
||||
// Note that the default render target will be destroyed on shutdown
|
||||
if (UTILS_LIKELY(rt != mDefaultRenderTarget)) {
|
||||
if (UTILS_UNLIKELY(rt == mDefaultRenderTarget)) {
|
||||
// Note that this should only happen on driver shutdown.
|
||||
mDefaultRenderTarget = {};
|
||||
} else {
|
||||
rt.dec();
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
|
||||
void VulkanDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||
VulkanCommandBuffer* cmdbuf;
|
||||
if (mCurrentRenderPass.commandBuffer) {
|
||||
cmdbuf = mCurrentRenderPass.commandBuffer;
|
||||
@@ -836,57 +802,19 @@ void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString tag) {
|
||||
// buffer.
|
||||
auto fence = resource_ptr<VulkanFence>::cast(&mResourceManager, fh);
|
||||
fence->fence = cmdbuf->getFenceStatus();
|
||||
mResourceManager.associateHandle(fh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createSyncR(Handle<HwSync> sh, utils::CString tag) {
|
||||
auto sync = resource_ptr<VulkanSync>::cast(&mResourceManager, sh);
|
||||
VkFence fence = VK_NULL_HANDLE;
|
||||
std::shared_ptr<VulkanCmdFence> fenceStatus;
|
||||
if (mCurrentRenderPass.commandBuffer) {
|
||||
VulkanCommandBuffer* cmdBuff = mCurrentRenderPass.commandBuffer;
|
||||
fence = cmdBuff->getVkFence();
|
||||
fenceStatus = cmdBuff->getFenceStatus();
|
||||
// If we're currently recording, flush so that the fence only applies
|
||||
// to commands already issued.
|
||||
mCommands.flush();
|
||||
} else {
|
||||
fence = mCommands.getMostRecentFence();
|
||||
fenceStatus = mCommands.getMostRecentFenceStatus();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(sync->lock);
|
||||
sync->sync = mPlatform->createSync(fence, fenceStatus);
|
||||
}
|
||||
|
||||
for (auto& cbData : sync->conversionCallbacks) {
|
||||
cbData->sync = sync->sync;
|
||||
scheduleCallback(cbData->handler, cbData.release(), syncCallbackWrapper);
|
||||
}
|
||||
|
||||
sync->conversionCallbacks.clear();
|
||||
mResourceManager.associateHandle(sh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
|
||||
utils::CString tag) {
|
||||
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
// Running gc() to guard against an edge case where the old swapchains need to have been
|
||||
// destroyed before the new swapchain can be created. Otherwise, we would fail
|
||||
// vkCreateSwapchainKHR with VK_ERROR_NATIVE_WINDOW_IN_USE_KHR.
|
||||
mResourceManager.gc();
|
||||
|
||||
// TODO: support MSAA swapchain
|
||||
|
||||
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
||||
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
|
||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
||||
}
|
||||
if ((flags & backend::SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES) != 0 && !isMSAASwapChainSupported(4)) {
|
||||
FVK_LOGW << "MSAAx4 swapchain requested, but Platform does not support it";
|
||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_MSAA_4_SAMPLES);
|
||||
}
|
||||
if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
|
||||
if (!isProtectedContentSupported()) {
|
||||
FVK_LOGW << "protected swapchain requested, but Platform does not support it";
|
||||
@@ -895,11 +823,10 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
auto swapChain = resource_ptr<VulkanSwapChain>::make(&mResourceManager, sch, mPlatform,
|
||||
mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nativeWindow, flags);
|
||||
swapChain.inc();
|
||||
mResourceManager.associateHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||
uint32_t height, uint64_t flags, utils::CString tag) {
|
||||
uint32_t height, uint64_t flags) {
|
||||
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
||||
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
|
||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
||||
@@ -909,24 +836,21 @@ void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
|
||||
mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nullptr, flags,
|
||||
VkExtent2D{width, height});
|
||||
swapChain.inc();
|
||||
mResourceManager.associateHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {
|
||||
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
mResourceManager.associateHandle(tqh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
backend::DescriptorSetLayout&& info, utils::CString tag) {
|
||||
backend::DescriptorSetLayout&& info) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info));
|
||||
layout.inc();
|
||||
mResourceManager.associateHandle(dslh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh, utils::CString tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout =
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
||||
@@ -936,8 +860,6 @@ void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
if (layout->hasExternalSamplers()) {
|
||||
mAppState.hasExternalSamplerLayouts = true;
|
||||
}
|
||||
|
||||
mResourceManager.associateHandle(dsh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
Handle<HwVertexBufferInfo> VulkanDriver::createVertexBufferInfoS() noexcept {
|
||||
@@ -1007,13 +929,6 @@ Handle<HwFence> VulkanDriver::createFenceS() noexcept {
|
||||
return handle;
|
||||
}
|
||||
|
||||
Handle<HwSync> VulkanDriver::createSyncS() noexcept {
|
||||
auto handle = mResourceManager.allocHandle<VulkanSync>();
|
||||
auto sync = resource_ptr<VulkanSync>::make(&mResourceManager, handle);
|
||||
sync.inc();
|
||||
return handle;
|
||||
}
|
||||
|
||||
Handle<HwSwapChain> VulkanDriver::createSwapChainS() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanSwapChain>();
|
||||
}
|
||||
@@ -1052,17 +967,6 @@ void VulkanDriver::destroySwapChain(Handle<HwSwapChain> sch) {
|
||||
void VulkanDriver::destroyStream(Handle<HwStream> sh) {
|
||||
}
|
||||
|
||||
void VulkanDriver::destroySync(Handle<HwSync> sh) {
|
||||
if (!sh) {
|
||||
return;
|
||||
}
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
auto sync = resource_ptr<VulkanSync>::cast(&mResourceManager, sh);
|
||||
mPlatform->destroySync(sync->sync);
|
||||
sync.dec();
|
||||
}
|
||||
|
||||
void VulkanDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
if (!tqh) {
|
||||
return;
|
||||
@@ -1081,16 +985,16 @@ void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
|
||||
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
|
||||
set.dec();
|
||||
|
||||
if (mAppState.hasExternalSamplers()) {
|
||||
if (mAppState.hasExternalSamplers() && set->getExternalSamplerVkSet() != VK_NULL_HANDLE) {
|
||||
mExternalImageManager.removeDescriptorSet(set);
|
||||
}
|
||||
}
|
||||
|
||||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> VulkanDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> VulkanDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1138,29 +1042,6 @@ FenceStatus VulkanDriver::getFenceStatus(Handle<HwFence> fh) {
|
||||
return FenceStatus::TIMEOUT_EXPIRED;
|
||||
}
|
||||
|
||||
void VulkanDriver::getPlatformSync(Handle<HwSync> sh, CallbackHandler* handler,
|
||||
Platform::SyncCallback cb, void* userData) {
|
||||
auto sync = resource_ptr<VulkanSync>::cast(&mResourceManager, sh);
|
||||
auto cbData = std::make_unique<VulkanSync::CallbackData>();
|
||||
cbData->handler = handler;
|
||||
cbData->cb = cb;
|
||||
cbData->userData = userData;
|
||||
|
||||
// If we haven't already set the handle, toss the conversion callback in the
|
||||
// back of the list.
|
||||
{
|
||||
std::lock_guard guard(sync->lock);
|
||||
if (sync->sync == nullptr) {
|
||||
sync->conversionCallbacks.push_back(std::move(cbData));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, go ahead and schedule the callback now.
|
||||
cbData->sync = sync->sync;
|
||||
scheduleCallback(cbData->handler, cbData.release(), syncCallbackWrapper);
|
||||
}
|
||||
|
||||
// We create all textures using VK_IMAGE_TILING_OPTIMAL, so our definition of "supported" is that
|
||||
// the GPU supports the given texture format with non-zero optimal tiling features.
|
||||
bool VulkanDriver::isTextureFormatSupported(TextureFormat format) {
|
||||
@@ -1223,10 +1104,6 @@ bool VulkanDriver::isSRGBSwapChainSupported() {
|
||||
return mIsSRGBSwapChainSupported;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isMSAASwapChainSupported(uint32_t) {
|
||||
return mIsMSAASwapChainSupported;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isProtectedContentSupported() {
|
||||
return mContext.isProtectedMemorySupported();
|
||||
}
|
||||
@@ -1730,7 +1607,7 @@ void VulkanDriver::commit(Handle<HwSwapChain> sch) {
|
||||
auto swapChain = resource_ptr<VulkanSwapChain>::cast(&mResourceManager, sch);
|
||||
|
||||
// Present the backbuffer after the most recent command buffer submission has finished.
|
||||
swapChain->present(*this);
|
||||
swapChain->present();
|
||||
}
|
||||
|
||||
void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
@@ -1911,14 +1788,9 @@ void VulkanDriver::blitDEPRECATED(TargetBufferFlags buffers,
|
||||
VkOffset3D const srcOffsets[2] = { { srcLeft, srcTop, 0 }, { srcRight, srcBottom, 1 }};
|
||||
VkOffset3D const dstOffsets[2] = { { dstLeft, dstTop, 0 }, { dstRight, dstBottom, 1 }};
|
||||
|
||||
auto const& dstAttachment = dstTarget->getColor0();
|
||||
auto const& srcAttachment = srcTarget->getColor0();
|
||||
|
||||
if (srcAttachment.texture->samples > 1) {
|
||||
mBlitter.resolve(dstAttachment, srcAttachment);
|
||||
} else {
|
||||
mBlitter.blit(vkfilter, dstAttachment, dstOffsets, srcAttachment, srcOffsets);
|
||||
}
|
||||
mBlitter.blit(vkfilter,
|
||||
dstTarget->getColor0(), dstOffsets,
|
||||
srcTarget->getColor0(), srcOffsets);
|
||||
}
|
||||
|
||||
void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
@@ -2207,6 +2079,10 @@ void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, cons
|
||||
void VulkanDriver::resetState(int) {
|
||||
}
|
||||
|
||||
void VulkanDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||
mResourceManager.associateHandle(handleId, std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::endCommandRecording() {
|
||||
mCommands.flush();
|
||||
mPipelineCache.resetBoundPipeline();
|
||||
|
||||
@@ -187,7 +187,6 @@ private:
|
||||
} mAppState;
|
||||
|
||||
bool const mIsSRGBSwapChainSupported;
|
||||
bool const mIsMSAASwapChainSupported;
|
||||
backend::StereoscopicType const mStereoscopicType;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <utils/compiler.h> // UTILS_FALLTHROUGH
|
||||
#include <utils/Panic.h> // ASSERT_POSTCONDITION
|
||||
#include <utils/CString.h>
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
@@ -286,7 +285,7 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||
utils::CString name{ builder.getName().c_str(), builder.getName().size() };
|
||||
std::string name{ builder.getName().c_str(), builder.getName().size() };
|
||||
switch (static_cast<ShaderStage>(i)) {
|
||||
case ShaderStage::VERTEX:
|
||||
name += "_vs";
|
||||
|
||||
@@ -308,10 +308,7 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
|
||||
// Creates a special "default" render target (i.e. associated with the swap chain)
|
||||
explicit VulkanRenderTarget();
|
||||
|
||||
VulkanRenderTarget(VulkanRenderTarget&& target)
|
||||
: HwRenderTarget(0, 0),
|
||||
mOffscreen(false),
|
||||
mProtected(false) {
|
||||
VulkanRenderTarget(VulkanRenderTarget&& target) {
|
||||
swap(std::move(target));
|
||||
}
|
||||
|
||||
@@ -368,8 +365,6 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
|
||||
|
||||
private:
|
||||
void swap(VulkanRenderTarget&& target) {
|
||||
std::swap(width, target.width);
|
||||
std::swap(height, target.height);
|
||||
std::swap(mOffscreen, target.mOffscreen);
|
||||
std::swap(mProtected, target.mProtected);
|
||||
std::swap(mInfo, target.mInfo);
|
||||
|
||||
@@ -93,7 +93,7 @@ void VulkanSwapChain::update() {
|
||||
mLayerCount = bundle.layerCount;
|
||||
}
|
||||
|
||||
void VulkanSwapChain::present(DriverBase& driver) {
|
||||
void VulkanSwapChain::present() {
|
||||
if (!mHeadless && mTransitionSwapChainImageLayoutForPresent) {
|
||||
VulkanCommandBuffer& commands = mCommands->get();
|
||||
VkImageSubresourceRange const subresources{
|
||||
@@ -120,14 +120,6 @@ void VulkanSwapChain::present(DriverBase& driver) {
|
||||
// We presented the last acquired buffer.
|
||||
mAcquired = false;
|
||||
mIsFirstRenderPass = true;
|
||||
|
||||
if (frameScheduled.callback) {
|
||||
driver.scheduleCallback(frameScheduled.handler,
|
||||
[callback = std::move(frameScheduled.callback)]() {
|
||||
PresentCallable noop = PresentCallable(PresentCallable::noopPresent, nullptr);
|
||||
callback(noop);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanSwapChain::acquire(bool& resized) {
|
||||
|
||||
@@ -47,7 +47,7 @@ struct VulkanSwapChain : public HwSwapChain, fvkmemory::Resource {
|
||||
|
||||
~VulkanSwapChain();
|
||||
|
||||
void present(DriverBase& driver);
|
||||
void present();
|
||||
|
||||
// Acquire a new image from the swapchain. If the image is not available it would wait until it
|
||||
// is.
|
||||
@@ -79,13 +79,6 @@ struct VulkanSwapChain : public HwSwapChain, fvkmemory::Resource {
|
||||
inline bool isProtected() noexcept {
|
||||
return mPlatform->isProtected(swapChain);
|
||||
}
|
||||
|
||||
inline void setFrameScheduledCallback(CallbackHandler* handler,
|
||||
FrameScheduledCallback&& callback) noexcept {
|
||||
frameScheduled.handler = handler;
|
||||
frameScheduled.callback = std::move(callback);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int IMAGE_READY_SEMAPHORE_COUNT = FVK_MAX_COMMAND_BUFFERS;
|
||||
|
||||
@@ -101,12 +94,6 @@ private:
|
||||
bool const mFlushAndWaitOnResize;
|
||||
bool const mTransitionSwapChainImageLayoutForPresent;
|
||||
|
||||
// These fields store a callback to notify the client that Filament is commiting a frame.
|
||||
struct {
|
||||
CallbackHandler* handler = nullptr;
|
||||
FrameScheduledCallback callback;
|
||||
} frameScheduled;
|
||||
|
||||
// We create VulkanTextures based on VkImages. VulkanTexture has facilities for doing layout
|
||||
// transitions, which are useful here.
|
||||
utils::FixedCapacityVector<fvkmemory::resource_ptr<VulkanTexture>> mColors;
|
||||
|
||||
@@ -106,7 +106,7 @@ VkComponentMapping composeSwizzle(VkComponentMapping const& prev, VkComponentMap
|
||||
return { vals[0], vals[1], vals[2], vals[3] };
|
||||
};
|
||||
|
||||
// We make sure all identities are mapped into respective channels so that actual channel
|
||||
// We make sure all all identities are mapped into respective channels so that actual channel
|
||||
// mapping will be passed onto the output.
|
||||
VkComponentMapping const prevExplicit = identityToChannel(prev);
|
||||
VkComponentMapping const nextExplicit = identityToChannel(next);
|
||||
|
||||
@@ -38,7 +38,6 @@ template ResourceType getTypeEnum<VulkanDescriptorSetLayout>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanDescriptorSet>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanFence>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanBuffer>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanSync>() noexcept;
|
||||
|
||||
template<typename D>
|
||||
ResourceType getTypeEnum() noexcept {
|
||||
@@ -93,13 +92,10 @@ ResourceType getTypeEnum() noexcept {
|
||||
if constexpr (std::is_same_v<D, VulkanBuffer>) {
|
||||
return ResourceType::VULKAN_BUFFER;
|
||||
}
|
||||
if constexpr (std::is_same_v<D, VulkanSync>) {
|
||||
return ResourceType::SYNC;
|
||||
}
|
||||
return ResourceType::UNDEFINED_TYPE;
|
||||
}
|
||||
|
||||
std::string_view getTypeStr(ResourceType type) {
|
||||
std::string getTypeStr(ResourceType type) {
|
||||
switch (type) {
|
||||
case ResourceType::BUFFER_OBJECT:
|
||||
return "BufferObject";
|
||||
@@ -135,8 +131,6 @@ std::string_view getTypeStr(ResourceType type) {
|
||||
return "Fence";
|
||||
case ResourceType::VULKAN_BUFFER:
|
||||
return "VulkanBuffer";
|
||||
case ResourceType::SYNC:
|
||||
return "Sync";
|
||||
case ResourceType::UNDEFINED_TYPE:
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -52,14 +52,13 @@ enum class ResourceType : uint8_t {
|
||||
VULKAN_BUFFER = 14,
|
||||
STAGE_SEGMENT = 15,
|
||||
STAGE_IMAGE = 16,
|
||||
SYNC = 17,
|
||||
UNDEFINED_TYPE = 18, // Must be the last enum because we use it for iterating over the enums.
|
||||
UNDEFINED_TYPE = 17, // Must be the last enum because we use it for iterating over the enums.
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
ResourceType getTypeEnum() noexcept;
|
||||
|
||||
std::string_view getTypeStr(ResourceType type);
|
||||
std::string getTypeStr(ResourceType type);
|
||||
|
||||
inline bool isThreadSafeType(ResourceType type) {
|
||||
return type == ResourceType::FENCE || type == ResourceType::TIMER_QUERY;
|
||||
|
||||
@@ -114,9 +114,6 @@ void ResourceManager::destroyWithType(ResourceType type, HandleId id) {
|
||||
case ResourceType::VULKAN_BUFFER:
|
||||
destruct<VulkanBuffer>(Handle<VulkanBuffer>(id));
|
||||
break;
|
||||
case ResourceType::SYNC:
|
||||
destruct<VulkanSync>(Handle<VulkanSync>(id));
|
||||
break;
|
||||
case ResourceType::UNDEFINED_TYPE:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
|
||||
ExtensionSet const TARGET_EXTS = {
|
||||
// Request all cross-platform extensions.
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
||||
|
||||
// Request these if available.
|
||||
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||
@@ -235,6 +236,9 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
|
||||
#if defined(__APPLE__)
|
||||
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
|
||||
#endif
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE2_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE3_EXTENSION_NAME,
|
||||
VK_KHR_MULTIVIEW_EXTENSION_NAME,
|
||||
};
|
||||
ExtensionSet exts;
|
||||
@@ -916,8 +920,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
context.mBlittableDepthStencilFormats =
|
||||
findBlittableDepthStencilFormats(mImpl->mPhysicalDevice);
|
||||
|
||||
context.mFenceExportFlags = getFenceExportFlags();
|
||||
|
||||
assert_invariant(context.mDepthStencilFormats.size() > 0);
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
|
||||
@@ -1000,17 +1002,6 @@ SwapChainPtr VulkanPlatform::createSwapChain(void* nativeWindow, uint64_t flags,
|
||||
return swapchain;
|
||||
}
|
||||
|
||||
Platform::Sync* VulkanPlatform::createSync(VkFence fence,
|
||||
std::shared_ptr<VulkanCmdFence> fenceStatus) noexcept {
|
||||
return new VulkanSync{.fence = fence, .fenceStatus = fenceStatus};
|
||||
}
|
||||
|
||||
void VulkanPlatform::destroySync(Platform::Sync* sync) noexcept {
|
||||
// Sync must be a VulkanSync*, since it was created by VulkanPlatform's
|
||||
// createSync object.
|
||||
delete sync;
|
||||
}
|
||||
|
||||
VkInstance VulkanPlatform::getInstance() const noexcept {
|
||||
return mImpl->mInstance;
|
||||
}
|
||||
@@ -1047,11 +1038,6 @@ VkQueue VulkanPlatform::getProtectedGraphicsQueue() const noexcept {
|
||||
return mImpl->mProtectedGraphicsQueue;
|
||||
}
|
||||
|
||||
VkExternalFenceHandleTypeFlagBits VulkanPlatform::getFenceExportFlags() const noexcept {
|
||||
// By default, fences should not be exportable.
|
||||
return static_cast<VkExternalFenceHandleTypeFlagBits>(0);
|
||||
}
|
||||
|
||||
ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() const {
|
||||
return getSwapchainInstanceExtensionsImpl();
|
||||
}
|
||||
|
||||
@@ -389,37 +389,6 @@ VulkanPlatform::ImageData VulkanPlatformAndroid::createVkImageFromExternal(
|
||||
};
|
||||
}
|
||||
|
||||
bool VulkanPlatformAndroid::convertSyncToFd(Platform::Sync* sync, int* fd) const noexcept {
|
||||
assert_invariant(sync && fd);
|
||||
|
||||
VulkanSync& vulkanSync = static_cast<VulkanSync&>(*sync);
|
||||
assert_invariant(vulkanSync.fenceStatus);
|
||||
|
||||
if (vulkanSync.fenceStatus->getStatus() == VK_SUCCESS) {
|
||||
// We've already signaled; return -1 so that operations will proceed
|
||||
// immediately. Also, signal that fence conversion was successful.
|
||||
*fd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
VkFenceGetFdInfoKHR getFdInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
|
||||
.fence = vulkanSync.fence,
|
||||
.handleType = getFenceExportFlags(),
|
||||
};
|
||||
VkResult res = vkGetFenceFdKHR(getDevice(), &getFdInfo, fd);
|
||||
if (res != VK_SUCCESS) {
|
||||
LOG(ERROR) << "Failed to convert sync to fd: " << res;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VkExternalFenceHandleTypeFlagBits VulkanPlatformAndroid::getFenceExportFlags() const noexcept {
|
||||
// On android, make fences that can be exported to fd's.
|
||||
return VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatformAndroid::getSwapchainInstanceExtensions() const {
|
||||
return {
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#ifndef VK_EXT_metal_surface
|
||||
#error VK_EXT_metal_surface is not defined
|
||||
#ifndef VK_MVK_macos_surface
|
||||
#error VK_MVK_macos_surface is not defined
|
||||
#endif
|
||||
|
||||
using namespace bluevk;
|
||||
@@ -38,7 +38,7 @@ namespace filament::backend {
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() {
|
||||
ExtensionSet const ret = {
|
||||
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
|
||||
VK_MVK_MACOS_SURFACE_EXTENSION_NAME, // TODO: replace with VK_EXT_metal_surface
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
@@ -46,18 +46,17 @@ VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl(
|
||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
|
||||
VkInstance instance, uint64_t flags) noexcept {
|
||||
VkSurfaceKHR surface;
|
||||
CAMetalLayer* mlayer = (__bridge CAMetalLayer*) nativeWindow;
|
||||
FILAMENT_CHECK_POSTCONDITION(mlayer) << "Unable to obtain Metal-backed layer.";
|
||||
NSView* nsview = (__bridge NSView*) nativeWindow;
|
||||
FILAMENT_CHECK_POSTCONDITION(nsview) << "Unable to obtain Metal-backed NSView.";
|
||||
|
||||
// Create the VkSurface.
|
||||
FILAMENT_CHECK_POSTCONDITION(vkCreateMetalSurfaceEXT)
|
||||
<< "Unable to load vkCreateMetalSurfaceEXT.";
|
||||
VkMetalSurfaceCreateInfoEXT createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
|
||||
.pLayer = mlayer,
|
||||
};
|
||||
VkResult result =
|
||||
vkCreateMetalSurfaceEXT(instance, &createInfo, VKALLOC, &surface);
|
||||
FILAMENT_CHECK_POSTCONDITION(vkCreateMacOSSurfaceMVK)
|
||||
<< "Unable to load vkCreateMacOSSurfaceMVK.";
|
||||
VkMacOSSurfaceCreateInfoMVK createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
createInfo.pView = (__bridge void*) nsview;
|
||||
VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC,
|
||||
(VkSurfaceKHR*) &surface);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkCreateMacOSSurfaceMVK. error=" << static_cast<int32_t>(result);
|
||||
return std::make_tuple(surface, VkExtent2D{});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,6 @@
|
||||
#include "WebGPURenderTarget.h"
|
||||
#include "WebGPUStrings.h"
|
||||
#include "WebGPUSwapChain.h"
|
||||
#include "WebGPUSync.h"
|
||||
#include "WebGPUTexture.h"
|
||||
#include "WebGPUTextureHelpers.h"
|
||||
#include "WebGPUVertexBuffer.h"
|
||||
@@ -155,8 +154,7 @@ void WebGPUDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||
|
||||
void WebGPUDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
|
||||
CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t flags) {
|
||||
auto swapChain = handleCast<WebGPUSwapChain>(sch);
|
||||
swapChain->setFrameScheduledCallback(handler, std::move(callback));
|
||||
|
||||
}
|
||||
|
||||
void WebGPUDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
|
||||
@@ -209,17 +207,7 @@ void WebGPUDriver::finish(int /* dummy */) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
mDevice.Tick();
|
||||
mAdapter.GetInstance().ProcessEvents();
|
||||
mReadPixelMapsCounter.waitForAllToFinish();
|
||||
flush();
|
||||
|
||||
// Some applications/samples might call finish in the very beginning of an application before
|
||||
// creating any resources/tasks to flush out the system on any pending work from previous runs.
|
||||
// Currently, gltf_viewer sample on android exhibit this behavior.
|
||||
// Bail out early to safeguard against those cases. Otherwise, OnSubmittedWorkDone will
|
||||
// hang on work that was never submitted.
|
||||
if (mCommandEncoder == nullptr) {
|
||||
return;
|
||||
}
|
||||
// Wait for all previously submitted work to finish.
|
||||
std::mutex syncPoint;
|
||||
std::condition_variable syncCondition;
|
||||
@@ -237,6 +225,7 @@ void WebGPUDriver::finish(int /* dummy */) {
|
||||
});
|
||||
std::unique_lock<std::mutex> lock(syncPoint);
|
||||
syncCondition.wait(lock, [&done] { return done; });
|
||||
mReadPixelMapsCounter.waitForAllToFinish();
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
@@ -378,10 +367,6 @@ Handle<HwFence> WebGPUDriver::createFenceS() noexcept {
|
||||
return allocAndConstructHandle<WebGPUFence, HwFence>();
|
||||
}
|
||||
|
||||
Handle<HwSync> WebGPUDriver::createSyncS() noexcept {
|
||||
return allocHandle<WebGPUSync>();
|
||||
}
|
||||
|
||||
Handle<HwTimerQuery> WebGPUDriver::createTimerQueryS() noexcept {
|
||||
return Handle<HwTimerQuery>((Handle<HwTimerQuery>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
@@ -450,11 +435,8 @@ Handle<HwTexture> WebGPUDriver::createTextureExternalImagePlaneS() noexcept {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
const uint64_t flags, utils::CString tag) {
|
||||
const uint64_t flags) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
|
||||
// TODO: support MSAA swapchain
|
||||
|
||||
mNativeWindow = nativeWindow;
|
||||
wgpu::Surface surface = mPlatform.createSurface(nativeWindow, flags);
|
||||
|
||||
@@ -475,12 +457,10 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
if (mDefaultRenderTarget) {
|
||||
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
|
||||
}
|
||||
|
||||
setDebugTag(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||
uint32_t height, uint64_t flags, utils::CString tag) {
|
||||
uint32_t height, uint64_t flags) {
|
||||
wgpu::Extent2D extent = { .width = width, .height = height };
|
||||
mSwapChain = constructHandle<WebGPUSwapChain>(sch, extent, mAdapter,
|
||||
mDevice, flags);
|
||||
@@ -488,69 +468,56 @@ void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
|
||||
if (mDefaultRenderTarget) {
|
||||
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
|
||||
}
|
||||
setDebugTag(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vertexBufferInfoHandle,
|
||||
const uint8_t bufferCount, const uint8_t attributeCount, const AttributeArray attributes,
|
||||
utils::CString tag) {
|
||||
const uint8_t bufferCount, const uint8_t attributeCount, const AttributeArray attributes) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUVertexBufferInfo>(vertexBufferInfoHandle, bufferCount, attributeCount,
|
||||
attributes, mDeviceLimits);
|
||||
setDebugTag(vertexBufferInfoHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createVertexBufferR(Handle<HwVertexBuffer> vertexBufferHandle,
|
||||
const uint32_t vertexCount, Handle<HwVertexBufferInfo> vertexBufferInfoHandle,
|
||||
utils::CString tag) {
|
||||
const uint32_t vertexCount, Handle<HwVertexBufferInfo> vertexBufferInfoHandle) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
const auto vertexBufferInfo = handleCast<WebGPUVertexBufferInfo>(vertexBufferInfoHandle);
|
||||
constructHandle<WebGPUVertexBuffer>(vertexBufferHandle, vertexCount,
|
||||
vertexBufferInfo->bufferCount, vertexBufferInfoHandle);
|
||||
setDebugTag(vertexBufferHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createIndexBufferR(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
const ElementType elementType, const uint32_t indexCount, const BufferUsage usage,
|
||||
utils::CString tag) {
|
||||
const ElementType elementType, const uint32_t indexCount, const BufferUsage usage) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
const auto elementSize = static_cast<uint8_t>(getElementTypeSize(elementType));
|
||||
constructHandle<WebGPUIndexBuffer>(indexBufferHandle, mDevice, elementSize, indexCount);
|
||||
setDebugTag(indexBufferHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createBufferObjectR(Handle<HwBufferObject> bufferObjectHandle,
|
||||
const uint32_t byteCount, const BufferObjectBinding bindingType, const BufferUsage usage,
|
||||
utils::CString tag) {
|
||||
const uint32_t byteCount, const BufferObjectBinding bindingType, const BufferUsage usage) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUBufferObject>(bufferObjectHandle, mDevice, bindingType, byteCount);
|
||||
setDebugTag(bufferObjectHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureR(Handle<HwTexture> textureHandle, const SamplerType target,
|
||||
const uint8_t levels, const TextureFormat format, const uint8_t samples,
|
||||
const uint32_t width, const uint32_t height, const uint32_t depth,
|
||||
const TextureUsage usage, utils::CString tag) {
|
||||
const TextureUsage usage) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUTexture>(textureHandle, target, levels, format, samples, width, height,
|
||||
depth, usage, mDevice);
|
||||
setDebugTag(textureHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureViewR(Handle<HwTexture> textureHandle,
|
||||
Handle<HwTexture> sourceTextureHandle, const uint8_t baseLevel, const uint8_t levelCount,
|
||||
utils::CString tag) {
|
||||
Handle<HwTexture> sourceTextureHandle, const uint8_t baseLevel, const uint8_t levelCount) {
|
||||
auto source = handleCast<WebGPUTexture>(sourceTextureHandle);
|
||||
|
||||
constructHandle<WebGPUTexture>(textureHandle, source, baseLevel, levelCount);
|
||||
|
||||
setDebugTag(textureHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> textureHandle,
|
||||
Handle<HwTexture> sourceTextureHandle, const backend::TextureSwizzle r,
|
||||
const backend::TextureSwizzle g, const backend::TextureSwizzle b,
|
||||
const backend::TextureSwizzle a, utils::CString tag) {
|
||||
const backend::TextureSwizzle a) {
|
||||
|
||||
if (!isTextureSwizzleSupported()) {
|
||||
FWGPU_LOGW << "WebGPUDriver::createTextureViewSwizzleR called while texture swizzling is "
|
||||
@@ -560,24 +527,37 @@ void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> textureHandle,
|
||||
auto sourceTexture{ handleCast<WebGPUTexture>(sourceTextureHandle) };
|
||||
assert_invariant(sourceTexture);
|
||||
|
||||
wgpu::TextureComponentSwizzle const nextSwizzle{
|
||||
wgpu::TextureComponentSwizzle swizzle
|
||||
{
|
||||
.r = toWGPUComponentSwizzle(r),
|
||||
.g = toWGPUComponentSwizzle(g),
|
||||
.b = toWGPUComponentSwizzle(b),
|
||||
.a = toWGPUComponentSwizzle(a),
|
||||
};
|
||||
|
||||
// The WebGPUTexture constructor for swizzled views will handle composing the swizzle and
|
||||
// creating the new texture view.
|
||||
constructHandle<WebGPUTexture>(textureHandle, sourceTexture, nextSwizzle);
|
||||
wgpu::TextureComponentSwizzleDescriptor swizzleDesc {};
|
||||
swizzleDesc.swizzle = swizzle;
|
||||
|
||||
setDebugTag(textureHandle.getId(), std::move(tag));
|
||||
const wgpu::TextureViewDescriptor viewDesc {
|
||||
.nextInChain = &swizzleDesc,
|
||||
.label = "swizzled_texture_view",
|
||||
.format = sourceTexture->getTexture().GetFormat(),
|
||||
.dimension = sourceTexture->getViewDimension(),
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = sourceTexture->getTexture().GetMipLevelCount(),
|
||||
.baseArrayLayer = 0,
|
||||
.arrayLayerCount = sourceTexture->getTexture().GetDepthOrArrayLayers(),
|
||||
};
|
||||
|
||||
wgpu::TextureView swizzledView{ sourceTexture->getTexture().CreateView(&viewDesc) };
|
||||
FILAMENT_CHECK_POSTCONDITION(swizzledView) << "Failed to create swizzled Texture view";
|
||||
constructHandle<WebGPUTexture>(textureHandle, sourceTexture, swizzledView);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImage2R(Handle<HwTexture> textureHandle,
|
||||
const backend::SamplerType target, const backend::TextureFormat format,
|
||||
const uint32_t width, const uint32_t height, const backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage, utils::CString tag) {
|
||||
Platform::ExternalImageHandleRef externalImage) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
@@ -585,27 +565,27 @@ void WebGPUDriver::createTextureExternalImage2R(Handle<HwTexture> textureHandle,
|
||||
void WebGPUDriver::createTextureExternalImageR(Handle<HwTexture> textureHandle,
|
||||
const backend::SamplerType target, const backend::TextureFormat format,
|
||||
const uint32_t width, const uint32_t height, const backend::TextureUsage usage,
|
||||
void* externalImage, utils::CString tag) {
|
||||
void* externalImage) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImagePlaneR(Handle<HwTexture> textureHandle,
|
||||
const backend::TextureFormat format, const uint32_t width, const uint32_t height,
|
||||
const backend::TextureUsage usage, void* image, const uint32_t plane, utils::CString tag) {
|
||||
const backend::TextureUsage usage, void* image, const uint32_t plane) {
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::importTextureR(Handle<HwTexture> textureHandle, const intptr_t id,
|
||||
const SamplerType target, const uint8_t levels, const TextureFormat format,
|
||||
const uint8_t samples, const uint32_t width, const uint32_t height, const uint32_t depth,
|
||||
const TextureUsage usage, utils::CString tag) {
|
||||
const TextureUsage usage) {
|
||||
PANIC_POSTCONDITION("Import WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> renderPrimitiveHandle,
|
||||
Handle<HwVertexBuffer> vertexBufferHandle, Handle<HwIndexBuffer> indexBufferHandle,
|
||||
const PrimitiveType primitiveType, utils::CString tag) {
|
||||
const PrimitiveType primitiveType) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
assert_invariant(mDevice);
|
||||
const auto renderPrimitive = constructHandle<WebGPURenderPrimitive>(renderPrimitiveHandle);
|
||||
@@ -614,31 +594,27 @@ void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> renderPrimit
|
||||
renderPrimitive->vertexBuffer = vertexBuffer;
|
||||
renderPrimitive->indexBuffer = indexBuffer;
|
||||
renderPrimitive->type = primitiveType;
|
||||
setDebugTag(renderPrimitiveHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> programHandle, Program&& program,
|
||||
utils::CString tag) {
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> programHandle, Program&& program) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUProgram>(programHandle, mDevice, program);
|
||||
setDebugTag(programHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
|
||||
utils::CString tag) {
|
||||
const int /* dummy */) {
|
||||
assert_invariant(!mDefaultRenderTarget);
|
||||
mDefaultRenderTarget = constructHandle<WebGPURenderTarget>(renderTargetHandle);
|
||||
assert_invariant(mDefaultRenderTarget);
|
||||
if (mSwapChain) {
|
||||
setDefaultTargetFlags(*mDefaultRenderTarget, *mSwapChain);
|
||||
}
|
||||
setDebugTag(renderTargetHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
|
||||
const TargetBufferFlags targetFlags, const uint32_t width, const uint32_t height,
|
||||
const uint8_t samples, const uint8_t layerCount, const MRT color,
|
||||
const TargetBufferInfo depth, const TargetBufferInfo stencil, utils::CString tag) {
|
||||
const TargetBufferInfo depth, const TargetBufferInfo stencil) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPURenderTarget>(
|
||||
renderTargetHandle, width, height, samples, layerCount, color, depth, stencil,
|
||||
@@ -647,49 +623,39 @@ void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle
|
||||
return handleCast<WebGPUTexture>(textureHandle);
|
||||
},
|
||||
mDevice);
|
||||
setDebugTag(renderTargetHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, utils::CString tag) {
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, const int /* dummy */) {
|
||||
// The handle is constructed synchronously in createFenceS.
|
||||
const auto fence = handleCast<WebGPUFence>(fenceHandle);
|
||||
assert_invariant(mQueue);
|
||||
fence->addMarkerToQueueState(mQueue);
|
||||
setDebugTag(fenceHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSyncR(Handle<HwSync> syncHandle, utils::CString tag) {
|
||||
// TODO: Ensure sync is active, and then invoke and clear all pending
|
||||
// callbacks.
|
||||
setDebugTag(syncHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString tag) {}
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
||||
backend::DescriptorSetLayout&& info, utils::CString tag) {
|
||||
backend::DescriptorSetLayout&& info) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUDescriptorSetLayout>(descriptorSetLayoutHandle, std::move(info), mDevice);
|
||||
setDebugTag(descriptorSetLayoutHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> descriptorSetHandle,
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle, utils::CString tag) {
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
auto layout = handleCast<WebGPUDescriptorSetLayout>(descriptorSetLayoutHandle);
|
||||
constructHandle<WebGPUDescriptorSet>(descriptorSetHandle, layout->getLayout(),
|
||||
layout->getBindGroupEntries());
|
||||
setDebugTag(descriptorSetHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
|
||||
return {
|
||||
//todo
|
||||
};
|
||||
}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> WebGPUDriver::createStreamAcquired() {
|
||||
return {
|
||||
//todo
|
||||
};
|
||||
@@ -732,18 +698,6 @@ FenceStatus WebGPUDriver::getFenceStatus(Handle<HwFence> fenceHandle) {
|
||||
return fence->getStatus();
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroySync(Handle<HwSync> syncHandle) {
|
||||
if (syncHandle) {
|
||||
destructHandle<WebGPUSync>(syncHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void WebGPUDriver::getPlatformSync(Handle<HwSync> syncHandle, CallbackHandler* handler,
|
||||
Platform::SyncCallback cb, void* userData) {
|
||||
// TODO: If the sync has been inserted into the command stream, execute
|
||||
// the callback. Otherwise, enqueue it.
|
||||
}
|
||||
|
||||
bool WebGPUDriver::isTextureFormatSupported(const TextureFormat format) {
|
||||
return toWGPUTextureFormat(format) != wgpu::TextureFormat::Undefined;
|
||||
}
|
||||
@@ -793,10 +747,6 @@ bool WebGPUDriver::isSRGBSwapChainSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebGPUDriver::isMSAASwapChainSupported(uint32_t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebGPUDriver::isProtectedContentSupported() {
|
||||
return false;
|
||||
}
|
||||
@@ -1403,7 +1353,7 @@ void WebGPUDriver::commit(Handle<HwSwapChain> swapChainHandle) {
|
||||
if (UTILS_VERY_UNLIKELY(!mCommandEncoder)) {
|
||||
// nothing to submit
|
||||
if (UTILS_LIKELY(mSwapChain)) {
|
||||
mSwapChain->present(*this);
|
||||
mSwapChain->present();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1437,7 +1387,7 @@ void WebGPUDriver::commit(Handle<HwSwapChain> swapChainHandle) {
|
||||
}
|
||||
mTextureView = nullptr;
|
||||
assert_invariant(mSwapChain);
|
||||
mSwapChain->present(*this);
|
||||
mSwapChain->present();
|
||||
}
|
||||
|
||||
void WebGPUDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
|
||||
@@ -68,7 +68,6 @@ private:
|
||||
[[nodiscard]] ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
[[nodiscard]] wgpu::Sampler makeSampler(SamplerParams const& params);
|
||||
[[nodiscard]] static wgpu::AddressMode fWrapModeToWAddressMode(const filament::backend::SamplerWrapMode& fUsage);
|
||||
void setDebugTag(HandleBase::HandleId handleId, utils::CString tag);
|
||||
|
||||
// The platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
|
||||
// handled in the WebGPUPlatform.
|
||||
|
||||
@@ -293,11 +293,10 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
|
||||
},
|
||||
.primitive = {
|
||||
.topology = toWebGPU(request.primitiveType),
|
||||
// TODO This won't always be the case for the primitives bound. But this particular field
|
||||
// in the pipeline struct is only meant for restarting the strip, which we don't need so far.
|
||||
.stripIndexFormat =
|
||||
isStripPrimitiveType(request.primitiveType)? wgpu::IndexFormat::Uint16 :
|
||||
wgpu::IndexFormat::Undefined,
|
||||
// TODO should we assume some constant format here or is there a way to get
|
||||
// this from PipelineState somehow or elsewhere?
|
||||
// Perhaps, cache/assert format from index buffers as they are requested?
|
||||
.stripIndexFormat = wgpu::IndexFormat::Undefined,
|
||||
.frontFace = request.rasterState.inverseFrontFaces ? wgpu::FrontFace::CW : wgpu::FrontFace::CCW,
|
||||
.cullMode = toWebGPU(request.rasterState.culling),
|
||||
// TODO no depth clamp in WebGPU supported directly. unclippedDepth is close, so we are
|
||||
@@ -313,10 +312,12 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
|
||||
},
|
||||
.fragment = nullptr // will add below if fragment module is included
|
||||
};
|
||||
FILAMENT_CHECK_POSTCONDITION(!isStripPrimitiveType(request.primitiveType) ||
|
||||
pipelineDescriptor.primitive.stripIndexFormat != wgpu::IndexFormat::Undefined)
|
||||
<< "If the topology is a strip format, e.g. TriangleStrip, the stripIndexFormat cannot "
|
||||
"be Undefined.";
|
||||
// TODO:
|
||||
if (pipelineDescriptor.primitive.topology == wgpu::PrimitiveTopology::LineStrip ||
|
||||
pipelineDescriptor.primitive.topology == wgpu::PrimitiveTopology::TriangleStrip) {
|
||||
PANIC_POSTCONDITION("stripIndexFormat must be set for strip topologies. "
|
||||
"This needs to be plumbed through from the RenderPrimitive.");
|
||||
}
|
||||
|
||||
wgpu::FragmentState fragmentState = {};
|
||||
const wgpu::BlendState blendState {
|
||||
|
||||
@@ -161,7 +161,7 @@ private:
|
||||
// render targets... //
|
||||
uint8_t multisampleCount{ 0 }; // 1 : 313
|
||||
uint8_t colorFormatCount{ 0 }; // 1 : 314
|
||||
uint8_t padding[5]{ 0 }; // 5 : 315
|
||||
uint8_t padding[5]{ 0 }; // 5 : 319
|
||||
TargetBufferFlags targetRenderFlags{ TargetBufferFlags::NONE }; // 4 : 320
|
||||
wgpu::TextureFormat depthStencilFormat { wgpu::TextureFormat::Undefined }; // 4 : 324
|
||||
wgpu::TextureFormat colorFormats[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]{ //
|
||||
|
||||
@@ -386,17 +386,10 @@ wgpu::Texture WebGPUSwapChain::getCurrentTexture() {
|
||||
|
||||
}
|
||||
|
||||
void WebGPUSwapChain::present(DriverBase& driver) {
|
||||
void WebGPUSwapChain::present() {
|
||||
if (!isHeadless()) {
|
||||
mSurface.Present();
|
||||
}
|
||||
if (frameScheduled.callback) {
|
||||
driver.scheduleCallback(frameScheduled.handler,
|
||||
[callback = std::move(frameScheduled.callback)]() {
|
||||
PresentCallable noop = PresentCallable(PresentCallable::noopPresent, nullptr);
|
||||
callback(noop);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -49,12 +49,7 @@ public:
|
||||
|
||||
[[nodiscard]] bool isHeadless() const { return mType == SwapChainType::HEADLESS; }
|
||||
|
||||
void present(DriverBase& driver);
|
||||
|
||||
void setFrameScheduledCallback(CallbackHandler* handler, FrameScheduledCallback&& callback) {
|
||||
frameScheduled.handler = handler;
|
||||
frameScheduled.callback = std::move(callback);
|
||||
}
|
||||
void present();
|
||||
|
||||
private:
|
||||
|
||||
@@ -80,11 +75,6 @@ private:
|
||||
uint8_t mHeadlessBufferIndex = 0;
|
||||
std::array<wgpu::Texture, mHeadlessBufferCount> mRenderTargetTextures;
|
||||
std::array<wgpu::TextureView, mHeadlessBufferCount> mRenderTargetViews;
|
||||
|
||||
struct {
|
||||
CallbackHandler* handler = nullptr;
|
||||
FrameScheduledCallback callback;
|
||||
} frameScheduled;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUSYNC_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUSYNC_H
|
||||
|
||||
#include "DriverBase.h"
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
// TODO: provide a more complete implementation of Sync.
|
||||
class WebGPUSync final : public HwSync {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_WEBGPUSYNC_H
|
||||
@@ -216,9 +216,7 @@ WebGPUTexture::WebGPUTexture(const SamplerType samplerType, const uint8_t levels
|
||||
mBlockWidth{ filament::backend::getBlockWidth(format) },
|
||||
mBlockHeight{ filament::backend::getBlockHeight(format) },
|
||||
mDefaultMipLevel{ 0 },
|
||||
mDefaultBaseArrayLayer{ 0 },
|
||||
// an undefined mSwizzle means that is not a swizzle view
|
||||
mSwizzle{} {
|
||||
mDefaultBaseArrayLayer{ 0 } {
|
||||
assert_invariant(
|
||||
samples == 1 ||
|
||||
samples == 4 &&
|
||||
@@ -281,36 +279,11 @@ WebGPUTexture::WebGPUTexture(WebGPUTexture const* src, const uint8_t baseLevel,
|
||||
mTexture{ src->mTexture },
|
||||
mDefaultMipLevel{ baseLevel },
|
||||
mDefaultBaseArrayLayer{ src->mArrayLayerCount },
|
||||
mMsaaSidecarTexture{ src->mMsaaSidecarTexture },
|
||||
mSwizzle{ src->mSwizzle } {
|
||||
const bool swizzleUndefined{ (src->mSwizzle.r == wgpu::ComponentSwizzle::Undefined) &&
|
||||
(src->mSwizzle.g == wgpu::ComponentSwizzle::Undefined) &&
|
||||
(src->mSwizzle.b == wgpu::ComponentSwizzle::Undefined) &&
|
||||
(src->mSwizzle.a == wgpu::ComponentSwizzle::Undefined) };
|
||||
if (swizzleUndefined) {
|
||||
mDefaultTextureView = makeTextureView(mDefaultMipLevel, levelCount, 0,
|
||||
mDefaultBaseArrayLayer, src->getViewDimension());
|
||||
} else {
|
||||
wgpu::TextureComponentSwizzleDescriptor swizzleDesc{};
|
||||
swizzleDesc.swizzle = mSwizzle;
|
||||
const wgpu::TextureViewDescriptor viewDesc{
|
||||
.nextInChain = &swizzleDesc,
|
||||
.label = "swizzled_texture_view",
|
||||
.format = mTexture.GetFormat(),
|
||||
.dimension = src->getViewDimension(),
|
||||
.baseMipLevel = mDefaultMipLevel,
|
||||
.mipLevelCount = levelCount,
|
||||
.baseArrayLayer = 0,
|
||||
.arrayLayerCount = mDefaultBaseArrayLayer,
|
||||
};
|
||||
mDefaultTextureView = mTexture.CreateView(&viewDesc);
|
||||
FILAMENT_CHECK_POSTCONDITION(mDefaultTextureView)
|
||||
<< "Failed to create swizzled Texture view";
|
||||
}
|
||||
}
|
||||
mDefaultTextureView{ makeTextureView(mDefaultMipLevel, levelCount, 0, mDefaultBaseArrayLayer,
|
||||
toWebGPUTextureViewDimension(src->target)) },
|
||||
mMsaaSidecarTexture{ src->mMsaaSidecarTexture } {}
|
||||
|
||||
WebGPUTexture::WebGPUTexture(const WebGPUTexture* src,
|
||||
const wgpu::TextureComponentSwizzle nextSwizzle) noexcept
|
||||
WebGPUTexture::WebGPUTexture(const WebGPUTexture* src, const wgpu::TextureView view) noexcept
|
||||
: HwTexture{ src->target, src->levels, src->samples, src->width, src->height, src->depth,
|
||||
src->format, src->usage},
|
||||
mViewFormat{ src->mViewFormat },
|
||||
@@ -325,19 +298,20 @@ WebGPUTexture::WebGPUTexture(const WebGPUTexture* src,
|
||||
mTexture{ src->mTexture },
|
||||
mDefaultMipLevel{ src->mDefaultMipLevel },
|
||||
mDefaultBaseArrayLayer{ 0 },
|
||||
mMsaaSidecarTexture{src->mMsaaSidecarTexture},
|
||||
mSwizzle{ composeSwizzle(src->getSwizzle(), nextSwizzle) } {
|
||||
wgpu::TextureComponentSwizzleDescriptor swizzleDesc{};
|
||||
swizzleDesc.swizzle = mSwizzle;
|
||||
mDefaultTextureView{ view },
|
||||
mMsaaSidecarTexture{src->mMsaaSidecarTexture}{}
|
||||
|
||||
const wgpu::TextureViewDescriptor viewDesc{
|
||||
.nextInChain = &swizzleDesc,
|
||||
.label = "swizzled_texture_view",
|
||||
.format = mTexture.GetFormat(),
|
||||
.dimension = src->getViewDimension(),
|
||||
};
|
||||
mDefaultTextureView = mTexture.CreateView(&viewDesc);
|
||||
FILAMENT_CHECK_POSTCONDITION(mDefaultTextureView) << "Failed to create swizzled Texture view";
|
||||
wgpu::Texture const& WebGPUTexture::getMsaaSidecarTexture(const uint8_t sampleCount) const {
|
||||
if (mMsaaSidecarTexture == nullptr) {
|
||||
return mMsaaSidecarTexture; // nullptr (no such sidecar)
|
||||
}
|
||||
FILAMENT_CHECK_PRECONDITION(sampleCount == mMsaaSidecarTexture.GetSampleCount())
|
||||
<< "The MSAA sidecar texture has a different sample count ("
|
||||
<< mMsaaSidecarTexture.GetSampleCount() << ") than requested (" << +sampleCount
|
||||
<< "). Note that this restriction was written when WebGPU only supported msaa "
|
||||
"textures with 4 samples. If that has changed, this implementation should be "
|
||||
"updated (e.g. map of sidecar textures by sampleCount or something).";
|
||||
return mMsaaSidecarTexture;
|
||||
}
|
||||
|
||||
bool WebGPUTexture::supportsMultipleMipLevelsViaStorageBinding(const wgpu::TextureFormat format) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user