Compare commits
57
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0404be5127 | ||
|
|
a784fb7d8b | ||
|
|
8459cbc91c | ||
|
|
344c04a2d8 | ||
|
|
55e2691f3f | ||
|
|
7be9cdc7f8 | ||
|
|
af792e3d18 | ||
|
|
f93677548d | ||
|
|
1eff66e4ec | ||
|
|
34f8b9aa20 | ||
|
|
6d07443188 | ||
|
|
13a23703ad | ||
|
|
57f6ca625c | ||
|
|
02f5903b67 | ||
|
|
c39a870abc | ||
|
|
09b8008e17 | ||
|
|
59b59cf6be | ||
|
|
0df6013263 | ||
|
|
d5041fced7 | ||
|
|
9c54b8a777 | ||
|
|
8a534d0940 | ||
|
|
130825422e | ||
|
|
984006ee25 | ||
|
|
b676002521 | ||
|
|
8bdf7bd1e5 | ||
|
|
1262cb286c | ||
|
|
ee6f3fb1dc | ||
|
|
b9a9586abb | ||
|
|
6ee20a57aa | ||
|
|
368fa2bf39 | ||
|
|
8f642892b4 | ||
|
|
5435a8ed3b | ||
|
|
5fd7a4e153 | ||
|
|
20ff230b92 | ||
|
|
44ff79ad34 | ||
|
|
102d2db008 | ||
|
|
5c9039e650 | ||
|
|
1203c24f06 | ||
|
|
9704d27aeb | ||
|
|
c6f2c3fc1c | ||
|
|
2faf868341 | ||
|
|
81f6260843 | ||
|
|
1a9063d53a | ||
|
|
6062b3c8c6 | ||
|
|
d9186c44ba | ||
|
|
6d06e00934 | ||
|
|
b4021a1fbc | ||
|
|
2c9559f9b8 | ||
|
|
e2da13f817 | ||
|
|
addae314b4 | ||
|
|
5e3c51822d | ||
|
|
9d817a0cc9 | ||
|
|
95ecc3d1e4 | ||
|
|
cabaa4323e | ||
|
|
d6b2ec49b0 | ||
|
|
93004aa5bc | ||
|
|
27fa8ab46d |
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
build-android:
|
||||
name: build-android
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
jobs:
|
||||
cocoapods-deploy:
|
||||
name: cocoapods-deploy
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Check out iOS/CocoaPods directory
|
||||
uses: Bhacaz/checkout-files@49fc3050859046bf4f4873678d46099985640e89
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
build-ios:
|
||||
name: build-ios
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
build-mac:
|
||||
name: build-mac
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
@@ -11,7 +11,7 @@ on:
|
||||
jobs:
|
||||
npm-deploy:
|
||||
name: npm-deploy
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04]
|
||||
os: [macos-14, ubuntu-22.04]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
build-android:
|
||||
name: build-android
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
build-ios:
|
||||
name: build-iOS
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04]
|
||||
os: [macos-14, ubuntu-22.04]
|
||||
|
||||
steps:
|
||||
- name: Decide Git ref
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
if: github.event_name == 'release' || github.event.inputs.platform == 'web'
|
||||
|
||||
steps:
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
|
||||
build-android:
|
||||
name: build-android
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
if: github.event_name == 'release' || github.event.inputs.platform == 'android'
|
||||
|
||||
steps:
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
|
||||
build-ios:
|
||||
name: build-ios
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
if: github.event_name == 'release' || github.event.inputs.platform == 'ios'
|
||||
|
||||
steps:
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
+15
-5
@@ -41,6 +41,8 @@ option(FILAMENT_LINUX_IS_MOBILE "Treat Linux as Mobile" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_ASAN_UBSAN "Enable Address and Undefined Behavior Sanitizers" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_TSAN "Enable Thread Sanitizer" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON)
|
||||
|
||||
set(FILAMENT_NDK_VERSION "" CACHE STRING
|
||||
@@ -426,7 +428,13 @@ endif()
|
||||
if (FILAMENT_ENABLE_ASAN_UBSAN)
|
||||
set(EXTRA_SANITIZE_OPTIONS "-fsanitize=address -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
if (FILAMENT_ENABLE_TSAN)
|
||||
set(EXTRA_SANITIZE_OPTIONS "-fsanitize=thread")
|
||||
endif()
|
||||
if (ANDROID)
|
||||
# keep STL debug infos (mimics what the NDK does)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-limit-debug-info")
|
||||
endif()
|
||||
if (NOT MSVC AND NOT WEBGL)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
|
||||
endif()
|
||||
@@ -626,9 +634,9 @@ function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
# Loop through the dependent libraries and query their location on disk.
|
||||
set(DEPS_FILES )
|
||||
foreach(DEPENDENCY ${DEPS})
|
||||
if(TARGET ${DEPENDENCY})
|
||||
if (TARGET ${DEPENDENCY})
|
||||
get_property(dep_type TARGET ${DEPENDENCY} PROPERTY TYPE)
|
||||
if(dep_type STREQUAL "STATIC_LIBRARY")
|
||||
if (dep_type STREQUAL "STATIC_LIBRARY")
|
||||
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
|
||||
endif()
|
||||
endif()
|
||||
@@ -698,7 +706,7 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
|
||||
set(RESGEN_OUTPUTS "${OUTPUTS}" PARENT_SCOPE)
|
||||
set(RESGEN_FLAGS -qx ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
|
||||
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}${ASM_SUFFIX}.S" PARENT_SCOPE)
|
||||
set(RESGEN_SOURCE_FLAGS "-I${ARCHIVE_DIR} ${ASM_ARCH_FLAG}" PARENT_SCOPE)
|
||||
set(RESGEN_SOURCE_FLAGS "-I'${ARCHIVE_DIR}' ${ASM_ARCH_FLAG}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -713,7 +721,6 @@ add_subdirectory(${LIBRARIES}/filabridge)
|
||||
add_subdirectory(${LIBRARIES}/filaflat)
|
||||
add_subdirectory(${LIBRARIES}/filagui)
|
||||
add_subdirectory(${LIBRARIES}/filameshio)
|
||||
add_subdirectory(${LIBRARIES}/geometry)
|
||||
add_subdirectory(${LIBRARIES}/gltfio)
|
||||
add_subdirectory(${LIBRARIES}/ibl)
|
||||
add_subdirectory(${LIBRARIES}/iblprefilter)
|
||||
@@ -741,6 +748,9 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
|
||||
add_subdirectory(${EXTERNAL}/stb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/getopt)
|
||||
|
||||
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
|
||||
add_subdirectory(${LIBRARIES}/geometry)
|
||||
|
||||
if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
|
||||
# spirv-tools must come before filamat, as filamat relies on the presence of the
|
||||
# spirv-tools_SOURCE_DIR variable.
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.49.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.50.2'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.49.2'
|
||||
pod 'Filament', '~> 1.50.2'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -7,6 +7,25 @@ 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.50.3
|
||||
|
||||
|
||||
## v1.50.2
|
||||
|
||||
|
||||
## v1.50.1
|
||||
|
||||
- Metal: fix some shader artifacts by disabling fast math optimizations.
|
||||
- backend: remove `atan2` overload which had a typo and wasn't useful. Fixes b/320856413.
|
||||
- utils: remove usages of `SpinLock`. Fixes b/321101014.
|
||||
|
||||
## v1.50.0
|
||||
- engine: TAA now supports 4x upscaling [BETA] [⚠️ **New Material Version**]
|
||||
|
||||
## v1.49.3
|
||||
|
||||
- matc: Generate stereo variants for FL0 materials [⚠️ **Recompile materials**]
|
||||
|
||||
## v1.49.2
|
||||
|
||||
|
||||
|
||||
@@ -484,7 +484,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBuilderConfig(JNIEnv*,
|
||||
jclass, jlong nativeBuilder, jlong commandBufferSizeMB, jlong perRenderPassArenaSizeMB,
|
||||
jlong driverHandleArenaSizeMB, jlong minCommandBufferSizeMB, jlong perFrameCommandsSizeMB,
|
||||
jlong jobSystemThreadCount, jlong stereoscopicEyeCount) {
|
||||
jlong jobSystemThreadCount, jlong stereoscopicEyeCount,
|
||||
jlong resourceAllocatorCacheSizeMB, jlong resourceAllocatorCacheMaxAge) {
|
||||
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
|
||||
Engine::Config config = {
|
||||
.commandBufferSizeMB = (uint32_t) commandBufferSizeMB,
|
||||
@@ -494,6 +495,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
|
||||
.perFrameCommandsSizeMB = (uint32_t) perFrameCommandsSizeMB,
|
||||
.jobSystemThreadCount = (uint32_t) jobSystemThreadCount,
|
||||
.stereoscopicEyeCount = (uint8_t) stereoscopicEyeCount,
|
||||
.resourceAllocatorCacheSizeMB = (uint32_t) resourceAllocatorCacheSizeMB,
|
||||
.resourceAllocatorCacheMaxAge = (uint8_t) resourceAllocatorCacheMaxAge,
|
||||
};
|
||||
builder->config(&config);
|
||||
}
|
||||
|
||||
@@ -211,7 +211,8 @@ public class Engine {
|
||||
nSetBuilderConfig(mNativeBuilder, config.commandBufferSizeMB,
|
||||
config.perRenderPassArenaSizeMB, config.driverHandleArenaSizeMB,
|
||||
config.minCommandBufferSizeMB, config.perFrameCommandsSizeMB,
|
||||
config.jobSystemThreadCount, config.stereoscopicEyeCount);
|
||||
config.jobSystemThreadCount, config.stereoscopicEyeCount,
|
||||
config.resourceAllocatorCacheSizeMB, config.resourceAllocatorCacheMaxAge);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -356,6 +357,18 @@ public class Engine {
|
||||
* @see Engine#getMaxStereoscopicEyes
|
||||
*/
|
||||
public long stereoscopicEyeCount = 2;
|
||||
|
||||
/*
|
||||
* Size in MiB of the frame graph texture cache. This should be adjusted based on the
|
||||
* size of used render targets (typically the screen).
|
||||
*/
|
||||
public long resourceAllocatorCacheSizeMB = 64;
|
||||
|
||||
/*
|
||||
* This value determines for how many frames are texture entries kept in the cache.
|
||||
* The default value of 30 corresponds to about half a second at 60 fps.
|
||||
*/
|
||||
public long resourceAllocatorCacheMaxAge = 30;
|
||||
}
|
||||
|
||||
private Engine(long nativeEngine, Config config) {
|
||||
@@ -1227,7 +1240,8 @@ public class Engine {
|
||||
private static native void nSetBuilderConfig(long nativeBuilder, long commandBufferSizeMB,
|
||||
long perRenderPassArenaSizeMB, long driverHandleArenaSizeMB,
|
||||
long minCommandBufferSizeMB, long perFrameCommandsSizeMB, long jobSystemThreadCount,
|
||||
long stereoscopicEyeCount);
|
||||
long stereoscopicEyeCount,
|
||||
long resourceAllocatorCacheSizeMB, long resourceAllocatorCacheMaxAge);
|
||||
private static native void nSetBuilderFeatureLevel(long nativeBuilder, int ordinal);
|
||||
private static native void nSetBuilderSharedContext(long nativeBuilder, long sharedContext);
|
||||
private static native long nBuilderBuild(long nativeBuilder);
|
||||
|
||||
@@ -1637,6 +1637,10 @@ public class View {
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
public float cocScale = 1.0f;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
public float cocAspectRatio = 1.0f;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
@@ -1852,7 +1856,7 @@ public class View {
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for Temporal Multi-Sample Anti-aliasing (MSAA)
|
||||
* Options for Multi-Sample Anti-aliasing (MSAA)
|
||||
* @see setMultiSampleAntiAliasingOptions()
|
||||
*/
|
||||
public static class MultiSampleAntiAliasingOptions {
|
||||
@@ -1878,7 +1882,11 @@ public class View {
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth` and `feedback`, however, could be changed an any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
*
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
public static class TemporalAntiAliasingOptions {
|
||||
@@ -1888,7 +1896,7 @@ public class View {
|
||||
*/
|
||||
AABB,
|
||||
/**
|
||||
* use the variance of the neighborhood
|
||||
* use the variance of the neighborhood (not recommended)
|
||||
*/
|
||||
VARIANCE,
|
||||
/**
|
||||
@@ -1912,18 +1920,38 @@ public class View {
|
||||
NONE,
|
||||
}
|
||||
|
||||
public enum JitterPattern {
|
||||
RGSS_X4,
|
||||
UNIFORM_HELIX_X4,
|
||||
HALTON_23_X8,
|
||||
HALTON_23_X16,
|
||||
HALTON_23_X32,
|
||||
}
|
||||
|
||||
/**
|
||||
* reconstruction filter width typically between 0.2 (sharper, aliased) and 1 (smoother)
|
||||
* reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
|
||||
*/
|
||||
public float filterWidth = 1.0f;
|
||||
/**
|
||||
* history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
*/
|
||||
public float feedback = 0.04f;
|
||||
public float feedback = 0.12f;
|
||||
/**
|
||||
* texturing lod bias (typically -1 or -2)
|
||||
*/
|
||||
public float lodBias = -1.0f;
|
||||
/**
|
||||
* post-TAA sharpen, especially useful when upscaling is true.
|
||||
*/
|
||||
public float sharpness = 0.0f;
|
||||
/**
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
*/
|
||||
public boolean upscaling = false;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
@@ -1940,12 +1968,15 @@ public class View {
|
||||
* type of color gamut box
|
||||
*/
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxType boxType = TemporalAntiAliasingOptions.BoxType.VARIANCE;
|
||||
public TemporalAntiAliasingOptions.BoxType boxType = TemporalAntiAliasingOptions.BoxType.AABB;
|
||||
/**
|
||||
* clipping algorithm
|
||||
*/
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxClipping boxClipping = TemporalAntiAliasingOptions.BoxClipping.ACCURATE;
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.JitterPattern jitterPattern = TemporalAntiAliasingOptions.JitterPattern.HALTON_23_X16;
|
||||
public float varianceGamma = 1.0f;
|
||||
/**
|
||||
* adjust the feedback dynamically to reduce flickering
|
||||
*/
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ public class FilamentInstance {
|
||||
*
|
||||
* Ignored if variantIndex is out of bounds.
|
||||
*/
|
||||
void applyMaterialVariant(@IntRange(from = 0) int variantIndex) {
|
||||
public void applyMaterialVariant(@IntRange(from = 0) int variantIndex) {
|
||||
nApplyMaterialVariant(mNativeObject, variantIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.49.2
|
||||
VERSION_NAME=1.50.2
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -125,7 +125,13 @@ if [[ "${has_universal}" == "true" ]]; then
|
||||
|
||||
arch_output="${OUTPUT_PATH%.a}_${arch}.a"
|
||||
arch_outputs+=("$arch_output")
|
||||
combine_static_libs "$arch_output" $(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a')
|
||||
|
||||
archives=()
|
||||
while IFS= read -r -d $'\0'; do
|
||||
archives+=("$REPLY")
|
||||
done < <(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a' -print0)
|
||||
|
||||
combine_static_libs "$arch_output" "$archives"
|
||||
done
|
||||
|
||||
# Finally, combine the single-architecture archives into a universal binary.
|
||||
|
||||
+15
-7
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+19
-17
@@ -209,10 +209,13 @@ set(PRIVATE_HDRS
|
||||
)
|
||||
|
||||
set(MATERIAL_SRCS
|
||||
src/materials/fsr/fsr_easu.mat
|
||||
src/materials/fsr/fsr_easu_mobile.mat
|
||||
src/materials/fsr/fsr_easu_mobileF.mat
|
||||
src/materials/fsr/fsr_rcas.mat
|
||||
src/materials/antiAliasing/fxaa.mat
|
||||
src/materials/antiAliasing/taa.mat
|
||||
src/materials/blitLow.mat
|
||||
src/materials/bloom/bloomDownsample.mat
|
||||
src/materials/bloom/bloomDownsample2x.mat
|
||||
src/materials/bloom/bloomDownsample9.mat
|
||||
src/materials/bloom/bloomUpsample.mat
|
||||
src/materials/colorGrading/colorGrading.mat
|
||||
src/materials/colorGrading/colorGradingAsSubpass.mat
|
||||
src/materials/colorGrading/customResolveAsSubpass.mat
|
||||
@@ -220,29 +223,28 @@ set(MATERIAL_SRCS
|
||||
src/materials/defaultMaterial.mat
|
||||
src/materials/dof/dof.mat
|
||||
src/materials/dof/dofCoc.mat
|
||||
src/materials/dof/dofDownsample.mat
|
||||
src/materials/dof/dofCombine.mat
|
||||
src/materials/dof/dofDilate.mat
|
||||
src/materials/dof/dofDownsample.mat
|
||||
src/materials/dof/dofMedian.mat
|
||||
src/materials/dof/dofMipmap.mat
|
||||
src/materials/dof/dofTiles.mat
|
||||
src/materials/dof/dofTilesSwizzle.mat
|
||||
src/materials/dof/dofDilate.mat
|
||||
src/materials/dof/dofMipmap.mat
|
||||
src/materials/dof/dofMedian.mat
|
||||
src/materials/flare/flare.mat
|
||||
src/materials/bloom/bloomDownsample.mat
|
||||
src/materials/bloom/bloomDownsample2x.mat
|
||||
src/materials/bloom/bloomDownsample9.mat
|
||||
src/materials/bloom/bloomUpsample.mat
|
||||
src/materials/fsr/fsr_easu.mat
|
||||
src/materials/fsr/fsr_easu_mobile.mat
|
||||
src/materials/fsr/fsr_easu_mobileF.mat
|
||||
src/materials/fsr/fsr_rcas.mat
|
||||
src/materials/resolveDepth.mat
|
||||
src/materials/separableGaussianBlur.mat
|
||||
src/materials/skybox.mat
|
||||
src/materials/shadowmap.mat
|
||||
src/materials/ssao/bilateralBlur.mat
|
||||
src/materials/ssao/bilateralBlurBentNormals.mat
|
||||
src/materials/ssao/mipmapDepth.mat
|
||||
src/materials/skybox.mat
|
||||
src/materials/ssao/sao.mat
|
||||
src/materials/ssao/saoBentNormals.mat
|
||||
src/materials/separableGaussianBlur.mat
|
||||
src/materials/antiAliasing/fxaa.mat
|
||||
src/materials/antiAliasing/taa.mat
|
||||
src/materials/vsmMipmap.mat
|
||||
src/materials/blitLow.mat
|
||||
)
|
||||
|
||||
set(MATERIAL_FL0_SRCS
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
#include <type_traits> // FIXME: STL headers are not allowed in public headers
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -17,16 +17,14 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
|
||||
#define TNT_FILAMENT_BACKEND_HANDLE_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#if !defined(NDEBUG)
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
#endif
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <type_traits> // FIXME: STL headers are not allowed in public headers
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -54,7 +52,7 @@ struct HwVertexBuffer;
|
||||
class HandleBase {
|
||||
public:
|
||||
using HandleId = uint32_t;
|
||||
static constexpr const HandleId nullid = HandleId{ std::numeric_limits<HandleId>::max() };
|
||||
static constexpr const HandleId nullid = HandleId{ UINT32_MAX };
|
||||
|
||||
constexpr HandleBase() noexcept: object(nullid) {}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <limits>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -33,10 +33,7 @@ struct PipelineState {
|
||||
RasterState rasterState;
|
||||
StencilState stencilState;
|
||||
PolygonOffset polygonOffset;
|
||||
Viewport scissor{ 0, 0,
|
||||
(uint32_t)std::numeric_limits<int32_t>::max(),
|
||||
(uint32_t)std::numeric_limits<int32_t>::max()
|
||||
};
|
||||
Viewport scissor{ 0, 0, (uint32_t)INT32_MAX, (uint32_t)INT32_MAX };
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORM_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Driver;
|
||||
@@ -41,18 +41,24 @@ public:
|
||||
struct Stream {};
|
||||
|
||||
struct DriverConfig {
|
||||
/*
|
||||
* size of handle arena in bytes. Setting to 0 indicates default value is to be used.
|
||||
/**
|
||||
* Size of handle arena in bytes. Setting to 0 indicates default value is to be used.
|
||||
* Driver clamps to valid values.
|
||||
*/
|
||||
size_t handleArenaSize = 0;
|
||||
|
||||
/*
|
||||
* this number of most-recently destroyed textures will be tracked for use-after-free.
|
||||
/**
|
||||
* This number of most-recently destroyed textures will be tracked for use-after-free.
|
||||
* Throws an exception when a texture is freed but still bound to a SamplerGroup and used in
|
||||
* a draw call. 0 disables completely. Currently only respected by the Metal backend.
|
||||
*/
|
||||
size_t textureUseAfterFreePoolSize = 0;
|
||||
|
||||
/**
|
||||
* Set to `true` to forcibly disable parallel shader compilation in the backend.
|
||||
* Currently only honored by the GL backend.
|
||||
*/
|
||||
bool disableParallelShaderCompile = false;
|
||||
};
|
||||
|
||||
Platform() noexcept;
|
||||
@@ -78,7 +84,7 @@ public:
|
||||
*
|
||||
* @return nullptr on failure, or a pointer to the newly created driver.
|
||||
*/
|
||||
virtual backend::Driver* createDriver(void* sharedContext,
|
||||
virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
|
||||
const DriverConfig& driverConfig) noexcept = 0;
|
||||
|
||||
/**
|
||||
@@ -96,7 +102,8 @@ public:
|
||||
* cache.
|
||||
*/
|
||||
using InsertBlobFunc = utils::Invocable<
|
||||
void(const void* key, size_t keySize, const void* value, size_t valueSize)>;
|
||||
void(const void* UTILS_NONNULL key, size_t keySize,
|
||||
const void* UTILS_NONNULL value, size_t valueSize)>;
|
||||
|
||||
/*
|
||||
* RetrieveBlobFunc is an Invocable to an application-provided function that a
|
||||
@@ -104,7 +111,8 @@ public:
|
||||
* cache.
|
||||
*/
|
||||
using RetrieveBlobFunc = utils::Invocable<
|
||||
size_t(const void* key, size_t keySize, void* value, size_t valueSize)>;
|
||||
size_t(const void* UTILS_NONNULL key, size_t keySize,
|
||||
void* UTILS_NONNULL value, size_t valueSize)>;
|
||||
|
||||
/**
|
||||
* Sets the callback functions that the backend can use to interact with caching functionality
|
||||
@@ -157,7 +165,8 @@ public:
|
||||
* @param value pointer to the beginning of the value data that is to be inserted
|
||||
* @param valueSize specifies the size in byte of the data pointed to by <value>
|
||||
*/
|
||||
void insertBlob(const void* key, size_t keySize, const void* value, size_t valueSize);
|
||||
void insertBlob(const void* UTILS_NONNULL key, size_t keySize,
|
||||
const void* UTILS_NONNULL value, size_t valueSize);
|
||||
|
||||
/**
|
||||
* To retrieve the binary value associated with a given key from the cache, a
|
||||
@@ -176,7 +185,8 @@ public:
|
||||
* @return If the cache contains a value associated with the given key then the
|
||||
* size of that binary value in bytes is returned. Otherwise 0 is returned.
|
||||
*/
|
||||
size_t retrieveBlob(const void* key, size_t keySize, void* value, size_t valueSize);
|
||||
size_t retrieveBlob(const void* UTILS_NONNULL key, size_t keySize,
|
||||
void* UTILS_NONNULL value, size_t valueSize);
|
||||
|
||||
private:
|
||||
InsertBlobFunc mInsertBlob;
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
|
||||
@@ -98,7 +97,6 @@ private:
|
||||
*/
|
||||
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRESENTCALLABLE
|
||||
|
||||
@@ -17,17 +17,19 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <array>
|
||||
#include <variant>
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
#include <utility> // FIXME: STL headers are not allowed in public headers
|
||||
#include <variant> // FIXME: STL headers are not allowed in public headers
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
struct UTILS_PUBLIC SamplerDescriptor {
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
|
||||
#define TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -18,8 +18,13 @@
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Driver;
|
||||
@@ -38,8 +43,8 @@ protected:
|
||||
* Derived classes can use this to instantiate the default OpenGLDriver backend.
|
||||
* This is typically called from your implementation of createDriver()
|
||||
*/
|
||||
static Driver* createDefaultDriver(OpenGLPlatform* platform,
|
||||
void* sharedContext, const DriverConfig& driverConfig);
|
||||
static Driver* UTILS_NULLABLE createDefaultDriver(OpenGLPlatform* UTILS_NONNULL platform,
|
||||
void* UTILS_NULLABLE sharedContext, const DriverConfig& driverConfig);
|
||||
|
||||
~OpenGLPlatform() noexcept override;
|
||||
|
||||
@@ -66,7 +71,8 @@ public:
|
||||
* @return The driver's SwapChain object.
|
||||
*
|
||||
*/
|
||||
virtual SwapChain* createSwapChain(void* nativeWindow, uint64_t flags) noexcept = 0;
|
||||
virtual SwapChain* UTILS_NONNULL createSwapChain(
|
||||
void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
|
||||
@@ -87,13 +93,14 @@ public:
|
||||
* TODO: we need a more generic way of passing construction parameters
|
||||
* A void* might be enough.
|
||||
*/
|
||||
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
|
||||
virtual SwapChain* UTILS_NULLABLE createSwapChain(
|
||||
uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Called by the driver to destroys the SwapChain
|
||||
* @param swapChain SwapChain to be destroyed.
|
||||
*/
|
||||
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
|
||||
virtual void destroySwapChain(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Returns the set of buffers that must be preserved up to the call to commit().
|
||||
@@ -106,7 +113,7 @@ public:
|
||||
* @return buffer that must be preserved
|
||||
* @see commit()
|
||||
*/
|
||||
virtual TargetBufferFlags getPreservedFlags(SwapChain* swapChain) noexcept;
|
||||
virtual TargetBufferFlags getPreservedFlags(SwapChain* UTILS_NONNULL swapChain) noexcept;
|
||||
|
||||
/**
|
||||
* Called by the driver to establish the default FBO. The default implementation returns 0.
|
||||
@@ -120,14 +127,16 @@ public:
|
||||
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
|
||||
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
|
||||
*/
|
||||
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
|
||||
virtual void makeCurrent(
|
||||
SwapChain* UTILS_NONNULL drawSwapChain,
|
||||
SwapChain* UTILS_NONNULL readSwapChain) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Called by the driver once the current frame finishes drawing. Typically, this should present
|
||||
* the drawSwapChain. This is for example where `eglMakeCurrent()` would be called.
|
||||
* @param swapChain the SwapChain to present.
|
||||
*/
|
||||
virtual void commit(SwapChain* swapChain) noexcept = 0;
|
||||
virtual void commit(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Set the time the next committed buffer should be presented to the user at.
|
||||
@@ -152,14 +161,14 @@ public:
|
||||
*
|
||||
* @return A Fence object. The default implementation returns nullptr.
|
||||
*/
|
||||
virtual Fence* createFence() noexcept;
|
||||
virtual Fence* UTILS_NULLABLE createFence() noexcept;
|
||||
|
||||
/**
|
||||
* Destroys a Fence object. The default implementation does nothing.
|
||||
*
|
||||
* @param fence Fence to destroy.
|
||||
*/
|
||||
virtual void destroyFence(Fence* fence) noexcept;
|
||||
virtual void destroyFence(Fence* UTILS_NONNULL fence) noexcept;
|
||||
|
||||
/**
|
||||
* Waits on a Fence.
|
||||
@@ -169,7 +178,7 @@ public:
|
||||
* @return Whether the fence signaled or timed out. See backend::FenceStatus.
|
||||
* The default implementation always return backend::FenceStatus::ERROR.
|
||||
*/
|
||||
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept;
|
||||
virtual backend::FenceStatus waitFence(Fence* UTILS_NONNULL fence, uint64_t timeout) noexcept;
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@@ -183,13 +192,13 @@ public:
|
||||
* @param nativeStream The native stream, this parameter depends on the concrete implementation.
|
||||
* @return A new Stream object.
|
||||
*/
|
||||
virtual Stream* createStream(void* nativeStream) noexcept;
|
||||
virtual Stream* UTILS_NULLABLE createStream(void* UTILS_NULLABLE nativeStream) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys a Stream.
|
||||
* @param stream Stream to destroy.
|
||||
*/
|
||||
virtual void destroyStream(Stream* stream) noexcept;
|
||||
virtual void destroyStream(Stream* UTILS_NONNULL stream) noexcept;
|
||||
|
||||
/**
|
||||
* The specified stream takes ownership of the texture (tname) object
|
||||
@@ -199,20 +208,21 @@ public:
|
||||
* @param stream Stream to take ownership of the texture
|
||||
* @param tname GL texture id to "bind" to the Stream.
|
||||
*/
|
||||
virtual void attach(Stream* stream, intptr_t tname) noexcept;
|
||||
virtual void attach(Stream* UTILS_NONNULL stream, intptr_t tname) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys the texture associated to the stream
|
||||
* @param stream Stream to detach from its texture
|
||||
*/
|
||||
virtual void detach(Stream* stream) noexcept;
|
||||
virtual void detach(Stream* UTILS_NONNULL stream) noexcept;
|
||||
|
||||
/**
|
||||
* Updates the content of the texture attached to the stream.
|
||||
* @param stream Stream to update
|
||||
* @param timestamp Output parameter: Timestamp of the image bound to the texture.
|
||||
*/
|
||||
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
|
||||
virtual void updateTexImage(Stream* UTILS_NONNULL stream,
|
||||
int64_t* UTILS_NONNULL timestamp) noexcept;
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@@ -225,13 +235,13 @@ public:
|
||||
* implementation could just return { 0, GL_TEXTURE_2D } at this point. The actual
|
||||
* values can be delayed until setExternalImage.
|
||||
*/
|
||||
virtual ExternalTexture *createExternalImageTexture() noexcept;
|
||||
virtual ExternalTexture* UTILS_NULLABLE createExternalImageTexture() noexcept;
|
||||
|
||||
/**
|
||||
* Destroys an external texture handle and associated data.
|
||||
* @param texture a pointer to the handle to destroy.
|
||||
*/
|
||||
virtual void destroyExternalImage(ExternalTexture* texture) noexcept;
|
||||
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
// called on the application thread to allow Filament to take ownership of the image
|
||||
|
||||
@@ -244,7 +254,7 @@ public:
|
||||
* @param externalImage A token representing the platform's external image.
|
||||
* @see destroyExternalImage
|
||||
*/
|
||||
virtual void retainExternalImage(void* externalImage) noexcept;
|
||||
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
|
||||
|
||||
/**
|
||||
* Called to bind the platform-specific externalImage to an ExternalTexture.
|
||||
@@ -258,7 +268,8 @@ public:
|
||||
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
|
||||
* @return true on success, false on error.
|
||||
*/
|
||||
virtual bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept;
|
||||
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
|
||||
ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
/**
|
||||
* The method allows platforms to convert a user-supplied external image object into a new type
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ struct PlatformCocoaTouchGLImpl;
|
||||
class PlatformCocoaTouchGL : public OpenGLPlatform {
|
||||
public:
|
||||
PlatformCocoaTouchGL();
|
||||
~PlatformCocoaTouchGL() noexcept;
|
||||
~PlatformCocoaTouchGL() noexcept override;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
@@ -17,18 +17,21 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglplatform.h>
|
||||
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,8 +17,14 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
#include <backend/Platform.h>
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
#include <backend/platforms/PlatformEGL.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class ExternalStreamManagerAndroid;
|
||||
|
||||
@@ -20,13 +20,18 @@
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/PrivateImplementation.h>
|
||||
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
using SwapChain = Platform::SwapChain;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -40,28 +40,36 @@ public:
|
||||
|
||||
~CircularBuffer() noexcept;
|
||||
|
||||
// allocates 'size' bytes in the circular buffer and returns a pointer to the memory
|
||||
// return the current head and moves it forward by size bytes
|
||||
inline void* allocate(size_t size) noexcept {
|
||||
static size_t getBlockSize() noexcept { return sPageSize; }
|
||||
|
||||
// Total size of circular buffer. This is a constant.
|
||||
size_t size() const noexcept { return mSize; }
|
||||
|
||||
// Allocates `s` bytes in the circular buffer and returns a pointer to the memory. All
|
||||
// allocations must not exceed size() bytes.
|
||||
inline void* allocate(size_t s) noexcept {
|
||||
// We can never allocate more that size().
|
||||
assert_invariant(getUsed() + s <= size());
|
||||
char* const cur = static_cast<char*>(mHead);
|
||||
mHead = cur + size;
|
||||
mHead = cur + s;
|
||||
return cur;
|
||||
}
|
||||
|
||||
// Total size of circular buffer
|
||||
size_t size() const noexcept { return mSize; }
|
||||
|
||||
// returns true if the buffer is empty (e.g. after calling flush)
|
||||
// Returns true if the buffer is empty, i.e.: no allocations were made since
|
||||
// calling getBuffer();
|
||||
bool empty() const noexcept { return mTail == mHead; }
|
||||
|
||||
void* getHead() const noexcept { return mHead; }
|
||||
// Returns the size used since the last call to getBuffer()
|
||||
size_t getUsed() const noexcept { return intptr_t(mHead) - intptr_t(mTail); }
|
||||
|
||||
void* getTail() const noexcept { return mTail; }
|
||||
|
||||
// call at least once every getRequiredSize() bytes allocated from the buffer
|
||||
void circularize() noexcept;
|
||||
|
||||
static size_t getBlockSize() noexcept { return sPageSize; }
|
||||
// Retrieves the current allocated range and frees it. It is the responsibility of the caller
|
||||
// to make sure the returned range is no longer in use by the time allocate() allocates
|
||||
// (size() - getUsed()) bytes.
|
||||
struct Range {
|
||||
void* tail;
|
||||
void* head;
|
||||
};
|
||||
Range getBuffer() noexcept;
|
||||
|
||||
private:
|
||||
void* alloc(size_t size) noexcept;
|
||||
@@ -69,10 +77,10 @@ private:
|
||||
|
||||
// pointer to the beginning of the circular buffer (constant)
|
||||
void* mData = nullptr;
|
||||
int mUsesAshmem = -1;
|
||||
int mAshmemFd = -1;
|
||||
|
||||
// size of the circular buffer (constant)
|
||||
size_t mSize = 0;
|
||||
size_t const mSize;
|
||||
|
||||
// pointer to the beginning of recorded data
|
||||
void* mTail = nullptr;
|
||||
|
||||
@@ -19,19 +19,21 @@
|
||||
|
||||
#include "private/backend/CircularBuffer.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/*
|
||||
* A producer-consumer command queue that uses a CircularBuffer as main storage
|
||||
*/
|
||||
class CommandBufferQueue {
|
||||
struct Slice {
|
||||
struct Range {
|
||||
void* begin;
|
||||
void* end;
|
||||
};
|
||||
@@ -44,7 +46,7 @@ class CommandBufferQueue {
|
||||
|
||||
mutable utils::Mutex mLock;
|
||||
mutable utils::Condition mCondition;
|
||||
mutable std::vector<Slice> mCommandBuffersToExecute;
|
||||
mutable std::vector<Range> mCommandBuffersToExecute;
|
||||
size_t mFreeSpace = 0;
|
||||
size_t mHighWatermark = 0;
|
||||
uint32_t mExitRequested = 0;
|
||||
@@ -56,17 +58,20 @@ public:
|
||||
CommandBufferQueue(size_t requiredSize, size_t bufferSize);
|
||||
~CommandBufferQueue();
|
||||
|
||||
CircularBuffer& getCircularBuffer() { return mCircularBuffer; }
|
||||
CircularBuffer& getCircularBuffer() noexcept { return mCircularBuffer; }
|
||||
CircularBuffer const& getCircularBuffer() const noexcept { return mCircularBuffer; }
|
||||
|
||||
size_t getCapacity() const noexcept { return mRequiredSize; }
|
||||
|
||||
size_t getHighWatermark() const noexcept { return mHighWatermark; }
|
||||
|
||||
// wait for commands to be available and returns an array containing these commands
|
||||
std::vector<Slice> waitForCommands() const;
|
||||
std::vector<Range> waitForCommands() const;
|
||||
|
||||
// return the memory used by this command buffer to the circular buffer
|
||||
// WARNING: releaseBuffer() must be called in sequence of the Slices returned by
|
||||
// waitForCommands()
|
||||
void releaseBuffer(Slice const& buffer);
|
||||
void releaseBuffer(Range const& buffer);
|
||||
|
||||
// all commands buffers (Slices) written to this point are returned by waitForCommand(). This
|
||||
// call blocks until the CircularBuffer has at least mRequiredSize bytes available.
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ThreadUtils.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -152,14 +154,14 @@ struct CommandType<void (Driver::*)(ARGS...)> {
|
||||
}
|
||||
|
||||
// placement new declared as "throw" to avoid the compiler's null-check
|
||||
inline void* operator new(std::size_t size, void* ptr) {
|
||||
inline void* operator new(std::size_t, void* ptr) {
|
||||
assert_invariant(ptr);
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// convert an method of "class Driver" into a Command<> type
|
||||
// convert a method of "class Driver" into a Command<> type
|
||||
#define COMMAND_TYPE(method) CommandType<decltype(&Driver::method)>::Command<&Driver::method>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -211,6 +213,8 @@ public:
|
||||
CommandStream(CommandStream const& rhs) noexcept = delete;
|
||||
CommandStream& operator=(CommandStream const& rhs) noexcept = delete;
|
||||
|
||||
CircularBuffer const& getCircularBuffer() const noexcept { return mCurrentBuffer; }
|
||||
|
||||
public:
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
inline void methodName(paramsDecl) { \
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Command debugging off. debugging virtuals are not called.
|
||||
|
||||
@@ -300,6 +300,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isAutoDepthResolveSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isSRGBSwapChainSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isStereoSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthStencilResolveSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
|
||||
@@ -22,9 +22,18 @@
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(NDEBUG) && UTILS_HAS_RTTI
|
||||
# define HANDLE_TYPE_SAFETY 1
|
||||
#else
|
||||
@@ -222,7 +231,7 @@ private:
|
||||
explicit Allocator(const utils::AreaPolicy::HeapArea& area);
|
||||
|
||||
// this is in fact always called with a constexpr size argument
|
||||
[[nodiscard]] inline void* alloc(size_t size, size_t alignment, size_t extra) noexcept {
|
||||
[[nodiscard]] inline void* alloc(size_t size, size_t, size_t extra = 0) noexcept {
|
||||
void* p = nullptr;
|
||||
if (size <= mPool0.getSize()) p = mPool0.alloc(size, 16, extra);
|
||||
else if (size <= mPool1.getSize()) p = mPool1.alloc(size, 16, extra);
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
|
||||
|
||||
#include "backend/DriverEnums.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include "utils/compiler.h"
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
|
||||
@@ -17,15 +17,13 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
|
||||
|
||||
#include "backend/DriverApiForward.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <backend/DriverApiForward.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/SamplerDescriptor.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
#include "private/backend/CircularBuffer.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/architecture.h>
|
||||
#include <utils/ashmem.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#if !defined(WIN32) && !defined(__EMSCRIPTEN__) && !defined(IOS)
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
@@ -24,23 +32,20 @@
|
||||
# define HAS_MMAP 0
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <utils/architecture.h>
|
||||
#include <utils/ashmem.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
size_t CircularBuffer::sPageSize = arch::getPageSize();
|
||||
|
||||
CircularBuffer::CircularBuffer(size_t size) {
|
||||
CircularBuffer::CircularBuffer(size_t size)
|
||||
: mSize(size) {
|
||||
mData = alloc(size);
|
||||
mSize = size;
|
||||
mTail = mData;
|
||||
mHead = mData;
|
||||
}
|
||||
@@ -85,7 +90,7 @@ void* CircularBuffer::alloc(size_t size) noexcept {
|
||||
MAP_PRIVATE, fd, (off_t)size);
|
||||
if (vaddr_guard != MAP_FAILED && (vaddr_guard == (char*)vaddr_shadow + size)) {
|
||||
// woo-hoo success!
|
||||
mUsesAshmem = fd;
|
||||
mAshmemFd = fd;
|
||||
data = vaddr;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +98,7 @@ void* CircularBuffer::alloc(size_t size) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
if (UTILS_UNLIKELY(mUsesAshmem < 0)) {
|
||||
if (UTILS_UNLIKELY(mAshmemFd < 0)) {
|
||||
// ashmem failed
|
||||
if (vaddr_guard != MAP_FAILED) {
|
||||
munmap(vaddr_guard, size);
|
||||
@@ -137,9 +142,9 @@ void CircularBuffer::dealloc() noexcept {
|
||||
if (mData) {
|
||||
size_t const BLOCK_SIZE = getBlockSize();
|
||||
munmap(mData, mSize * 2 + BLOCK_SIZE);
|
||||
if (mUsesAshmem >= 0) {
|
||||
close(mUsesAshmem);
|
||||
mUsesAshmem = -1;
|
||||
if (mAshmemFd >= 0) {
|
||||
close(mAshmemFd);
|
||||
mAshmemFd = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -149,23 +154,37 @@ void CircularBuffer::dealloc() noexcept {
|
||||
}
|
||||
|
||||
|
||||
void CircularBuffer::circularize() noexcept {
|
||||
if (mUsesAshmem > 0) {
|
||||
intptr_t const overflow = intptr_t(mHead) - (intptr_t(mData) + ssize_t(mSize));
|
||||
if (overflow >= 0) {
|
||||
assert_invariant(size_t(overflow) <= mSize);
|
||||
mHead = (void *) (intptr_t(mData) + overflow);
|
||||
#ifndef NDEBUG
|
||||
memset(mData, 0xA5, size_t(overflow));
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// Only circularize if mHead if in the second buffer.
|
||||
if (intptr_t(mHead) - intptr_t(mData) > ssize_t(mSize)) {
|
||||
CircularBuffer::Range CircularBuffer::getBuffer() noexcept {
|
||||
Range const range{ .tail = mTail, .head = mHead };
|
||||
|
||||
char* const pData = static_cast<char*>(mData);
|
||||
char const* const pEnd = pData + mSize;
|
||||
char const* const pHead = static_cast<char const*>(mHead);
|
||||
if (UTILS_UNLIKELY(pHead >= pEnd)) {
|
||||
size_t const overflow = pHead - pEnd;
|
||||
if (UTILS_LIKELY(mAshmemFd > 0)) {
|
||||
assert_invariant(overflow <= mSize);
|
||||
mHead = static_cast<void*>(pData + overflow);
|
||||
// Data Tail End Head [virtual]
|
||||
// v v v v
|
||||
// +-------------:----+-----:--------------+
|
||||
// | : | : |
|
||||
// +-----:------------+--------------------+
|
||||
// Head |<------ copy ------>| [physical]
|
||||
} else {
|
||||
// Data Tail End Head
|
||||
// v v v v
|
||||
// +-------------:----+-----:--------------+
|
||||
// | : | : |
|
||||
// +-----|------------+-----|--------------+
|
||||
// |<---------------->|
|
||||
// sliding window
|
||||
mHead = mData;
|
||||
}
|
||||
}
|
||||
mTail = mHead;
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -15,14 +15,25 @@
|
||||
*/
|
||||
|
||||
#include "private/backend/CommandBufferQueue.h"
|
||||
#include "private/backend/CircularBuffer.h"
|
||||
#include "private/backend/CommandStream.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/ostream.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include "private/backend/BackendUtils.h"
|
||||
#include "private/backend/CommandStream.h"
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace utils;
|
||||
|
||||
@@ -65,50 +76,53 @@ void CommandBufferQueue::flush() noexcept {
|
||||
// always guaranteed to have enough space for the NoopCommand
|
||||
new(circularBuffer.allocate(sizeof(NoopCommand))) NoopCommand(nullptr);
|
||||
|
||||
// end of this slice
|
||||
void* const head = circularBuffer.getHead();
|
||||
const size_t requiredSize = mRequiredSize;
|
||||
|
||||
// beginning of this slice
|
||||
void* const tail = circularBuffer.getTail();
|
||||
// get the current buffer
|
||||
auto const [begin, end] = circularBuffer.getBuffer();
|
||||
|
||||
// size of this slice
|
||||
uint32_t const used = uint32_t(intptr_t(head) - intptr_t(tail));
|
||||
assert_invariant(circularBuffer.empty());
|
||||
|
||||
circularBuffer.circularize();
|
||||
// size of the current buffer
|
||||
size_t const used = std::distance(
|
||||
static_cast<char const*>(begin), static_cast<char const*>(end));
|
||||
|
||||
std::unique_lock<utils::Mutex> lock(mLock);
|
||||
mCommandBuffersToExecute.push_back({ tail, head });
|
||||
mCommandBuffersToExecute.push_back({ begin, end });
|
||||
mCondition.notify_one();
|
||||
|
||||
// circular buffer is too small, we corrupted the stream
|
||||
ASSERT_POSTCONDITION(used <= mFreeSpace,
|
||||
"Backend CommandStream overflow. Commands are corrupted and unrecoverable.\n"
|
||||
"Please increase minCommandBufferSizeMB inside the Config passed to Engine::create.\n"
|
||||
"Space used at this time: %u bytes",
|
||||
(unsigned)used);
|
||||
"Space used at this time: %u bytes, overflow: %u bytes",
|
||||
(unsigned)used, unsigned(used - mFreeSpace));
|
||||
|
||||
// wait until there is enough space in the buffer
|
||||
mFreeSpace -= used;
|
||||
const size_t requiredSize = mRequiredSize;
|
||||
if (UTILS_UNLIKELY(mFreeSpace < requiredSize)) {
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_t totalUsed = circularBuffer.size() - mFreeSpace;
|
||||
mHighWatermark = std::max(mHighWatermark, totalUsed);
|
||||
if (UTILS_UNLIKELY(totalUsed > requiredSize)) {
|
||||
slog.d << "CommandStream used too much space: " << totalUsed
|
||||
<< ", out of " << requiredSize << " (will block)" << io::endl;
|
||||
}
|
||||
size_t const totalUsed = circularBuffer.size() - mFreeSpace;
|
||||
slog.d << "CommandStream used too much space (will block): "
|
||||
<< "needed space " << requiredSize << " out of " << mFreeSpace
|
||||
<< ", totalUsed=" << totalUsed << ", current=" << used
|
||||
<< ", queue size=" << mCommandBuffersToExecute.size() << " buffers"
|
||||
<< io::endl;
|
||||
|
||||
mHighWatermark = std::max(mHighWatermark, totalUsed);
|
||||
#endif
|
||||
|
||||
mCondition.notify_one();
|
||||
if (UTILS_LIKELY(mFreeSpace < requiredSize)) {
|
||||
SYSTRACE_NAME("waiting: CircularBuffer::flush()");
|
||||
mCondition.wait(lock, [this, requiredSize]() -> bool {
|
||||
// TODO: on macOS, we need to call pumpEvents from time to time
|
||||
return mFreeSpace >= requiredSize;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CommandBufferQueue::Slice> CommandBufferQueue::waitForCommands() const {
|
||||
std::vector<CommandBufferQueue::Range> CommandBufferQueue::waitForCommands() const {
|
||||
if (!UTILS_HAS_THREADING) {
|
||||
return std::move(mCommandBuffersToExecute);
|
||||
}
|
||||
@@ -123,7 +137,7 @@ std::vector<CommandBufferQueue::Slice> CommandBufferQueue::waitForCommands() con
|
||||
return std::move(mCommandBuffersToExecute);
|
||||
}
|
||||
|
||||
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Slice const& buffer) {
|
||||
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Range const& buffer) {
|
||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
||||
mFreeSpace += uintptr_t(buffer.end) - uintptr_t(buffer.begin);
|
||||
mCondition.notify_one();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <math/half.h>
|
||||
@@ -29,6 +34,13 @@
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace utils;
|
||||
using namespace filament::math;
|
||||
|
||||
@@ -119,7 +131,8 @@ void DriverBase::purge() noexcept {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
|
||||
scheduleCallback(buffer.getHandler(), [buffer = std::move(buffer)]() {
|
||||
auto const handler = buffer.getHandler();
|
||||
scheduleCallback(handler, [buffer = std::move(buffer)]() {
|
||||
// user callback is called when BufferDescriptor gets destroyed
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,24 +34,12 @@ public:
|
||||
|
||||
explicit MetalBlitter(MetalContext& context) noexcept;
|
||||
|
||||
enum class FormatType { NONE, COLOR, DEPTH, STENCIL, DEPTH_STENCIL };
|
||||
static FormatType getFormatType(TextureFormat format) noexcept {
|
||||
bool const depth = isDepthFormat(format);
|
||||
bool const stencil = isStencilFormat(format);
|
||||
if (depth && stencil) return FormatType::DEPTH_STENCIL;
|
||||
if (depth) return FormatType::DEPTH;
|
||||
if (stencil) return FormatType::STENCIL;
|
||||
return FormatType::COLOR;
|
||||
}
|
||||
|
||||
struct BlitArgs {
|
||||
struct Attachment {
|
||||
using Type = FormatType;
|
||||
id<MTLTexture> texture = nil;
|
||||
MTLRegion region = {};
|
||||
uint8_t level = 0;
|
||||
uint32_t slice = 0; // must be 0 on source attachment
|
||||
Type type = Type::NONE;
|
||||
};
|
||||
|
||||
// Valid source formats: 2D, 2DArray, 2DMultisample, 3D
|
||||
@@ -60,16 +48,6 @@ public:
|
||||
Attachment destination;
|
||||
SamplerMagFilter filter;
|
||||
|
||||
bool blitColor() const {
|
||||
return source.type == Attachment::Type::COLOR &&
|
||||
destination.type == Attachment::Type::COLOR;
|
||||
}
|
||||
|
||||
bool blitDepth() const {
|
||||
return source.type == Attachment::Type::DEPTH &&
|
||||
destination.type == Attachment::Type::DEPTH;
|
||||
}
|
||||
|
||||
bool destinationIsFullAttachment() const {
|
||||
return destination.texture.width == destination.region.size.width &&
|
||||
destination.texture.height == destination.region.size.height;
|
||||
@@ -90,31 +68,20 @@ private:
|
||||
const BlitArgs& args, uint32_t depthPlane);
|
||||
|
||||
struct BlitFunctionKey {
|
||||
bool blitColor;
|
||||
bool blitDepth;
|
||||
bool msaaColorSource;
|
||||
bool msaaDepthSource;
|
||||
bool sources3D;
|
||||
|
||||
char padding[3];
|
||||
bool msaaColorSource{};
|
||||
bool sources3D{};
|
||||
char padding[2]{};
|
||||
|
||||
bool isValid() const noexcept {
|
||||
// MSAA 3D textures do not exist.
|
||||
bool const hasMsaa = msaaColorSource || msaaDepthSource;
|
||||
bool const hasMsaa = msaaColorSource;
|
||||
return !(hasMsaa && sources3D);
|
||||
}
|
||||
|
||||
bool operator==(const BlitFunctionKey& rhs) const noexcept {
|
||||
return blitColor == rhs.blitColor &&
|
||||
blitDepth == rhs.blitDepth &&
|
||||
msaaColorSource == rhs.msaaColorSource &&
|
||||
msaaDepthSource == rhs.msaaDepthSource &&
|
||||
return msaaColorSource == rhs.msaaColorSource &&
|
||||
sources3D == rhs.sources3D;
|
||||
}
|
||||
|
||||
BlitFunctionKey() {
|
||||
std::memset(this, 0, sizeof(BlitFunctionKey));
|
||||
}
|
||||
};
|
||||
|
||||
static bool blitFastPath(id<MTLCommandBuffer> cmdBuffer,
|
||||
@@ -123,9 +90,8 @@ private:
|
||||
void blitSlowPath(id<MTLCommandBuffer> cmdBuffer,
|
||||
const BlitArgs& args, const char* label);
|
||||
|
||||
void blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor, bool blitDepth,
|
||||
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest,
|
||||
const char* label);
|
||||
void blitDepthPlane(id <MTLCommandBuffer> cmdBuffer, const BlitArgs& args,
|
||||
uint32_t depthPlaneSource, uint32_t depthPlaneDest, const char* label);
|
||||
|
||||
id<MTLFunction> compileFragmentFunction(BlitFunctionKey key) const;
|
||||
id<MTLFunction> getBlitVertexFunction();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "MetalUtils.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -36,13 +37,7 @@ struct VertexOut
|
||||
|
||||
struct FragmentOut
|
||||
{
|
||||
#ifdef BLIT_COLOR
|
||||
float4 color [[color(0)]];
|
||||
#endif
|
||||
|
||||
#ifdef BLIT_DEPTH
|
||||
float depth [[depth(any)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
vertex VertexOut
|
||||
@@ -66,7 +61,6 @@ fragment FragmentOut
|
||||
blitterFrag(VertexOut in [[stage_in]],
|
||||
sampler sourceSampler [[sampler(0)]],
|
||||
|
||||
#ifdef BLIT_COLOR
|
||||
#ifdef MSAA_COLOR_SOURCE
|
||||
texture2d_ms<float, access::read> sourceColor [[texture(0)]],
|
||||
#elif SOURCES_3D
|
||||
@@ -74,32 +68,18 @@ blitterFrag(VertexOut in [[stage_in]],
|
||||
#else
|
||||
texture2d<float, access::sample> sourceColor [[texture(0)]],
|
||||
#endif // MSAA_COLOR_SOURCE
|
||||
#endif // BLIT_COLOR
|
||||
|
||||
#ifdef BLIT_DEPTH
|
||||
#ifdef MSAA_DEPTH_SOURCE
|
||||
texture2d_ms<float, access::read> sourceDepth [[texture(1)]],
|
||||
#elif SOURCES_3D
|
||||
texture3d<float, access::sample> sourceDepth [[texture(1)]],
|
||||
#else
|
||||
texture2d<float, access::sample> sourceDepth [[texture(1)]],
|
||||
#endif // MSAA_DEPTH_SOURCE
|
||||
#endif // BLIT_DEPTH
|
||||
|
||||
constant FragmentArgs* args [[buffer(0)]])
|
||||
{
|
||||
FragmentOut out = {};
|
||||
|
||||
#if defined(BLIT_COLOR) || defined(BLIT_DEPTH)
|
||||
// These coordinates match the Vulkan vkCmdBlitImage spec:
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdBlitImage.html
|
||||
float2 uvbase = in.position.xy; // unnormalized coordinates at center of texel: (1.5, 2.5, etc)
|
||||
float2 uvoffset = uvbase - args->dstOffset;
|
||||
float2 uvscaled = uvoffset * args->scale;
|
||||
float2 uv = uvscaled + args->srcOffset;
|
||||
#endif
|
||||
|
||||
#ifdef BLIT_COLOR
|
||||
#ifdef MSAA_COLOR_SOURCE
|
||||
out.color = float4(0.0);
|
||||
for (uint s = 0; s < sourceColor.get_num_samples(); s++) {
|
||||
@@ -115,25 +95,7 @@ blitterFrag(VertexOut in [[stage_in]],
|
||||
float2 uvnorm = uv / float2(sourceColor.get_width(args->lod), sourceColor.get_height(args->lod));
|
||||
out.color += sourceColor.sample(sourceSampler, uvnorm, level(args->lod));
|
||||
#endif // MSAA_COLOR_SOURCE
|
||||
#endif // BLIT_COLOR
|
||||
|
||||
#ifdef BLIT_DEPTH
|
||||
#ifdef MSAA_DEPTH_SOURCE
|
||||
out.depth = 0.0;
|
||||
for (uint s = 0; s < sourceDepth.get_num_samples(); s++) {
|
||||
out.depth += sourceDepth.read(static_cast<uint2>(uv), s).r;
|
||||
}
|
||||
out.depth /= sourceDepth.get_num_samples();
|
||||
#elif SOURCES_3D
|
||||
float2 uvnormd = uv / float2(sourceDepth.get_width(args->lod), sourceDepth.get_height(args->lod));
|
||||
float3 coords = float3(uvnormd, (static_cast<float>(args->depthPlane) + 0.5) /
|
||||
sourceDepth.get_depth(args->lod));
|
||||
out.depth = sourceDepth.sample(sourceSampler, coords, level(args->lod)).r;
|
||||
#else
|
||||
float2 uvnormd = uv / float2(sourceDepth.get_width(args->lod), sourceDepth.get_height(args->lod));
|
||||
out.depth = sourceDepth.sample(sourceSampler, uvnormd, level(args->lod)).r;
|
||||
#endif // MSAA_DEPTH_SOURCE
|
||||
#endif // BLIT_DEPTH
|
||||
return out;
|
||||
}
|
||||
)";
|
||||
@@ -158,9 +120,12 @@ void MetalBlitter::blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args, co
|
||||
return;
|
||||
}
|
||||
|
||||
// If the destination is MSAA, and we weren't able to use the fast path (meaning formats
|
||||
// didn't match or sample count didn't match), report an error, as blitting to a MSAA texture
|
||||
// isn't supported through the "slow path" yet.
|
||||
// If we end-up here, it means that either:
|
||||
// - we're resolving a color texture
|
||||
// - src/dest formats didn't match, or we're scaling -- this can only happen with the legacy
|
||||
// blit() path and implies that the format is not depth.
|
||||
// note: in the future we will support a fast-path resolve
|
||||
|
||||
UTILS_UNUSED_IN_RELEASE
|
||||
const bool destinationIsMultisample =
|
||||
args.destination.texture.textureType == MTLTextureType2DMultisample;
|
||||
@@ -197,49 +162,31 @@ bool MetalBlitter::blitFastPath(id<MTLCommandBuffer> cmdBuffer,
|
||||
|
||||
void MetalBlitter::blitSlowPath(id<MTLCommandBuffer> cmdBuffer,
|
||||
const BlitArgs& args, const char* label) {
|
||||
bool const blitColor = args.blitColor();
|
||||
bool const blitDepth = args.blitDepth();
|
||||
// scaling in any dimension is not allowed
|
||||
assert_invariant(args.source.region.size.depth == args.destination.region.size.depth);
|
||||
// we're always blitting a single plane
|
||||
assert_invariant(blitColor != blitDepth);
|
||||
uint32_t depthPlaneSource = args.source.region.origin.z;
|
||||
uint32_t depthPlaneDest = args.destination.region.origin.z;
|
||||
for (NSUInteger d = 0; d < args.source.region.size.depth; d++) {
|
||||
blitDepthPlane(cmdBuffer, blitColor, blitDepth, args,
|
||||
blitDepthPlane(cmdBuffer, args,
|
||||
depthPlaneSource++, depthPlaneDest++, label);
|
||||
}
|
||||
}
|
||||
|
||||
void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor, bool blitDepth,
|
||||
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest,
|
||||
const char* label) {
|
||||
|
||||
assert_invariant(blitColor != blitDepth);
|
||||
void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args,
|
||||
uint32_t depthPlaneSource, uint32_t depthPlaneDest, const char* label) {
|
||||
|
||||
MTLRenderPassDescriptor* const descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
|
||||
if (blitColor) {
|
||||
setupAttachment(descriptor.colorAttachments[0], args, depthPlaneDest);
|
||||
}
|
||||
|
||||
if (blitDepth) {
|
||||
setupAttachment(descriptor.depthAttachment, args, depthPlaneDest);
|
||||
}
|
||||
setupAttachment(descriptor.colorAttachments[0], args, depthPlaneDest);
|
||||
|
||||
id<MTLRenderCommandEncoder> const encoder =
|
||||
[cmdBuffer renderCommandEncoderWithDescriptor:descriptor];
|
||||
encoder.label = @(label);
|
||||
|
||||
BlitFunctionKey key;
|
||||
key.blitColor = blitColor;
|
||||
key.blitDepth = blitDepth;
|
||||
key.msaaColorSource = blitColor && args.source.texture.textureType == MTLTextureType2DMultisample;
|
||||
key.msaaDepthSource = blitDepth && args.source.texture.textureType == MTLTextureType2DMultisample;
|
||||
key.sources3D = blitColor && args.source.texture.textureType == MTLTextureType3D;
|
||||
if (key.sources3D && blitDepth) {
|
||||
assert_invariant(args.source.texture.textureType == MTLTextureType3D);
|
||||
}
|
||||
key.msaaColorSource = args.source.texture.textureType == MTLTextureType2DMultisample;
|
||||
key.sources3D = args.source.texture.textureType == MTLTextureType3D;
|
||||
id<MTLFunction> const fragmentFunction = getBlitFragmentFunction(key);
|
||||
|
||||
MetalPipelineState const pipelineState {
|
||||
@@ -247,7 +194,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
.fragmentFunction = fragmentFunction,
|
||||
.vertexDescription = {},
|
||||
.colorAttachmentPixelFormat = {
|
||||
blitColor ? args.destination.texture.pixelFormat : MTLPixelFormatInvalid,
|
||||
args.destination.texture.pixelFormat,
|
||||
MTLPixelFormatInvalid,
|
||||
MTLPixelFormatInvalid,
|
||||
MTLPixelFormatInvalid,
|
||||
@@ -256,8 +203,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
MTLPixelFormatInvalid,
|
||||
MTLPixelFormatInvalid
|
||||
},
|
||||
.depthAttachmentPixelFormat =
|
||||
blitDepth ? args.destination.texture.pixelFormat : MTLPixelFormatInvalid,
|
||||
.depthAttachmentPixelFormat = MTLPixelFormatInvalid,
|
||||
.sampleCount = 1,
|
||||
.blendState = {}
|
||||
};
|
||||
@@ -267,21 +213,11 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
|
||||
// For texture arrays, create a view of the texture at the given slice (layer).
|
||||
|
||||
if (blitColor) {
|
||||
id<MTLTexture> srcTextureColor = args.source.texture;
|
||||
if (srcTextureColor && srcTextureColor.textureType == MTLTextureType2DArray) {
|
||||
srcTextureColor = createTextureViewWithSingleSlice(srcTextureColor, args.source.slice);
|
||||
}
|
||||
[encoder setFragmentTexture:srcTextureColor atIndex:0];
|
||||
}
|
||||
|
||||
if (blitDepth) {
|
||||
id<MTLTexture> srcTextureDepth = args.source.texture;
|
||||
if (srcTextureDepth && srcTextureDepth.textureType == MTLTextureType2DArray) {
|
||||
srcTextureDepth = createTextureViewWithSingleSlice(srcTextureDepth, args.source.slice);
|
||||
}
|
||||
[encoder setFragmentTexture:srcTextureDepth atIndex:1];
|
||||
id<MTLTexture> srcTextureColor = args.source.texture;
|
||||
if (srcTextureColor && srcTextureColor.textureType == MTLTextureType2DArray) {
|
||||
srcTextureColor = createTextureViewWithSingleSlice(srcTextureColor, args.source.slice);
|
||||
}
|
||||
[encoder setFragmentTexture:srcTextureColor atIndex:0];
|
||||
|
||||
SamplerMinFilter filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST;
|
||||
if (args.filter == SamplerMagFilter::NEAREST) {
|
||||
@@ -310,7 +246,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
|
||||
DepthStencilState const depthStencilState {
|
||||
.depthCompare = MTLCompareFunctionAlways,
|
||||
.depthWriteEnabled = blitDepth
|
||||
.depthWriteEnabled = false
|
||||
};
|
||||
id<MTLDepthStencilState> const depthStencil =
|
||||
mContext.depthStencilStateCache.getOrCreateState(depthStencilState);
|
||||
@@ -370,18 +306,9 @@ void MetalBlitter::setupAttachment(MTLRenderPassAttachmentDescriptor* descriptor
|
||||
id<MTLFunction> MetalBlitter::compileFragmentFunction(BlitFunctionKey key) const {
|
||||
MTLCompileOptions* const options = [MTLCompileOptions new];
|
||||
NSMutableDictionary* const macros = [NSMutableDictionary dictionary];
|
||||
if (key.blitColor) {
|
||||
macros[@"BLIT_COLOR"] = @"1";
|
||||
}
|
||||
if (key.blitDepth) {
|
||||
macros[@"BLIT_DEPTH"] = @"1";
|
||||
}
|
||||
if (key.msaaColorSource) {
|
||||
macros[@"MSAA_COLOR_SOURCE"] = @"1";
|
||||
}
|
||||
if (key.msaaDepthSource) {
|
||||
macros[@"MSAA_DEPTH_SOURCE"] = @"1";
|
||||
}
|
||||
if (key.sources3D) {
|
||||
macros[@"SOURCES_3D"] = @"1";
|
||||
}
|
||||
|
||||
@@ -73,7 +73,10 @@ private:
|
||||
std::unordered_set<MetalBufferPoolEntry const*> mUsedStages;
|
||||
|
||||
// Store the current "time" (really just a frame count) and LRU eviction parameters.
|
||||
uint64_t mCurrentFrame = 0;
|
||||
// An atomic is necessary as mCurrentFrame is incremented in gc() (called on
|
||||
// the driver thread) and read from acquireBuffer() and releaseBuffer(),
|
||||
// which may be called on non-driver threads.
|
||||
std::atomic<uint64_t> mCurrentFrame = 0;
|
||||
static constexpr uint32_t TIME_BEFORE_EVICTION = 10;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "MetalContext.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/trap.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
@@ -142,7 +142,10 @@ struct MetalContext {
|
||||
// Fences, only supported on macOS 10.14 and iOS 12 and above.
|
||||
API_AVAILABLE(macos(10.14), ios(12.0))
|
||||
MTLSharedEventListener* eventListener = nil;
|
||||
uint64_t signalId = 1;
|
||||
// signalId is incremented in the MetalFence constructor, which is called on
|
||||
// both the driver (MetalTimerQueryFence::beginTimeElapsedQuery) and main
|
||||
// threads (in createFenceS), so an atomic is necessary.
|
||||
std::atomic<uint64_t> signalId = 1;
|
||||
|
||||
MetalTimerQueryInterface* timerQueryImpl;
|
||||
|
||||
|
||||
@@ -730,6 +730,10 @@ bool MetalDriver::isParallelShaderCompileSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetalDriver::isDepthStencilResolveSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
@@ -1260,11 +1264,9 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
|
||||
args.source.level = miplevel;
|
||||
args.source.region = MTLRegionMake2D(0, 0, srcTexture.width >> miplevel, srcTexture.height >> miplevel);
|
||||
args.source.texture = srcTexture;
|
||||
args.source.type = MetalBlitter::BlitArgs::Attachment::Type::COLOR;
|
||||
args.destination.level = 0;
|
||||
args.destination.region = MTLRegionMake2D(0, 0, readPixelsTexture.width, readPixelsTexture.height);
|
||||
args.destination.texture = readPixelsTexture;
|
||||
args.destination.type = MetalBlitter::BlitArgs::Attachment::Type::COLOR;
|
||||
|
||||
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "readPixels blit");
|
||||
|
||||
@@ -1322,6 +1324,12 @@ void MetalDriver::resolve(
|
||||
ASSERT_PRECONDITION(srcTexture->format == dstTexture->format,
|
||||
"src and dst texture format don't match");
|
||||
|
||||
ASSERT_PRECONDITION(!isDepthFormat(srcTexture->format),
|
||||
"can't resolve depth formats");
|
||||
|
||||
ASSERT_PRECONDITION(!isStencilFormat(srcTexture->format),
|
||||
"can't resolve stencil formats");
|
||||
|
||||
ASSERT_PRECONDITION(any(dstTexture->usage & TextureUsage::BLIT_DST),
|
||||
"texture doesn't have BLIT_DST");
|
||||
|
||||
@@ -1381,9 +1389,7 @@ void MetalDriver::blit(
|
||||
// FIXME: we shouldn't need to know the type here. This is an artifact of using the old API.
|
||||
|
||||
args.source.texture = srcTexture->getMtlTextureForRead();
|
||||
args.source.type = MetalBlitter::getFormatType(srcTexture->format);
|
||||
args.destination.texture = dstTexture->getMtlTextureForWrite();
|
||||
args.destination.type = MetalBlitter::getFormatType(dstTexture->format);
|
||||
args.source.level = srcLevel;
|
||||
args.source.slice = srcLayer;
|
||||
args.destination.level = dstLevel;
|
||||
@@ -1438,13 +1444,11 @@ void MetalDriver::blitDEPRECATED(TargetBufferFlags buffers,
|
||||
args.source.texture = srcColorAttachment.getTexture();
|
||||
args.source.level = srcColorAttachment.level;
|
||||
args.source.slice = srcColorAttachment.layer;
|
||||
args.source.type = MetalBlitter::FormatType::COLOR;
|
||||
|
||||
args.destination.region = dstTarget->getRegionFromClientRect(dstRect);
|
||||
args.destination.texture = dstColorAttachment.getTexture();
|
||||
args.destination.level = dstColorAttachment.level;
|
||||
args.destination.slice = dstColorAttachment.layer;
|
||||
args.destination.type = MetalBlitter::FormatType::COLOR;
|
||||
|
||||
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "blitDEPRECATED");
|
||||
}
|
||||
@@ -1584,7 +1588,7 @@ void MetalDriver::draw(PipelineState ps, Handle<HwRenderPrimitive> rph, uint32_t
|
||||
stencilPixelFormat = stencilAttachment.getPixelFormat();
|
||||
assert_invariant(isMetalFormatStencil(stencilPixelFormat));
|
||||
}
|
||||
MetalPipelineState pipelineState {
|
||||
MetalPipelineState const pipelineState {
|
||||
.vertexFunction = vertex,
|
||||
.fragmentFunction = fragment,
|
||||
.vertexDescription = primitive->vertexDescription,
|
||||
@@ -1602,13 +1606,13 @@ void MetalDriver::draw(PipelineState ps, Handle<HwRenderPrimitive> rph, uint32_t
|
||||
.stencilAttachmentPixelFormat = stencilPixelFormat,
|
||||
.sampleCount = mContext->currentRenderTarget->getSamples(),
|
||||
.blendState = BlendState {
|
||||
.blendingEnabled = rs.hasBlending(),
|
||||
.rgbBlendOperation = getMetalBlendOperation(rs.blendEquationRGB),
|
||||
.alphaBlendOperation = getMetalBlendOperation(rs.blendEquationAlpha),
|
||||
.sourceRGBBlendFactor = getMetalBlendFactor(rs.blendFunctionSrcRGB),
|
||||
.sourceAlphaBlendFactor = getMetalBlendFactor(rs.blendFunctionSrcAlpha),
|
||||
.rgbBlendOperation = getMetalBlendOperation(rs.blendEquationRGB),
|
||||
.destinationAlphaBlendFactor = getMetalBlendFactor(rs.blendFunctionDstAlpha),
|
||||
.destinationRGBBlendFactor = getMetalBlendFactor(rs.blendFunctionDstRGB),
|
||||
.destinationAlphaBlendFactor = getMetalBlendFactor(rs.blendFunctionDstAlpha)
|
||||
.sourceAlphaBlendFactor = getMetalBlendFactor(rs.blendFunctionSrcAlpha),
|
||||
.sourceRGBBlendFactor = getMetalBlendFactor(rs.blendFunctionSrcRGB),
|
||||
.blendingEnabled = rs.hasBlending(),
|
||||
},
|
||||
.colorWrite = rs.colorWrite
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "MetalUtils.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/trap.h>
|
||||
|
||||
#define NSERROR_CHECK(message) \
|
||||
|
||||
@@ -245,30 +245,53 @@ void MetalSwapChain::present() {
|
||||
}
|
||||
}
|
||||
|
||||
struct PresentDrawableData {
|
||||
void* drawable = nullptr;
|
||||
MetalDriver* driver = nullptr;
|
||||
#ifndef FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD
|
||||
#define FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD 1
|
||||
#endif
|
||||
|
||||
class PresentDrawableData {
|
||||
public:
|
||||
PresentDrawableData() = delete;
|
||||
PresentDrawableData(const PresentDrawableData&) = delete;
|
||||
PresentDrawableData& operator=(const PresentDrawableData&) = delete;
|
||||
|
||||
static PresentDrawableData* create(id<CAMetalDrawable> drawable, MetalDriver* driver) {
|
||||
assert_invariant(driver);
|
||||
return new PresentDrawableData(drawable, driver);
|
||||
}
|
||||
|
||||
static void maybePresentAndDestroyAsync(PresentDrawableData* that, bool shouldPresent) {
|
||||
if (shouldPresent) {
|
||||
[that->mDrawable present];
|
||||
}
|
||||
|
||||
#if FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD == 1
|
||||
// mDrawable is acquired on the driver thread. Typically, we would release this object on
|
||||
// the same thread, but after receiving consistent crash reports from within
|
||||
// [CAMetalDrawable dealloc], we suspect this object requires releasing on the main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ cleanupAndDestroy(that); });
|
||||
#else
|
||||
that->mDriver->runAtNextTick([that]() { cleanupAndDestroy(that); });
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
PresentDrawableData(id<CAMetalDrawable> drawable, MetalDriver* driver)
|
||||
: mDrawable(drawable), mDriver(driver) {}
|
||||
|
||||
static void cleanupAndDestroy(PresentDrawableData *that) {
|
||||
that->mDrawable = nil;
|
||||
that->mDriver = nullptr;
|
||||
delete that;
|
||||
}
|
||||
|
||||
id<CAMetalDrawable> mDrawable;
|
||||
MetalDriver* mDriver = nullptr;
|
||||
};
|
||||
|
||||
void presentDrawable(bool presentFrame, void* user) {
|
||||
auto* presentDrawableData = static_cast<PresentDrawableData*>(user);
|
||||
|
||||
// CFBridgingRelease here is used to balance the CFBridgingRetain inside acquireDrawable.
|
||||
id<CAMetalDrawable> drawable =
|
||||
(id<CAMetalDrawable>)CFBridgingRelease(presentDrawableData->drawable);
|
||||
if (presentFrame) {
|
||||
[drawable present];
|
||||
}
|
||||
|
||||
// Schedule the drawable destruction on the driver thread.
|
||||
void* voidDrawable = (void*) CFBridgingRetain(drawable);
|
||||
MetalDriver* driver = presentDrawableData->driver;
|
||||
driver->runAtNextTick([voidDrawable]() {
|
||||
// The drawable is released here.
|
||||
CFBridgingRelease(voidDrawable);
|
||||
});
|
||||
|
||||
delete presentDrawableData;
|
||||
PresentDrawableData::maybePresentAndDestroyAsync(presentDrawableData, presentFrame);
|
||||
}
|
||||
|
||||
void MetalSwapChain::scheduleFrameScheduledCallback() {
|
||||
@@ -277,21 +300,16 @@ void MetalSwapChain::scheduleFrameScheduledCallback() {
|
||||
}
|
||||
|
||||
assert_invariant(drawable);
|
||||
FrameScheduledCallback callback = frameScheduledCallback;
|
||||
// This block strongly captures drawable to keep it alive until the handler executes.
|
||||
// We cannot simply reference this->drawable inside the block because the block would then only
|
||||
// capture the _this_ pointer (MetalSwapChain*) instead of the drawable.
|
||||
id<CAMetalDrawable> d = drawable;
|
||||
|
||||
// Destroy this by calling maybePresentAndDestroyAsync() later.
|
||||
auto* presentData = PresentDrawableData::create(drawable, context.driver);
|
||||
|
||||
FrameScheduledCallback userCallback = frameScheduledCallback;
|
||||
void* userData = frameScheduledUserData;
|
||||
MetalDriver* driver = context.driver;
|
||||
|
||||
[getPendingCommandBuffer(&context) addScheduledHandler:^(id<MTLCommandBuffer> cb) {
|
||||
// CFBridgingRetain is used here to give the drawable a +1 retain count before
|
||||
// casting it to a void*.
|
||||
auto* presentDrawableData = new PresentDrawableData;
|
||||
presentDrawableData->drawable = (void*) CFBridgingRetain(d);
|
||||
presentDrawableData->driver = driver;
|
||||
PresentCallable callable(presentDrawable, (void*) presentDrawableData);
|
||||
callback(callable, userData);
|
||||
PresentCallable callable(presentDrawable, static_cast<void*>(presentData));
|
||||
userCallback(callable, userData);
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -820,12 +838,10 @@ void MetalTexture::loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region
|
||||
args.source.slice = 0;
|
||||
args.source.region = sourceRegion;
|
||||
args.source.texture = stagingTexture;
|
||||
args.source.type = MetalBlitter::FormatType::COLOR;
|
||||
args.destination.level = level;
|
||||
args.destination.slice = slice;
|
||||
args.destination.region = region;
|
||||
args.destination.texture = destinationTexture;
|
||||
args.destination.type = MetalBlitter::FormatType::COLOR;
|
||||
context.blitter->blit(getPendingCommandBuffer(&context), args, "Texture upload blit");
|
||||
}
|
||||
|
||||
|
||||
@@ -103,10 +103,19 @@ void MetalShaderCompiler::terminate() noexcept {
|
||||
NSString* objcSource = [[NSString alloc] initWithBytes:source.data()
|
||||
length:source.size() - 1
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point arithmetic,
|
||||
// which is crucial for half precision floats in scenarios where fast math optimizations
|
||||
// lead to inaccuracies, such as in handling special values like NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
|
||||
NSError* error = nil;
|
||||
// When options is nil, Metal uses the most recent language version available.
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
|
||||
options:nil
|
||||
options:options
|
||||
error:&error];
|
||||
if (library == nil) {
|
||||
if (error) {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "MetalEnums.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
|
||||
@@ -182,6 +182,10 @@ bool NoopDriver::isParallelShaderCompileSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isDepthStencilResolveSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NoopDriver::isWorkaroundNeeded(Workaround) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -274,6 +274,7 @@ void OpenGLContext::setDefaultState() noexcept {
|
||||
glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_NICEST);
|
||||
#endif
|
||||
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
if (ext.EXT_clip_control) {
|
||||
#if defined(BACKEND_OPENGL_VERSION_GL)
|
||||
glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
|
||||
@@ -281,6 +282,7 @@ void OpenGLContext::setDefaultState() noexcept {
|
||||
glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ext.EXT_clip_cull_distance) {
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
@@ -309,7 +311,9 @@ void OpenGLContext::initProcs(Procs* procs,
|
||||
# ifdef BACKEND_OPENGL_VERSION_GL
|
||||
procs->getQueryObjectui64v = glGetQueryObjectui64v; // only core in GL
|
||||
# elif defined(GL_EXT_disjoint_timer_query)
|
||||
procs->getQueryObjectui64v = glGetQueryObjectui64vEXT;
|
||||
# ifndef __EMSCRIPTEN__
|
||||
procs->getQueryObjectui64v = glGetQueryObjectui64vEXT;
|
||||
# endif
|
||||
# endif // BACKEND_OPENGL_VERSION_GL
|
||||
|
||||
// core in ES 3.0 and GL 4.3
|
||||
@@ -321,6 +325,7 @@ void OpenGLContext::initProcs(Procs* procs,
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
# ifndef IOS // IOS is guaranteed to have ES3.x
|
||||
# ifndef __EMSCRIPTEN__
|
||||
if (UTILS_UNLIKELY(major == 2)) {
|
||||
// Runtime OpenGL version is ES 2.x
|
||||
if (UTILS_LIKELY(ext.OES_vertex_array_object)) {
|
||||
@@ -348,6 +353,7 @@ void OpenGLContext::initProcs(Procs* procs,
|
||||
|
||||
procs->maxShaderCompilerThreadsKHR = glMaxShaderCompilerThreadsKHR;
|
||||
}
|
||||
# endif // __EMSCRIPTEN__
|
||||
# endif // IOS
|
||||
#else
|
||||
procs->maxShaderCompilerThreadsKHR = glMaxShaderCompilerThreadsARB;
|
||||
@@ -421,7 +427,6 @@ void OpenGLContext::initBugs(Bugs* bugs, Extensions const& exts,
|
||||
if (strstr(renderer, "Mali-T")) {
|
||||
bugs->disable_glFlush = true;
|
||||
bugs->disable_shared_context_draws = true;
|
||||
bugs->texture_external_needs_rebind = true;
|
||||
// We have not verified that timer queries work on Mali-T, so we disable to be safe.
|
||||
bugs->dont_use_timer_query = true;
|
||||
}
|
||||
@@ -580,17 +585,23 @@ void OpenGLContext::initExtensionsGLES(Extensions* ext, GLint major, GLint minor
|
||||
// figure out and initialize the extensions we need
|
||||
using namespace std::literals;
|
||||
ext->APPLE_color_buffer_packed_float = exts.has("GL_APPLE_color_buffer_packed_float"sv);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_clip_control = exts.has("GL_EXT_clip_control"sv);
|
||||
#endif
|
||||
ext->EXT_clip_cull_distance = exts.has("GL_EXT_clip_cull_distance"sv);
|
||||
ext->EXT_color_buffer_float = exts.has("GL_EXT_color_buffer_float"sv);
|
||||
ext->EXT_color_buffer_half_float = exts.has("GL_EXT_color_buffer_half_float"sv);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
#endif
|
||||
ext->EXT_discard_framebuffer = exts.has("GL_EXT_discard_framebuffer"sv);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_disjoint_timer_query = exts.has("GL_EXT_disjoint_timer_query"sv);
|
||||
ext->EXT_multisampled_render_to_texture = exts.has("GL_EXT_multisampled_render_to_texture"sv);
|
||||
ext->EXT_multisampled_render_to_texture2 = exts.has("GL_EXT_multisampled_render_to_texture2"sv);
|
||||
#endif
|
||||
ext->EXT_shader_framebuffer_fetch = exts.has("GL_EXT_shader_framebuffer_fetch"sv);
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_texture_compression_etc2 = true;
|
||||
#endif
|
||||
ext->EXT_texture_compression_s3tc = exts.has("GL_EXT_texture_compression_s3tc"sv);
|
||||
|
||||
@@ -222,10 +222,6 @@ public:
|
||||
// Some drivers have gl state issues when drawing from shared contexts
|
||||
bool disable_shared_context_draws;
|
||||
|
||||
// Some drivers require the GL_TEXTURE_EXTERNAL_OES target to be bound when
|
||||
// the texture image changes, even if it's already bound to that texture
|
||||
bool texture_external_needs_rebind;
|
||||
|
||||
// Some web browsers seem to immediately clear the default framebuffer when calling
|
||||
// glInvalidateFramebuffer with WebGL 2.0
|
||||
bool disable_invalidate_framebuffer;
|
||||
@@ -433,9 +429,6 @@ private:
|
||||
{ bugs.disable_shared_context_draws,
|
||||
"disable_shared_context_draws",
|
||||
""},
|
||||
{ bugs.texture_external_needs_rebind,
|
||||
"texture_external_needs_rebind",
|
||||
""},
|
||||
{ bugs.disable_invalidate_framebuffer,
|
||||
"disable_invalidate_framebuffer",
|
||||
""},
|
||||
@@ -711,7 +704,7 @@ void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId, size_t
|
||||
update_state(state.textures.units[unit].targets[targetIndex].texture_id, texId, [&]() {
|
||||
activeTexture(unit);
|
||||
glBindTexture(target, texId);
|
||||
}, (target == GL_TEXTURE_EXTERNAL_OES) && bugs.texture_external_needs_rebind);
|
||||
}, target == GL_TEXTURE_EXTERNAL_OES);
|
||||
}
|
||||
|
||||
void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId) noexcept {
|
||||
|
||||
@@ -147,9 +147,9 @@ Driver* OpenGLDriver::create(OpenGLPlatform* const platform,
|
||||
#endif
|
||||
|
||||
size_t const defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
|
||||
Platform::DriverConfig validConfig {driverConfig};
|
||||
Platform::DriverConfig validConfig{ driverConfig };
|
||||
validConfig.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize);
|
||||
OpenGLDriver* const driver = new OpenGLDriver(ec, validConfig);
|
||||
OpenGLDriver* const driver = new(std::nothrow) OpenGLDriver(ec, validConfig);
|
||||
return driver;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,8 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
|
||||
mContext(),
|
||||
mShaderCompilerService(*this),
|
||||
mHandleAllocator("Handles", driverConfig.handleArenaSize),
|
||||
mSamplerMap(32) {
|
||||
mSamplerMap(32),
|
||||
mDriverConfig(driverConfig) {
|
||||
|
||||
std::fill(mSamplerBindings.begin(), mSamplerBindings.end(), nullptr);
|
||||
|
||||
@@ -1064,6 +1065,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
||||
}
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
} else
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_multisampled_render_to_texture
|
||||
// EXT_multisampled_render_to_texture only support GL_COLOR_ATTACHMENT0
|
||||
if (!attachmentTypeNotSupportedByMSRTT && (t->depth <= 1)
|
||||
@@ -1076,7 +1078,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
||||
// This extension only exists on OpenGL ES.
|
||||
gl.bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo);
|
||||
if (any(t->usage & TextureUsage::SAMPLEABLE)) {
|
||||
glext::glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
|
||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
|
||||
attachment, target, t->gl.id, binfo.level, rt->gl.samples);
|
||||
} else {
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,
|
||||
@@ -1084,7 +1086,8 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
||||
}
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
} else
|
||||
#endif
|
||||
#endif // GL_EXT_multisampled_render_to_texture
|
||||
#endif // __EMSCRIPTEN__
|
||||
if (!any(t->usage & TextureUsage::SAMPLEABLE) && t->samples > 1) {
|
||||
assert_invariant(rt->gl.samples > 1);
|
||||
assert_invariant(glIsRenderbuffer(t->gl.id));
|
||||
@@ -1183,6 +1186,7 @@ void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32
|
||||
uint32_t height, uint8_t samples) const noexcept {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
if (samples > 1) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_multisampled_render_to_texture
|
||||
auto& gl = mContext;
|
||||
if (gl.ext.EXT_multisampled_render_to_texture ||
|
||||
@@ -1190,7 +1194,8 @@ void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32
|
||||
glext::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
|
||||
samples, internalformat, width, height);
|
||||
} else
|
||||
#endif
|
||||
#endif // GL_EXT_multisampled_render_to_texture
|
||||
#endif // __EMSCRIPTEN__
|
||||
{
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER,
|
||||
@@ -1906,6 +1911,10 @@ bool OpenGLDriver::isParallelShaderCompileSupported() {
|
||||
return mShaderCompilerService.isParallelShaderCompileSupported();
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isDepthStencilResolveSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
@@ -2982,16 +2991,18 @@ GLuint OpenGLDriver::getSamplerSlow(SamplerParams params) const noexcept {
|
||||
#endif
|
||||
|
||||
void OpenGLDriver::insertEventMarker(char const* string, uint32_t len) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_debug_marker
|
||||
auto& gl = mContext;
|
||||
if (gl.ext.EXT_debug_marker) {
|
||||
glInsertEventMarkerEXT(GLsizei(len ? len : strlen(string)), string);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_debug_marker
|
||||
#if DEBUG_MARKER_LEVEL & DEBUG_MARKER_OPENGL
|
||||
if (UTILS_LIKELY(mContext.ext.EXT_debug_marker)) {
|
||||
@@ -3004,9 +3015,11 @@ void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
SYSTRACE_CONTEXT();
|
||||
SYSTRACE_NAME_BEGIN(string);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::popGroupMarker(int) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_debug_marker
|
||||
#if DEBUG_MARKER_LEVEL & DEBUG_MARKER_OPENGL
|
||||
if (UTILS_LIKELY(mContext.ext.EXT_debug_marker)) {
|
||||
@@ -3019,6 +3032,7 @@ void OpenGLDriver::popGroupMarker(int) {
|
||||
SYSTRACE_CONTEXT();
|
||||
SYSTRACE_NAME_END();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::startCapture(int) {
|
||||
|
||||
@@ -400,6 +400,9 @@ private:
|
||||
// timer query implementation
|
||||
OpenGLTimerQueryInterface* mTimerQueryImpl = nullptr;
|
||||
|
||||
const Platform::DriverConfig mDriverConfig;
|
||||
Platform::DriverConfig const& getDriverConfig() const noexcept { return mDriverConfig; }
|
||||
|
||||
// for ES2 sRGB support
|
||||
GLSwapChain* mCurrentDrawSwapChain = nullptr;
|
||||
bool mRec709OutputColorspace = false;
|
||||
|
||||
@@ -151,6 +151,12 @@ bool ShaderCompilerService::isParallelShaderCompileSupported() const noexcept {
|
||||
}
|
||||
|
||||
void ShaderCompilerService::init() noexcept {
|
||||
if (UTILS_UNLIKELY(mDriver.getDriverConfig().disableParallelShaderCompile)) {
|
||||
// user disabled parallel shader compile
|
||||
mMode = Mode::SYNCHRONOUS;
|
||||
return;
|
||||
}
|
||||
|
||||
// Here we decide which mode we'll be using. We always prefer our own thread-pool if
|
||||
// that mode is available because, we have no control on how the compilation queues are
|
||||
// handled if done by the driver (so at the very least we'd need to decode this per-driver).
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
};
|
||||
|
||||
enum class Mode {
|
||||
UNDEFINED, // init() has not beed called yet.
|
||||
UNDEFINED, // init() has not been called yet.
|
||||
SYNCHRONOUS, // synchronous shader compilation
|
||||
THREAD_POOL, // asynchronous shader compilation using a thread-pool (most common)
|
||||
ASYNCHRONOUS // asynchronous shader compilation using KHR_parallel_shader_compile
|
||||
|
||||
@@ -28,6 +28,7 @@ static void getProcAddress(T& pfn, const char* name) noexcept {
|
||||
}
|
||||
|
||||
namespace glext {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_OES_EGL_image
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
|
||||
#endif
|
||||
@@ -72,10 +73,11 @@ PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glMaxShaderCompilerThreadsKHR;
|
||||
// use getProcAddress for ES3.1 and above entry points.
|
||||
PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
|
||||
#endif
|
||||
|
||||
static std::once_flag sGlExtInitialized;
|
||||
#endif // __EMSCRIPTEN__
|
||||
|
||||
void importGLESExtensionsEntryPoints() {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
std::call_once(sGlExtInitialized, +[]() {
|
||||
#ifdef GL_OES_EGL_image
|
||||
getProcAddress(glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
|
||||
@@ -119,6 +121,7 @@ void importGLESExtensionsEntryPoints() {
|
||||
getProcAddress(glDispatchCompute, "glDispatchCompute");
|
||||
#endif
|
||||
});
|
||||
#endif // __EMSCRIPTEN__
|
||||
}
|
||||
|
||||
} // namespace glext
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace glext {
|
||||
// it is currently called from PlatformEGL.
|
||||
void importGLESExtensionsEntryPoints();
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_OES_EGL_image
|
||||
extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
|
||||
#endif
|
||||
@@ -153,6 +154,7 @@ extern PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glMaxShaderCompilerThreadsKHR;
|
||||
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||
extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
|
||||
#endif
|
||||
#endif // __EMSCRIPTEN__
|
||||
} // namespace glext
|
||||
|
||||
using namespace glext;
|
||||
|
||||
@@ -154,18 +154,14 @@ struct BlitterUniforms {
|
||||
|
||||
}// anonymous namespace
|
||||
|
||||
VulkanBlitter::VulkanBlitter(VulkanStagePool& stagePool, VulkanPipelineCache& pipelineCache,
|
||||
VulkanFboCache& fboCache, VulkanSamplerCache& samplerCache) noexcept
|
||||
: mStagePool(stagePool), mPipelineCache(pipelineCache), mFramebufferCache(fboCache),
|
||||
mSamplerCache(samplerCache) {}
|
||||
VulkanBlitter::VulkanBlitter() noexcept = default;
|
||||
|
||||
void VulkanBlitter::initialize(VkPhysicalDevice physicalDevice, VkDevice device,
|
||||
VmaAllocator allocator, VulkanCommands* commands, VulkanTexture* emptyTexture) noexcept {
|
||||
VmaAllocator allocator, VulkanCommands* commands) noexcept {
|
||||
mPhysicalDevice = physicalDevice;
|
||||
mDevice = device;
|
||||
mAllocator = allocator;
|
||||
mCommands = commands;
|
||||
mEmptyTexture = emptyTexture;
|
||||
}
|
||||
|
||||
void VulkanBlitter::resolve(VulkanAttachment dst, VulkanAttachment src) {
|
||||
@@ -173,14 +169,7 @@ void VulkanBlitter::resolve(VulkanAttachment dst, VulkanAttachment src) {
|
||||
// src and dst should have the same aspect here
|
||||
VkImageAspectFlags const aspect = src.texture->getImageAspect();
|
||||
|
||||
if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT &&
|
||||
src.texture->samples > 1 && dst.texture->samples == 1) {
|
||||
// we're resolving the depth here, which is not supported by the blitter in vulkan
|
||||
// I think, eventually we want to do that inside filament, instead.
|
||||
// FIXME: remove this once filament does it
|
||||
resolveSlowDepth(src, dst);
|
||||
return;
|
||||
}
|
||||
assert_invariant(!(aspect & VK_IMAGE_ASPECT_DEPTH_BIT));
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_BLIT_FORMAT)
|
||||
VkPhysicalDevice const gpu = mPhysicalDevice;
|
||||
@@ -231,272 +220,6 @@ void VulkanBlitter::blit(VkFilter filter,
|
||||
}
|
||||
|
||||
void VulkanBlitter::terminate() noexcept {
|
||||
if (mDepthResolveProgram) {
|
||||
delete mDepthResolveProgram;
|
||||
mDepthResolveProgram = nullptr;
|
||||
}
|
||||
|
||||
if (mTriangleBuffer) {
|
||||
delete mTriangleBuffer;
|
||||
mTriangleBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (mParamsBuffer) {
|
||||
delete mParamsBuffer;
|
||||
mParamsBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If we created these shader modules in the constructor, the device might not be ready yet.
|
||||
// It is easier to do lazy initialization, which can also improve load time.
|
||||
void VulkanBlitter::lazyInit() noexcept {
|
||||
if (mDepthResolveProgram != nullptr) {
|
||||
return;
|
||||
}
|
||||
assert_invariant(mDevice);
|
||||
|
||||
auto decode = [device = mDevice](const uint8_t* compressed, int compressedSize) {
|
||||
const size_t spirvSize = smolv::GetDecodedBufferSize(compressed, compressedSize);
|
||||
FixedCapacityVector<uint8_t> spirv(spirvSize);
|
||||
smolv::Decode(compressed, compressedSize, spirv.data(), spirvSize);
|
||||
|
||||
VkShaderModuleCreateInfo moduleInfo = {};
|
||||
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleInfo.codeSize = spirvSize;
|
||||
moduleInfo.pCode = (uint32_t*) spirv.data();
|
||||
|
||||
VkShaderModule result = VK_NULL_HANDLE;
|
||||
vkCreateShaderModule(device, &moduleInfo, VKALLOC, &result);
|
||||
assert_invariant(result);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
VkShaderModule vertexShader = decode(VKSHADERS_BLITDEPTHVS_DATA, VKSHADERS_BLITDEPTHVS_SIZE);
|
||||
VkShaderModule fragmentShader = decode(VKSHADERS_BLITDEPTHFS_DATA, VKSHADERS_BLITDEPTHFS_SIZE);
|
||||
|
||||
// Allocate one anonymous sampler at slot 0.
|
||||
VulkanProgram::CustomSamplerInfoList const samplers = {
|
||||
{ 0, 0, ShaderStageFlags::FRAGMENT },
|
||||
};
|
||||
mDepthResolveProgram = new(std::nothrow) VulkanProgram(mDevice, vertexShader, fragmentShader, samplers);
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_BLITTER)
|
||||
utils::slog.d << "Created Shader Module for VulkanBlitter "
|
||||
<< "shaders = (" << vertexShader << ", " << fragmentShader << ")"
|
||||
<< utils::io::endl;
|
||||
#endif
|
||||
|
||||
static const float kTriangleVertices[] = {
|
||||
-1.0f, -1.0f,
|
||||
+1.0f, -1.0f,
|
||||
-1.0f, +1.0f,
|
||||
+1.0f, +1.0f,
|
||||
};
|
||||
|
||||
VulkanCommandBuffer const& commands = mCommands->get();
|
||||
VkCommandBuffer const cmdbuffer = commands.buffer();
|
||||
|
||||
mTriangleBuffer = new(std::nothrow) VulkanBuffer(mAllocator, mStagePool, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
sizeof(kTriangleVertices));
|
||||
|
||||
mTriangleBuffer->loadFromCpu(cmdbuffer, kTriangleVertices, 0, sizeof(kTriangleVertices));
|
||||
|
||||
mParamsBuffer = new(std::nothrow) VulkanBuffer(mAllocator, mStagePool, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
sizeof(BlitterUniforms));
|
||||
}
|
||||
|
||||
// At a high level, the procedure for resolving depth looks like this:
|
||||
// 1. Load uniforms
|
||||
// 2. Begin render pass
|
||||
// 3. Draw a big triangle
|
||||
// 4. End render pass.
|
||||
void VulkanBlitter::resolveSlowDepth(VulkanAttachment src, VulkanAttachment dst) {
|
||||
lazyInit();
|
||||
|
||||
const VkOffset3D dstRect[2] = {
|
||||
{ 0, 0, 0 },
|
||||
{ (int32_t)dst.texture->width, (int32_t)dst.texture->height, 1 }};
|
||||
|
||||
VulkanCommandBuffer* commands = &mCommands->get();
|
||||
VkCommandBuffer const cmdbuffer = commands->buffer();
|
||||
commands->acquire(src.texture);
|
||||
commands->acquire(dst.texture);
|
||||
|
||||
BlitterUniforms const uniforms = {
|
||||
.sampleCount = src.texture->samples,
|
||||
.inverseSampleCount = 1.0f / float(src.texture->samples),
|
||||
};
|
||||
mParamsBuffer->loadFromCpu(cmdbuffer, &uniforms, 0, sizeof(uniforms));
|
||||
|
||||
VkImageAspectFlags const aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
// We will transition the src into sampler layout and also keep it in sampler layout for
|
||||
// consistency.
|
||||
VulkanLayout const samplerLayout = VulkanLayout::DEPTH_SAMPLER;
|
||||
|
||||
// BEGIN RENDER PASS
|
||||
// -----------------
|
||||
|
||||
const VulkanFboCache::RenderPassKey rpkey = {
|
||||
.initialColorLayoutMask = 0,
|
||||
.initialDepthLayout = VulkanLayout::UNDEFINED,
|
||||
.renderPassDepthLayout = samplerLayout,
|
||||
.finalDepthLayout = samplerLayout,
|
||||
.depthFormat = dst.getFormat(),
|
||||
.clear = {},
|
||||
.discardStart = TargetBufferFlags::DEPTH,
|
||||
.samples = 1,
|
||||
};
|
||||
|
||||
const VkRenderPass renderPass = mFramebufferCache.getRenderPass(rpkey);
|
||||
mPipelineCache.bindRenderPass(renderPass, 0);
|
||||
|
||||
const VulkanFboCache::FboKey fbkey {
|
||||
.renderPass = renderPass,
|
||||
.width = (uint16_t) (dst.texture->width >> dst.level),
|
||||
.height = (uint16_t) (dst.texture->height >> dst.level),
|
||||
.layers = 1,
|
||||
.samples = rpkey.samples,
|
||||
.color = {},
|
||||
.resolve = {},
|
||||
.depth = dst.getImageView(aspect),
|
||||
};
|
||||
const VkFramebuffer vkfb = mFramebufferCache.getFramebuffer(fbkey);
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = renderPass,
|
||||
.framebuffer = vkfb,
|
||||
};
|
||||
renderPassInfo.renderArea.offset.x = dstRect[0].x;
|
||||
renderPassInfo.renderArea.offset.y = dstRect[0].y;
|
||||
renderPassInfo.renderArea.extent.width = dstRect[1].x - dstRect[0].x;
|
||||
renderPassInfo.renderArea.extent.height = dstRect[1].y - dstRect[0].y;
|
||||
|
||||
// We need to transition the source into a sampler since it'll be sampled in the shader.
|
||||
const VkImageSubresourceRange srcRange = {
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = src.level,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = src.layer,
|
||||
.layerCount = 1,
|
||||
};
|
||||
src.texture->transitionLayout(cmdbuffer, srcRange, samplerLayout);
|
||||
|
||||
vkCmdBeginRenderPass(cmdbuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
VkViewport const viewport = {
|
||||
.x = (float) dstRect[0].x,
|
||||
.y = (float) dstRect[0].y,
|
||||
.width = (float) renderPassInfo.renderArea.extent.width,
|
||||
.height = (float) renderPassInfo.renderArea.extent.height,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
|
||||
vkCmdSetViewport(cmdbuffer, 0, 1, &viewport);
|
||||
|
||||
// DRAW THE TRIANGLE
|
||||
// -----------------
|
||||
|
||||
mPipelineCache.bindProgram(mDepthResolveProgram);
|
||||
mPipelineCache.bindPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
|
||||
|
||||
auto vkraster = mPipelineCache.getCurrentRasterState();
|
||||
vkraster.depthWriteEnable = true;
|
||||
vkraster.depthCompareOp = SamplerCompareFunc::A;
|
||||
vkraster.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
||||
vkraster.alphaToCoverageEnable = false,
|
||||
vkraster.blendEnable = VK_FALSE,
|
||||
vkraster.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
vkraster.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||
vkraster.colorBlendOp = BlendEquation::ADD,
|
||||
vkraster.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
vkraster.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||
vkraster.alphaBlendOp = BlendEquation::ADD,
|
||||
vkraster.colorWriteMask = (VkColorComponentFlags) 0,
|
||||
vkraster.cullMode = VK_CULL_MODE_NONE;
|
||||
vkraster.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
vkraster.depthBiasEnable = VK_FALSE;
|
||||
vkraster.colorTargetCount = 0;
|
||||
mPipelineCache.bindRasterState(vkraster);
|
||||
|
||||
VkBuffer buffers[1] = {};
|
||||
VkDeviceSize offsets[1] = {};
|
||||
buffers[0] = mTriangleBuffer->getGpuBuffer();
|
||||
VkVertexInputAttributeDescription const attribDesc = {
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
};
|
||||
VkVertexInputBindingDescription const bufferDesc = {
|
||||
.binding = 0,
|
||||
.stride = sizeof(float) * 2,
|
||||
};
|
||||
mPipelineCache.bindVertexArray(&attribDesc, &bufferDesc, 1);
|
||||
|
||||
// Select nearest filtering and clamp_to_edge.
|
||||
VkSampler vksampler = mSamplerCache.getSampler({});
|
||||
|
||||
VkDescriptorImageInfo samplers[VulkanPipelineCache::SAMPLER_BINDING_COUNT];
|
||||
VulkanTexture* textures[VulkanPipelineCache::SAMPLER_BINDING_COUNT] = {nullptr};
|
||||
for (auto& sampler : samplers) {
|
||||
sampler = {
|
||||
.sampler = vksampler,
|
||||
.imageView = mEmptyTexture->getPrimaryImageView(),
|
||||
.imageLayout = ImgUtil::getVkLayout(VulkanLayout::READ_WRITE),
|
||||
};
|
||||
}
|
||||
|
||||
samplers[0] = {
|
||||
.sampler = vksampler,
|
||||
.imageView = src.getImageView(VK_IMAGE_ASPECT_DEPTH_BIT),
|
||||
.imageLayout = ImgUtil::getVkLayout(samplerLayout),
|
||||
};
|
||||
textures[0] = src.texture;
|
||||
|
||||
mPipelineCache.bindSamplers(samplers, textures,
|
||||
VulkanPipelineCache::getUsageFlags(0, ShaderStageFlags::FRAGMENT));
|
||||
|
||||
auto previousUbo = mPipelineCache.getUniformBufferBinding(0);
|
||||
mPipelineCache.bindUniformBuffer(0, mParamsBuffer->getGpuBuffer());
|
||||
|
||||
if (!mPipelineCache.bindDescriptors(cmdbuffer)) {
|
||||
assert_invariant(false);
|
||||
}
|
||||
|
||||
const VkRect2D scissor = {
|
||||
.offset = renderPassInfo.renderArea.offset,
|
||||
.extent = renderPassInfo.renderArea.extent,
|
||||
};
|
||||
|
||||
mPipelineCache.bindScissor(cmdbuffer, scissor);
|
||||
|
||||
if (!mPipelineCache.bindPipeline(commands)) {
|
||||
assert_invariant(false);
|
||||
}
|
||||
|
||||
vkCmdBindVertexBuffers(cmdbuffer, 0, 1, buffers, offsets);
|
||||
vkCmdDraw(cmdbuffer, 4, 1, 0, 0);
|
||||
|
||||
// END RENDER PASS
|
||||
// ---------------
|
||||
|
||||
vkCmdEndRenderPass(cmdbuffer);
|
||||
|
||||
VkMemoryBarrier const barrier {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
};
|
||||
VkPipelineStageFlags const srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
vkCmdPipelineBarrier(cmdbuffer, srcStageMask,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | // <== For Mali
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||
|
||||
mPipelineCache.bindUniformBuffer(0, previousUbo.buffer, previousUbo.offset, previousUbo.size);
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -32,11 +32,10 @@ struct VulkanProgram;
|
||||
|
||||
class VulkanBlitter {
|
||||
public:
|
||||
VulkanBlitter(VulkanStagePool& stagePool, VulkanPipelineCache& pipelineCache,
|
||||
VulkanFboCache& fboCache, VulkanSamplerCache& samplerCache) noexcept;
|
||||
VulkanBlitter() noexcept;
|
||||
|
||||
void initialize(VkPhysicalDevice physicalDevice, VkDevice device, VmaAllocator allocator,
|
||||
VulkanCommands* commands, VulkanTexture* emptyTexture) noexcept;
|
||||
void initialize(VkPhysicalDevice physicalDevice, VkDevice device,
|
||||
VmaAllocator allocator, VulkanCommands* commands) noexcept;
|
||||
|
||||
void blit(VkFilter filter,
|
||||
VulkanAttachment dst, const VkOffset3D* dstRectPair,
|
||||
@@ -47,24 +46,10 @@ public:
|
||||
void terminate() noexcept;
|
||||
|
||||
private:
|
||||
void lazyInit() noexcept;
|
||||
|
||||
void resolveSlowDepth(VulkanAttachment src, VulkanAttachment dst);
|
||||
|
||||
VulkanBuffer* mTriangleBuffer = nullptr;
|
||||
VulkanBuffer* mParamsBuffer = nullptr;
|
||||
VulkanProgram* mDepthResolveProgram = nullptr;
|
||||
|
||||
UTILS_UNUSED VkPhysicalDevice mPhysicalDevice;
|
||||
VkDevice mDevice;
|
||||
VmaAllocator mAllocator;
|
||||
VulkanCommands* mCommands;
|
||||
VulkanTexture* mEmptyTexture;
|
||||
|
||||
VulkanStagePool& mStagePool;
|
||||
VulkanPipelineCache& mPipelineCache;
|
||||
VulkanFboCache& mFramebufferCache;
|
||||
VulkanSamplerCache& mSamplerCache;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -156,7 +156,6 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
|
||||
mResourceManager(&mResourceAllocator),
|
||||
mThreadSafeResourceManager(&mResourceAllocator),
|
||||
mPipelineCache(&mResourceAllocator),
|
||||
mBlitter(mStagePool, mPipelineCache, mFramebufferCache, mSamplerCache),
|
||||
mReadPixels(mPlatform->getDevice()),
|
||||
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported) {
|
||||
|
||||
@@ -206,7 +205,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
|
||||
|
||||
mPipelineCache.setDummyTexture(mEmptyTexture->getPrimaryImageView());
|
||||
mBlitter.initialize(mPlatform->getPhysicalDevice(), mPlatform->getDevice(), mAllocator,
|
||||
mCommands.get(), mEmptyTexture.get());
|
||||
mCommands.get());
|
||||
}
|
||||
|
||||
VulkanDriver::~VulkanDriver() noexcept = default;
|
||||
@@ -757,6 +756,7 @@ bool VulkanDriver::isFrameTimeSupported() {
|
||||
}
|
||||
|
||||
bool VulkanDriver::isAutoDepthResolveSupported() {
|
||||
// TODO: this could be supported with vk 1.2 or VK_KHR_depth_stencil_resolve
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -772,6 +772,11 @@ bool VulkanDriver::isParallelShaderCompileSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isDepthStencilResolveSupported() {
|
||||
// TODO: apparently it could be supported in core 1.2 and/or with VK_KHR_depth_stencil_resolve
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU: {
|
||||
@@ -1497,6 +1502,12 @@ void VulkanDriver::resolve(
|
||||
ASSERT_PRECONDITION(srcTexture->format == dstTexture->format,
|
||||
"src and dst texture format don't match");
|
||||
|
||||
ASSERT_PRECONDITION(!isDepthFormat(srcTexture->format),
|
||||
"can't resolve depth formats");
|
||||
|
||||
ASSERT_PRECONDITION(!isStencilFormat(srcTexture->format),
|
||||
"can't resolve stencil formats");
|
||||
|
||||
ASSERT_PRECONDITION(any(dstTexture->usage & TextureUsage::BLIT_DST),
|
||||
"texture doesn't have BLIT_DST");
|
||||
|
||||
@@ -1545,7 +1556,7 @@ void VulkanDriver::blit(
|
||||
VkOffset3D const srcOffsets[2] = { { srcLeft, srcTop, 0 }, { srcRight, srcBottom, 1 }};
|
||||
VkOffset3D const dstOffsets[2] = { { dstLeft, dstTop, 0 }, { dstRight, dstBottom, 1 }};
|
||||
|
||||
// no scallng guaranteed
|
||||
// no scaling guaranteed
|
||||
mBlitter.blit(VK_FILTER_NEAREST,
|
||||
{ .texture = dstTexture, .level = dstLevel, .layer = dstLayer }, dstOffsets,
|
||||
{ .texture = srcTexture, .level = srcLevel, .layer = srcLayer }, srcOffsets);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
#include "vulkan/VulkanDriverFactory.h"
|
||||
@@ -23,6 +24,11 @@
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#define LINUX_OR_FREEBSD 1
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,14 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -70,7 +74,7 @@ public:
|
||||
* @return This bounding box
|
||||
*/
|
||||
Box& set(const math::float3& min, const math::float3& max) noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
// float3 ctor needed for Visual Studio
|
||||
center = (max + min) * math::float3(0.5f);
|
||||
halfExtent = (max - min) * math::float3(0.5f);
|
||||
return *this;
|
||||
@@ -130,17 +134,17 @@ public:
|
||||
struct UTILS_PUBLIC Aabb {
|
||||
|
||||
/** min coordinates */
|
||||
math::float3 min = std::numeric_limits<float>::max();
|
||||
math::float3 min = FLT_MAX;
|
||||
|
||||
/** max coordinates */
|
||||
math::float3 max = std::numeric_limits<float>::lowest();
|
||||
math::float3 max = -FLT_MAX;
|
||||
|
||||
/**
|
||||
* Computes the center of the box.
|
||||
* @return (max + min)/2
|
||||
*/
|
||||
math::float3 center() const noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
// float3 ctor needed for Visual Studio
|
||||
return (max + min) * math::float3(0.5f);
|
||||
}
|
||||
|
||||
@@ -149,7 +153,7 @@ struct UTILS_PUBLIC Aabb {
|
||||
* @return (max - min)/2
|
||||
*/
|
||||
math::float3 extent() const noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
// float3 ctor needed for Visual Studio
|
||||
return (max - min) * math::float3(0.5f);
|
||||
}
|
||||
|
||||
@@ -198,12 +202,14 @@ struct UTILS_PUBLIC Aabb {
|
||||
* @return the maximum signed distance to the box. Negative if p is in the box
|
||||
*/
|
||||
float contains(math::float3 p) const noexcept {
|
||||
// we don't use std::max to avoid a dependency on <algorithm>
|
||||
auto const maximum = [](auto a, auto b) { return a > b ? a : b; };
|
||||
float d = min.x - p.x;
|
||||
d = std::max(d, min.y - p.y);
|
||||
d = std::max(d, min.z - p.z);
|
||||
d = std::max(d, p.x - max.x);
|
||||
d = std::max(d, p.y - max.y);
|
||||
d = std::max(d, p.z - max.z);
|
||||
d = maximum(d, min.y - p.y);
|
||||
d = maximum(d, min.z - p.z);
|
||||
d = maximum(d, p.x - max.x);
|
||||
d = maximum(d, p.y - max.y);
|
||||
d = maximum(d, p.z - max.z);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FBufferObject;
|
||||
@@ -82,8 +84,7 @@ public:
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this BufferObject with.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
* @return pointer to the newly created object
|
||||
*
|
||||
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
|
||||
* memory or other resources.
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
*
|
||||
* @see IndexBuffer::setBuffer
|
||||
*/
|
||||
BufferObject* build(Engine& engine);
|
||||
BufferObject* UTILS_NONNULL build(Engine& engine);
|
||||
private:
|
||||
friend class FBufferObject;
|
||||
};
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
#include <math/vec4.h>
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
@@ -184,7 +189,7 @@ public:
|
||||
* @see Fov.
|
||||
*/
|
||||
static math::mat4 projection(Fov direction, double fovInDegrees,
|
||||
double aspect, double near, double far = std::numeric_limits<double>::infinity());
|
||||
double aspect, double near, double far = INFINITY);
|
||||
|
||||
/** Returns the projection matrix from the focal length.
|
||||
*
|
||||
@@ -194,7 +199,7 @@ public:
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
*/
|
||||
static math::mat4 projection(double focalLengthInMillimeters,
|
||||
double aspect, double near, double far = std::numeric_limits<double>::infinity());
|
||||
double aspect, double near, double far = INFINITY);
|
||||
|
||||
|
||||
/** Sets the projection matrix from a frustum defined by six planes.
|
||||
@@ -301,7 +306,7 @@ public:
|
||||
* @see setCustomProjection
|
||||
* @see Engine::Config::stereoscopicEyeCount
|
||||
*/
|
||||
void setCustomEyeProjection(math::mat4 const* projection, size_t count,
|
||||
void setCustomEyeProjection(math::mat4 const* UTILS_NONNULL projection, size_t count,
|
||||
math::mat4 const& projectionForCulling, double near, double far);
|
||||
|
||||
/** Sets an additional matrix that scales the projection matrix.
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
//! RGB color in linear space
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
@@ -200,7 +203,7 @@ public:
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& toneMapper(const ToneMapper* toneMapper) noexcept;
|
||||
Builder& toneMapper(ToneMapper const* UTILS_NULLABLE toneMapper) noexcept;
|
||||
|
||||
/**
|
||||
* Selects the tone mapping operator to apply to the HDR color buffer as the last
|
||||
@@ -470,10 +473,9 @@ public:
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this ColorGrading with.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
* @return pointer to the newly created object.
|
||||
*/
|
||||
ColorGrading* build(Engine& engine);
|
||||
ColorGrading* UTILS_NONNULL build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FColorGrading;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define TNT_FILAMENT_COLOR_SPACE_H
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
namespace filament::color {
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -39,27 +39,12 @@ namespace filament {
|
||||
class UTILS_PUBLIC DebugRegistry : public FilamentAPI {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Type of a property
|
||||
*/
|
||||
enum Type {
|
||||
BOOL, INT, FLOAT, FLOAT2, FLOAT3, FLOAT4
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about a property
|
||||
*/
|
||||
struct Property {
|
||||
const char* name; //!< property name
|
||||
Type type; //!< property type
|
||||
};
|
||||
|
||||
/**
|
||||
* Queries whether a property exists
|
||||
* @param name The name of the property to query
|
||||
* @return true if the property exists, false otherwise
|
||||
*/
|
||||
bool hasProperty(const char* name) const noexcept;
|
||||
bool hasProperty(const char* UTILS_NONNULL name) const noexcept;
|
||||
|
||||
/**
|
||||
* Queries the address of a property's data from its name
|
||||
@@ -67,28 +52,30 @@ public:
|
||||
* @return Address of the data of the \p name property
|
||||
* @{
|
||||
*/
|
||||
void* getPropertyAddress(const char* name);
|
||||
void* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name);
|
||||
|
||||
void const* getPropertyAddress(const char* name) const noexcept;
|
||||
void const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept;
|
||||
|
||||
template<typename T>
|
||||
inline T* getPropertyAddress(const char* name) {
|
||||
inline T* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) {
|
||||
return static_cast<T*>(getPropertyAddress(name));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T const* getPropertyAddress(const char* name) const noexcept {
|
||||
inline T const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept {
|
||||
return static_cast<T*>(getPropertyAddress(name));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool getPropertyAddress(const char* name, T** p) {
|
||||
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
|
||||
T* UTILS_NULLABLE* UTILS_NONNULL p) {
|
||||
*p = getPropertyAddress<T>(name);
|
||||
return *p != nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool getPropertyAddress(const char* name, T* const* p) const noexcept {
|
||||
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
|
||||
T* const UTILS_NULLABLE* UTILS_NONNULL p) const noexcept {
|
||||
*p = getPropertyAddress<T>(name);
|
||||
return *p != nullptr;
|
||||
}
|
||||
@@ -101,12 +88,12 @@ public:
|
||||
* @return true if the operation was successful, false otherwise.
|
||||
* @{
|
||||
*/
|
||||
bool setProperty(const char* name, bool v) noexcept;
|
||||
bool setProperty(const char* name, int v) noexcept;
|
||||
bool setProperty(const char* name, float v) noexcept;
|
||||
bool setProperty(const char* name, math::float2 v) noexcept;
|
||||
bool setProperty(const char* name, math::float3 v) noexcept;
|
||||
bool setProperty(const char* name, math::float4 v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, bool v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, int v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, float v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, math::float2 v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, math::float3 v) noexcept;
|
||||
bool setProperty(const char* UTILS_NONNULL name, math::float4 v) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
@@ -116,20 +103,20 @@ public:
|
||||
* @return true if the call was successful and \p v was updated
|
||||
* @{
|
||||
*/
|
||||
bool getProperty(const char* name, bool* v) const noexcept;
|
||||
bool getProperty(const char* name, int* v) const noexcept;
|
||||
bool getProperty(const char* name, float* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float2* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float3* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float4* v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, bool* UTILS_NONNULL v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, int* UTILS_NONNULL v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, float* UTILS_NONNULL v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, math::float2* UTILS_NONNULL v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, math::float3* UTILS_NONNULL v) const noexcept;
|
||||
bool getProperty(const char* UTILS_NONNULL name, math::float4* UTILS_NONNULL v) const noexcept;
|
||||
/** @}*/
|
||||
|
||||
struct DataSource {
|
||||
void const* data;
|
||||
void const* UTILS_NULLABLE data;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
DataSource getDataSource(const char* name) const noexcept;
|
||||
DataSource getDataSource(const char* UTILS_NONNULL name) const noexcept;
|
||||
|
||||
struct FrameHistory {
|
||||
using duration_ms = float;
|
||||
|
||||
@@ -19,9 +19,14 @@
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
@@ -300,11 +305,23 @@ public:
|
||||
* @see Engine::getMaxStereoscopicEyes
|
||||
*/
|
||||
uint8_t stereoscopicEyeCount = 2;
|
||||
|
||||
/*
|
||||
* Size in MiB of the frame graph texture cache. This should be adjusted based on the
|
||||
* size of used render targets (typically the screen).
|
||||
*/
|
||||
uint32_t resourceAllocatorCacheSizeMB = 64;
|
||||
|
||||
/*
|
||||
* This value determines for how many frames are texture entries kept in the cache.
|
||||
* The default value of 30 corresponds to about half a second at 60 fps.
|
||||
*/
|
||||
uint32_t resourceAllocatorCacheMaxAge = 30;
|
||||
};
|
||||
|
||||
|
||||
#if UTILS_HAS_THREADING
|
||||
using CreateCallback = void(void* user, void* token);
|
||||
using CreateCallback = void(void* UTILS_NULLABLE user, void* UTILS_NONNULL token);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -343,7 +360,7 @@ public:
|
||||
*
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& platform(Platform* platform) noexcept;
|
||||
Builder& platform(Platform* UTILS_NULLABLE platform) noexcept;
|
||||
|
||||
/**
|
||||
* @param config A pointer to optional parameters to specify memory size
|
||||
@@ -351,7 +368,7 @@ public:
|
||||
*
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& config(const Config* config) noexcept;
|
||||
Builder& config(const Config* UTILS_NULLABLE config) noexcept;
|
||||
|
||||
/**
|
||||
* @param sharedContext A platform-dependant context used as a shared context
|
||||
@@ -359,7 +376,7 @@ public:
|
||||
*
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& sharedContext(void* sharedContext) noexcept;
|
||||
Builder& sharedContext(void* UTILS_NULLABLE sharedContext) noexcept;
|
||||
|
||||
/**
|
||||
* @param featureLevel The feature level at which initialize Filament.
|
||||
@@ -374,7 +391,7 @@ public:
|
||||
* @param callback Callback called once the engine is initialized and it is safe to
|
||||
* call Engine::getEngine().
|
||||
*/
|
||||
void build(utils::Invocable<void(void* token)>&& callback) const;
|
||||
void build(utils::Invocable<void(void* UTILS_NONNULL token)>&& callback) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -389,16 +406,17 @@ public:
|
||||
* allocate the command buffer. If exceptions are disabled, this condition if
|
||||
* fatal and this function will abort.
|
||||
*/
|
||||
Engine* build() const;
|
||||
Engine* UTILS_NULLABLE build() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backward compatibility helper to create an Engine.
|
||||
* @see Builder
|
||||
*/
|
||||
static inline Engine* create(Backend backend = Backend::DEFAULT,
|
||||
Platform* platform = nullptr, void* sharedContext = nullptr,
|
||||
const Config* config = nullptr) {
|
||||
static inline Engine* UTILS_NULLABLE create(Backend backend = Backend::DEFAULT,
|
||||
Platform* UTILS_NULLABLE platform = nullptr,
|
||||
void* UTILS_NULLABLE sharedContext = nullptr,
|
||||
const Config* UTILS_NULLABLE config = nullptr) {
|
||||
return Engine::Builder()
|
||||
.backend(backend)
|
||||
.platform(platform)
|
||||
@@ -413,16 +431,18 @@ public:
|
||||
* Backward compatibility helper to create an Engine asynchronously.
|
||||
* @see Builder
|
||||
*/
|
||||
static inline void createAsync(CreateCallback callback, void* user,
|
||||
static inline void createAsync(CreateCallback callback,
|
||||
void* UTILS_NULLABLE user,
|
||||
Backend backend = Backend::DEFAULT,
|
||||
Platform* platform = nullptr, void* sharedContext = nullptr,
|
||||
const Config* config = nullptr) {
|
||||
Platform* UTILS_NULLABLE platform = nullptr,
|
||||
void* UTILS_NULLABLE sharedContext = nullptr,
|
||||
const Config* UTILS_NULLABLE config = nullptr) {
|
||||
Engine::Builder()
|
||||
.backend(backend)
|
||||
.platform(platform)
|
||||
.sharedContext(sharedContext)
|
||||
.config(config)
|
||||
.build([callback, user](void* token) {
|
||||
.build([callback, user](void* UTILS_NONNULL token) {
|
||||
callback(user, token);
|
||||
});
|
||||
}
|
||||
@@ -439,7 +459,7 @@ public:
|
||||
* allocate the command buffer. If exceptions are disabled, this condition if fatal and
|
||||
* this function will abort.
|
||||
*/
|
||||
static Engine* getEngine(void* token);
|
||||
static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -469,7 +489,7 @@ public:
|
||||
* \remark
|
||||
* This method is thread-safe.
|
||||
*/
|
||||
static void destroy(Engine** engine);
|
||||
static void destroy(Engine* UTILS_NULLABLE* UTILS_NULLABLE engine);
|
||||
|
||||
/**
|
||||
* Destroy the Engine instance and all associated resources.
|
||||
@@ -496,7 +516,7 @@ public:
|
||||
* \remark
|
||||
* This method is thread-safe.
|
||||
*/
|
||||
static void destroy(Engine* engine);
|
||||
static void destroy(Engine* UTILS_NULLABLE engine);
|
||||
|
||||
/**
|
||||
* Query the feature level supported by the selected backend.
|
||||
@@ -644,11 +664,11 @@ public:
|
||||
* `ANativeWindow*`.
|
||||
* @param flags One or more configuration flags as defined in `SwapChain`.
|
||||
*
|
||||
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created SwapChain.
|
||||
*
|
||||
* @see Renderer.beginFrame()
|
||||
*/
|
||||
SwapChain* createSwapChain(void* nativeWindow, uint64_t flags = 0) noexcept;
|
||||
SwapChain* UTILS_NONNULL createSwapChain(void* UTILS_NULLABLE nativeWindow, uint64_t flags = 0) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
@@ -658,42 +678,42 @@ public:
|
||||
* @param height Height of the drawing buffer in pixels.
|
||||
* @param flags One or more configuration flags as defined in `SwapChain`.
|
||||
*
|
||||
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created SwapChain.
|
||||
*
|
||||
* @see Renderer.beginFrame()
|
||||
*/
|
||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
|
||||
SwapChain* UTILS_NONNULL createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
|
||||
|
||||
/**
|
||||
* Creates a renderer associated to this engine.
|
||||
*
|
||||
* A Renderer is intended to map to a *window* on screen.
|
||||
*
|
||||
* @return A pointer to the newly created Renderer or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created Renderer.
|
||||
*/
|
||||
Renderer* createRenderer() noexcept;
|
||||
Renderer* UTILS_NONNULL createRenderer() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a View.
|
||||
*
|
||||
* @return A pointer to the newly created View or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created View.
|
||||
*/
|
||||
View* createView() noexcept;
|
||||
View* UTILS_NONNULL createView() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a Scene.
|
||||
*
|
||||
* @return A pointer to the newly created Scene or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created Scene.
|
||||
*/
|
||||
Scene* createScene() noexcept;
|
||||
Scene* UTILS_NONNULL createScene() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a Camera component.
|
||||
*
|
||||
* @param entity Entity to add the camera component to.
|
||||
* @return A pointer to the newly created Camera or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created Camera.
|
||||
*/
|
||||
Camera* createCamera(utils::Entity entity) noexcept;
|
||||
Camera* UTILS_NONNULL createCamera(utils::Entity entity) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Camera component of the given entity.
|
||||
@@ -703,7 +723,7 @@ public:
|
||||
* have a Camera component. The pointer is valid until destroyCameraComponent()
|
||||
* is called or the entity itself is destroyed.
|
||||
*/
|
||||
Camera* getCameraComponent(utils::Entity entity) noexcept;
|
||||
Camera* UTILS_NULLABLE getCameraComponent(utils::Entity entity) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys the Camera component associated with the given entity.
|
||||
@@ -715,17 +735,17 @@ public:
|
||||
/**
|
||||
* Creates a Fence.
|
||||
*
|
||||
* @return A pointer to the newly created Fence or nullptr if it couldn't be created.
|
||||
* @return A pointer to the newly created Fence.
|
||||
*/
|
||||
Fence* createFence() noexcept;
|
||||
Fence* UTILS_NONNULL createFence() noexcept;
|
||||
|
||||
bool destroy(const BufferObject* p); //!< Destroys a BufferObject object.
|
||||
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
|
||||
bool destroy(const Fence* p); //!< Destroys a Fence object.
|
||||
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
|
||||
bool destroy(const SkinningBuffer* p); //!< Destroys a SkinningBuffer object.
|
||||
bool destroy(const MorphTargetBuffer* p); //!< Destroys a MorphTargetBuffer object.
|
||||
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
|
||||
bool destroy(const BufferObject* UTILS_NULLABLE p); //!< Destroys a BufferObject object.
|
||||
bool destroy(const VertexBuffer* UTILS_NULLABLE p); //!< Destroys an VertexBuffer object.
|
||||
bool destroy(const Fence* UTILS_NULLABLE p); //!< Destroys a Fence object.
|
||||
bool destroy(const IndexBuffer* UTILS_NULLABLE p); //!< Destroys an IndexBuffer object.
|
||||
bool destroy(const SkinningBuffer* UTILS_NULLABLE p); //!< Destroys a SkinningBuffer object.
|
||||
bool destroy(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Destroys a MorphTargetBuffer object.
|
||||
bool destroy(const IndirectLight* UTILS_NULLABLE p); //!< Destroys an IndirectLight object.
|
||||
|
||||
/**
|
||||
* Destroys a Material object
|
||||
@@ -735,38 +755,38 @@ public:
|
||||
* @exception utils::PreConditionPanic is thrown if some MaterialInstances remain.
|
||||
* no-op if exceptions are disabled and some MaterialInstances remain.
|
||||
*/
|
||||
bool destroy(const Material* p);
|
||||
bool destroy(const MaterialInstance* p); //!< Destroys a MaterialInstance object.
|
||||
bool destroy(const Renderer* p); //!< Destroys a Renderer object.
|
||||
bool destroy(const Scene* p); //!< Destroys a Scene object.
|
||||
bool destroy(const Skybox* p); //!< Destroys a SkyBox object.
|
||||
bool destroy(const ColorGrading* p); //!< Destroys a ColorGrading object.
|
||||
bool destroy(const SwapChain* p); //!< Destroys a SwapChain object.
|
||||
bool destroy(const Stream* p); //!< Destroys a Stream object.
|
||||
bool destroy(const Texture* p); //!< Destroys a Texture object.
|
||||
bool destroy(const RenderTarget* p); //!< Destroys a RenderTarget object.
|
||||
bool destroy(const View* p); //!< Destroys a View object.
|
||||
bool destroy(const InstanceBuffer* p); //!< Destroys an InstanceBuffer object.
|
||||
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
|
||||
bool destroy(const Material* UTILS_NULLABLE p);
|
||||
bool destroy(const MaterialInstance* UTILS_NULLABLE p); //!< Destroys a MaterialInstance object.
|
||||
bool destroy(const Renderer* UTILS_NULLABLE p); //!< Destroys a Renderer object.
|
||||
bool destroy(const Scene* UTILS_NULLABLE p); //!< Destroys a Scene object.
|
||||
bool destroy(const Skybox* UTILS_NULLABLE p); //!< Destroys a SkyBox object.
|
||||
bool destroy(const ColorGrading* UTILS_NULLABLE p); //!< Destroys a ColorGrading object.
|
||||
bool destroy(const SwapChain* UTILS_NULLABLE p); //!< Destroys a SwapChain object.
|
||||
bool destroy(const Stream* UTILS_NULLABLE p); //!< Destroys a Stream object.
|
||||
bool destroy(const Texture* UTILS_NULLABLE p); //!< Destroys a Texture object.
|
||||
bool destroy(const RenderTarget* UTILS_NULLABLE p); //!< Destroys a RenderTarget object.
|
||||
bool destroy(const View* UTILS_NULLABLE p); //!< Destroys a View object.
|
||||
bool destroy(const InstanceBuffer* UTILS_NULLABLE p); //!< Destroys an InstanceBuffer object.
|
||||
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
|
||||
|
||||
bool isValid(const BufferObject* p); //!< Tells whether a BufferObject object is valid
|
||||
bool isValid(const VertexBuffer* p); //!< Tells whether an VertexBuffer object is valid
|
||||
bool isValid(const Fence* p); //!< Tells whether a Fence object is valid
|
||||
bool isValid(const IndexBuffer* p); //!< Tells whether an IndexBuffer object is valid
|
||||
bool isValid(const SkinningBuffer* p); //!< Tells whether a SkinningBuffer object is valid
|
||||
bool isValid(const MorphTargetBuffer* p); //!< Tells whether a MorphTargetBuffer object is valid
|
||||
bool isValid(const IndirectLight* p); //!< Tells whether an IndirectLight object is valid
|
||||
bool isValid(const Material* p); //!< Tells whether an IndirectLight object is valid
|
||||
bool isValid(const Renderer* p); //!< Tells whether a Renderer object is valid
|
||||
bool isValid(const Scene* p); //!< Tells whether a Scene object is valid
|
||||
bool isValid(const Skybox* p); //!< Tells whether a SkyBox object is valid
|
||||
bool isValid(const ColorGrading* p); //!< Tells whether a ColorGrading object is valid
|
||||
bool isValid(const SwapChain* p); //!< Tells whether a SwapChain object is valid
|
||||
bool isValid(const Stream* p); //!< Tells whether a Stream object is valid
|
||||
bool isValid(const Texture* p); //!< Tells whether a Texture object is valid
|
||||
bool isValid(const RenderTarget* p); //!< Tells whether a RenderTarget object is valid
|
||||
bool isValid(const View* p); //!< Tells whether a View object is valid
|
||||
bool isValid(const InstanceBuffer* p); //!< Tells whether an InstanceBuffer object is valid
|
||||
bool isValid(const BufferObject* UTILS_NULLABLE p); //!< Tells whether a BufferObject object is valid
|
||||
bool isValid(const VertexBuffer* UTILS_NULLABLE p); //!< Tells whether an VertexBuffer object is valid
|
||||
bool isValid(const Fence* UTILS_NULLABLE p); //!< Tells whether a Fence object is valid
|
||||
bool isValid(const IndexBuffer* UTILS_NULLABLE p); //!< Tells whether an IndexBuffer object is valid
|
||||
bool isValid(const SkinningBuffer* UTILS_NULLABLE p); //!< Tells whether a SkinningBuffer object is valid
|
||||
bool isValid(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Tells whether a MorphTargetBuffer object is valid
|
||||
bool isValid(const IndirectLight* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
|
||||
bool isValid(const Material* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
|
||||
bool isValid(const Renderer* UTILS_NULLABLE p); //!< Tells whether a Renderer object is valid
|
||||
bool isValid(const Scene* UTILS_NULLABLE p); //!< Tells whether a Scene object is valid
|
||||
bool isValid(const Skybox* UTILS_NULLABLE p); //!< Tells whether a SkyBox object is valid
|
||||
bool isValid(const ColorGrading* UTILS_NULLABLE p); //!< Tells whether a ColorGrading object is valid
|
||||
bool isValid(const SwapChain* UTILS_NULLABLE p); //!< Tells whether a SwapChain object is valid
|
||||
bool isValid(const Stream* UTILS_NULLABLE p); //!< Tells whether a Stream object is valid
|
||||
bool isValid(const Texture* UTILS_NULLABLE p); //!< Tells whether a Texture object is valid
|
||||
bool isValid(const RenderTarget* UTILS_NULLABLE p); //!< Tells whether a RenderTarget object is valid
|
||||
bool isValid(const View* UTILS_NULLABLE p); //!< Tells whether a View object is valid
|
||||
bool isValid(const InstanceBuffer* UTILS_NULLABLE p); //!< Tells whether an InstanceBuffer object is valid
|
||||
|
||||
/**
|
||||
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
|
||||
@@ -806,7 +826,7 @@ public:
|
||||
*
|
||||
* @return A pointer to the default Material instance (a singleton).
|
||||
*/
|
||||
const Material* getDefaultMaterial() const noexcept;
|
||||
Material const* UTILS_NONNULL getDefaultMaterial() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the resolved backend.
|
||||
@@ -837,7 +857,7 @@ public:
|
||||
* @return A pointer to the Platform object that was provided to Engine::create, or the
|
||||
* Filament-created one.
|
||||
*/
|
||||
Platform* getPlatform() const noexcept;
|
||||
Platform* UTILS_NULLABLE getPlatform() const noexcept;
|
||||
|
||||
/**
|
||||
* Allocate a small amount of memory directly in the command stream. The allocated memory is
|
||||
@@ -850,7 +870,7 @@ public:
|
||||
* @note there is no need to destroy this buffer, it will be freed automatically when
|
||||
* the current command buffer is executed.
|
||||
*/
|
||||
void* streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
|
||||
void* UTILS_NULLABLE streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
|
||||
|
||||
/**
|
||||
* Invokes one iteration of the render loop, used only on single-threaded platforms.
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
@@ -74,7 +76,7 @@ public:
|
||||
* @return FenceStatus::CONDITION_SATISFIED on success,
|
||||
* FenceStatus::ERROR otherwise.
|
||||
*/
|
||||
static FenceStatus waitAndDestroy(Fence* fence, Mode mode = Mode::FLUSH);
|
||||
static FenceStatus waitAndDestroy(Fence* UTILS_NONNULL fence, Mode mode = Mode::FLUSH);
|
||||
|
||||
protected:
|
||||
// prevent heap allocation
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <utils/unwindows.h> // Because we define NEAR and FAR in the Plane enum.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Box;
|
||||
@@ -76,14 +79,14 @@ public:
|
||||
* @param planes six plane equations encoded as in getNormalizedPlane() in
|
||||
* left, right, bottom, top, far, near order
|
||||
*/
|
||||
void getNormalizedPlanes(math::float4 planes[6]) const noexcept;
|
||||
void getNormalizedPlanes(math::float4 planes[UTILS_NONNULL 6]) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns all six frustum planes in left, right, bottom, top, far, near order
|
||||
* @return six plane equations encoded as in getNormalizedPlane() in
|
||||
* left, right, bottom, top, far, near order
|
||||
*/
|
||||
math::float4 const* getNormalizedPlanes() const noexcept { return mPlanes; }
|
||||
math::float4 const* UTILS_NONNULL getNormalizedPlanes() const noexcept { return mPlanes; }
|
||||
|
||||
/**
|
||||
* Returns whether a box intersects the frustum (i.e. is visible)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
@@ -88,8 +89,7 @@ public:
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this IndexBuffer with.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
* @return pointer to the newly created object.
|
||||
*
|
||||
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
|
||||
* memory or other resources.
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
*
|
||||
* @see IndexBuffer::setBuffer
|
||||
*/
|
||||
IndexBuffer* build(Engine& engine);
|
||||
IndexBuffer* UTILS_NONNULL build(Engine& engine);
|
||||
private:
|
||||
friend class FIndexBuffer;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
@@ -114,7 +116,7 @@ public:
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
*/
|
||||
Builder& reflections(Texture const* cubemap) noexcept;
|
||||
Builder& reflections(Texture const* UTILS_NULLABLE cubemap) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance as Spherical Harmonics.
|
||||
@@ -160,7 +162,7 @@ public:
|
||||
* Because the coefficients are pre-scaled, `sh[0]` is the environment's
|
||||
* average irradiance.
|
||||
*/
|
||||
Builder& irradiance(uint8_t bands, math::float3 const* sh) noexcept;
|
||||
Builder& irradiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance from the radiance expressed as Spherical Harmonics.
|
||||
@@ -192,7 +194,7 @@ public:
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& radiance(uint8_t bands, math::float3 const* sh) noexcept;
|
||||
Builder& radiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance as a cubemap.
|
||||
@@ -211,7 +213,7 @@ public:
|
||||
*
|
||||
* @see irradiance(uint8_t bands, math::float3 const* sh)
|
||||
*/
|
||||
Builder& irradiance(Texture const* cubemap) noexcept;
|
||||
Builder& irradiance(Texture const* UTILS_NULLABLE cubemap) noexcept;
|
||||
|
||||
/**
|
||||
* (optional) Environment intensity.
|
||||
@@ -247,7 +249,7 @@ public:
|
||||
* memory or other resources.
|
||||
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
|
||||
*/
|
||||
IndirectLight* build(Engine& engine);
|
||||
IndirectLight* UTILS_NONNULL build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FIndirectLight;
|
||||
@@ -284,12 +286,12 @@ public:
|
||||
/**
|
||||
* Returns the associated reflection map, or null if it does not exist.
|
||||
*/
|
||||
Texture const* getReflectionsTexture() const noexcept;
|
||||
Texture const* UTILS_NULLABLE getReflectionsTexture() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the associated irradiance map, or null if it does not exist.
|
||||
*/
|
||||
Texture const* getIrradianceTexture() const noexcept;
|
||||
Texture const* UTILS_NULLABLE getIrradianceTexture() const noexcept;
|
||||
|
||||
/**
|
||||
* Helper to estimate the direction of the dominant light in the environment represented by
|
||||
@@ -312,7 +314,7 @@ public:
|
||||
* @see LightManager::Builder::direction()
|
||||
* @see getColorEstimate()
|
||||
*/
|
||||
static math::float3 getDirectionEstimate(const math::float3 sh[9]) noexcept;
|
||||
static math::float3 getDirectionEstimate(const math::float3 sh[UTILS_NONNULL 9]) noexcept;
|
||||
|
||||
/**
|
||||
* Helper to estimate the color and relative intensity of the environment represented by
|
||||
@@ -332,7 +334,8 @@ public:
|
||||
* @see LightManager::Builder::intensity()
|
||||
* @see getDirectionEstimate, getIntensity, setIntensity
|
||||
*/
|
||||
static math::float4 getColorEstimate(const math::float3 sh[9], math::float3 direction) noexcept;
|
||||
static math::float4 getColorEstimate(const math::float3 sh[UTILS_NONNULL 9],
|
||||
math::float3 direction) noexcept;
|
||||
|
||||
|
||||
/** @deprecated use static versions instead */
|
||||
|
||||
@@ -18,11 +18,14 @@
|
||||
#define TNT_FILAMENT_INSTANCEBUFFER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
@@ -45,7 +48,7 @@ public:
|
||||
* >= 1 and <= \c Engine::getMaxAutomaticInstances()
|
||||
* @see Engine::getMaxAutomaticInstances
|
||||
*/
|
||||
Builder(size_t instanceCount) noexcept;
|
||||
explicit Builder(size_t instanceCount) noexcept;
|
||||
|
||||
Builder(Builder const& rhs) noexcept;
|
||||
Builder(Builder&& rhs) noexcept;
|
||||
@@ -65,12 +68,12 @@ public:
|
||||
* @param localTransforms an array of math::mat4f with length instanceCount, must remain
|
||||
* valid until after build() is called
|
||||
*/
|
||||
Builder& localTransforms(math::mat4f const* localTransforms) noexcept;
|
||||
Builder& localTransforms(math::mat4f const* UTILS_NULLABLE localTransforms) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the InstanceBuffer object and returns a pointer to it.
|
||||
*/
|
||||
InstanceBuffer* build(Engine& engine);
|
||||
InstanceBuffer* UTILS_NONNULL build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FInstanceBuffer;
|
||||
@@ -90,7 +93,8 @@ public:
|
||||
* @param count the number of local transforms
|
||||
* @param offset index of the first instance to set local transforms
|
||||
*/
|
||||
void setLocalTransforms(math::mat4f const* localTransforms, size_t count, size_t offset = 0);
|
||||
void setLocalTransforms(math::mat4f const* UTILS_NONNULL localTransforms,
|
||||
size_t count, size_t offset = 0);
|
||||
|
||||
protected:
|
||||
// prevent heap allocation
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <math/mathfwd.h>
|
||||
#include <math/quat.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
@@ -173,7 +176,7 @@ public:
|
||||
* Retrieve the Entities of all the components of this manager.
|
||||
* @return A list, in no particular order, of all the entities managed by this manager.
|
||||
*/
|
||||
utils::Entity const* getEntities() const noexcept;
|
||||
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets an Instance representing the Light component associated with the given Entity.
|
||||
@@ -391,7 +394,7 @@ public:
|
||||
* positions into
|
||||
* @param cascades the number of shadow cascades, at most 4
|
||||
*/
|
||||
static void computeUniformSplits(float* splitPositions, uint8_t cascades);
|
||||
static void computeUniformSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades);
|
||||
|
||||
/**
|
||||
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a logarithmic
|
||||
@@ -403,7 +406,7 @@ public:
|
||||
* @param near the camera near plane
|
||||
* @param far the camera far plane
|
||||
*/
|
||||
static void computeLogSplits(float* splitPositions, uint8_t cascades,
|
||||
static void computeLogSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
|
||||
float near, float far);
|
||||
|
||||
/**
|
||||
@@ -423,7 +426,7 @@ public:
|
||||
* @param lambda a float in the range [0, 1] that interpolates between log and
|
||||
* uniform split schemes
|
||||
*/
|
||||
static void computePracticalSplits(float* splitPositions, uint8_t cascades,
|
||||
static void computePracticalSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
|
||||
float near, float far, float lambda);
|
||||
};
|
||||
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace utils {
|
||||
class CString;
|
||||
@@ -69,7 +74,7 @@ public:
|
||||
*/
|
||||
struct ParameterInfo {
|
||||
//! Name of the parameter.
|
||||
const char* name;
|
||||
const char* UTILS_NONNULL name;
|
||||
//! Whether the parameter is a sampler (texture).
|
||||
bool isSampler;
|
||||
//! Whether the parameter is a subpass type.
|
||||
@@ -105,7 +110,7 @@ public:
|
||||
* @param payload Pointer to the material data, must stay valid until build() is called.
|
||||
* @param size Size of the material data pointed to by "payload" in bytes.
|
||||
*/
|
||||
Builder& package(const void* payload, size_t size);
|
||||
Builder& package(const void* UTILS_NONNULL payload, size_t size);
|
||||
|
||||
template<typename T>
|
||||
using is_supported_constant_parameter_t = typename std::enable_if<
|
||||
@@ -127,11 +132,11 @@ public:
|
||||
* in the material definition.
|
||||
*/
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
Builder& constant(const char* name, size_t nameLength, T value);
|
||||
Builder& constant(const char* UTILS_NONNULL name, size_t nameLength, T value);
|
||||
|
||||
/** inline helper to provide the constant name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
inline Builder& constant(const char* name, T value) {
|
||||
inline Builder& constant(const char* UTILS_NONNULL name, T value) {
|
||||
return constant(name, strlen(name), value);
|
||||
}
|
||||
|
||||
@@ -147,7 +152,7 @@ public:
|
||||
* memory or other resources.
|
||||
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
|
||||
*/
|
||||
Material* build(Engine& engine);
|
||||
Material* UTILS_NULLABLE build(Engine& engine);
|
||||
private:
|
||||
friend class FMaterial;
|
||||
};
|
||||
@@ -193,22 +198,22 @@ public:
|
||||
*/
|
||||
void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterMask variants,
|
||||
backend::CallbackHandler* handler = nullptr,
|
||||
utils::Invocable<void(Material*)>&& callback = {}) noexcept;
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept;
|
||||
|
||||
inline void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterBit variants,
|
||||
backend::CallbackHandler* handler = nullptr,
|
||||
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
|
||||
compile(priority, UserVariantFilterMask(variants), handler,
|
||||
std::forward<utils::Invocable<void(Material*)>>(callback));
|
||||
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
|
||||
}
|
||||
|
||||
inline void compile(CompilerPriorityQueue priority,
|
||||
backend::CallbackHandler* handler = nullptr,
|
||||
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
|
||||
compile(priority, UserVariantFilterBit::ALL, handler,
|
||||
std::forward<utils::Invocable<void(Material*)>>(callback));
|
||||
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,13 +225,13 @@ public:
|
||||
*
|
||||
* @return A pointer to the new instance.
|
||||
*/
|
||||
MaterialInstance* createInstance(const char* name = nullptr) const noexcept;
|
||||
MaterialInstance* UTILS_NONNULL createInstance(const char* UTILS_NULLABLE name = nullptr) const noexcept;
|
||||
|
||||
//! Returns the name of this material as a null-terminated string.
|
||||
const char* getName() const noexcept;
|
||||
const char* UTILS_NONNULL getName() const noexcept;
|
||||
|
||||
//! Returns the shading model of this material.
|
||||
Shading getShading() const noexcept;
|
||||
Shading getShading() const noexcept;
|
||||
|
||||
//! Returns the interpolation mode of this material. This affects how variables are interpolated.
|
||||
Interpolation getInterpolation() const noexcept;
|
||||
@@ -312,13 +317,13 @@ public:
|
||||
*
|
||||
* @return The number of parameters written to the parameters pointer.
|
||||
*/
|
||||
size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept;
|
||||
size_t getParameters(ParameterInfo* UTILS_NONNULL parameters, size_t count) const noexcept;
|
||||
|
||||
//! Indicates whether a parameter of the given name exists on this material.
|
||||
bool hasParameter(const char* name) const noexcept;
|
||||
bool hasParameter(const char* UTILS_NONNULL name) const noexcept;
|
||||
|
||||
//! Indicates whether an existing parameter is a sampler or not.
|
||||
bool isSampler(const char* name) const noexcept;
|
||||
bool isSampler(const char* UTILS_NONNULL name) const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the value of the given parameter on this material's default instance.
|
||||
@@ -329,7 +334,7 @@ public:
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
template <typename T>
|
||||
void setDefaultParameter(const char* name, T value) noexcept {
|
||||
void setDefaultParameter(const char* UTILS_NONNULL name, T value) noexcept {
|
||||
getDefaultInstance()->setParameter(name, value);
|
||||
}
|
||||
|
||||
@@ -342,8 +347,8 @@ public:
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, Texture const* texture,
|
||||
TextureSampler const& sampler) noexcept {
|
||||
void setDefaultParameter(const char* UTILS_NONNULL name,
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) noexcept {
|
||||
getDefaultInstance()->setParameter(name, texture, sampler);
|
||||
}
|
||||
|
||||
@@ -356,7 +361,7 @@ public:
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, RgbType type, math::float3 color) noexcept {
|
||||
void setDefaultParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) noexcept {
|
||||
getDefaultInstance()->setParameter(name, type, color);
|
||||
}
|
||||
|
||||
@@ -369,15 +374,15 @@ public:
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, RgbaType type, math::float4 color) noexcept {
|
||||
void setDefaultParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) noexcept {
|
||||
getDefaultInstance()->setParameter(name, type, color);
|
||||
}
|
||||
|
||||
//! Returns this material's default instance.
|
||||
MaterialInstance* getDefaultInstance() noexcept;
|
||||
MaterialInstance* UTILS_NONNULL getDefaultInstance() noexcept;
|
||||
|
||||
//! Returns this material's default instance.
|
||||
MaterialInstance const* getDefaultInstance() const noexcept;
|
||||
MaterialInstance const* UTILS_NONNULL getDefaultInstance() const noexcept;
|
||||
|
||||
protected:
|
||||
// prevent heap allocation
|
||||
|
||||
@@ -28,6 +28,12 @@
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Material;
|
||||
@@ -41,7 +47,7 @@ class UTILS_PUBLIC MaterialInstance : public FilamentAPI {
|
||||
using StringLiteralHelper = const char[N];
|
||||
|
||||
struct StringLiteral {
|
||||
const char* data;
|
||||
const char* UTILS_NONNULL data;
|
||||
size_t size;
|
||||
template<size_t N>
|
||||
StringLiteral(StringLiteralHelper<N> const& s) noexcept // NOLINT(google-explicit-constructor)
|
||||
@@ -89,17 +95,18 @@ public:
|
||||
* @param name A name for the new MaterialInstance or nullptr to use the template's name
|
||||
* @return A new MaterialInstance
|
||||
*/
|
||||
static MaterialInstance* duplicate(MaterialInstance const* other, const char* name = nullptr) noexcept;
|
||||
static MaterialInstance* UTILS_NONNULL duplicate(MaterialInstance const* UTILS_NONNULL other,
|
||||
const char* UTILS_NULLABLE name = nullptr) noexcept;
|
||||
|
||||
/**
|
||||
* @return the Material associated with this instance
|
||||
*/
|
||||
Material const* getMaterial() const noexcept;
|
||||
Material const* UTILS_NONNULL getMaterial() const noexcept;
|
||||
|
||||
/**
|
||||
* @return the name associated with this instance
|
||||
*/
|
||||
const char* getName() const noexcept;
|
||||
const char* UTILS_NONNULL getName() const noexcept;
|
||||
|
||||
/**
|
||||
* Set a uniform by name
|
||||
@@ -110,7 +117,7 @@ public:
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, size_t nameLength, T const& value);
|
||||
void setParameter(const char* UTILS_NONNULL name, size_t nameLength, T const& value);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
@@ -120,7 +127,7 @@ public:
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline void setParameter(const char* name, T const& value) {
|
||||
inline void setParameter(const char* UTILS_NONNULL name, T const& value) {
|
||||
setParameter<T>(name, strlen(name), value);
|
||||
}
|
||||
|
||||
@@ -135,17 +142,19 @@ public:
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, size_t nameLength, const T* values, size_t count);
|
||||
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
|
||||
const T* UTILS_NONNULL values, size_t count);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline void setParameter(StringLiteral name, const T* values, size_t count) {
|
||||
inline void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) {
|
||||
setParameter<T>(name.data, name.size, values, count);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline void setParameter(const char* name, const T* values, size_t count) {
|
||||
inline void setParameter(const char* UTILS_NONNULL name,
|
||||
const T* UTILS_NONNULL values, size_t count) {
|
||||
setParameter<T>(name, strlen(name), values, count);
|
||||
}
|
||||
|
||||
@@ -162,18 +171,18 @@ public:
|
||||
* @param sampler Sampler parameters.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name, size_t nameLength,
|
||||
Texture const* texture, TextureSampler const& sampler);
|
||||
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
inline void setParameter(StringLiteral name,
|
||||
Texture const* texture, TextureSampler const& sampler) {
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
|
||||
setParameter(name.data, name.size, texture, sampler);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
inline void setParameter(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) {
|
||||
inline void setParameter(const char* UTILS_NONNULL name,
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
|
||||
setParameter(name, strlen(name), texture, sampler);
|
||||
}
|
||||
|
||||
@@ -188,7 +197,8 @@ public:
|
||||
* @param color Array of read, green, blue channels values.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name, size_t nameLength, RgbType type, math::float3 color);
|
||||
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
|
||||
RgbType type, math::float3 color);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
inline void setParameter(StringLiteral name, RgbType type, math::float3 color) {
|
||||
@@ -196,7 +206,7 @@ public:
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
inline void setParameter(const char* name, RgbType type, math::float3 color) {
|
||||
inline void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) {
|
||||
setParameter(name, strlen(name), type, color);
|
||||
}
|
||||
|
||||
@@ -211,7 +221,8 @@ public:
|
||||
* @param color Array of read, green, blue and alpha channels values.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name, size_t nameLength, RgbaType type, math::float4 color);
|
||||
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
|
||||
RgbaType type, math::float4 color);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
inline void setParameter(StringLiteral name, RgbaType type, math::float4 color) {
|
||||
@@ -219,7 +230,7 @@ public:
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
inline void setParameter(const char* name, RgbaType type, math::float4 color) {
|
||||
inline void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) {
|
||||
setParameter(name, strlen(name), type, color);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
|
||||
#include <filament/Engine.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -65,14 +68,13 @@ public:
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this MorphTargetBuffer with.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
* @return pointer to the newly created object.
|
||||
*
|
||||
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
|
||||
* memory or other resources.
|
||||
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
|
||||
*/
|
||||
MorphTargetBuffer* build(Engine& engine);
|
||||
MorphTargetBuffer* UTILS_NONNULL build(Engine& engine);
|
||||
private:
|
||||
friend class FMorphTargetBuffer;
|
||||
};
|
||||
@@ -92,7 +94,7 @@ public:
|
||||
* @see setTangentsAt
|
||||
*/
|
||||
void setPositionsAt(Engine& engine, size_t targetIndex,
|
||||
math::float3 const* positions, size_t count, size_t offset = 0);
|
||||
math::float3 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Updates positions for the given morph target.
|
||||
@@ -107,7 +109,7 @@ public:
|
||||
* @see setTangentsAt
|
||||
*/
|
||||
void setPositionsAt(Engine& engine, size_t targetIndex,
|
||||
math::float4 const* positions, size_t count, size_t offset = 0);
|
||||
math::float4 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Updates tangents for the given morph target.
|
||||
@@ -123,7 +125,7 @@ public:
|
||||
* @see setPositionsAt
|
||||
*/
|
||||
void setTangentsAt(Engine& engine, size_t targetIndex,
|
||||
math::short4 const* tangents, size_t count, size_t offset = 0);
|
||||
math::short4 const* UTILS_NONNULL tangents, size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Returns the vertex count of this MorphTargetBuffer.
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
|
||||
#include <filament/Color.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Texture;
|
||||
@@ -293,6 +296,7 @@ struct DepthOfFieldOptions {
|
||||
MEDIAN
|
||||
};
|
||||
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
|
||||
float cocAspectRatio = 1.0f; //!< width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
|
||||
bool enabled = false; //!< enable or disable depth of field effect
|
||||
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
|
||||
@@ -401,7 +405,7 @@ struct AmbientOcclusionOptions {
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for Temporal Multi-Sample Anti-aliasing (MSAA)
|
||||
* Options for Multi-Sample Anti-aliasing (MSAA)
|
||||
* @see setMultiSampleAntiAliasingOptions()
|
||||
*/
|
||||
struct MultiSampleAntiAliasingOptions {
|
||||
@@ -426,17 +430,24 @@ struct MultiSampleAntiAliasingOptions {
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth` and `feedback`, however, could be changed an any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
*
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
struct TemporalAntiAliasingOptions {
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1 (smoother)
|
||||
float feedback = 0.04f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
|
||||
float feedback = 0.12f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
float lodBias = -1.0f; //!< texturing lod bias (typically -1 or -2)
|
||||
float sharpness = 0.0f; //!< post-TAA sharpen, especially useful when upscaling is true.
|
||||
bool enabled = false; //!< enables or disables temporal anti-aliasing
|
||||
bool upscaling = false; //!< 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
|
||||
enum class BoxType : uint8_t {
|
||||
AABB, //!< use an AABB neighborhood
|
||||
VARIANCE, //!< use the variance of the neighborhood
|
||||
VARIANCE, //!< use the variance of the neighborhood (not recommended)
|
||||
AABB_VARIANCE //!< use both AABB and variance
|
||||
};
|
||||
|
||||
@@ -446,11 +457,21 @@ struct TemporalAntiAliasingOptions {
|
||||
NONE //!< no rejections (use for debugging)
|
||||
};
|
||||
|
||||
enum class JitterPattern : uint8_t {
|
||||
RGSS_X4, //! 4-samples, rotated grid sampling
|
||||
UNIFORM_HELIX_X4, //! 4-samples, uniform grid in helix sequence
|
||||
HALTON_23_X8, //! 8-samples of halton 2,3
|
||||
HALTON_23_X16, //! 16-samples of halton 2,3
|
||||
HALTON_23_X32 //! 32-samples of halton 2,3
|
||||
};
|
||||
|
||||
bool filterHistory = true; //!< whether to filter the history buffer
|
||||
bool filterInput = true; //!< whether to apply the reconstruction filter to the input
|
||||
bool useYCoCg = false; //!< whether to use the YcoCg color-space for history rejection
|
||||
BoxType boxType = BoxType::VARIANCE; //!< type of color gamut box
|
||||
BoxClipping boxClipping = BoxClipping::ACCURATE; //!< clipping algorithm
|
||||
BoxType boxType = BoxType::AABB; //!< type of color gamut box
|
||||
BoxClipping boxClipping = BoxClipping::ACCURATE; //!< clipping algorithm
|
||||
JitterPattern jitterPattern = JitterPattern::HALTON_23_X16; //! Jitter Pattern
|
||||
float varianceGamma = 1.0f; //! High values increases ghosting artefact, lower values increases jittering, range [0.75, 1.25]
|
||||
|
||||
bool preventFlickering = false; //!< adjust the feedback dynamically to reduce flickering
|
||||
bool historyReprojection = true; //!< whether to apply history reprojection (debug option)
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -103,7 +106,7 @@ public:
|
||||
* @param texture The associated texture object.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& texture(AttachmentPoint attachment, Texture* texture) noexcept;
|
||||
Builder& texture(AttachmentPoint attachment, Texture* UTILS_NULLABLE texture) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the mipmap level for a given attachment point.
|
||||
@@ -135,10 +138,9 @@ public:
|
||||
/**
|
||||
* Creates the RenderTarget object and returns a pointer to it.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
* @return pointer to the newly created object.
|
||||
*/
|
||||
RenderTarget* build(Engine& engine);
|
||||
RenderTarget* UTILS_NONNULL build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FRenderTarget;
|
||||
@@ -149,7 +151,7 @@ public:
|
||||
* @param attachment Attachment point
|
||||
* @return A Texture object or nullptr if no texture is set for this attachment point
|
||||
*/
|
||||
Texture* getTexture(AttachmentPoint attachment) const noexcept;
|
||||
Texture* UTILS_NULLABLE getTexture(AttachmentPoint attachment) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the mipmap level set on the given attachment point
|
||||
|
||||
@@ -29,9 +29,15 @@
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <float.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
@@ -123,7 +129,7 @@ public:
|
||||
* Retrieve the Entities of all the components of this manager.
|
||||
* @return A list, in no particular order, of all the entities managed by this manager.
|
||||
*/
|
||||
utils::Entity const* getEntities() const noexcept;
|
||||
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* The transformation associated with a skinning joint.
|
||||
@@ -184,9 +190,19 @@ public:
|
||||
* @param maxIndex specifies the maximum index contained in the index buffer
|
||||
* @param count number of indices to read (for triangles, this should be a multiple of 3)
|
||||
*/
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t count) noexcept; //!< \overload
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices) noexcept; //!< \overload
|
||||
Builder& geometry(size_t index, PrimitiveType type,
|
||||
VertexBuffer* UTILS_NONNULL vertices,
|
||||
IndexBuffer* UTILS_NONNULL indices,
|
||||
size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
|
||||
|
||||
Builder& geometry(size_t index, PrimitiveType type,
|
||||
VertexBuffer* UTILS_NONNULL vertices,
|
||||
IndexBuffer* UTILS_NONNULL indices,
|
||||
size_t offset, size_t count) noexcept; //!< \overload
|
||||
|
||||
Builder& geometry(size_t index, PrimitiveType type,
|
||||
VertexBuffer* UTILS_NONNULL vertices,
|
||||
IndexBuffer* UTILS_NONNULL indices) noexcept; //!< \overload
|
||||
|
||||
/**
|
||||
* Binds a material instance to the specified primitive.
|
||||
@@ -203,7 +219,8 @@ public:
|
||||
*
|
||||
* @see Engine::setActiveFeatureLevel
|
||||
*/
|
||||
Builder& material(size_t index, MaterialInstance const* materialInstance) noexcept;
|
||||
Builder& material(size_t index,
|
||||
MaterialInstance const* UTILS_NONNULL materialInstance) noexcept;
|
||||
|
||||
/**
|
||||
* The axis-aligned bounding box of the renderable.
|
||||
@@ -351,7 +368,8 @@ public:
|
||||
* @param count 0 to disable, otherwise the number of bone transforms (up to 255)
|
||||
* @param offset offset in the SkinningBuffer
|
||||
*/
|
||||
Builder& skinning(SkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept;
|
||||
Builder& skinning(SkinningBuffer* UTILS_NONNULL skinningBuffer,
|
||||
size_t count, size_t offset) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
@@ -369,8 +387,8 @@ public:
|
||||
* @param boneCount 0 to disable, otherwise the number of bone transforms (up to 255)
|
||||
* @param transforms the initial set of transforms (one for each bone)
|
||||
*/
|
||||
Builder& skinning(size_t boneCount, math::mat4f const* transforms) noexcept;
|
||||
Builder& skinning(size_t boneCount, Bone const* bones) noexcept; //!< \overload
|
||||
Builder& skinning(size_t boneCount, math::mat4f const* UTILS_NONNULL transforms) noexcept;
|
||||
Builder& skinning(size_t boneCount, Bone const* UTILS_NONNULL bones) noexcept; //!< \overload
|
||||
Builder& skinning(size_t boneCount) noexcept; //!< \overload
|
||||
|
||||
/**
|
||||
@@ -399,7 +417,8 @@ public:
|
||||
* @see VertexBuffer:Builder:advancedSkinning
|
||||
*/
|
||||
Builder& boneIndicesAndWeights(size_t primitiveIndex,
|
||||
math::float2 const* indicesAndWeights, size_t count, size_t bonesPerVertex) noexcept;
|
||||
math::float2 const* UTILS_NONNULL indicesAndWeights,
|
||||
size_t count, size_t bonesPerVertex) noexcept;
|
||||
|
||||
/**
|
||||
* Define bone indices and weights "pairs" for vertex skinning as a float2.
|
||||
@@ -462,10 +481,11 @@ public:
|
||||
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
|
||||
*/
|
||||
Builder& morphing(uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept;
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer,
|
||||
size_t offset, size_t count) noexcept;
|
||||
|
||||
inline Builder& morphing(uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer) noexcept;
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the drawing order for blended primitives. The drawing order is either global or
|
||||
@@ -532,7 +552,8 @@ public:
|
||||
* the result of Engine::getMaxAutomaticInstances().
|
||||
* @param instanceBuffer an InstanceBuffer containing at least instanceCount transforms
|
||||
*/
|
||||
Builder& instances(size_t instanceCount, InstanceBuffer* instanceBuffer) noexcept;
|
||||
Builder& instances(size_t instanceCount,
|
||||
InstanceBuffer* UTILS_NONNULL instanceBuffer) noexcept;
|
||||
|
||||
/**
|
||||
* Adds the Renderable component to an entity.
|
||||
@@ -559,18 +580,18 @@ public:
|
||||
friend class FRenderPrimitive;
|
||||
friend class FRenderableManager;
|
||||
struct Entry {
|
||||
VertexBuffer* vertices = nullptr;
|
||||
IndexBuffer* indices = nullptr;
|
||||
VertexBuffer* UTILS_NULLABLE vertices = nullptr;
|
||||
IndexBuffer* UTILS_NULLABLE indices = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t minIndex = 0;
|
||||
size_t maxIndex = 0;
|
||||
size_t count = 0;
|
||||
MaterialInstance const* materialInstance = nullptr;
|
||||
MaterialInstance const* UTILS_NULLABLE materialInstance = nullptr;
|
||||
PrimitiveType type = PrimitiveType::TRIANGLES;
|
||||
uint16_t blendOrder = 0;
|
||||
bool globalBlendOrderEnabled = false;
|
||||
struct {
|
||||
MorphTargetBuffer* buffer = nullptr;
|
||||
MorphTargetBuffer* UTILS_NULLABLE buffer = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t count = 0;
|
||||
} morphing;
|
||||
@@ -688,8 +709,11 @@ public:
|
||||
* Updates the bone transforms in the range [offset, offset + boneCount).
|
||||
* The bones must be pre-allocated using Builder::skinning().
|
||||
*/
|
||||
void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0);
|
||||
void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0); //!< \overload
|
||||
void setBones(Instance instance, Bone const* UTILS_NONNULL transforms,
|
||||
size_t boneCount = 1, size_t offset = 0);
|
||||
|
||||
void setBones(Instance instance, math::mat4f const* UTILS_NONNULL transforms,
|
||||
size_t boneCount = 1, size_t offset = 0); //!< \overload
|
||||
|
||||
/**
|
||||
* Associates a region of a SkinningBuffer to a renderable instance
|
||||
@@ -702,7 +726,7 @@ public:
|
||||
* @param count Size of the region in bones, must be smaller or equal to 256.
|
||||
* @param offset Start offset of the region in bones
|
||||
*/
|
||||
void setSkinningBuffer(Instance instance, SkinningBuffer* skinningBuffer,
|
||||
void setSkinningBuffer(Instance instance, SkinningBuffer* UTILS_NONNULL skinningBuffer,
|
||||
size_t count, size_t offset);
|
||||
|
||||
/**
|
||||
@@ -717,24 +741,25 @@ public:
|
||||
* @param offset Index of the first morph target weight to set at instance.
|
||||
*/
|
||||
void setMorphWeights(Instance instance,
|
||||
float const* weights, size_t count, size_t offset = 0);
|
||||
float const* UTILS_NONNULL weights, size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Associates a MorphTargetBuffer to the given primitive.
|
||||
*/
|
||||
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count);
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, size_t offset, size_t count);
|
||||
|
||||
/**
|
||||
* Utility method to change a MorphTargetBuffer to the given primitive
|
||||
*/
|
||||
inline void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer);
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer);
|
||||
|
||||
/**
|
||||
* Get a MorphTargetBuffer to the given primitive or null if it doesn't exist.
|
||||
*/
|
||||
MorphTargetBuffer* getMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept;
|
||||
MorphTargetBuffer* UTILS_NULLABLE getMorphTargetBufferAt(Instance instance,
|
||||
uint8_t level, size_t primitiveIndex) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of morphing in the given entity.
|
||||
@@ -776,20 +801,22 @@ public:
|
||||
* @see Engine::setActiveFeatureLevel
|
||||
*/
|
||||
void setMaterialInstanceAt(Instance instance,
|
||||
size_t primitiveIndex, MaterialInstance const* materialInstance);
|
||||
size_t primitiveIndex, MaterialInstance const* UTILS_NONNULL materialInstance);
|
||||
|
||||
/**
|
||||
* Retrieves the material instance that is bound to the given primitive.
|
||||
*/
|
||||
MaterialInstance* getMaterialInstanceAt(Instance instance, size_t primitiveIndex) const noexcept;
|
||||
MaterialInstance* UTILS_NULLABLE getMaterialInstanceAt(
|
||||
Instance instance, size_t primitiveIndex) const noexcept;
|
||||
|
||||
/**
|
||||
* Changes the geometry for the given primitive.
|
||||
*
|
||||
* \see Builder::geometry()
|
||||
*/
|
||||
void setGeometryAt(Instance instance, size_t primitiveIndex,
|
||||
PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices,
|
||||
void setGeometryAt(Instance instance, size_t primitiveIndex, PrimitiveType type,
|
||||
VertexBuffer* UTILS_NONNULL vertices,
|
||||
IndexBuffer* UTILS_NONNULL indices,
|
||||
size_t offset, size_t count) noexcept;
|
||||
|
||||
/**
|
||||
@@ -850,7 +877,9 @@ public:
|
||||
template<typename VECTOR, typename INDEX,
|
||||
typename = typename is_supported_vector_type<VECTOR>::type,
|
||||
typename = typename is_supported_index_type<INDEX>::type>
|
||||
static Box computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
|
||||
static Box computeAABB(
|
||||
VECTOR const* UTILS_NONNULL vertices,
|
||||
INDEX const* UTILS_NONNULL indices, size_t count,
|
||||
size_t stride = sizeof(VECTOR)) noexcept;
|
||||
|
||||
protected:
|
||||
@@ -858,23 +887,27 @@ protected:
|
||||
~RenderableManager() = default;
|
||||
};
|
||||
|
||||
RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer) noexcept {
|
||||
RenderableManager::Builder& RenderableManager::Builder::morphing(
|
||||
uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
|
||||
return morphing(level, primitiveIndex, morphTargetBuffer, 0,
|
||||
morphTargetBuffer->getVertexCount());
|
||||
}
|
||||
|
||||
void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* morphTargetBuffer) {
|
||||
void RenderableManager::setMorphTargetBufferAt(
|
||||
Instance instance, uint8_t level, size_t primitiveIndex,
|
||||
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) {
|
||||
setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0,
|
||||
morphTargetBuffer->getVertexCount());
|
||||
}
|
||||
|
||||
template<typename VECTOR, typename INDEX, typename, typename>
|
||||
Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
|
||||
size_t stride) noexcept {
|
||||
math::float3 bmin(std::numeric_limits<float>::max());
|
||||
math::float3 bmax(std::numeric_limits<float>::lowest());
|
||||
Box RenderableManager::computeAABB(
|
||||
VECTOR const* UTILS_NONNULL vertices,
|
||||
INDEX const* UTILS_NONNULL indices,
|
||||
size_t count, size_t stride) noexcept {
|
||||
math::float3 bmin(FLT_MAX);
|
||||
math::float3 bmax(-FLT_MAX);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
VECTOR const* p = reinterpret_cast<VECTOR const*>(
|
||||
(char const*)vertices + indices[i] * stride);
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <backend/PresentCallable.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -184,14 +181,14 @@ public:
|
||||
*
|
||||
* @return A pointer to the Engine instance this Renderer is associated to.
|
||||
*/
|
||||
Engine* getEngine() noexcept;
|
||||
Engine* UTILS_NONNULL getEngine() noexcept;
|
||||
|
||||
/**
|
||||
* Get the Engine that created this Renderer.
|
||||
*
|
||||
* @return A constant pointer to the Engine instance this Renderer is associated to.
|
||||
*/
|
||||
inline Engine const* getEngine() const noexcept {
|
||||
inline Engine const* UTILS_NONNULL getEngine() const noexcept {
|
||||
return const_cast<Renderer *>(this)->getEngine();
|
||||
}
|
||||
|
||||
@@ -267,7 +264,7 @@ public:
|
||||
* @see
|
||||
* endFrame()
|
||||
*/
|
||||
bool beginFrame(SwapChain* swapChain,
|
||||
bool beginFrame(SwapChain* UTILS_NONNULL swapChain,
|
||||
uint64_t vsyncSteadyClockTimeNano = 0u);
|
||||
|
||||
/**
|
||||
@@ -338,7 +335,7 @@ public:
|
||||
* beginFrame(), endFrame(), View
|
||||
*
|
||||
*/
|
||||
void render(View const* view);
|
||||
void render(View const* UTILS_NONNULL view);
|
||||
|
||||
/**
|
||||
* Copy the currently rendered view to the indicated swap chain, using the
|
||||
@@ -353,7 +350,7 @@ public:
|
||||
* copyFrame() should be called after a frame is rendered using render()
|
||||
* but before endFrame() is called.
|
||||
*/
|
||||
void copyFrame(SwapChain* dstSwapChain, Viewport const& dstViewport,
|
||||
void copyFrame(SwapChain* UTILS_NONNULL dstSwapChain, Viewport const& dstViewport,
|
||||
Viewport const& srcViewport, uint32_t flags = 0);
|
||||
|
||||
/**
|
||||
@@ -493,7 +490,7 @@ public:
|
||||
* readPixels() is intended for debugging and testing. It will impact performance significantly.
|
||||
*
|
||||
*/
|
||||
void readPixels(RenderTarget* renderTarget,
|
||||
void readPixels(RenderTarget* UTILS_NONNULL renderTarget,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
backend::PixelBufferDescriptor&& buffer);
|
||||
|
||||
@@ -520,7 +517,7 @@ public:
|
||||
* However, internally, renderStandaloneView() is highly multi-threaded to both improve
|
||||
* performance in mitigate the call's latency.
|
||||
*/
|
||||
void renderStandaloneView(View const* view);
|
||||
void renderStandaloneView(View const* UTILS_NONNULL view);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
@@ -73,14 +75,14 @@ public:
|
||||
*
|
||||
* @param skybox The Skybox to use to fill untouched pixels, or nullptr to unset the Skybox.
|
||||
*/
|
||||
void setSkybox(Skybox* skybox) noexcept;
|
||||
void setSkybox(Skybox* UTILS_NULLABLE skybox) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Skybox associated with the Scene.
|
||||
*
|
||||
* @return The associated Skybox, or nullptr if there is none.
|
||||
*/
|
||||
Skybox* getSkybox() const noexcept;
|
||||
Skybox* UTILS_NULLABLE getSkybox() const noexcept;
|
||||
|
||||
/**
|
||||
* Set the IndirectLight to use when rendering the Scene.
|
||||
@@ -91,7 +93,7 @@ public:
|
||||
* @param ibl The IndirectLight to use when rendering the Scene or nullptr to unset.
|
||||
* @see getIndirectLight
|
||||
*/
|
||||
void setIndirectLight(IndirectLight* ibl) noexcept;
|
||||
void setIndirectLight(IndirectLight* UTILS_NULLABLE ibl) noexcept;
|
||||
|
||||
/**
|
||||
* Get the IndirectLight or nullptr if none is set.
|
||||
@@ -99,7 +101,7 @@ public:
|
||||
* @return the the IndirectLight or nullptr if none is set
|
||||
* @see setIndirectLight
|
||||
*/
|
||||
IndirectLight* getIndirectLight() const noexcept;
|
||||
IndirectLight* UTILS_NULLABLE getIndirectLight() const noexcept;
|
||||
|
||||
/**
|
||||
* Adds an Entity to the Scene.
|
||||
@@ -118,7 +120,7 @@ public:
|
||||
* @param entities Array containing entities to add to the scene.
|
||||
* @param count Size of the entity array.
|
||||
*/
|
||||
void addEntities(const utils::Entity* entities, size_t count);
|
||||
void addEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
|
||||
|
||||
/**
|
||||
* Removes the Renderable from the Scene.
|
||||
@@ -137,7 +139,7 @@ public:
|
||||
* @param entities Array containing entities to remove from the scene.
|
||||
* @param count Size of the entity array.
|
||||
*/
|
||||
void removeEntities(const utils::Entity* entities, size_t count);
|
||||
void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
|
||||
|
||||
/**
|
||||
* Returns the total number of Entities in the Scene, whether alive or not.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user