diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml
index ae7efb2ebe..9745f29131 100644
--- a/.github/workflows/presubmit.yml
+++ b/.github/workflows/presubmit.yml
@@ -92,27 +92,33 @@ jobs:
test-renderdiff:
name: test-renderdiff
- runs-on: ubuntu-22.04-4core
-
+ runs-on: macos-14-xlarge
steps:
- uses: actions/checkout@v4.1.6
- - uses: ./.github/actions/ubuntu-apt-add-src
+ - name: Set up Homebrew
+ id: set-up-homebrew
+ uses: Homebrew/actions/setup-homebrew@master
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+ - name: Install python prereqs
+ run: pip install mako setuptools pyyaml
- name: Run script
run: |
- echo "Disabled renderdiff due to Mesa -> Currently planned outage: 2025-03-16 -> 2025-03-22"
-# source ./build/linux/ci-common.sh && bash test/renderdiff/test.sh
+ bash test/renderdiff/test.sh
- uses: actions/upload-artifact@v4
with:
name: presubmit-renderdiff-result
path: ./out/renderdiff_tests
- validate-wgsl-pipeline:
- name: validate-wgsl-pipeline
- runs-on: ubuntu-22.04-4core
+ validate-wgsl-webgpu:
+ name: validate-wgsl-webgpu
+ runs-on: ubuntu-22.04-8core
steps:
- uses: actions/checkout@v4.1.6
- name: Run build script
- run: source ./build/linux/ci-common.sh && ./build.sh -W debug test_filamat
+ run: source ./build/linux/ci-common.sh && ./build.sh -W debug test_filamat filament
- name: Run test
- run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
\ No newline at end of file
+ run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f00a15c1ec..c81f49fe70 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -139,14 +139,14 @@ else()
set(LINUX FALSE)
endif()
-if (LINUX)
- if (NOT FILAMENT_OSMESA_PATH STREQUAL "")
- if (NOT EXISTS ${FILAMENT_OSMESA_PATH}/)
- message(FATAL_ERROR "Cannot find specified OSMesa build directory: ${FILAMENT_OSMESA_PATH}")
- endif()
- set(FILAMENT_SUPPORTS_OSMESA TRUE)
+if (NOT FILAMENT_OSMESA_PATH STREQUAL "")
+ if (NOT EXISTS ${FILAMENT_OSMESA_PATH}/)
+ message(FATAL_ERROR "Cannot find specified OSMesa build directory: ${FILAMENT_OSMESA_PATH}")
endif()
+ set(FILAMENT_SUPPORTS_OSMESA TRUE)
+endif()
+if (LINUX)
if (FILAMENT_SUPPORTS_WAYLAND)
add_definitions(-DFILAMENT_SUPPORTS_WAYLAND)
set(FILAMENT_SUPPORTS_X11 FALSE)
@@ -184,6 +184,12 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS AND NOT FILAMENT_LINUX_IS_MOBILE)
set(IS_HOST_PLATFORM TRUE)
endif()
+if (APPLE)
+ if (FILAMENT_SUPPORTS_OSMESA)
+ add_definitions(-DFILAMENT_SUPPORTS_OSMESA)
+ endif()
+endif()
+
if (WIN32)
# Link statically against c/c++ lib to avoid missing redistriburable such as
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
diff --git a/README.md b/README.md
index 54795d7a83..ce0adf1558 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
- implementation 'com.google.android.filament:filament-android:1.58.0'
+ implementation 'com.google.android.filament:filament-android:1.58.1'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
-pod 'Filament', '~> 1.58.0'
+pod 'Filament', '~> 1.58.1'
```
## Documentation
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index e2b39c788f..8c9612ce22 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -7,6 +7,10 @@ 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.58.2
+
+- engine: Generate 1D instead of 3D LUTs for color grading whenever possible.
+
## v1.58.1
diff --git a/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java b/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java
index 680e2585b8..e0397b199b 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java
@@ -46,9 +46,8 @@ import static com.google.android.filament.Asserts.assertFloat4In;
*
*
Performance
*
- * Creating a new ColorGrading object may be more expensive than other Filament objects as a
- * 3D LUT may need to be generated. The generation of a 3D LUT, if necessary, may happen on
- * the CPU.
+ * Creating a new ColorGrading object may be more expensive than other Filament objects as a LUT may
+ * need to be generated. The generation of this LUT, if necessary, may happen on the CPU.
*
* Ordering
*
@@ -160,6 +159,10 @@ public class ColorGrading {
* quality level will use a 32x32x32 10 bit LUT, a high quality will use a 32x32x32 16 bit
* LUT, and a ultra quality will use a 64x64x64 16 bit LUT.
*
+ * This setting has no effect if generating a 1D LUT.
+ *
+ * This overrides the values set by format() and dimensions().
+ *
* The default quality is {@link QualityLevel#MEDIUM}.
*
* @param qualityLevel The desired quality of the color grading process
@@ -175,6 +178,8 @@ public class ColorGrading {
* When color grading is implemented using a 3D LUT, this sets the texture format of
* of the LUT. This overrides the value set by quality().
*
+ * This setting has no effect if generating a 1D LUT.
+ *
* The default is INTEGER
*
* @param format The desired format of the 3D LUT.
@@ -190,6 +195,8 @@ public class ColorGrading {
* When color grading is implemented using a 3D LUT, this sets the dimension of the LUT.
* This overrides the value set by quality().
*
+ * This setting has no effect if generating a 1D LUT.
+ *
* The default is 32
*
* @param dim The desired dimension of the LUT. Between 16 and 64.
@@ -616,4 +623,3 @@ public class ColorGrading {
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
}
-
diff --git a/android/filament-android/src/main/java/com/google/android/filament/ToneMapper.java b/android/filament-android/src/main/java/com/google/android/filament/ToneMapper.java
index c3d3490441..89b12541c2 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/ToneMapper.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/ToneMapper.java
@@ -31,8 +31,6 @@ package com.google.android.filament;
* DisplayRangeToneMapper
*
*
- *
- * You can create custom tone mapping operators by subclassing ToneMapper.
*/
public class ToneMapper {
private final long mNativeObject;
diff --git a/android/gradle.properties b/android/gradle.properties
index 3833fd5bca..3007050a8a 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
-VERSION_NAME=1.58.0
+VERSION_NAME=1.58.1
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
diff --git a/build/linux/ci-common.sh b/build/linux/ci-common.sh
index c03ed4eeee..7d88065205 100755
--- a/build/linux/ci-common.sh
+++ b/build/linux/ci-common.sh
@@ -31,7 +31,7 @@ if [[ "$GITHUB_WORKFLOW" ]]; then
sudo apt-get install mesa-common-dev libxi-dev libxxf86vm-dev
# For dawn
- sudo apt-get install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
+ sudo apt-get install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libx11-xcb-dev
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${GITHUB_CLANG_VERSION} 100
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100
diff --git a/docs/Materials.md.html b/docs/Materials.md.html
index fae697661c..7671c8f97c 100644
--- a/docs/Materials.md.html
+++ b/docs/Materials.md.html
@@ -78,26 +78,27 @@ in table [standardProperties].
Property | Definition
-----------------------:|:---------------------
**baseColor** | Diffuse albedo for non-metallic surfaces, and specular color for metallic surfaces
-**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
**roughness** | Perceived smoothness (1.0) or roughness (0.0) of a surface. Smooth surfaces exhibit sharp reflections
+**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
**reflectance** | Fresnel reflectance at normal incidence for dielectric surfaces. This directly controls the strength of the reflections
-**sheenColor** | Strength of the sheen layer
-**sheenRoughness** | Perceived smoothness or roughness of the sheen layer
+**ambientOcclusion** | Defines how much of the ambient light is accessible to a surface point. It is a per-pixel shadowing factor between 0.0 and 1.0
**clearCoat** | Strength of the clear coat layer
**clearCoatRoughness** | Perceived smoothness or roughness of the clear coat layer
+**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
**anisotropy** | Amount of anisotropy in either the tangent or bitangent direction
**anisotropyDirection** | Local surface direction in tangent space
-**ambientOcclusion** | Defines how much of the ambient light is accessible to a surface point. It is a per-pixel shadowing factor between 0.0 and 1.0
-**normal** | A detail normal used to perturb the surface using _bump mapping_ (_normal mapping_)
-**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
-**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
-**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
-**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
-**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
-**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
-**absorption** | Absorption factor for refractive objects
-**microThickness** | Thickness of the thin layer of refractive objects
**thickness** | Thickness of the solid volume of refractive objects
+**sheenColor** | Strength of the sheen layer
+**sheenRoughness** | Perceived smoothness or roughness of the sheen layer
+**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
+**normal** | A detail normal used to perturb the surface using _bump mapping_ (_normal mapping_)
+**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
+**absorption** | Absorption factor for refractive objects
+**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
+**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
+**microThickness** | Thickness of the thin layer of refractive objects
+**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
+**shadowStrength** | Strength factor between 0 and 1 for all shadows received by this material
[Table [standardProperties]: Properties of the standard model]
The type and range of each property is described in table [standardPropertiesTypes].
diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt
index 6f66f1f457..24c7a15587 100644
--- a/filament/backend/CMakeLists.txt
+++ b/filament/backend/CMakeLists.txt
@@ -108,8 +108,12 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm)
elseif (APPLE)
- list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
- list(APPEND SRCS src/opengl/platforms/CocoaExternalImage.mm)
+ if (FILAMENT_SUPPORTS_OSMESA)
+ list(APPEND SRCS src/opengl/platforms/PlatformOSMesa.cpp)
+ else()
+ list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
+ list(APPEND SRCS src/opengl/platforms/CocoaExternalImage.mm)
+ endif()
elseif (WEBGL)
list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp)
elseif (LINUX)
@@ -173,10 +177,12 @@ endif()
if (FILAMENT_SUPPORTS_VULKAN)
list(APPEND SRCS
include/backend/platforms/VulkanPlatform.h
- src/vulkan/caching/VulkanDescriptorSetManager.cpp
- src/vulkan/caching/VulkanDescriptorSetManager.h
- src/vulkan/caching/VulkanPipelineLayoutCache.cpp
- src/vulkan/caching/VulkanPipelineLayoutCache.h
+ src/vulkan/VulkanDescriptorSetCache.cpp
+ src/vulkan/VulkanDescriptorSetCache.h
+ src/vulkan/VulkanDescriptorSetLayoutCache.cpp
+ src/vulkan/VulkanDescriptorSetLayoutCache.h
+ src/vulkan/VulkanPipelineLayoutCache.cpp
+ src/vulkan/VulkanPipelineLayoutCache.h
src/vulkan/memory/ResourceManager.cpp
src/vulkan/memory/ResourceManager.h
src/vulkan/memory/ResourcePointer.h
@@ -416,9 +422,12 @@ set(LINUX_LINKER_OPTIMIZATION_FLAGS
-Wl,--exclude-libs,bluegl
)
-if (LINUX AND FILAMENT_SUPPORTS_OSMESA)
- set(OSMESA_COMPILE_FLAGS
- -I${FILAMENT_OSMESA_PATH}/include/GL)
+if (FILAMENT_SUPPORTS_OSMESA)
+ if (LINUX)
+ set(OSMESA_COMPILE_FLAGS -I${FILAMENT_OSMESA_PATH}/include/GL)
+ elseif (APPLE)
+ set(OSMESA_COMPILE_FLAGS -I${FILAMENT_OSMESA_PATH}/include)
+ endif()
endif()
if (MSVC)
diff --git a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h
index ecd8fc8ab4..d3d1f3a60c 100644
--- a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h
+++ b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
@@ -43,8 +44,21 @@ public:
PlatformEGLAndroid() noexcept;
~PlatformEGLAndroid() noexcept override;
-protected:
+ /**
+ * Creates an ExternalImage from a EGLImageKHR
+ */
+ ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer, bool sRGB) noexcept;
+ struct ExternalImageDescAndroid {
+ uint32_t width; // Texture width
+ uint32_t height; // Texture height
+ TextureFormat format;// Texture format
+ TextureUsage usage; // Texture usage flags
+ };
+
+ ExternalImageDescAndroid getExternalImageDesc(ExternalImageHandle externalImage) noexcept;
+
+protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
@@ -57,11 +71,6 @@ protected:
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
- /**
- * Creates an ExternalImage from a EGLImageKHR
- */
- ExternalImageHandle createExternalImage(AHardwareBuffer const *buffer, bool sRGB) noexcept;
-
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
@@ -95,15 +104,26 @@ protected:
*/
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
- bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
+ OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
+ void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
struct ExternalImageEGLAndroid : public ExternalImageEGL {
AHardwareBuffer* aHardwareBuffer = nullptr;
+ uint32_t width; // Texture width
+ uint32_t height; // Texture height
+ TextureFormat format;// Texture format
+ TextureUsage usage; // Texture usage flags
bool sRGB = false;
+
protected:
~ExternalImageEGLAndroid() override;
};
+ bool setExternalImage(ExternalImageHandleRef externalImage,
+ ExternalTexture* texture) noexcept override;
+ bool setImage(ExternalImageEGLAndroid const* eglExternalImage,
+ ExternalTexture* texture) noexcept;
+
protected:
bool makeCurrent(ContextType type,
SwapChain* drawSwapChain,
diff --git a/filament/backend/include/backend/platforms/PlatformOSMesa.h b/filament/backend/include/backend/platforms/PlatformOSMesa.h
index a1a72fc6f7..5f6658f94d 100644
--- a/filament/backend/include/backend/platforms/PlatformOSMesa.h
+++ b/filament/backend/include/backend/platforms/PlatformOSMesa.h
@@ -21,7 +21,12 @@
#include "bluegl/BlueGL.h"
+#if defined(__linux__)
#include
+#elif defined(__APPLE__)
+#undef GLAPI
+#include
+#endif
#include
#include
diff --git a/filament/backend/include/backend/platforms/VulkanPlatform.h b/filament/backend/include/backend/platforms/VulkanPlatform.h
index 404b67249b..10f6dff3ab 100644
--- a/filament/backend/include/backend/platforms/VulkanPlatform.h
+++ b/filament/backend/include/backend/platforms/VulkanPlatform.h
@@ -368,8 +368,16 @@ public:
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
VkImageViewType viewType, VkComponentMapping swizzle);
+protected:
+ virtual ExtensionSet getSwapchainInstanceExtensions() const;
+
+ using SurfaceBundle = std::tuple;
+ virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
+ uint64_t flags) const noexcept;
+
private:
- static ExtensionSet getSwapchainInstanceExtensions();
+ // Platform dependent helper methods
+ static ExtensionSet getSwapchainInstanceExtensionsImpl();
static ExternalImageMetadata getExternalImageMetadataImpl(ExternalImageHandleRef externalImage,
VkDevice device);
@@ -386,8 +394,7 @@ private:
VkComponentMapping swizzle);
// Platform dependent helper methods
- using SurfaceBundle = std::tuple;
- static SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
+ static SurfaceBundle createVkSurfaceKHRImpl(void* nativeWindow, VkInstance instance,
uint64_t flags) noexcept;
friend struct VulkanPlatformPrivate;
diff --git a/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h b/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h
index ca6cd888ae..f08ff384cc 100644
--- a/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h
+++ b/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h
@@ -17,27 +17,55 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
-#include
+#include
+#include
#include
-namespace filament::backend::fvkandroid {
+namespace filament::backend {
-struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
- AHardwareBuffer* aHardwareBuffer = nullptr;
- bool sRGB = false;
- unsigned int width; // Texture width
- unsigned int height; // Texture height
- TextureFormat format; // Texture format
- TextureUsage usage; // Texture usage flags
+class VulkanPlatformAndroid : public VulkanPlatform {
+public:
+ Platform::ExternalImageHandle UTILS_PUBLIC createExternalImage(AHardwareBuffer const* buffer,
+ bool sRGB) noexcept;
+
+ struct UTILS_PUBLIC ExternalImageDescAndroid {
+ uint32_t width; // Texture width
+ uint32_t height; // Texture height
+ TextureFormat format;// Texture format
+ TextureUsage usage; // Texture usage flags
+ };
+
+ ExternalImageDescAndroid UTILS_PUBLIC getExternalImageDesc(
+ ExternalImageHandleRef externalImage) const noexcept;
protected:
- ~ExternalImageVulkanAndroid() override;
+ struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
+ AHardwareBuffer* aHardwareBuffer = nullptr;
+ bool sRGB = false;
+ unsigned int width; // Texture width
+ unsigned int height; // Texture height
+ TextureFormat format;// Texture format
+ TextureUsage usage; // Texture usage flags
+
+ protected:
+ ~ExternalImageVulkanAndroid() override;
+ };
+
+ virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage);
+
+ using ImageData = VulkanPlatform::ImageData;
+ virtual ImageData createExternalImageData(ExternalImageHandleRef externalImage,
+ const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
+ VkImageUsageFlags usage);
+
+ virtual ExtensionSet getSwapchainInstanceExtensions() const;
+
+ using SurfaceBundle = VulkanPlatform::SurfaceBundle;
+ virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
+ uint64_t flags) const noexcept;
};
-Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer,
- bool sRGB) noexcept;
+}// namespace filament::backend
-} // namespace filament::backend::fvkandroid
-
-#endif // TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
+#endif// TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
diff --git a/filament/backend/src/PlatformFactory.cpp b/filament/backend/src/PlatformFactory.cpp
index bf1ec35176..d5055daee5 100644
--- a/filament/backend/src/PlatformFactory.cpp
+++ b/filament/backend/src/PlatformFactory.cpp
@@ -19,6 +19,11 @@
#include
#include
+// We need to keep this up top for the linux (X11) name collisions.
+#if defined(FILAMENT_SUPPORTS_WEBGPU)
+ #include "backend/platforms/WebGPUPlatform.h"
+#endif
+
#if defined(__ANDROID__)
#include
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
@@ -30,7 +35,11 @@
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
- #include
+ #if defined(FILAMENT_SUPPORTS_OSMESA)
+ #include
+ #else
+ #include
+ #endif
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
@@ -55,7 +64,11 @@
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
- #include "backend/platforms/VulkanPlatform.h"
+ #if defined(__ANDROID__)
+ #include "backend/platforms/VulkanPlatformAndroid.h"
+ #else
+ #include "backend/platforms/VulkanPlatform.h"
+ #endif
#endif
#if defined (FILAMENT_SUPPORTS_METAL)
@@ -65,9 +78,6 @@ filament::backend::Platform* createDefaultMetalPlatform();
#endif
#include "noop/PlatformNoop.h"
-#if defined(FILAMENT_SUPPORTS_WEBGPU)
- #include "backend/platforms/WebGPUPlatform.h"
-#endif
namespace filament::backend {
@@ -104,7 +114,11 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
}
if (*backend == Backend::VULKAN) {
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
- return new VulkanPlatform();
+ #if defined(__ANDROID__)
+ return new VulkanPlatformAndroid();
+ #else
+ return new VulkanPlatform();
+ #endif
#else
return nullptr;
#endif
@@ -132,7 +146,11 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
#elif defined(FILAMENT_IOS)
return new PlatformCocoaTouchGL();
#elif defined(__APPLE__)
- return new PlatformCocoaGL();
+ #if defined(FILAMENT_SUPPORTS_OSMESA)
+ return new PlatformOSMesa();
+ #else
+ return new PlatformCocoaGL();
+ #endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
return new PlatformGLX();
diff --git a/filament/backend/src/noop/PlatformNoop.cpp b/filament/backend/src/noop/PlatformNoop.cpp
index 70e222e55e..5fb65c683e 100644
--- a/filament/backend/src/noop/PlatformNoop.cpp
+++ b/filament/backend/src/noop/PlatformNoop.cpp
@@ -20,7 +20,7 @@
namespace filament::backend {
-Driver* PlatformNoop::createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
+Driver* PlatformNoop::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
return NoopDriver::create();
}
diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp
index 9500c124c7..1c4a9a6e2e 100644
--- a/filament/backend/src/opengl/OpenGLDriver.cpp
+++ b/filament/backend/src/opengl/OpenGLDriver.cpp
@@ -148,8 +148,8 @@ using namespace utils;
namespace filament::backend {
Driver* OpenGLDriverFactory::create(
- OpenGLPlatform* const platform,
- void* const sharedGLContext,
+ OpenGLPlatform* platform,
+ void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
return OpenGLDriver::create(platform, sharedGLContext, driverConfig);
}
@@ -159,10 +159,10 @@ using namespace GLUtils;
// ------------------------------------------------------------------------------------------------
UTILS_NOINLINE
-OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* const platform,
- void* const /*sharedGLContext*/, const Platform::DriverConfig& driverConfig) noexcept {
+OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* platform,
+ void* /*sharedGLContext*/, const Platform::DriverConfig& driverConfig) noexcept {
assert_invariant(platform);
- OpenGLPlatform* const ec = platform;
+ OpenGLPlatform* ec = platform;
#if 0
// this is useful for development, but too verbose even for debug builds
@@ -230,7 +230,7 @@ OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* const platform,
constexpr size_t defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
Platform::DriverConfig validConfig{ driverConfig };
validConfig.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize);
- OpenGLDriver* const driver = new(std::nothrow) OpenGLDriver(ec, validConfig);
+ OpenGLDriver* driver = new(std::nothrow) OpenGLDriver(ec, validConfig);
return driver;
}
diff --git a/filament/backend/src/opengl/platforms/PlatformCocoaTouchGL.mm b/filament/backend/src/opengl/platforms/PlatformCocoaTouchGL.mm
index e37e61a109..681a6a81b9 100644
--- a/filament/backend/src/opengl/platforms/PlatformCocoaTouchGL.mm
+++ b/filament/backend/src/opengl/platforms/PlatformCocoaTouchGL.mm
@@ -64,7 +64,7 @@ PlatformCocoaTouchGL::~PlatformCocoaTouchGL() noexcept {
delete pImpl;
}
-Driver* PlatformCocoaTouchGL::createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
+Driver* PlatformCocoaTouchGL::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
EAGLSharegroup* sharegroup = (__bridge EAGLSharegroup*) sharedGLContext;
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
diff --git a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp
index e32adb864e..a321eef83f 100644
--- a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include "opengl/GLUtils.h"
@@ -34,6 +35,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -231,26 +234,133 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
return driver;
}
-PlatformEGLAndroid::ExternalImageEGLAndroid::~ExternalImageEGLAndroid() = default;
+PlatformEGLAndroid::ExternalImageEGLAndroid::~ExternalImageEGLAndroid() {
+ if (__builtin_available(android 26, *)) {
+ if (aHardwareBuffer) {
+ AHardwareBuffer_release(aHardwareBuffer);
+ }
+ }
+}
-Platform::ExternalImageHandle PlatformEGLAndroid::createExternalImage(AHardwareBuffer const* buffer, bool sRGB) noexcept {
- auto* const p = new(std::nothrow) ExternalImageEGLAndroid;
- p->aHardwareBuffer = const_cast(buffer);
- p->sRGB = sRGB;
- return ExternalImageHandle{ p };
+Platform::ExternalImageHandle PlatformEGLAndroid::createExternalImage(AHardwareBuffer const* buffer,
+ bool sRGB) noexcept {
+ if (__builtin_available(android 26, *)) {
+ auto* const p = new (std::nothrow) ExternalImageEGLAndroid;
+ auto hardwareBuffer = const_cast(buffer);
+ AHardwareBuffer_acquire(hardwareBuffer);
+ p->aHardwareBuffer = hardwareBuffer;
+ p->sRGB = sRGB;
+ AHardwareBuffer_Desc hardwareBufferDescription = {};
+ AHardwareBuffer_describe(hardwareBuffer, &hardwareBufferDescription);
+ p->height = hardwareBufferDescription.height;
+ p->width = hardwareBufferDescription.width;
+ auto textureFormat = mapToFilamentFormat(hardwareBufferDescription.format, sRGB);
+ p->usage = mapToFilamentUsage(hardwareBufferDescription.usage, textureFormat);
+ return ExternalImageHandle{ p };
+ }
+
+ return Platform::ExternalImageHandle{};
+}
+
+PlatformEGLAndroid::ExternalImageDescAndroid PlatformEGLAndroid::getExternalImageDesc(
+ ExternalImageHandle externalImage) noexcept {
+ auto const* const eglExternalImage =
+ static_cast(externalImage.get());
+ ExternalImageDescAndroid metadata = {};
+ if (!eglExternalImage) {
+ return metadata;
+ }
+ metadata.height = eglExternalImage->height;
+ metadata.width = eglExternalImage->width;
+ metadata.format = eglExternalImage->format;
+ metadata.usage = eglExternalImage->usage;
+ return metadata;
}
bool PlatformEGLAndroid::setExternalImage(ExternalImageHandleRef externalImage,
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
- auto const* const eglExternalImage = static_cast(externalImage.get());
+ auto const* const eglExternalImage =
+ static_cast(externalImage.get());
if (eglExternalImage->aHardwareBuffer) {
- // TODO: implement PlatformEGLAndroid::setExternalImage w/ AHardwareBuffer
- return true;
+ return PlatformEGLAndroid::setImage(eglExternalImage, texture);
}
// not a AHardwareBuffer, fallback to the inherited version
return PlatformEGL::setExternalImage(externalImage, texture);
}
+OpenGLPlatform::ExternalTexture* PlatformEGLAndroid::createExternalImageTexture() noexcept {
+ ExternalTexture* outTexture = new (std::nothrow) ExternalTexture{};
+ glGenTextures(1, &outTexture->id);
+ return outTexture;
+}
+
+void PlatformEGLAndroid::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
+ glDeleteTextures(1, &texture->id);
+ delete texture;
+}
+
+bool PlatformEGLAndroid::setImage(ExternalImageEGLAndroid const* eglExternalImage,
+ UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
+ AHardwareBuffer* hardwareBuffer = eglExternalImage->aHardwareBuffer;
+
+ // Get the EGL client buffer from AHardwareBuffer
+ EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
+ EGLint imageAttrs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE, EGL_NONE, // Reserve space
+ EGL_NONE, EGL_NONE, // Reserve space
+ EGL_NONE // Ensure the list always ends with EGL_NONE
+ };
+ int attrIndex = 2;
+ if (eglExternalImage->sRGB) {
+ imageAttrs[attrIndex++] = EGL_GL_COLORSPACE;
+ imageAttrs[attrIndex++] = EGL_GL_COLORSPACE_SRGB;
+ }
+
+ if (static_cast(eglExternalImage->usage & TextureUsage::PROTECTED)) {
+ imageAttrs[attrIndex++] = EGL_PROTECTED_CONTENT_EXT;
+ imageAttrs[attrIndex++] = EGL_TRUE;
+ }
+ // Create an EGLImage from the client buffer
+ EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+ if (eglImage == EGL_NO_IMAGE_KHR) {
+ // Handle error
+ slog.e << "Failed to create EGL image" << io::endl;
+ glDeleteTextures(1, &texture->id);
+ return false;
+ }
+
+ // Create and bind the OpenGL texture
+ GLint prevActiveTexture, prevTexture;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &prevActiveTexture);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTexture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->id);
+ GLenum error = glGetError();
+ if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
+ slog.e << "Error after glBindTexture: " << error << io::endl;
+ glDeleteTextures(1, &texture->id);
+ eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
+ glActiveTexture(prevActiveTexture);
+ glBindTexture(GL_TEXTURE_2D, prevTexture);
+ return false;
+ }
+ glEGLImageTargetTexture2DOES(texture->target, static_cast(eglImage));
+ error = glGetError();
+ if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
+ slog.e << "Error after glEGLImageTargetTexture2DOES: " << error << io::endl;
+ glDeleteTextures(1, &texture->id);
+ eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
+ glActiveTexture(prevActiveTexture);
+ glBindTexture(GL_TEXTURE_2D, prevTexture);
+ return false;
+ }
+ glActiveTexture(prevActiveTexture);
+ glBindTexture(GL_TEXTURE_2D, prevTexture);
+ return true;
+}
+
void PlatformEGLAndroid::setPresentationTime(int64_t presentationTimeInNanosecond) noexcept {
EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
if (currentDrawSurface != EGL_NO_SURFACE) {
diff --git a/filament/backend/src/opengl/platforms/PlatformGLX.cpp b/filament/backend/src/opengl/platforms/PlatformGLX.cpp
index f7a64bda62..c3b1a76ff8 100644
--- a/filament/backend/src/opengl/platforms/PlatformGLX.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformGLX.cpp
@@ -128,7 +128,7 @@ namespace filament::backend {
using namespace backend;
-Driver* PlatformGLX::createDriver(void* const sharedGLContext,
+Driver* PlatformGLX::createDriver(void* sharedGLContext,
const DriverConfig& driverConfig) noexcept {
loadLibraries();
// Get the display device
diff --git a/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp b/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp
index 831e30cc62..16d52de0d2 100644
--- a/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp
@@ -22,9 +22,11 @@
#include
#include
+#if defined(__linux__)
// This is to ensure that linking during compilation will not fail even if
// OSMesaGetProcAddress is not linked.
__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
+#endif
namespace filament::backend {
@@ -48,20 +50,27 @@ struct OSMesaSwapchain {
struct OSMesaAPI {
private:
- using CreateContextFunc = OSMesaContext (*)(GLenum format, OSMesaContext);
+ using CreateContextAttribsFunc = OSMesaContext (*)(const int *, OSMesaContext);
using DestroyContextFunc = GLboolean (*)(OSMesaContext);
using MakeCurrentFunc = GLboolean (*)(OSMesaContext ctx, void* buffer, GLenum type,
GLsizei width, GLsizei height);
using GetProcAddressFunc = OSMESAproc (*)(const char* funcName);
public:
- CreateContextFunc fOSMesaCreateContext;
+ CreateContextAttribsFunc fOSMesaCreateContextAttribs;
DestroyContextFunc fOSMesaDestroyContext;
MakeCurrentFunc fOSMesaMakeCurrent;
GetProcAddressFunc fOSMesaGetProcAddress;
OSMesaAPI() {
- constexpr char const* libraryNames[] = {"libOSMesa.so", "libosmesa.so"};
+ static constexpr char const* libraryNames[] = {
+#if defined(__linux__)
+ "libOSMesa.so",
+ "libosmesa.so",
+#elif defined(__APPLE__)
+ "libOSMesa.dylib",
+#endif
+ };
for (char const* libName: libraryNames) {
mLib = dlopen(libName, RTLD_GLOBAL | RTLD_NOW);
if (mLib) {
@@ -71,22 +80,24 @@ public:
if (mLib) {
// Loading from a libosmesa.os
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
- } else {
+ }
+#if defined(__linux__)
+ else {
// Filament is built into a .so
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
}
-
if (!fOSMesaGetProcAddress) {
// Statically linking osmesa
fOSMesaGetProcAddress = OSMesaGetProcAddress;
}
+#endif // __linux__
FILAMENT_CHECK_PRECONDITION(fOSMesaGetProcAddress)
<< "Unable to link against libOSMesa to create a software GL context";
- fOSMesaCreateContext = (CreateContextFunc) fOSMesaGetProcAddress("OSMesaCreateContext");
- fOSMesaDestroyContext =
- (DestroyContextFunc) fOSMesaGetProcAddress("OSMesaDestroyContext");
+ fOSMesaCreateContextAttribs =
+ (CreateContextAttribsFunc) fOSMesaGetProcAddress("OSMesaCreateContextAttribs");
+ fOSMesaDestroyContext = (DestroyContextFunc) fOSMesaGetProcAddress("OSMesaDestroyContext");
fOSMesaMakeCurrent = (MakeCurrentFunc) fOSMesaGetProcAddress("OSMesaMakeCurrent");
}
@@ -101,14 +112,24 @@ private:
}// anonymous namespace
-Driver* PlatformOSMesa::createDriver(void* const sharedGLContext,
+Driver* PlatformOSMesa::createDriver(void* sharedGLContext,
const DriverConfig& driverConfig) noexcept {
+
OSMesaAPI* api = new OSMesaAPI();
mOsMesaApi = api;
+ static constexpr int attribs[] = {
+ OSMESA_FORMAT, GL_RGBA,
+ OSMESA_DEPTH_BITS, 24,
+ OSMESA_STENCIL_BITS, 8,
+ OSMESA_ACCUM_BITS, 0,
+ OSMESA_PROFILE, OSMESA_CORE_PROFILE,
+ 0,
+ };
+
FILAMENT_CHECK_PRECONDITION(sharedGLContext == nullptr)
<< "shared GL context is not supported with PlatformOSMesa";
- mContext = api->fOSMesaCreateContext(GL_RGBA, NULL);
+ mContext = api->fOSMesaCreateContextAttribs(attribs, NULL);
// We need to do a no-op makecurrent here so that the context will be in a correct state before
// any GL calls.
diff --git a/filament/backend/src/opengl/platforms/PlatformWGL.cpp b/filament/backend/src/opengl/platforms/PlatformWGL.cpp
index 57c3e4668d..094ecf3e2c 100644
--- a/filament/backend/src/opengl/platforms/PlatformWGL.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformWGL.cpp
@@ -75,7 +75,7 @@ struct WGLSwapChain {
static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
-Driver* PlatformWGL::createDriver(void* const sharedGLContext,
+Driver* PlatformWGL::createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
int result = 0;
int pixelFormat = 0;
diff --git a/filament/backend/src/opengl/platforms/PlatformWebGL.cpp b/filament/backend/src/opengl/platforms/PlatformWebGL.cpp
index a6d4c5c5a2..4f522b2991 100644
--- a/filament/backend/src/opengl/platforms/PlatformWebGL.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformWebGL.cpp
@@ -20,7 +20,7 @@ namespace filament::backend {
using namespace backend;
-Driver* PlatformWebGL::createDriver(void* const sharedGLContext,
+Driver* PlatformWebGL::createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
}
diff --git a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp
similarity index 73%
rename from filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp
rename to filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp
index 570dcc5df2..eb89ad8eab 100644
--- a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp
+++ b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp
@@ -14,35 +14,25 @@
* limitations under the License.
*/
-#include "VulkanDescriptorSetManager.h"
+#include "VulkanDescriptorSetCache.h"
-#include "vulkan/VulkanCommands.h"
-#include "vulkan/VulkanHandles.h"
-#include "vulkan/VulkanConstants.h"
+#include "VulkanCommands.h"
+#include "VulkanHandles.h"
+#include "VulkanConstants.h"
#include
#include
-#include
-
#include
#include
-#include
#include
namespace filament::backend {
namespace {
-using BitmaskGroup = VulkanDescriptorSetLayout::Bitmask;
using DescriptorCount = VulkanDescriptorSetLayout::Count;
-using DescriptorSetLayoutArray = VulkanDescriptorSetManager::DescriptorSetLayoutArray;
-using BitmaskGroupHashFn = utils::hash::MurmurHashFn;
-struct BitmaskGroupEqual {
- bool operator()(BitmaskGroup const& k1, BitmaskGroup const& k2) const {
- return k1 == k2;
- }
-};
+using DescriptorSetLayoutArray = VulkanDescriptorSetCache::DescriptorSetLayoutArray;
// We create a pool for each layout as defined by the number of descriptors of each type. For
// example, a layout of
@@ -199,72 +189,12 @@ struct Equal {
}
};
-template
-uint32_t createBindings(VkDescriptorSetLayoutBinding* toBind, uint32_t count, VkDescriptorType type,
- Bitmask const& mask) {
- Bitmask alreadySeen;
- mask.forEachSetBit([&](size_t index) {
- VkShaderStageFlags stages = 0;
- uint32_t binding = 0;
- if (index < fvkutils::getFragmentStageShift()) {
- binding = (uint32_t) index;
- stages |= VK_SHADER_STAGE_VERTEX_BIT;
- auto fragIndex = index + fvkutils::getFragmentStageShift();
- if (mask.test(fragIndex)) {
- stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
- alreadySeen.set(fragIndex);
- }
- } else if (!alreadySeen.test(index)) {
- // We are in fragment stage bits
- binding = (uint32_t) (index - fvkutils::getFragmentStageShift());
- stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
- }
-
- if (stages) {
- toBind[count++] = {
- .binding = binding,
- .descriptorType = type,
- .descriptorCount = 1,
- .stageFlags = stages,
- };
- }
- });
- return count;
-}
-
-inline VkDescriptorSetLayout createLayout(VkDevice device, BitmaskGroup const& bitmaskGroup) {
- // Note that the following *needs* to be static so that VkDescriptorSetLayoutCreateInfo will not
- // refer to stack memory.
- VkDescriptorSetLayoutBinding toBind[VulkanDescriptorSetLayout::MAX_BINDINGS];
- uint32_t count = 0;
-
- count = createBindings(toBind, count, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- bitmaskGroup.dynamicUbo);
- count = createBindings(toBind, count, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bitmaskGroup.ubo);
- count = createBindings(toBind, count, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- bitmaskGroup.sampler);
- count = createBindings(toBind, count, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
- bitmaskGroup.inputAttachment);
-
- assert_invariant(count != 0 && "Need at least one binding for descriptor set layout.");
- VkDescriptorSetLayoutCreateInfo dlinfo = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .bindingCount = count,
- .pBindings = toBind,
- };
-
- VkDescriptorSetLayout layout;
- vkCreateDescriptorSetLayout(device, &dlinfo, VKALLOC, &layout);
- return layout;
-}
-
} // anonymous namespace
// This is an ever-expanding pool of sets where it
// 1. Keeps a list of smaller pools of different layout-dimensions.
// 2. Will add a pool if existing pool are not compatible with the requested layout o runs out.
-class VulkanDescriptorSetManager::DescriptorInfinitePool {
+class VulkanDescriptorSetCache::DescriptorInfinitePool {
private:
static constexpr uint16_t EXPECTED_SET_COUNT = 10;
static constexpr float SET_COUNT_GROWTH_FACTOR = 1.5;
@@ -319,61 +249,34 @@ private:
std::vector> mPools;
};
-class VulkanDescriptorSetManager::DescriptorSetLayoutManager {
-public:
- DescriptorSetLayoutManager(VkDevice device)
- : mDevice(device) {}
- VkDescriptorSetLayout getVkLayout(VulkanDescriptorSetLayout::Bitmask const& bitmasks) {
- if (auto itr = mVkLayouts.find(bitmasks); itr != mVkLayouts.end()) {
- return itr->second;
- }
- auto vklayout = createLayout(mDevice, bitmasks);
- mVkLayouts[bitmasks] = vklayout;
- return vklayout;
- }
-
- ~DescriptorSetLayoutManager() {
- for (auto& itr: mVkLayouts) {
- vkDestroyDescriptorSetLayout(mDevice, itr.second, VKALLOC);
- }
- }
-
-private:
- VkDevice mDevice;
- tsl::robin_map
- mVkLayouts;
-};
-
-VulkanDescriptorSetManager::VulkanDescriptorSetManager(VkDevice device,
+VulkanDescriptorSetCache::VulkanDescriptorSetCache(VkDevice device,
fvkmemory::ResourceManager* resourceManager)
: mDevice(device),
mResourceManager(resourceManager),
- mLayoutManager(std::make_unique(device)),
mDescriptorPool(std::make_unique(device)) {}
-VulkanDescriptorSetManager::~VulkanDescriptorSetManager() = default;
+VulkanDescriptorSetCache::~VulkanDescriptorSetCache() = default;
-void VulkanDescriptorSetManager::terminate() noexcept{
- mLayoutManager.reset();
+void VulkanDescriptorSetCache::terminate() noexcept{
mDescriptorPool.reset();
clearHistory();
}
// bind() is not really binding the set but just stashing until we have all the info
// (pipelinelayout).
-void VulkanDescriptorSetManager::bind(uint8_t setIndex,
+void VulkanDescriptorSetCache::bind(uint8_t setIndex,
fvkmemory::resource_ptr set,
backend::DescriptorSetOffsetArray&& offsets) {
set->setOffsets(std::move(offsets));
mStashedSets[setIndex] = set;
}
-void VulkanDescriptorSetManager::unbind(uint8_t setIndex) {
+void VulkanDescriptorSetCache::unbind(uint8_t setIndex) {
mStashedSets[setIndex] = {};
}
-void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands,
+void VulkanDescriptorSetCache::commit(VulkanCommandBuffer* commands,
VkPipelineLayout pipelineLayout, fvkutils::DescriptorSetMask const& setMask) {
// setMask indicates the set of descriptor sets the driver wants to bind, curMask is the
// actual set of sets that *needs* to be bound.
@@ -412,7 +315,7 @@ void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands,
};
}
-void VulkanDescriptorSetManager::updateBuffer(fvkmemory::resource_ptr set,
+void VulkanDescriptorSetCache::updateBuffer(fvkmemory::resource_ptr set,
uint8_t binding, fvkmemory::resource_ptr bufferObject,
VkDeviceSize offset, VkDeviceSize size) noexcept {
VkDescriptorBufferInfo const info = {
@@ -438,7 +341,7 @@ void VulkanDescriptorSetManager::updateBuffer(fvkmemory::resource_ptracquire(bufferObject);
}
-void VulkanDescriptorSetManager::updateSampler(fvkmemory::resource_ptr set,
+void VulkanDescriptorSetCache::updateSampler(fvkmemory::resource_ptr set,
uint8_t binding, fvkmemory::resource_ptr texture,
VkSampler sampler) noexcept {
VkDescriptorImageInfo info{
@@ -470,13 +373,13 @@ void VulkanDescriptorSetManager::updateSampler(fvkmemory::resource_ptracquire(texture);
}
-void VulkanDescriptorSetManager::updateInputAttachment(
+void VulkanDescriptorSetCache::updateInputAttachment(
fvkmemory::resource_ptr set,
VulkanAttachment const& attachment) noexcept {
- // TOOD: fill-in this region
+ // TOOD: fill this in.
}
-fvkmemory::resource_ptr VulkanDescriptorSetManager::createSet(
+fvkmemory::resource_ptr VulkanDescriptorSetCache::createSet(
Handle handle, fvkmemory::resource_ptr layout) {
auto const vkSet = mDescriptorPool->obtainSet(layout);
auto const& count = layout->count;
@@ -492,12 +395,7 @@ fvkmemory::resource_ptr VulkanDescriptorSetManager::createS
});
}
-void VulkanDescriptorSetManager::initVkLayout(
- fvkmemory::resource_ptr layout) {
- layout->setVkLayout(mLayoutManager->getVkLayout(layout->bitmask));
-}
-
-void VulkanDescriptorSetManager::clearHistory() {
+void VulkanDescriptorSetCache::clearHistory() {
mStashedSets = {};
}
diff --git a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h b/filament/backend/src/vulkan/VulkanDescriptorSetCache.h
similarity index 76%
rename from filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h
rename to filament/backend/src/vulkan/VulkanDescriptorSetCache.h
index 87aa076213..898b314be9 100644
--- a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h
+++ b/filament/backend/src/vulkan/VulkanDescriptorSetCache.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H
-#define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H
+#ifndef TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETCACHE_H
+#define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETCACHE_H
-#include "vulkan/VulkanHandles.h"
+#include "VulkanHandles.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Definitions.h" // For DescriptorSetMask
@@ -34,20 +34,16 @@
namespace filament::backend {
-// [GDSR]: Great-Descriptor-Set-Refactor: As of 03/20/24, the Filament frontend is planning to
-// introduce descriptor set. This PR will arrive before that change is complete. As such, some of
-// the methods introduced here will be obsolete, and certain logic will be generalized.
-
-// Abstraction over the pool and the layout cache.
-class VulkanDescriptorSetManager {
+// Abstraction over the descriptor set pool.
+class VulkanDescriptorSetCache {
public:
static constexpr uint8_t UNIQUE_DESCRIPTOR_SET_COUNT =
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT;
using DescriptorSetLayoutArray = VulkanDescriptorSetLayout::DescriptorSetLayoutArray;
- VulkanDescriptorSetManager(VkDevice device, fvkmemory::ResourceManager* resourceManager);
- ~VulkanDescriptorSetManager();
+ VulkanDescriptorSetCache(VkDevice device, fvkmemory::ResourceManager* resourceManager);
+ ~VulkanDescriptorSetCache();
void terminate() noexcept;
@@ -72,12 +68,9 @@ public:
fvkmemory::resource_ptr createSet(Handle handle,
fvkmemory::resource_ptr layout);
- void initVkLayout(fvkmemory::resource_ptr layout);
-
void clearHistory();
private:
- class DescriptorSetLayoutManager;
class DescriptorInfinitePool;
using DescriptorSetArray =
@@ -85,7 +78,6 @@ private:
VkDevice mDevice;
fvkmemory::ResourceManager* mResourceManager;
- std::unique_ptr mLayoutManager;
std::unique_ptr mDescriptorPool;
std::pair mInputAttachment;
DescriptorSetArray mStashedSets = {};
@@ -99,4 +91,4 @@ private:
}// namespace filament::backend
-#endif// TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H
+#endif// TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETCACHE_H
diff --git a/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.cpp b/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.cpp
new file mode 100644
index 0000000000..666827cd19
--- /dev/null
+++ b/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VulkanDescriptorSetLayoutCache.h"
+
+#include "VulkanHandles.h"
+
+namespace filament::backend {
+
+namespace {
+
+using BitmaskGroup = VulkanDescriptorSetLayout::Bitmask;
+
+template
+uint32_t appendBindings(VkDescriptorSetLayoutBinding* toBind, VkDescriptorType type,
+ Bitmask const& mask) {
+ uint32_t count = 0;
+ Bitmask alreadySeen;
+ mask.forEachSetBit([&](size_t index) {
+ VkShaderStageFlags stages = 0;
+ uint32_t binding = 0;
+ if (index < fvkutils::getFragmentStageShift()) {
+ binding = (uint32_t) index;
+ stages |= VK_SHADER_STAGE_VERTEX_BIT;
+ auto fragIndex = index + fvkutils::getFragmentStageShift();
+ if (mask.test(fragIndex)) {
+ stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
+ alreadySeen.set(fragIndex);
+ }
+ } else if (!alreadySeen.test(index)) {
+ // We are in fragment stage bits
+ binding = (uint32_t) (index - fvkutils::getFragmentStageShift());
+ stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
+ }
+
+ if (stages) {
+ toBind[count++] = {
+ .binding = binding,
+ .descriptorType = type,
+ .descriptorCount = 1,
+ .stageFlags = stages,
+ };
+ }
+ });
+ return count;
+}
+
+} // anonymous namespace
+
+VulkanDescriptorSetLayoutCache::VulkanDescriptorSetLayoutCache(VkDevice device,
+ fvkmemory::ResourceManager* resourceManager)
+ : mDevice(device),
+ mResourceManager(resourceManager) {}
+
+VulkanDescriptorSetLayoutCache::~VulkanDescriptorSetLayoutCache() = default;
+
+void VulkanDescriptorSetLayoutCache::terminate() noexcept {
+ for (auto& itr: mVkLayouts) {
+ vkDestroyDescriptorSetLayout(mDevice, itr.second, VKALLOC);
+ }
+}
+
+fvkmemory::resource_ptr VulkanDescriptorSetLayoutCache::createLayout(
+ Handle handle, backend::DescriptorSetLayout&& info) {
+ auto layout = fvkmemory::resource_ptr::make(mResourceManager, handle,
+ info);
+ VkDescriptorSetLayout vklayout = VK_NULL_HANDLE;
+ auto const& bitmasks = layout->bitmask;
+ if (auto itr = mVkLayouts.find(bitmasks); itr != mVkLayouts.end()) {
+ vklayout = itr->second;
+ } else {
+ VkDescriptorSetLayoutBinding toBind[VulkanDescriptorSetLayout::MAX_BINDINGS];
+ uint32_t count = 0;
+ count += appendBindings(&toBind[count], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ bitmasks.dynamicUbo);
+ count += appendBindings(&toBind[count], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bitmasks.ubo);
+ count += appendBindings(&toBind[count], VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ bitmasks.sampler);
+ count += appendBindings(&toBind[count], VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ bitmasks.inputAttachment);
+
+ assert_invariant(count != 0 && "Need at least one binding for descriptor set layout.");
+ VkDescriptorSetLayoutCreateInfo dlinfo = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .bindingCount = count,
+ .pBindings = toBind,
+ };
+
+ vkCreateDescriptorSetLayout(mDevice, &dlinfo, VKALLOC, &vklayout);
+ mVkLayouts[bitmasks] = vklayout;
+ }
+ layout->setVkLayout(vklayout);
+ return layout;
+}
+
+} // namespace filament::backend
diff --git a/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.h b/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.h
new file mode 100644
index 0000000000..a1f6461249
--- /dev/null
+++ b/filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETLAYOUTCACHE_H
+#define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETLAYOUTCACHE_H
+
+#include "VulkanHandles.h"
+
+#include "vulkan/memory/ResourcePointer.h"
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+namespace filament::backend {
+
+class VulkanDescriptorSetLayoutCache {
+public:
+ VulkanDescriptorSetLayoutCache(VkDevice device, fvkmemory::ResourceManager* resourceManager);
+ ~VulkanDescriptorSetLayoutCache();
+
+ void terminate() noexcept;
+
+ fvkmemory::resource_ptr createLayout(
+ Handle handle, backend::DescriptorSetLayout&& info);
+
+private:
+ VkDevice mDevice;
+ fvkmemory::ResourceManager* mResourceManager;
+
+ using BitmaskGroup = VulkanDescriptorSetLayout::Bitmask;
+ using BitmaskGroupHashFn = utils::hash::MurmurHashFn;
+ struct BitmaskGroupEqual {
+ bool operator()(BitmaskGroup const& k1, BitmaskGroup const& k2) const { return k1 == k2; }
+ };
+
+ tsl::robin_map
+ mVkLayouts;
+};
+
+} // namespace filament::backend
+
+#endif// TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETLAYOUTCACHE_H
diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp
index eb6629bafa..8cfadd3728 100644
--- a/filament/backend/src/vulkan/VulkanDriver.cpp
+++ b/filament/backend/src/vulkan/VulkanDriver.cpp
@@ -17,7 +17,6 @@
#include "VulkanDriver.h"
#include "CommandStreamDispatcher.h"
-#include "DataReshaper.h"
#include "SystraceProfile.h"
#include "VulkanAsyncHandles.h"
#include "VulkanBuffer.h"
@@ -35,7 +34,6 @@
#include
#include
-#include
#include
#ifndef NDEBUG
@@ -44,8 +42,6 @@
using namespace bluevk;
-using utils::FixedCapacityVector;
-
#if defined(__clang__)
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
// to a stack-allocated variable.
@@ -219,7 +215,8 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
mSamplerCache(mPlatform->getDevice()),
mBlitter(mPlatform->getPhysicalDevice(), &mCommands),
mReadPixels(mPlatform->getDevice()),
- mDescriptorSetManager(mPlatform->getDevice(), &mResourceManager),
+ mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager),
+ mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager),
mQueryManager(mPlatform->getDevice()),
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported),
mStereoscopicType(driverConfig.stereoscopicType) {
@@ -329,7 +326,8 @@ void VulkanDriver::terminate() {
mPipelineCache.terminate();
mFramebufferCache.reset();
mSamplerCache.terminate();
- mDescriptorSetManager.terminate();
+ mDescriptorSetLayoutCache.terminate();
+ mDescriptorSetCache.terminate();
mPipelineLayoutCache.terminate();
// Before terminating ResourceManager, we must make sure all of the resource_ptrs have been unset.
@@ -365,7 +363,7 @@ void VulkanDriver::collectGarbage() {
FVK_SYSTRACE_SCOPE();
// Command buffers need to be submitted and completed before other resources can be gc'd.
mCommands.gc();
- mDescriptorSetManager.clearHistory();
+ mDescriptorSetCache.clearHistory();
mStagePool.gc();
mFramebufferCache.gc();
mPipelineCache.gc();
@@ -408,7 +406,7 @@ void VulkanDriver::updateDescriptorSetBuffer(
FVK_SYSTRACE_SCOPE();
auto set = resource_ptr::cast(&mResourceManager, dsh);
auto buffer = resource_ptr::cast(&mResourceManager, boh);
- mDescriptorSetManager.updateBuffer(set, binding, buffer, offset, size);
+ mDescriptorSetCache.updateBuffer(set, binding, buffer, offset, size);
}
void VulkanDriver::updateDescriptorSetTexture(
@@ -421,7 +419,7 @@ void VulkanDriver::updateDescriptorSetTexture(
auto texture = resource_ptr::cast(&mResourceManager, th);
VkSampler const vksampler = mSamplerCache.getSampler(params);
- mDescriptorSetManager.updateSampler(set, binding, texture, vksampler);
+ mDescriptorSetCache.updateSampler(set, binding, texture, vksampler);
}
void VulkanDriver::flush(int) {
@@ -778,8 +776,7 @@ void VulkanDriver::createTimerQueryR(Handle tqh, int) {
void VulkanDriver::createDescriptorSetLayoutR(Handle dslh,
backend::DescriptorSetLayout&& info) {
- auto layout = resource_ptr::make(&mResourceManager, dslh, info);
- mDescriptorSetManager.initVkLayout(layout);
+ auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info));
layout.inc();
}
@@ -788,7 +785,7 @@ void VulkanDriver::createDescriptorSetR(Handle dsh,
FVK_SYSTRACE_SCOPE();
fvkmemory::resource_ptr layout =
fvkmemory::resource_ptr::cast(&mResourceManager, dslh);
- auto set = mDescriptorSetManager.createSet(dsh, layout);
+ auto set = mDescriptorSetCache.createSet(dsh, layout);
set.inc();
}
@@ -1493,7 +1490,7 @@ void VulkanDriver::nextSubpass(int) {
if (mCurrentRenderPass.params.subpassMask & 0x1) {
VulkanAttachment& subpassInput = renderTarget->getColor0();
- mDescriptorSetManager.updateInputAttachment({}, subpassInput);
+ mDescriptorSetCache.updateInputAttachment({}, subpassInput);
}
}
@@ -1820,9 +1817,9 @@ void VulkanDriver::bindDescriptorSet(
backend::DescriptorSetOffsetArray&& offsets) {
if (dsh) {
auto set = resource_ptr::cast(&mResourceManager, dsh);
- mDescriptorSetManager.bind(setIndex, set, std::move(offsets));
+ mDescriptorSetCache.bind(setIndex, set, std::move(offsets));
} else {
- mDescriptorSetManager.unbind(setIndex);
+ mDescriptorSetCache.unbind(setIndex);
}
}
@@ -1830,7 +1827,7 @@ void VulkanDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t ins
FVK_SYSTRACE_SCOPE();
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();
- mDescriptorSetManager.commit(mCurrentRenderPass.commandBuffer,
+ mDescriptorSetCache.commit(mCurrentRenderPass.commandBuffer,
mBoundPipeline.pipelineLayout,
mBoundPipeline.descriptorSetMask);
diff --git a/filament/backend/src/vulkan/VulkanDriver.h b/filament/backend/src/vulkan/VulkanDriver.h
index f488200abe..613e4d5a6c 100644
--- a/filament/backend/src/vulkan/VulkanDriver.h
+++ b/filament/backend/src/vulkan/VulkanDriver.h
@@ -27,8 +27,9 @@
#include "VulkanSamplerCache.h"
#include "VulkanStagePool.h"
#include "VulkanQueryManager.h"
-#include "vulkan/caching/VulkanDescriptorSetManager.h"
-#include "vulkan/caching/VulkanPipelineLayoutCache.h"
+#include "vulkan/VulkanDescriptorSetCache.h"
+#include "vulkan/VulkanDescriptorSetLayoutCache.h"
+#include "vulkan/VulkanPipelineLayoutCache.h"
#include "vulkan/memory/ResourceManager.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Definitions.h"
@@ -137,7 +138,8 @@ private:
VulkanSamplerCache mSamplerCache;
VulkanBlitter mBlitter;
VulkanReadPixels mReadPixels;
- VulkanDescriptorSetManager mDescriptorSetManager;
+ VulkanDescriptorSetLayoutCache mDescriptorSetLayoutCache;
+ VulkanDescriptorSetCache mDescriptorSetCache;
VulkanQueryManager mQueryManager;
// This is necessary for us to write to push constants after binding a pipeline.
diff --git a/filament/backend/src/vulkan/VulkanPipelineCache.cpp b/filament/backend/src/vulkan/VulkanPipelineCache.cpp
index 9260eaa14a..da5f36b92c 100644
--- a/filament/backend/src/vulkan/VulkanPipelineCache.cpp
+++ b/filament/backend/src/vulkan/VulkanPipelineCache.cpp
@@ -15,15 +15,12 @@
*/
#include "VulkanPipelineCache.h"
-#include "VulkanMemory.h"
-#include "caching/VulkanDescriptorSetManager.h"
#include
#include
#include "VulkanConstants.h"
#include "VulkanHandles.h"
-#include "VulkanTexture.h"
#include "vulkan/utils/Conversion.h"
#if defined(__clang__)
diff --git a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp b/filament/backend/src/vulkan/VulkanPipelineLayoutCache.cpp
similarity index 100%
rename from filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp
rename to filament/backend/src/vulkan/VulkanPipelineLayoutCache.cpp
diff --git a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h b/filament/backend/src/vulkan/VulkanPipelineLayoutCache.h
similarity index 98%
rename from filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h
rename to filament/backend/src/vulkan/VulkanPipelineLayoutCache.h
index 212ad60b0c..2f2a241d57 100644
--- a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h
+++ b/filament/backend/src/vulkan/VulkanPipelineLayoutCache.h
@@ -17,7 +17,8 @@
#ifndef TNT_FILAMENT_BACKEND_VULKANPIPELINELAYOUTCACHE_H
#define TNT_FILAMENT_BACKEND_VULKANPIPELINELAYOUTCACHE_H
-#include
+#include "VulkanHandles.h"
+
#include
#include
diff --git a/filament/backend/src/vulkan/platform/VulkanPlatform.cpp b/filament/backend/src/vulkan/platform/VulkanPlatform.cpp
index 6ad19912c7..87753d1438 100644
--- a/filament/backend/src/vulkan/platform/VulkanPlatform.cpp
+++ b/filament/backend/src/vulkan/platform/VulkanPlatform.cpp
@@ -1000,6 +1000,15 @@ VkImageView VulkanPlatform::createExternalImageView(SamplerYcbcrConversion chrom
return createExternalImageViewImpl(mImpl->mDevice, chroma, internalFormat, image, range,
viewType, swizzle);
}
+
+ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() const {
+ return getSwapchainInstanceExtensionsImpl();
+}
+
+VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
+ VkInstance instance, uint64_t flags) const noexcept {
+ return createVkSurfaceKHRImpl(nativeWindow, instance, flags);
+}
#undef SWAPCHAIN_RET_FUNC
}// namespace filament::backend
diff --git a/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp b/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp
index 9cdd3750ec..441004e995 100644
--- a/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp
+++ b/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include
+#include
#include
-#include
#include
#include "vulkan/VulkanConstants.h"
@@ -157,7 +156,7 @@ VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevic
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
};
- VkImageCreateInfo imageInfo{.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
+ VkImageCreateInfo imageInfo{ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
imageInfo.pNext = &externalCreateInfo;
imageInfo.format = metadata.format;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
@@ -200,14 +199,12 @@ VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevic
return data;
}
-} // namespace
+}// namespace
-namespace fvkandroid {
+VulkanPlatformAndroid::ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() = default;
-ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() = default;
-
-Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer,
- bool sRGB) noexcept {
+Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage(
+ AHardwareBuffer const* buffer, bool sRGB) noexcept {
if (__builtin_available(android 26, *)) {
AHardwareBuffer_Desc hardwareBufferDescription = {};
AHardwareBuffer_describe(buffer, &hardwareBufferDescription);
@@ -226,12 +223,23 @@ Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer,
return Platform::ExternalImageHandle{};
}
-} // namespace fvkandroid
-
-VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
- ExternalImageHandleRef externalImage, VkDevice device) {
+VulkanPlatformAndroid::ExternalImageDescAndroid VulkanPlatformAndroid::getExternalImageDesc(
+ ExternalImageHandleRef externalImage) const noexcept {
auto const* fvkExternalImage =
- static_cast(externalImage.get());
+ static_cast(externalImage.get());
+
+ return {
+ .width = fvkExternalImage->width,
+ .height = fvkExternalImage->height,
+ .format = fvkExternalImage->format,
+ .usage = fvkExternalImage->usage,
+ };
+}
+
+VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::getExternalImageMetadata(
+ ExternalImageHandleRef externalImage) {
+ auto const* fvkExternalImage =
+ static_cast(externalImage.get());
ExternalImageMetadata metadata;
AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer;
@@ -245,7 +253,7 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
std::tie(metadata.format, metadata.usage) =
getVKFormatAndUsage(bufferDesc, fvkExternalImage->sRGB);
}
-
+
metadata.samples = VK_SAMPLE_COUNT_1_BIT;
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = {
@@ -256,11 +264,11 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
.pNext = &formatInfo,
};
- VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID(device, buffer, &properties);
+ VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID(getDevice(), buffer, &properties);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
- << "vkGetAndroidHardwareBufferProperties failed with error="
- << static_cast(result);
-
+ << "vkGetAndroidHardwareBufferProperties failed with error="
+ << static_cast(result);
+
VkFormat bufferPropertiesFormat = transformVkFormat(formatInfo.format, fvkExternalImage->sRGB);
FILAMENT_CHECK_POSTCONDITION(metadata.format == bufferPropertiesFormat)
<< "mismatched image format( " << metadata.format << ") and queried format("
@@ -271,14 +279,14 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
return metadata;
}
-VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
- ExternalImageHandleRef externalImage, VkDevice device,
- const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
+VulkanPlatformAndroid::ImageData VulkanPlatformAndroid::createExternalImageData(
+ ExternalImageHandleRef externalImage, const ExternalImageMetadata& metadata,
+ uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
auto const* fvkExternalImage =
- static_cast(externalImage.get());
- ImageData data = allocateExternalImage(fvkExternalImage->aHardwareBuffer, device, metadata,
+ static_cast(externalImage.get());
+ ImageData data = allocateExternalImage(fvkExternalImage->aHardwareBuffer, getDevice(), metadata,
memoryTypeIndex, usage);
- VkResult result = vkBindImageMemory(device, data.first, data.second, 0);
+ VkResult result = vkBindImageMemory(getDevice(), data.first, data.second, 0);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
<< "vkBindImageMemory error=" << static_cast(result);
return data;
@@ -397,14 +405,14 @@ VkSampler VulkanPlatform::createExternalSamplerImpl(
return sampler;
}
-VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
+VulkanPlatform::ExtensionSet VulkanPlatformAndroid::getSwapchainInstanceExtensions() const {
return {
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
};
}
-VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
- VkInstance instance, uint64_t flags) noexcept {
+VulkanPlatform::SurfaceBundle VulkanPlatformAndroid::createVkSurfaceKHR(void* nativeWindow,
+ VkInstance instance, uint64_t flags) const noexcept {
VkSurfaceKHR surface;
VkExtent2D extent;
@@ -416,6 +424,26 @@ VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWin
vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC, (VkSurfaceKHR*) &surface);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
<< "vkCreateAndroidSurfaceKHR with error=" << static_cast(result);
- return {surface, extent};
+ return { surface, extent };
}
+
+// Deprecated platform dependent helper methods
+VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() { return {}; }
+
+VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
+ ExternalImageHandleRef externalImage, VkDevice device) {
+ return ExternalImageMetadata{};
}
+
+VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
+ ExternalImageHandleRef externalImage, VkDevice device,
+ const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
+ return ImageData{};
+}
+
+VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
+ VkInstance instance, uint64_t flags) noexcept {
+ return SurfaceBundle{};
+}
+
+}// namespace filament::backend
diff --git a/filament/backend/src/vulkan/platform/VulkanPlatformApple.mm b/filament/backend/src/vulkan/platform/VulkanPlatformApple.mm
index 9f28051cfb..c9e354f450 100644
--- a/filament/backend/src/vulkan/platform/VulkanPlatformApple.mm
+++ b/filament/backend/src/vulkan/platform/VulkanPlatformApple.mm
@@ -52,7 +52,7 @@ using namespace bluevk;
namespace filament::backend {
-VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
+VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() {
ExtensionSet const ret = {
#if defined(__APPLE__)
VK_MVK_MACOS_SURFACE_EXTENSION_NAME, // TODO: replace with VK_EXT_metal_surface
@@ -87,7 +87,7 @@ VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
return VK_NULL_HANDLE;
}
-VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
+VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
VkInstance instance, uint64_t flags) noexcept {
VkSurfaceKHR surface;
#if defined(__APPLE__)
diff --git a/filament/backend/src/vulkan/platform/VulkanPlatformLinuxWindows.cpp b/filament/backend/src/vulkan/platform/VulkanPlatformLinuxWindows.cpp
index cf2706fc96..d563317014 100644
--- a/filament/backend/src/vulkan/platform/VulkanPlatformLinuxWindows.cpp
+++ b/filament/backend/src/vulkan/platform/VulkanPlatformLinuxWindows.cpp
@@ -108,7 +108,7 @@ VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
return VK_NULL_HANDLE;
}
-VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
+VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() {
VulkanPlatform::ExtensionSet const ret = {
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
@@ -126,7 +126,7 @@ VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
return ret;
}
-VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
+VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
VkInstance instance, uint64_t flags) noexcept {
VkSurfaceKHR surface;
diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp
index c3eaeb7785..88a3a42c69 100644
--- a/filament/backend/src/webgpu/WebGPUDriver.cpp
+++ b/filament/backend/src/webgpu/WebGPUDriver.cpp
@@ -651,11 +651,11 @@ uint8_t WebGPUDriver::getMaxDrawBuffers() {
return MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
}
-size_t WebGPUDriver::getMaxUniformBufferSize(SamplerType) {
+size_t WebGPUDriver::getMaxUniformBufferSize() {
return 16384u;
}
-size_t WebGPUDriver::getMaxTextureSize() {
+size_t WebGPUDriver::getMaxTextureSize(SamplerType target) {
return 2048u;
}
diff --git a/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp b/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp
index e83acb0016..51d7d1ebf3 100644
--- a/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp
+++ b/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp
@@ -143,7 +143,7 @@ wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
return device;
}
-Driver* WebGPUPlatform::createDriver(void* const sharedContext,
+Driver* WebGPUPlatform::createDriver(void* sharedContext,
const Platform::DriverConfig& /*driverConfig*/) noexcept {
if (sharedContext) {
FWGPU_LOGW << "sharedContext is ignored/unused in the WebGPU backend. A non-null "
diff --git a/filament/backend/src/webgpu/platform/WebGPUPlatformLinux.cpp b/filament/backend/src/webgpu/platform/WebGPUPlatformLinux.cpp
index 16623891c9..00d1651e26 100644
--- a/filament/backend/src/webgpu/platform/WebGPUPlatformLinux.cpp
+++ b/filament/backend/src/webgpu/platform/WebGPUPlatformLinux.cpp
@@ -15,6 +15,8 @@
*/
#include
+#include
+
#include
#include
@@ -118,7 +120,9 @@ wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t flags)
if (useXcb) {
wgpu::SurfaceSourceXCBWindow surfaceSourceXcb{};
surfaceSourceXcb.connection = g_x11.connection;
- surfaceSourceXcb.window = reinterpret_cast(nativeWindow);
+
+ // TODO: this looks really wrong, please fix!!
+ surfaceSourceXcb.window = *((uint32_t*) nativeWindow);
wgpu::SurfaceDescriptor surfaceDescriptor{
.nextInChain = &surfaceSourceXcb,
.label = "linux_xcb_surface"
diff --git a/filament/include/filament/ColorGrading.h b/filament/include/filament/ColorGrading.h
index e5c8f3cae3..3e4916fbb2 100644
--- a/filament/include/filament/ColorGrading.h
+++ b/filament/include/filament/ColorGrading.h
@@ -64,9 +64,8 @@ class ColorSpace;
* Performance
* ===========
*
- * Creating a new ColorGrading object may be more expensive than other Filament objects as a
- * 3D LUT may need to be generated. The generation of a 3D LUT, if necessary, may happen on
- * the CPU.
+ * Creating a new ColorGrading object may be more expensive than other Filament objects as a LUT may
+ * need to be generated. The generation of this LUT, if necessary, may happen on the CPU.
*
* Ordering
* ========
@@ -155,6 +154,9 @@ public:
* 3D texture. For instance, a low quality level will use a 16x16x16 10 bit LUT, a medium
* quality level will use a 32x32x32 10 bit LUT, a high quality will use a 32x32x32 16 bit
* LUT, and a ultra quality will use a 64x64x64 16 bit LUT.
+ *
+ * This setting has no effect if generating a 1D LUT.
+ *
* This overrides the values set by format() and dimensions().
*
* The default quality is medium.
@@ -169,6 +171,8 @@ public:
* When color grading is implemented using a 3D LUT, this sets the texture format of
* of the LUT. This overrides the value set by quality().
*
+ * This setting has no effect if generating a 1D LUT.
+ *
* The default is INTEGER
*
* @param format The desired format of the 3D LUT.
@@ -181,6 +185,8 @@ public:
* When color grading is implemented using a 3D LUT, this sets the dimension of the LUT.
* This overrides the value set by quality().
*
+ * This setting has no effect if generating a 1D LUT.
+ *
* The default is 32
*
* @param dim The desired dimension of the LUT. Between 16 and 64.
diff --git a/filament/include/filament/ToneMapper.h b/filament/include/filament/ToneMapper.h
index e89e702c99..cff0576eef 100644
--- a/filament/include/filament/ToneMapper.h
+++ b/filament/include/filament/ToneMapper.h
@@ -68,6 +68,21 @@ struct UTILS_PUBLIC ToneMapper {
* function applied ("linear")
*/
virtual math::float3 operator()(math::float3 c) const noexcept = 0;
+
+ /**
+ * If true, then this function holds that f(x) = vec3(f(x.r), f(x.g), f(x.b))
+ *
+ * This may be used to indicate that the color grading's LUT only requires a 1D texture instead
+ * of a 3D texture, potentially saving a significant amount of memory and generation time.
+ */
+ virtual bool isOneDimensional() const noexcept { return false; }
+
+ /**
+ * True if this tonemapper only works in low-dynamic-range.
+ *
+ * This may be used to indicate that the color grading's LUT doesn't need to be log encoded.
+ */
+ virtual bool isLDR() const noexcept { return false; }
};
/**
@@ -79,6 +94,8 @@ struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
~LinearToneMapper() noexcept final;
math::float3 operator()(math::float3 c) const noexcept override;
+ bool isOneDimensional() const noexcept override { return true; }
+ bool isLDR() const noexcept override { return true; }
};
/**
@@ -91,6 +108,8 @@ struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
~ACESToneMapper() noexcept final;
math::float3 operator()(math::float3 c) const noexcept override;
+ bool isOneDimensional() const noexcept override { return false; }
+ bool isLDR() const noexcept override { return false; }
};
/**
@@ -104,6 +123,8 @@ struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
~ACESLegacyToneMapper() noexcept final;
math::float3 operator()(math::float3 c) const noexcept override;
+ bool isOneDimensional() const noexcept override { return false; }
+ bool isLDR() const noexcept override { return false; }
};
/**
@@ -117,6 +138,8 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
~FilmicToneMapper() noexcept final;
math::float3 operator()(math::float3 x) const noexcept override;
+ bool isOneDimensional() const noexcept override { return true; }
+ bool isLDR() const noexcept override { return false; }
};
/**
@@ -129,6 +152,8 @@ struct UTILS_PUBLIC PBRNeutralToneMapper final : public ToneMapper {
~PBRNeutralToneMapper() noexcept final;
math::float3 operator()(math::float3 x) const noexcept override;
+ bool isOneDimensional() const noexcept override { return false; }
+ bool isLDR() const noexcept override { return false; }
};
/**
@@ -150,6 +175,8 @@ struct UTILS_PUBLIC AgxToneMapper final : public ToneMapper {
~AgxToneMapper() noexcept final;
math::float3 operator()(math::float3 x) const noexcept override;
+ bool isOneDimensional() const noexcept override { return false; }
+ bool isLDR() const noexcept override { return false; }
AgxLook look;
};
@@ -194,6 +221,8 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
GenericToneMapper& operator=(GenericToneMapper&& rhs) noexcept;
math::float3 operator()(math::float3 x) const noexcept override;
+ bool isOneDimensional() const noexcept override { return true; }
+ bool isLDR() const noexcept override { return false; }
/** Returns the contrast of the curve as a strictly positive value. */
float getContrast() const noexcept;
@@ -256,6 +285,8 @@ struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
~DisplayRangeToneMapper() noexcept override;
math::float3 operator()(math::float3 c) const noexcept override;
+ bool isOneDimensional() const noexcept override { return false; }
+ bool isLDR() const noexcept override { return false; }
};
} // namespace filament
diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp
index 469c0122ed..78b78e770a 100644
--- a/filament/src/PostProcessManager.cpp
+++ b/filament/src/PostProcessManager.cpp
@@ -2306,36 +2306,11 @@ void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver,
const FColorGrading* colorGrading, ColorGradingConfig const& colorGradingConfig,
VignetteOptions const& vignetteOptions, uint32_t const width, uint32_t const height) noexcept {
- float4 const vignetteParameters = getVignetteParameters(vignetteOptions, width, height);
-
- auto const& material = getPostProcessMaterial("colorGradingAsSubpass");
- FMaterialInstance* const mi = PostProcessMaterial::getMaterialInstance(mEngine, material);
-
- mi->setParameter("lut", colorGrading->getHwHandle(), {
- .filterMag = SamplerMagFilter::LINEAR,
- .filterMin = SamplerMinFilter::LINEAR,
- .wrapS = SamplerWrapMode::CLAMP_TO_EDGE,
- .wrapT = SamplerWrapMode::CLAMP_TO_EDGE,
- .wrapR = SamplerWrapMode::CLAMP_TO_EDGE,
- .anisotropyLog2 = 0
- });
- const float lutDimension = float(colorGrading->getDimension());
- mi->setParameter("lutSize", float2{
- 0.5f / lutDimension, (lutDimension - 1.0f) / lutDimension,
- });
-
- const float temporalNoise = mUniformDistribution(mEngine.getRandomEngine());
-
- mi->setParameter("vignette", vignetteParameters);
- mi->setParameter("vignetteColor", vignetteOptions.color);
- mi->setParameter("dithering", colorGradingConfig.dithering);
- mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
- mi->setParameter("temporalNoise", temporalNoise);
+ auto& material = getPostProcessMaterial("colorGradingAsSubpass");
+ FMaterialInstance* const mi =
+ configureColorGradingMaterial(material, colorGrading, colorGradingConfig,
+ vignetteOptions, width, height);
mi->commit(driver);
-
- // load both variants
- material.getMaterial(mEngine, PostProcessVariant::OPAQUE);
- material.getMaterial(mEngine, PostProcessVariant::TRANSLUCENT);
}
void PostProcessManager::colorGradingSubpass(DriverApi& driver,
@@ -2487,22 +2462,14 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg,
auto const& out = resources.getRenderPassInfo();
- auto const& material = getPostProcessMaterial("colorGrading");
-
- PostProcessVariant const variant = colorGradingConfig.translucent ?
- PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
+ auto const& input = resources.getDescriptor(data.input);
+ auto const& output = resources.getDescriptor(data.output);
+ auto& material = getPostProcessMaterial("colorGrading");
FMaterialInstance* const mi =
- PostProcessMaterial::getMaterialInstance(mEngine, material, variant);
+ configureColorGradingMaterial(material, colorGrading, colorGradingConfig,
+ vignetteOptions, output.width, output.height);
- mi->setParameter("lut", colorGrading->getHwHandle(), {
- .filterMag = SamplerMagFilter::LINEAR,
- .filterMin = SamplerMinFilter::LINEAR
- });
- const float lutDimension = float(colorGrading->getDimension());
- mi->setParameter("lutSize", float2{
- 0.5f / lutDimension, (lutDimension - 1.0f) / lutDimension,
- });
mi->setParameter("colorBuffer", colorTexture, { /* shader uses texelFetch */ });
mi->setParameter("bloomBuffer", bloomTexture, {
.filterMag = SamplerMagFilter::LINEAR,
@@ -2534,19 +2501,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg,
bloomParameters.y = 1.0f - bloomParameters.x;
}
- auto const& input = resources.getDescriptor(data.input);
- auto const& output = resources.getDescriptor(data.output);
- float4 const vignetteParameters = getVignetteParameters(
- vignetteOptions, output.width, output.height);
-
- const float temporalNoise = mUniformDistribution(mEngine.getRandomEngine());
-
- mi->setParameter("dithering", colorGradingConfig.dithering);
mi->setParameter("bloom", bloomParameters);
- mi->setParameter("vignette", vignetteParameters);
- mi->setParameter("vignetteColor", vignetteOptions.color);
- mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
- mi->setParameter("temporalNoise", temporalNoise);
mi->setParameter("viewport", float4{
float(vp.left) / input.width,
float(vp.bottom) / input.height,
@@ -2554,7 +2509,9 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg,
float(vp.height) / input.height
});
- commitAndRenderFullScreenQuad(driver, out, mi, variant);
+ commitAndRenderFullScreenQuad(driver, out, mi,
+ colorGradingConfig.translucent
+ ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE);
}
);
@@ -2692,11 +2649,70 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial(
setConstantParameter(ma, "varianceGamma", taaOptions.varianceGamma);
if (dirty) {
ma->invalidate();
- // TODO: call Material::compile(), we can't si that now because it works only
+ // TODO: call Material::compile(), we can't do that now because it works only
// with surface materials
}
}
+FMaterialInstance* PostProcessManager::configureColorGradingMaterial(
+ PostProcessMaterial& material, FColorGrading const* colorGrading,
+ ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions,
+ uint32_t const width, uint32_t const height) noexcept {
+ FMaterial* const ma = material.getMaterial(mEngine);
+ bool dirty = false;
+
+ auto setConstantParameter =
+ [&dirty](FMaterial* const material, std::string_view const name, auto value) noexcept {
+ auto id = material->getSpecializationConstantId(name);
+ if (id.has_value()) {
+ if (material->setConstant(id.value(), value)) {
+ dirty = true;
+ }
+ }
+ };
+
+ setConstantParameter(ma, "isOneDimensional", colorGrading->isOneDimensional());
+ setConstantParameter(ma, "isLDR", colorGrading->isLDR());
+
+ if (dirty) {
+ ma->invalidate();
+ // TODO: call Material::compile(), we can't do that now because it works only
+ // with surface materials
+ }
+
+ PostProcessVariant const variant = colorGradingConfig.translucent ?
+ PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
+ FMaterialInstance* const mi =
+ PostProcessMaterial::getMaterialInstance(mEngine, material, variant);
+
+ const SamplerParams params = {
+ .filterMag = SamplerMagFilter::LINEAR,
+ .filterMin = SamplerMinFilter::LINEAR,
+ .wrapS = SamplerWrapMode::CLAMP_TO_EDGE,
+ .wrapT = SamplerWrapMode::CLAMP_TO_EDGE,
+ .wrapR = SamplerWrapMode::CLAMP_TO_EDGE,
+ .anisotropyLog2 = 0
+ };
+
+ mi->setParameter("lut", colorGrading->getHwHandle(), params);
+
+ const float lutDimension = float(colorGrading->getDimension());
+ mi->setParameter("lutSize", float2{
+ 0.5f / lutDimension, (lutDimension - 1.0f) / lutDimension,
+ });
+
+ const float temporalNoise = mUniformDistribution(mEngine.getRandomEngine());
+
+ float4 const vignetteParameters = getVignetteParameters(vignetteOptions, width, height);
+ mi->setParameter("vignette", vignetteParameters);
+ mi->setParameter("vignetteColor", vignetteOptions.color);
+ mi->setParameter("dithering", colorGradingConfig.dithering);
+ mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
+ mi->setParameter("temporalNoise", temporalNoise);
+
+ return mi;
+}
+
FrameGraphId PostProcessManager::taa(FrameGraph& fg,
FrameGraphId input,
FrameGraphId const depth,
diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h
index 677cec30cb..09a6bb52ae 100644
--- a/filament/src/PostProcessManager.h
+++ b/filament/src/PostProcessManager.h
@@ -401,6 +401,13 @@ public:
FMaterialInstance const* mi,
PostProcessVariant variant = PostProcessVariant::OPAQUE) const noexcept;
+ // Sets the necessary spec constants and uniforms common to both colorGrading.mat and
+ // colorGradingAsSubpass.mat.
+ FMaterialInstance* configureColorGradingMaterial(
+ PostProcessMaterial& material, FColorGrading const* colorGrading,
+ ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions,
+ uint32_t const width, uint32_t const height) noexcept;
+
private:
backend::RenderPrimitiveHandle mFullScreenQuadRph;
backend::VertexBufferInfoHandle mFullScreenQuadVbih;
diff --git a/filament/src/details/ColorGrading.cpp b/filament/src/details/ColorGrading.cpp
index a1077f771b..939f0cbbbc 100644
--- a/filament/src/details/ColorGrading.cpp
+++ b/filament/src/details/ColorGrading.cpp
@@ -35,7 +35,6 @@
#include
#include
-#include
#include
namespace filament {
@@ -581,8 +580,11 @@ static float3 luminanceScaling(float3 x,
// Quality
//------------------------------------------------------------------------------
-static std::tuple
- selectLutTextureParams(ColorGrading::LutFormat const lutFormat) noexcept {
+static std::tuple selectLutTextureParams(
+ ColorGrading::LutFormat const lutFormat, const bool isOneDimensional) noexcept {
+ if (isOneDimensional) {
+ return { TextureFormat::R16F, PixelDataFormat::R, PixelDataType::HALF };
+ }
// We use RGBA16F for high quality modes instead of RGB16F because RGB16F
// is not supported everywhere
switch (lutFormat) {
@@ -658,27 +660,43 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
DriverApi& driver = engine.getDriverApi();
- Config c;
- // This lock protects the data inside Config, which is written to by the Filament thread,
- // and read from multiple Job threads.
- Mutex configLock;
- {
- std::lock_guard const lock(configLock);
- c.lutDimension = builder->dimension;
- c.adaptationTransform = adaptationTransform(builder->whiteBalance);
- c.colorGradingIn = selectColorGradingTransformIn(builder->toneMapping);
- c.colorGradingOut = selectColorGradingTransformOut(builder->toneMapping);
- c.colorGradingLuminance = selectColorGradingLuminance(builder->toneMapping);
- c.oetf = selectOETF(builder->outputColorSpace);
+ // XXX: The following two conditions also only hold true as long as the input and output color
+ // spaces are the same, but we currently don't check that. We must revise these conditions if we
+ // ever handle this case.
+ mIsOneDimensional = !builder->hasAdjustments && !builder->luminanceScaling
+ && builder->toneMapper->isOneDimensional();
+ mIsLDR = mIsOneDimensional && builder->toneMapper->isLDR();
+
+ const Config config = {
+ mIsOneDimensional ? 512u : builder->dimension,
+ adaptationTransform(builder->whiteBalance),
+ selectColorGradingTransformIn(builder->toneMapping),
+ selectColorGradingTransformOut(builder->toneMapping),
+ selectColorGradingLuminance(builder->toneMapping),
+ selectOETF(builder->outputColorSpace),
+ };
+
+ mDimension = config.lutDimension;
+
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
+ if (mIsOneDimensional) {
+ width = config.lutDimension;
+ height = 1;
+ depth = 1;
+ } else {
+ width = config.lutDimension;
+ height = config.lutDimension;
+ depth = config.lutDimension;
}
- mDimension = c.lutDimension;
-
- size_t lutElementCount = c.lutDimension * c.lutDimension * c.lutDimension;
- size_t elementSize = sizeof(half4);
+ size_t lutElementCount = width * height * depth;
+ size_t elementSize = mIsOneDimensional ? sizeof(half) : sizeof(half4);
void* data = malloc(lutElementCount * elementSize);
- auto [textureFormat, format, type] = selectLutTextureParams(builder->format);
+ auto [textureFormat, format, type] =
+ selectLutTextureParams(builder->format, mIsOneDimensional);
assert_invariant(FTexture::isTextureFormatSupported(engine, textureFormat));
assert_invariant(FTexture::validatePixelFormatAndType(textureFormat, format, type));
@@ -688,170 +706,185 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
converted = malloc(lutElementCount * sizeof(uint32_t));
}
+ auto hdrColorAt = [builder, config](size_t r, size_t g, size_t b) {
+ float3 v = float3{r, g, b} * (1.0f / float(config.lutDimension - 1u));
+
+ // LogC encoding
+ v = LogC_to_linear(v);
+
+ // Kill negative values near 0.0f due to imprecision in the log conversion
+ v = max(v, 0.0f);
+
+ if (builder->hasAdjustments) {
+ // Exposure
+ v = adjustExposure(v, builder->exposure);
+
+ // Purkinje shift ("low-light" vision)
+ v = scotopicAdaptation(v, builder->nightAdaptation);
+ }
+
+ // Move to color grading color space
+ v = config.colorGradingIn * v;
+
+ if (builder->hasAdjustments) {
+ // White balance
+ v = chromaticAdaptation(v, config.adaptationTransform);
+
+ // Kill negative values before the next transforms
+ v = max(v, 0.0f);
+
+ // Channel mixer
+ v = channelMixer(v, builder->outRed, builder->outGreen, builder->outBlue);
+
+ // Shadows/mid-tones/highlights
+ v = tonalRanges(v, config.colorGradingLuminance,
+ builder->shadows, builder->midtones, builder->highlights,
+ builder->tonalRanges);
+
+ // The adjustments below behave better in log space
+ v = linear_to_LogC(v);
+
+ // ASC CDL
+ v = colorDecisionList(v, builder->slope, builder->offset, builder->power);
+
+ // Contrast in log space
+ v = contrast(v, builder->contrast);
+
+ // Back to linear space
+ v = LogC_to_linear(v);
+
+ // Vibrance in linear space
+ v = vibrance(v, config.colorGradingLuminance, builder->vibrance);
+
+ // Saturation in linear space
+ v = saturation(v, config.colorGradingLuminance, builder->saturation);
+
+ // Kill negative values before curves
+ v = max(v, 0.0f);
+
+ // RGB curves
+ v = curves(v,
+ builder->shadowGamma, builder->midPoint, builder->highlightScale);
+ }
+
+ // Tone mapping
+ if (builder->luminanceScaling) {
+ v = luminanceScaling(v, *builder->toneMapper, config.colorGradingLuminance);
+ } else {
+ v = (*builder->toneMapper)(v);
+ }
+
+ // Go back to display color space
+ v = config.colorGradingOut * v;
+
+ // Apply gamut mapping
+ if (builder->gamutMapping) {
+ // TODO: This should depend on the output color space
+ v = gamutMapping_sRGB(v);
+ }
+
+ // TODO: We should convert to the output color space if we use a working
+ // color space that's not sRGB
+ // TODO: Allow the user to customize the output color space
+
+ // We need to clamp for the output transfer function
+ v = saturate(v);
+
+ // Apply OETF
+ v = config.oetf(v);
+
+ return v;
+ };
+
//auto now = std::chrono::steady_clock::now();
- // Multithreadedly generate the tone mapping 3D look-up table using 32 jobs
- // Slices are 8 KiB (128 cache lines) apart.
- // This takes about 3-6ms on Android in Release
- JobSystem& js = engine.getJobSystem();
- auto *slices = js.createJob();
- for (size_t b = 0; b < c.lutDimension; b++) {
- auto *job = js.createJob(slices,
- [data, converted, b, &c, &configLock, builder](JobSystem&, JobSystem::Job*) {
- Config config;
- {
- std::lock_guard lock(configLock);
- config = c;
+ if (mIsOneDimensional) {
+ half* UTILS_RESTRICT p = (half*) data;
+ if (mIsLDR) {
+ for (size_t rgb = 0; rgb < config.lutDimension; rgb++) {
+ float3 v = float3(rgb) * (1.0f / float(config.lutDimension - 1u));
+
+ v = (*builder->toneMapper)(float3(v));
+
+ // We need to clamp for the output transfer function
+ v = saturate(v);
+
+ // Apply OETF
+ v = config.oetf(v);
+
+ *p++ = half(v.r);
}
- half4* UTILS_RESTRICT p = (half4*) data + b * config.lutDimension * config.lutDimension;
- for (size_t g = 0; g < config.lutDimension; g++) {
- for (size_t r = 0; r < config.lutDimension; r++) {
- float3 v = float3{r, g, b} * (1.0f / float(config.lutDimension - 1u));
-
- // LogC encoding
- v = LogC_to_linear(v);
-
- // Kill negative values near 0.0f due to imprecision in the log conversion
- v = max(v, 0.0f);
-
- if (builder->hasAdjustments) {
- // Exposure
- v = adjustExposure(v, builder->exposure);
-
- // Purkinje shift ("low-light" vision)
- v = scotopicAdaptation(v, builder->nightAdaptation);
+ } else {
+ for (size_t rgb = 0; rgb < config.lutDimension; rgb++) {
+ *p++ = half(hdrColorAt(rgb, rgb, rgb).r);
+ }
+ }
+ } else {
+ // Multithreadedly generate the tone mapping 3D look-up table using 32 jobs
+ // Slices are 8 KiB (128 cache lines) apart.
+ // This takes about 3-6ms on Android in Release
+ JobSystem& js = engine.getJobSystem();
+ auto *slices = js.createJob();
+ for (size_t b = 0; b < config.lutDimension; b++) {
+ auto* job = js.createJob(slices,
+ [data, converted, b, &config, builder, &hdrColorAt](
+ JobSystem&, JobSystem::Job*) {
+ half4* UTILS_RESTRICT p =
+ (half4*) data + b * config.lutDimension * config.lutDimension;
+ for (size_t g = 0; g < config.lutDimension; g++) {
+ for (size_t r = 0; r < config.lutDimension; r++) {
+ *p++ = half4{hdrColorAt(r, g, b), 0.0f};
}
-
- // Move to color grading color space
- v = c.colorGradingIn * v;
-
- if (builder->hasAdjustments) {
- // White balance
- v = chromaticAdaptation(v, config.adaptationTransform);
-
- // Kill negative values before the next transforms
- v = max(v, 0.0f);
-
- // Channel mixer
- v = channelMixer(v, builder->outRed, builder->outGreen, builder->outBlue);
-
- // Shadows/mid-tones/highlights
- v = tonalRanges(v, c.colorGradingLuminance,
- builder->shadows, builder->midtones, builder->highlights,
- builder->tonalRanges);
-
- // The adjustments below behave better in log space
- v = linear_to_LogC(v);
-
- // ASC CDL
- v = colorDecisionList(v, builder->slope, builder->offset, builder->power);
-
- // Contrast in log space
- v = contrast(v, builder->contrast);
-
- // Back to linear space
- v = LogC_to_linear(v);
-
- // Vibrance in linear space
- v = vibrance(v, c.colorGradingLuminance, builder->vibrance);
-
- // Saturation in linear space
- v = saturation(v, c.colorGradingLuminance, builder->saturation);
-
- // Kill negative values before curves
- v = max(v, 0.0f);
-
- // RGB curves
- v = curves(v,
- builder->shadowGamma, builder->midPoint, builder->highlightScale);
- }
-
- // Tone mapping
- if (builder->luminanceScaling) {
- v = luminanceScaling(v, *builder->toneMapper, c.colorGradingLuminance);
- } else {
- v = (*builder->toneMapper)(v);
- }
-
- // Go back to display color space
- v = c.colorGradingOut * v;
-
- // Apply gamut mapping
- if (builder->gamutMapping) {
- // TODO: This should depend on the output color space
- v = gamutMapping_sRGB(v);
- }
-
- // TODO: We should convert to the output color space if we use a working
- // color space that's not sRGB
- // TODO: Allow the user to customize the output color space
-
- // We need to clamp for the output transfer function
- v = saturate(v);
-
- // Apply OETF
- v = c.oetf(v);
-
- *p++ = half4{v, 0.0f};
}
- }
- if (converted) {
- uint32_t* const UTILS_RESTRICT dst = (uint32_t*) converted +
- b * config.lutDimension * config.lutDimension;
- half4* UTILS_RESTRICT src = (half4*) data +
- b * config.lutDimension * config.lutDimension;
- // we use a vectorize width of 8 because, on ARMv8 it allows the compiler to write eight
- // 32-bits results in one go.
- const size_t count = (config.lutDimension * config.lutDimension) & ~0x7u; // tell the compiler that we're a multiple of 8
+ if (converted) {
+ uint32_t* const UTILS_RESTRICT dst = (uint32_t*) converted +
+ b * config.lutDimension * config.lutDimension;
+ half4* UTILS_RESTRICT src = (half4*) data +
+ b * config.lutDimension * config.lutDimension;
+ // we use a vectorize width of 8 because, on ARMv8 it allows the compiler to
+ // write eight 32-bits results in one go.
+ const size_t count = (config.lutDimension * config.lutDimension) & ~0x7u; // tell the compiler that we're a multiple of 8
#if defined(__clang__)
- #pragma clang loop vectorize_width(8)
+#pragma clang loop vectorize_width(8)
#endif
- for (size_t i = 0; i < count; ++i) {
- float4 v{src[i]};
- uint32_t pr = uint32_t(std::floor(v.x * 1023.0f + 0.5f));
- uint32_t pg = uint32_t(std::floor(v.y * 1023.0f + 0.5f));
- uint32_t pb = uint32_t(std::floor(v.z * 1023.0f + 0.5f));
- dst[i] = (pb << 20u) | (pg << 10u) | pr;
+ for (size_t i = 0; i < count; ++i) {
+ float4 v{src[i]};
+ uint32_t pr = uint32_t(std::floor(v.x * 1023.0f + 0.5f));
+ uint32_t pg = uint32_t(std::floor(v.y * 1023.0f + 0.5f));
+ uint32_t pb = uint32_t(std::floor(v.z * 1023.0f + 0.5f));
+ dst[i] = (pb << 20u) | (pg << 10u) | pr;
+ }
}
- }
+ });
+ js.run(job);
+ }
- });
- js.run(job);
+ // TODO: Should we do a runAndRetain() and defer the wait() + texture creation until
+ // getHwHandle() is invoked?
+ js.runAndWait(slices);
}
- // TODO: Should we do a runAndRetain() and defer the wait() + texture creation until
- // getHwHandle() is invoked?
- js.runAndWait(slices);
-
//std::chrono::duration duration = std::chrono::steady_clock::now() - now;
//slog.d << "LUT generation time: " << duration.count() << " ms" << io::endl;
- mLutHandle = driver.createTexture(
- SamplerType::SAMPLER_3D,
- 1,
- textureFormat,
- 1,
- c.lutDimension,
- c.lutDimension,
- c.lutDimension,
- TextureUsage::DEFAULT
- );
-
if (converted) {
free(data);
data = converted;
elementSize = sizeof(uint32_t);
}
+ // Create texture.
+ mLutHandle = driver.createTexture(SamplerType::SAMPLER_3D, 1, textureFormat, 1,
+ width, height, depth, TextureUsage::DEFAULT);
+
driver.update3DImage(mLutHandle, 0,
0, 0, 0,
- c.lutDimension, c.lutDimension, c.lutDimension,
+ width, height, depth,
PixelBufferDescriptor{
- data, lutElementCount * elementSize,format, type,
- [](void* buffer, size_t, void*) { free(buffer); }
- }
- );
+ data, lutElementCount * elementSize, format, type,
+ [](void* buffer, size_t, void*) { free(buffer); }
+ });
}
FColorGrading::~FColorGrading() noexcept = default;
diff --git a/filament/src/details/ColorGrading.h b/filament/src/details/ColorGrading.h
index e224b5cace..5ac65c129f 100644
--- a/filament/src/details/ColorGrading.h
+++ b/filament/src/details/ColorGrading.h
@@ -42,12 +42,15 @@ public:
void terminate(FEngine& engine);
backend::TextureHandle getHwHandle() const noexcept { return mLutHandle; }
-
uint32_t getDimension() const noexcept { return mDimension; }
+ bool isOneDimensional() const noexcept { return mIsOneDimensional; }
+ bool isLDR() const noexcept { return mIsLDR; }
private:
backend::TextureHandle mLutHandle;
uint32_t mDimension;
+ bool mIsOneDimensional;
+ bool mIsLDR;
};
FILAMENT_DOWNCAST(ColorGrading)
diff --git a/filament/src/details/Texture.cpp b/filament/src/details/Texture.cpp
index e9becb0ec7..8a367a2fd3 100644
--- a/filament/src/details/Texture.cpp
+++ b/filament/src/details/Texture.cpp
@@ -153,9 +153,10 @@ Texture::Builder& Texture::Builder::name(const char* name, size_t const len) noe
}
Texture* Texture::Builder::build(Engine& engine) {
- FILAMENT_CHECK_PRECONDITION(Texture::isTextureFormatSupported(engine, mImpl->mFormat))
- << "Texture format " << uint16_t(mImpl->mFormat) << " not supported on this platform";
-
+ if (mImpl->mTarget != SamplerType::SAMPLER_EXTERNAL) {
+ FILAMENT_CHECK_PRECONDITION(Texture::isTextureFormatSupported(engine, mImpl->mFormat))
+ << "Texture format " << uint16_t(mImpl->mFormat) << " not supported on this platform";
+ }
const bool isProtectedTexturesSupported =
downcast(engine).getDriverApi().isProtectedTexturesSupported();
const bool useProtectedMemory = bool(mImpl->mUsage & TextureUsage::PROTECTED);
diff --git a/filament/src/materials/colorGrading/colorGrading.fs b/filament/src/materials/colorGrading/colorGrading.fs
index 2b2000142d..195b3ff749 100644
--- a/filament/src/materials/colorGrading/colorGrading.fs
+++ b/filament/src/materials/colorGrading/colorGrading.fs
@@ -1,13 +1,29 @@
-vec3 colorGrade(mediump sampler3D lut, const vec3 x) {
+vec3 LogC_to_linear(const vec3 x) {
// Alexa LogC EI 1000
const float a = 5.555556;
const float b = 0.047996;
const float c = 0.244161 / log2(10.0);
const float d = 0.386036;
- vec3 logc = c * log2(a * x + b) + d;
+ return c * log2(a * x + b) + d;
+}
- // Remap to sample pixel centers
- logc = materialParams.lutSize.x + logc * materialParams.lutSize.y;
+vec3 colorGrade3D(mediump sampler3D lut, const vec3 v) {
+ return textureLod(lut, v, 0.0).rgb;
+}
- return textureLod(lut, logc, 0.0).rgb;
+vec3 colorGrade1D(mediump sampler3D lut, const vec3 v) {
+ return vec3(
+ textureLod(lut, vec3(v.r, 0.5, 0.5), 0.0).r,
+ textureLod(lut, vec3(v.g, 0.5, 0.5), 0.0).r,
+ textureLod(lut, vec3(v.b, 0.5, 0.5), 0.0).r);
+}
+
+vec3 colorGrade(mediump sampler3D lut, vec3 v) {
+ if (!materialConstants_isLDR) {
+ v = LogC_to_linear(v);
+ }
+ // Remap to sample pixel centers.
+ v = materialParams.lutSize.x + v * materialParams.lutSize.y;
+ return materialConstants_isOneDimensional
+ ? colorGrade1D(lut, v) : colorGrade3D(lut, v);
}
diff --git a/filament/src/materials/colorGrading/colorGrading.mat b/filament/src/materials/colorGrading/colorGrading.mat
index 20315b5a62..8c14501771 100644
--- a/filament/src/materials/colorGrading/colorGrading.mat
+++ b/filament/src/materials/colorGrading/colorGrading.mat
@@ -66,6 +66,16 @@ material {
precision : high
}
],
+ constants : [
+ {
+ type : bool,
+ name : isOneDimensional
+ },
+ {
+ type : bool,
+ name : isLDR
+ }
+ ],
variables : [
vertex
],
@@ -154,7 +164,7 @@ void postProcess(inout PostProcessInputs postProcess) {
}
// Color grading
- color.rgb = colorGrade(materialParams_lut, color.rgb);
+ color.rgb = colorGrade(materialParams_lut, color.rgb);
// output in premultiplied alpha
#if !POST_PROCESS_OPAQUE
diff --git a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat
index 3d9aa0b799..49992f78ca 100644
--- a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat
+++ b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat
@@ -32,6 +32,16 @@ material {
name : vignetteColor
}
],
+ constants : [
+ {
+ type : bool,
+ name : isOneDimensional
+ },
+ {
+ type : bool,
+ name : isLDR
+ }
+ ],
subpasses : [
{
type : subpassInput,
@@ -103,7 +113,7 @@ void postProcess(inout PostProcessInputs postProcess) {
}
// Color grading
- color.rgb = colorGrade(materialParams_lut, color.rgb);
+ color.rgb = colorGrade(materialParams_lut, color.rgb);
// output in premultiplied alpha
#if !POST_PROCESS_OPAQUE
diff --git a/ios/CocoaPods/Filament.podspec b/ios/CocoaPods/Filament.podspec
index af2ff75e12..23a0c603c1 100644
--- a/ios/CocoaPods/Filament.podspec
+++ b/ios/CocoaPods/Filament.podspec
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
- spec.version = "1.58.0"
+ spec.version = "1.58.1"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
- spec.source = { :http => "https://github.com/google/filament/releases/download/v1.58.0/filament-v1.58.0-ios.tgz" }
+ spec.source = { :http => "https://github.com/google/filament/releases/download/v1.58.1/filament-v1.58.1-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
diff --git a/libs/bluegl/CMakeLists.txt b/libs/bluegl/CMakeLists.txt
index fa495ec80c..b43a204b96 100644
--- a/libs/bluegl/CMakeLists.txt
+++ b/libs/bluegl/CMakeLists.txt
@@ -31,13 +31,17 @@ if (WIN32)
set(SRCS ${SRCS} src/BlueGLCoreWindowsImpl.S)
endif()
elseif (APPLE AND NOT IOS)
- set(SRCS ${SRCS} src/BlueGLDarwin.cpp)
+ if (FILAMENT_SUPPORTS_OSMESA)
+ set(SRCS ${SRCS} src/BlueGLOSMesa.cpp)
+ else()
+ set(SRCS ${SRCS} src/BlueGLDarwin.cpp)
+ endif()
set(SRCS ${SRCS} src/BlueGLCoreDarwinUniversalImpl.S)
elseif(LINUX)
- if(FILAMENT_SUPPORTS_EGL_ON_LINUX)
+ if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
set(SRCS ${SRCS} src/BlueGLLinuxEGL.cpp)
- elseif(FILAMENT_SUPPORTS_OSMESA)
- set(SRCS ${SRCS} src/BlueGLLinuxOSMesa.cpp)
+ elseif (FILAMENT_SUPPORTS_OSMESA)
+ set(SRCS ${SRCS} src/BlueGLOSMesa.cpp)
else()
set(SRCS ${SRCS} src/BlueGLLinux.cpp)
endif()
@@ -53,7 +57,11 @@ include_directories(${PUBLIC_HDR_DIR})
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
if(FILAMENT_SUPPORTS_OSMESA)
- target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include/GL)
+ if (APPLE)
+ target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include)
+ else()
+ target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include/GL)
+ endif()
endif()
# specify where the public headers of this library are
diff --git a/libs/bluegl/src/BlueGLLinuxOSMesa.cpp b/libs/bluegl/src/BlueGLOSMesa.cpp
similarity index 78%
rename from libs/bluegl/src/BlueGLLinuxOSMesa.cpp
rename to libs/bluegl/src/BlueGLOSMesa.cpp
index 7b2e4624d4..88ab35ad3a 100644
--- a/libs/bluegl/src/BlueGLLinuxOSMesa.cpp
+++ b/libs/bluegl/src/BlueGLOSMesa.cpp
@@ -17,42 +17,64 @@
#include
#include
+#if defined(__linux__)
+
#include
+// This is to ensure that linking during compilation will not fail even if
+// OSMesaGetProcAddress is not linked.
+__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
+
+#elif defined(__APPLE__)
+
+#include
+
+#endif // __linux__
+
+#if defined(__linux__)
+#endif
+
namespace bluegl {
namespace {
using ProcAddressFunc = void*(*)(char const* funcName);
}
-// This is to ensure that linking during compilation will not fail even if
-// OSMesaGetProcAddress is not linked.
-__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
-
struct Driver {
ProcAddressFunc OSMesaGetProcAddress;
void* library;
} g_driver = {nullptr, nullptr};
bool initBinder() {
- constexpr char const* libraryNames[] = {"libOSMesa.so", "libosmesa.so"};
+ static constexpr char const* libraryNames[] = {
+#if defined(__linux__)
+ "libOSMesa.so",
+ "libosmesa.so",
+#elif defined(__APPLE__)
+ "libOSMesa.dylib",
+#endif
+ };
for (char const* name: libraryNames) {
g_driver.library = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
if (g_driver.library) {
break;
}
}
- if (!g_driver.library) {
- // The library has been linked explicitly during compile.
- g_driver.OSMesaGetProcAddress = (ProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
- } else {
+ if (g_driver.library) {
+ // Linking against a libosmesa.so.
g_driver.OSMesaGetProcAddress =
(ProcAddressFunc) dlsym(g_driver.library, "OSMesaGetProcAddress");
}
-
+#if defined(__linux__)
+ else {
+ // If Filament was built as a dynamic library.
+ g_driver.OSMesaGetProcAddress = (ProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
+ }
if (!g_driver.OSMesaGetProcAddress) {
+ // If statically linking OSMesa.
g_driver.OSMesaGetProcAddress = (ProcAddressFunc) OSMesaGetProcAddress;
}
+#endif
return g_driver.OSMesaGetProcAddress;
}
diff --git a/libs/fgviewer/README.md b/libs/fgviewer/README.md
index 48361f5164..aafa65140a 100644
--- a/libs/fgviewer/README.md
+++ b/libs/fgviewer/README.md
@@ -12,7 +12,7 @@
## Capabilities
-fgviewer is a library and web application for real-time visualization of the frame graph in Filament.
+fgviewer is a library and web application for real-time visualization of the frame graph in Filament.
It displays active passes and resource usage, providing insights into the rendering pipeline.
## Setup for Desktop
diff --git a/libs/fgviewer/include/fgviewer/FrameGraphInfo.h b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h
index d1e3b292df..b44420d0a2 100644
--- a/libs/fgviewer/include/fgviewer/FrameGraphInfo.h
+++ b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h
@@ -58,7 +58,7 @@ public:
utils::CString name;
utils::CString value;
};
-
+
Resource(ResourceId id, utils::CString name,
std::vector properties);
diff --git a/libs/fgviewer/src/ApiHandler.cpp b/libs/fgviewer/src/ApiHandler.cpp
index 5f49c3605b..dbfc5a8c67 100644
--- a/libs/fgviewer/src/ApiHandler.cpp
+++ b/libs/fgviewer/src/ApiHandler.cpp
@@ -17,14 +17,22 @@
#include "ApiHandler.h"
+#include <__chrono/duration.h>
#include
#include
#include
#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+
namespace filament::fgviewer {
using namespace std::chrono_literals;
diff --git a/libs/fgviewer/src/DebugServer.cpp b/libs/fgviewer/src/DebugServer.cpp
index a68413bdad..159578ed6e 100644
--- a/libs/fgviewer/src/DebugServer.cpp
+++ b/libs/fgviewer/src/DebugServer.cpp
@@ -21,36 +21,45 @@
#include
-#include
-#include
#include
+#include
+#include
+#include
#include
#include
-namespace filament::fgviewer {
// If set to 0, this serves HTML from a resgen resource. Use 1 only during local development, which
// serves files directly from the source code tree.
#define SERVE_FROM_SOURCE_TREE 0
#if SERVE_FROM_SOURCE_TREE
+
namespace {
std::string const BASE_URL = "libs/fgviewer/web";
} // anonymous
+
#else
+
#include "fgviewer_resources.h"
#include
namespace {
+
struct Asset {
std::string_view mime;
std::string_view data;
};
+
std::unordered_map ASSET_MAP;
+
} // anonymous
+
#endif // SERVE_FROM_SOURCE_TREE
+namespace filament::fgviewer {
+
using namespace utils;
std::string_view const DebugServer::kSuccessHeader =
diff --git a/libs/fgviewer/src/FrameGraphInfo.cpp b/libs/fgviewer/src/FrameGraphInfo.cpp
index 90cca55bc1..a1b02a261f 100644
--- a/libs/fgviewer/src/FrameGraphInfo.cpp
+++ b/libs/fgviewer/src/FrameGraphInfo.cpp
@@ -16,6 +16,11 @@
#include
+#include
+
+#include
+#include
+
namespace filament::fgviewer {
FrameGraphInfo::FrameGraphInfo(utils::CString viewName):
diff --git a/libs/fgviewer/src/JsonWriter.cpp b/libs/fgviewer/src/JsonWriter.cpp
index 24daab079e..d43c8a4218 100644
--- a/libs/fgviewer/src/JsonWriter.cpp
+++ b/libs/fgviewer/src/JsonWriter.cpp
@@ -14,11 +14,15 @@
* limitations under the License.
*/
-#include
#include
+#include
-#include
+#include
+
+#include
+#include
#include
+#include
namespace filament::fgviewer {
diff --git a/libs/fgviewer/web/app.js b/libs/fgviewer/web/app.js
index ccc2c01bb4..071a33e479 100644
--- a/libs/fgviewer/web/app.js
+++ b/libs/fgviewer/web/app.js
@@ -223,8 +223,8 @@ class FrameGraphSidePanel extends LitElement {
return html`
${this.framegraphs.map(({ fgid, name }) => html`
- this._handleFrameGraphClick(fgid)}"
+
this._handleFrameGraphClick(fgid)}"
data-id="${fgid}">
${fgid === this.selectedFrameGraph ? '● ' : ''}${name}
@@ -440,15 +440,15 @@ class FrameGraphTable extends LitElement {
return html`
|
- ${hasSubresources
+ ${hasSubresources
? html`
{ e.stopPropagation(); this._toggleCollapse(resourceIndex); }}">
${isExpanded ? '▼' : '▶'}
- `
+ `
: nothing}
${resource.name}
- ${hasSubresources && isExpanded ? nothing : html`(${subresourceIds.length})`}
+ ${hasSubresources && !isExpanded ? html`(${subresourceIds.length})` : nothing}
|
${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR)}
@@ -592,12 +592,12 @@ class FrameGraphViewer extends LitElement {
return html`
-
`;
diff --git a/libs/filabridge/include/filament/MaterialEnums.h b/libs/filabridge/include/filament/MaterialEnums.h
index f5676640fe..2edbd41a12 100644
--- a/libs/filabridge/include/filament/MaterialEnums.h
+++ b/libs/filabridge/include/filament/MaterialEnums.h
@@ -203,7 +203,7 @@ enum class ReflectionMode : uint8_t {
// can't really use std::underlying_type
::type because the driver takes a uint32_t
using AttributeBitset = utils::bitset32;
-static constexpr size_t MATERIAL_PROPERTIES_COUNT = 29;
+static constexpr size_t MATERIAL_PROPERTIES_COUNT = 30;
enum class Property : uint8_t {
BASE_COLOR, //!< float4, all shading models
ROUGHNESS, //!< float, lit shading models only
@@ -234,6 +234,7 @@ enum class Property : uint8_t {
BENT_NORMAL, //!< float3, all shading models only, except unlit
SPECULAR_FACTOR, //!< float, lit shading models only, except subsurface and cloth
SPECULAR_COLOR_FACTOR, //!< float3, lit shading models only, except subsurface and cloth
+ SHADOW_STRENGTH, //!< float, [0, 1] strength of shadows received by this material
// when adding new Properties, make sure to update MATERIAL_PROPERTIES_COUNT
};
diff --git a/libs/filamat/src/Enums.cpp b/libs/filamat/src/Enums.cpp
index bb163425da..cf23a5efb0 100644
--- a/libs/filamat/src/Enums.cpp
+++ b/libs/filamat/src/Enums.cpp
@@ -49,7 +49,8 @@ std::unordered_map Enums::mStringToProperty = {
{ "microThickness", Property::MICRO_THICKNESS },
{ "bentNormal", Property::BENT_NORMAL },
{ "specularFactor", Property::SPECULAR_FACTOR },
- { "specularColorFactor", Property::SPECULAR_COLOR_FACTOR }
+ { "specularColorFactor", Property::SPECULAR_COLOR_FACTOR },
+ { "shadowStrength", Property::SHADOW_STRENGTH }
};
template <>
diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp
index c61e384cbc..63a8eec613 100644
--- a/libs/filamat/src/shaders/CodeGenerator.cpp
+++ b/libs/filamat/src/shaders/CodeGenerator.cpp
@@ -1218,6 +1218,7 @@ char const* CodeGenerator::getConstantName(MaterialBuilder::Property property) n
case Property::BENT_NORMAL: return "BENT_NORMAL";
case Property::SPECULAR_FACTOR: return "SPECULAR_FACTOR";
case Property::SPECULAR_COLOR_FACTOR: return "SPECULAR_COLOR_FACTOR";
+ case Property::SHADOW_STRENGTH: return "SHADOW_STRENGTH";
}
}
diff --git a/libs/filamat/tests/test_filamat.cpp b/libs/filamat/tests/test_filamat.cpp
index 4696685cfa..37baf3e820 100644
--- a/libs/filamat/tests/test_filamat.cpp
+++ b/libs/filamat/tests/test_filamat.cpp
@@ -696,6 +696,25 @@ TEST_F(MaterialCompiler, StaticCodeAnalyzerBentNormal) {
EXPECT_TRUE(PropertyListsMatch(expected, properties));
}
+TEST_F(MaterialCompiler, StaticCodeAnalyzerShadowStrength) {
+ std::string fragmentCode(R"(
+ void material(inout MaterialInputs material) {
+ prepareMaterial(material);
+ material.shadowStrength = 0.1;
+ }
+ )");
+
+ std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
+ fragmentCode);
+
+ GLSLTools glslTools;
+ MaterialBuilder::PropertyList properties{ false };
+ glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
+ MaterialBuilder::PropertyList expected{ false };
+ expected[size_t(filamat::MaterialBuilder::Property::SHADOW_STRENGTH)] = true;
+ EXPECT_TRUE(PropertyListsMatch(expected, properties));
+}
+
TEST_F(MaterialCompiler, StaticCodeAnalyzerOutputFactor) {
std::string fragmentCode(R"(
void material(inout MaterialInputs material) {
diff --git a/shaders/src/surface_light_directional.fs b/shaders/src/surface_light_directional.fs
index 9ef63c79e8..fe054e0774 100644
--- a/shaders/src/surface_light_directional.fs
+++ b/shaders/src/surface_light_directional.fs
@@ -58,6 +58,9 @@ void evaluateDirectionalLight(const MaterialInputs material,
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
highp vec4 shadowPosition = getShadowPosition(cascade);
visibility = shadow(true, sampler0_shadowMap, cascade, shadowPosition, 0.0);
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+ applyShadowStrength(visibility, material.shadowStrength);
+#endif
// shadow far attenuation
highp vec3 v = getWorldPosition() - getWorldCameraPosition();
// (viewFromWorld * v).z == dot(transpose(viewFromWorld), v)
diff --git a/shaders/src/surface_light_punctual.fs b/shaders/src/surface_light_punctual.fs
index a4d1f91257..44c29fb439 100644
--- a/shaders/src/surface_light_punctual.fs
+++ b/shaders/src/surface_light_punctual.fs
@@ -222,6 +222,9 @@ void evaluatePunctualLights(const MaterialInputs material,
highp vec4 shadowPosition = getShadowPosition(shadowIndex, light.direction, light.zLight);
visibility = shadow(false, sampler0_shadowMap, shadowIndex,
shadowPosition, light.zLight);
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+ applyShadowStrength(visibility, material.shadowStrength);
+#endif
}
if (light.contactShadows && visibility > 0.0) {
if ((object_uniforms_flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0) {
diff --git a/shaders/src/surface_material_inputs.fs b/shaders/src/surface_material_inputs.fs
index 32923dc90a..bd59519526 100644
--- a/shaders/src/surface_material_inputs.fs
+++ b/shaders/src/surface_material_inputs.fs
@@ -98,6 +98,10 @@ struct MaterialInputs {
vec3 specularColorFactor;
#endif
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+ float shadowStrength;
+#endif
+
};
void initMaterial(out MaterialInputs material) {
@@ -195,6 +199,9 @@ void initMaterial(out MaterialInputs material) {
material.specularColorFactor = vec3(1.0);
#endif
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+ material.shadowStrength = 0.0;
+#endif
}
#if defined(MATERIAL_HAS_CUSTOM_SURFACE_SHADING)
diff --git a/shaders/src/surface_shading_unlit.fs b/shaders/src/surface_shading_unlit.fs
index a3ff0059c8..88b1bd258e 100644
--- a/shaders/src/surface_shading_unlit.fs
+++ b/shaders/src/surface_shading_unlit.fs
@@ -47,6 +47,9 @@ vec4 evaluateMaterial(const MaterialInputs material) {
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
highp vec4 shadowPosition = getShadowPosition(cascade);
visibility = shadow(true, sampler0_shadowMap, cascade, shadowPosition, 0.0);
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+ applyShadowStrength(visibility, material.shadowStrength);
+#endif
// shadow far attenuation
highp vec3 v = getWorldPosition() - getWorldCameraPosition();
// (viewFromWorld * v).z == dot(transpose(viewFromWorld), v)
diff --git a/shaders/src/surface_shadowing.fs b/shaders/src/surface_shadowing.fs
index cde6d8a9ee..f4c8b18c9c 100644
--- a/shaders/src/surface_shadowing.fs
+++ b/shaders/src/surface_shadowing.fs
@@ -511,6 +511,12 @@ int getPointLightFace(const highp vec3 r) {
}
}
+#if defined(MATERIAL_HAS_SHADOW_STRENGTH)
+void applyShadowStrength(inout float visibility, float strength) {
+ visibility = 1.0 - (1.0 - visibility) * strength;
+}
+#endif
+
// PCF sampling
float shadow(const bool DIRECTIONAL,
const mediump sampler2DArrayShadow shadowMap,
diff --git a/test/renderdiff/src/run.py b/test/renderdiff/src/run.py
index 9b63ebd4b3..15c5663eba 100644
--- a/test/renderdiff/src/run.py
+++ b/test/renderdiff/src/run.py
@@ -46,7 +46,12 @@ def render_test(gltf_viewer, test_config, output_dir,
for backend in test_config.backends:
env = None
if backend == 'opengl' and opengl_lib and os.path.isdir(opengl_lib):
- env = {'LD_LIBRARY_PATH': opengl_lib}
+ env = {
+ 'LD_LIBRARY_PATH': opengl_lib,
+
+ # for macOS
+ 'DYLD_LIBRARY_PATH': opengl_lib,
+ }
for model in test.models:
model_path = test_config.models[model]
diff --git a/test/renderdiff/test.sh b/test/renderdiff/test.sh
index 7321a468ae..ea8c6399ac 100755
--- a/test/renderdiff/test.sh
+++ b/test/renderdiff/test.sh
@@ -18,11 +18,19 @@ OUTPUT_DIR="$(pwd)/out/renderdiff_tests"
RENDERDIFF_TEST_DIR="$(pwd)/test/renderdiff"
TEST_UTILS_DIR="$(pwd)/test/utils"
MESA_DIR="$(pwd)/mesa/out/"
-MESA_LIB_DIR="${MESA_DIR}/lib/x86_64-linux-gnu"
+
+os_name=$(uname -s)
+if [[ "$os_name" == "Linux" ]]; then
+ MESA_LIB_DIR="${MESA_DIR}lib/x86_64-linux-gnu"
+elif [[ "$os_name" == "Darwin" ]]; then
+ MESA_LIB_DIR="${MESA_DIR}lib"
+else
+ echo "Unsupported platform for renderdiff tests"
+ exit 1
+fi
function prepare_mesa() {
if [ ! -d ${MESA_LIB_DIR} ]; then
- rm -rf mesa
bash ${TEST_UTILS_DIR}/get_mesa.sh
fi
}
diff --git a/test/renderdiff/tests/presubmit.json b/test/renderdiff/tests/presubmit.json
index 761f043fc5..4ddde454c0 100644
--- a/test/renderdiff/tests/presubmit.json
+++ b/test/renderdiff/tests/presubmit.json
@@ -8,7 +8,8 @@
"models": ["lucy", "DamagedHelmet"],
"rendering": {
"viewer.cameraFocusDistance": 0,
- "view.postProcessingEnabled": true
+ "view.postProcessingEnabled": true,
+ "view.dithering": "NONE"
}
}
],
diff --git a/test/utils/get_mesa.sh b/test/utils/get_mesa.sh
index 6ecb325d22..d44d0b7103 100755
--- a/test/utils/get_mesa.sh
+++ b/test/utils/get_mesa.sh
@@ -17,55 +17,109 @@
set -xe
# GITHUB_CLANG_VERSION is set in build/linux/ci-common.sh
+os_name=$(uname -s)
+LLVM_VERSION=16
+MESA_DIR=$(pwd)/mesa
-if [[ "$GITHUB_WORKFLOW" ]]; then
- # We only want to do this if it is a CI machine.
- sudo apt-get -y remove llvm-*
+if [[ "$os_name" == "Linux" ]]; then
+ if [[ "$GITHUB_WORKFLOW" ]]; then
+ # We only want to do this if it is a CI machine.
+ sudo apt-get -y remove llvm-*
- # We do a manual install of dependencies instead of `apt-get -y build-dep mesa`
- # because this allows us to compile an older mesa, and also because build-deps
- # is constantly being updated and sometimes not compatible with the current
- # linux platform.
- # Note that we assume this platform is compatible with ubuntu-22.04 x86_64
- sudo apt-get -y install \
- autoconf automake autopoint autotools-dev bindgen bison build-essential bzip2 cpp cpp-11 debhelper debugedit dh-autoreconf dh-strip-nondeterminism diffstat directx-headers-dev dpkg-dev dwz flex g++ g++-11 gcc gcc-11 gcc-11-base:amd64 gettext glslang-tools icu-devtools intltool-debian lib32gcc-s1 lib32stdc++6 libarchive-zip-perl libasan6:amd64 libatomic1:amd64 libc-dev-bin libc6-dbg:amd64 libc6-dev:amd64 libc6-i386 libcc1-0:amd64 libclang-${GITHUB_CLANG_VERSION}-dev libclang-common-${GITHUB_CLANG_VERSION}-dev libclang-cpp${GITHUB_CLANG_VERSION} libclang-cpp${GITHUB_CLANG_VERSION}-dev libclang1-14 libclang1-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION}-dev libcrypt-dev:amd64 libdebhelper-perl libdpkg-perl libdrm-amdgpu1:amd64 libdrm-dev:amd64 libdrm-intel1:amd64 libdrm-nouveau2:amd64 libdrm-radeon1:amd64 libelf-dev:amd64 libexpat1-dev:amd64 libffi-dev:amd64 libfile-stripnondeterminism-perl libgc1:amd64 libgcc-11-dev:amd64 libgl1:amd64 libgl1-mesa-dri:amd64 libglapi-mesa:amd64 libglvnd-core-dev:amd64 libglvnd0:amd64 libglx-mesa0:amd64 libglx0:amd64 libgomp1:amd64 libicu-dev:amd64 libisl23:amd64 libitm1:amd64 libllvm14:amd64 libllvm${GITHUB_CLANG_VERSION}:amd64 libllvmspirvlib-${GITHUB_CLANG_VERSION}-dev:amd64 libllvmspirvlib${GITHUB_CLANG_VERSION}:amd64 liblsan0:amd64 libmpc3:amd64 libncurses-dev:amd64 libnsl-dev:amd64 libobjc-11-dev:amd64 libobjc4:amd64 libpciaccess-dev:amd64 libpciaccess0:amd64 libpfm4:amd64 libpthread-stubs0-dev:amd64 libquadmath0:amd64 libsensors-config libsensors-dev:amd64 libsensors5:amd64 libset-scalar-perl libstd-rust-1.75:amd64 libstd-rust-dev:amd64 libstdc++-11-dev:amd64 libsub-override-perl libtinfo-dev:amd64 libtirpc-dev:amd64 libtool libtsan0:amd64 libubsan1:amd64 libva-dev:amd64 libva-drm2:amd64 libva-glx2:amd64 libva-wayland2:amd64 libva-x11-2:amd64 libva2:amd64 libvdpau-dev:amd64 libvdpau1:amd64 libvulkan-dev:amd64 libvulkan1:amd64 libwayland-bin libwayland-client0:amd64 libwayland-cursor0:amd64 libwayland-dev:amd64 libwayland-egl-backend-dev:amd64 libwayland-egl1:amd64 libwayland-server0:amd64 libx11-dev:amd64 libx11-xcb-dev:amd64 libx11-xcb1:amd64 libxau-dev:amd64 libxcb-dri2-0:amd64 libxcb-dri2-0-dev:amd64 libxcb-dri3-0:amd64 libxcb-dri3-dev:amd64 libxcb-glx0:amd64 libxcb-glx0-dev:amd64 libxcb-present-dev:amd64 libxcb-present0:amd64 libxcb-randr0:amd64 libxcb-randr0-dev:amd64 libxcb-render0:amd64 libxcb-render0-dev:amd64 libxcb-shape0:amd64 libxcb-shape0-dev:amd64 libxcb-shm0:amd64 libxcb-shm0-dev:amd64 libxcb-sync-dev:amd64 libxcb-sync1:amd64 libxcb-xfixes0:amd64 libxcb-xfixes0-dev:amd64 libxcb1-dev:amd64 libxdmcp-dev:amd64 libxext-dev:amd64 libxfixes-dev:amd64 libxfixes3:amd64 libxml2-dev:amd64 libxrandr-dev:amd64 libxrandr2:amd64 libxrender-dev:amd64 libxrender1:amd64 libxshmfence-dev:amd64 libxshmfence1:amd64 libxxf86vm-dev:amd64 libxxf86vm1:amd64 libz3-4:amd64 libz3-dev:amd64 libzstd-dev:amd64 linux-libc-dev:amd64 llvm-${GITHUB_CLANG_VERSION} llvm-${GITHUB_CLANG_VERSION}-dev llvm-${GITHUB_CLANG_VERSION}-linker-tools llvm-${GITHUB_CLANG_VERSION}-runtime llvm-${GITHUB_CLANG_VERSION}-tools llvm-spirv-${GITHUB_CLANG_VERSION} lto-disabled-list m4 make meson ninja-build pkg-config po-debconf python3-mako python3-ply python3-pygments quilt rpcsvc-proto rustc spirv-tools valgrind wayland-protocols x11proto-dev xorg-sgml-doctools xtrans-dev zlib1g-dev:amd64 \
- clang-$GITHUB_CLANG_VERSION libc++-$GITHUB_CLANG_VERSION-dev libc++abi-$GITHUB_CLANG_VERSION-dev
+ # We do a manual install of dependencies instead of `apt-get -y build-dep mesa`
+ # because this allows us to compile an older mesa, and also because build-deps
+ # is constantly being updated and sometimes not compatible with the current
+ # linux platform.
+ # Note that we assume this platform is compatible with ubuntu-22.04 x86_64
+ sudo apt-get -y install \
+ autoconf automake autopoint autotools-dev bindgen bison build-essential bzip2 cpp cpp-11 debhelper debugedit dh-autoreconf dh-strip-nondeterminism diffstat directx-headers-dev dpkg-dev dwz flex g++ g++-11 gcc gcc-11 gcc-11-base:amd64 gettext glslang-tools icu-devtools intltool-debian lib32gcc-s1 lib32stdc++6 libarchive-zip-perl libasan6:amd64 libatomic1:amd64 libc-dev-bin libc6-dbg:amd64 libc6-dev:amd64 libc6-i386 libcc1-0:amd64 libclang-${GITHUB_CLANG_VERSION}-dev libclang-common-${GITHUB_CLANG_VERSION}-dev libclang-cpp${GITHUB_CLANG_VERSION} libclang-cpp${GITHUB_CLANG_VERSION}-dev libclang1-14 libclang1-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION}-dev libcrypt-dev:amd64 libdebhelper-perl libdpkg-perl libdrm-amdgpu1:amd64 libdrm-dev:amd64 libdrm-intel1:amd64 libdrm-nouveau2:amd64 libdrm-radeon1:amd64 libelf-dev:amd64 libexpat1-dev:amd64 libffi-dev:amd64 libfile-stripnondeterminism-perl libgc1:amd64 libgcc-11-dev:amd64 libgl1:amd64 libgl1-mesa-dri:amd64 libglapi-mesa:amd64 libglvnd-core-dev:amd64 libglvnd0:amd64 libglx-mesa0:amd64 libglx0:amd64 libgomp1:amd64 libicu-dev:amd64 libisl23:amd64 libitm1:amd64 libllvm14:amd64 libllvm${GITHUB_CLANG_VERSION}:amd64 libllvmspirvlib-${GITHUB_CLANG_VERSION}-dev:amd64 libllvmspirvlib${GITHUB_CLANG_VERSION}:amd64 liblsan0:amd64 libmpc3:amd64 libncurses-dev:amd64 libnsl-dev:amd64 libobjc-11-dev:amd64 libobjc4:amd64 libpciaccess-dev:amd64 libpciaccess0f:amd64 libpfm4:amd64 libpthread-stubs0-dev:amd64 libquadmath0:amd64 libsensors-config libsensors-dev:amd64 libsensors5:amd64 libset-scalar-perl libstd-rust-1.75:amd64 libstd-rust-dev:amd64 libstdc++-11-dev:amd64 libsub-override-perl libtinfo-dev:amd64 libtirpc-dev:amd64 libtool libtsan0:amd64 libubsan1:amd64 libva-dev:amd64 libva-drm2:amd64 libva-glx2:amd64 libva-wayland2:amd64 libva-x11-2:amd64 libva2:amd64 libvdpau-dev:amd64 libvdpau1:amd64 libvulkan-dev:amd64 libvulkan1:amd64 libwayland-bin libwayland-client0:amd64 libwayland-cursor0:amd64 libwayland-dev:amd64 libwayland-egl-backend-dev:amd64 libwayland-egl1:amd64 libwayland-server0:amd64 libx11-dev:amd64 libx11-xcb-dev:amd64 libx11-xcb1:amd64 libxau-dev:amd64 libxcb-dri2-0:amd64 libxcb-dri2-0-dev:amd64 libxcb-dri3-0:amd64 libxcb-dri3-dev:amd64 libxcb-glx0:amd64 libxcb-glx0-dev:amd64 libxcb-present-dev:amd64 libxcb-present0:amd64 libxcb-randr0:amd64 libxcb-randr0-dev:amd64 libxcb-render0:amd64 libxcb-render0-dev:amd64 libxcb-shape0:amd64 libxcb-shape0-dev:amd64 libxcb-shm0:amd64 libxcb-shm0-dev:amd64 libxcb-sync-dev:amd64 libxcb-sync1:amd64 libxcb-xfixes0:amd64 libxcb-xfixes0-dev:amd64 libxcb1-dev:amd64 libxdmcp-dev:amd64 libxext-dev:amd64 libxfixes-dev:amd64 libxfixes3:amd64 libxml2-dev:amd64 libxrandr-dev:amd64 libxrandr2:amd64 libxrender-dev:amd64 libxrender1:amd64 libxshmfence-dev:amd64 libxshmfence1:amd64 libxxf86vm-dev:amd64 libxxf86vm1:amd64 libz3-4:amd64 libz3-dev:amd64 libzstd-dev:amd64 linux-libc-dev:amd64 llvm-${LLVM_VERSION} llvm-${LLVM_VERSION}-dev llvm-${LLVM_VERSION}-linker-tools llvm-${LLVM_VERSION}-runtime llvm-${LLVM_VERSION}-tools llvm-spirv-${LLVM_VERSION} lto-disabled-list m4 make meson ninja-build pkg-config po-debconf python3-mako python3-ply python3-pygments quilt rpcsvc-proto rustc spirv-tools valgrind wayland-protocols x11proto-dev xorg-sgml-doctools xtrans-dev zlib1g-dev:amd64 \
+ clang-$GITHUB_CLANG_VERSION libc++-$GITHUB_CLANG_VERSION-dev libc++abi-$GITHUB_CLANG_VERSION-dev
- sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${GITHUB_CLANG_VERSION} 100
- sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100
+ sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${GITHUB_CLANG_VERSION} 100
+ sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100
+ else
+ set +e
+ sudo apt-get -y build-dep mesa
+ sudo apt -y remove llvm-18 llvm-18-* llvm-19 llvm-19-*
+ set -e
+ CURRENT_CLANG_VERSION=$(clang --version | head -n 1 | awk '{ print $4 }' | awk 'BEGIN { FS="\\." } { print $1 }')
+ GITHUB_CLANG_VERSION=${GITHUB_CLANG_VERSION:-${CURRENT_CLANG_VERSION}}
+ sudo apt-get -y install clang-${GITHUB_CLANG_VERSION} \
+ libc++-${GITHUB_CLANG_VERSION}-dev \
+ libc++abi-${GITHUB_CLANG_VERSION}-dev \
+ llvm-${LLVM_VERSION} \
+ llvm-${LLVM_VERSION}-{dev,tools,runtime}
+ fi # [[ "$GITHUB_WORKFLOW" ]]
+elif [[ "$os_name" == "Darwin" ]]; then
+ if [[ ! "$GITHUB_WORKFLOW" ]]; then
+ if [ ! command -v brew > /dev/null 2>&1 ]; then
+ echo "Error: need to install homebrew to continue"
+ exit 1
+ fi
+ fi
+ brew install autoconf automake libx11 libxext libxrandr llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
+
+ NEEDED_PYTHON_DEPS=("mako" "setuptools")
+ for cmd in "${NEEDED_PYTHON_DEPS[@]}"; do
+ if ! pip3 show "${cmd}" >/dev/null 2>&1; then
+ sudo pip3 install ${cmd}
+ fi
+ done
+fi # [[ "$os_name" == x ]]
+
+LOCAL_LDFLAGS=${LDFLAGS}
+LOCAL_CPPFLAGS=${CPPFLAGS}
+LOCAL_PATH=${PATH}
+LOCAL_CXX=$(which clang++)
+LOCAL_CC=$(which clang)
+
+CHECKOUT_MESA=false
+if [[ -d "${MESA_DIR}" ]]; then
+ cd ${MESA_DIR}
+ if ! git fsck --connectivity-only > /dev/null 2>&1; then
+ echo "git fsck failed for mesa; try redownloading"
+ CHECKOUT_MESA=true;
+ fi
+ cd ..;
else
- set +e
- sudo apt-get -y build-dep mesa
- sudo apt -y remove llvm-18 llvm-18-* llvm-19 llvm-19-*
- set -e
-
- CURRENT_CLANG_VERSION=$(clang --version | head -n 1 | awk '{ print $4 }' | awk 'BEGIN { FS="\\." } { print $1 }')
- GITHUB_CLANG_VERSION=${GITHUB_CLANG_VERSION:-${CURRENT_CLANG_VERSION}}
-
- sudo apt-get -y install clang-${GITHUB_CLANG_VERSION} \
- libc++-${GITHUB_CLANG_VERSION}-dev \
- libc++abi-${GITHUB_CLANG_VERSION}-dev \
- llvm-${GITHUB_CLANG_VERSION} \
- llvm-${GITHUB_CLANG_VERSION}-{dev,tools,runtime}
+ CHECKOUT_MESA=true
fi
+if [[ "$CHECKOUT_MESA" = "true" ]]; then
+ rm -rf ${MESA_DIR}
-export CXX=`which clang++` && export CC=`which clang`
-
-git clone https://gitlab.freedesktop.org/mesa/mesa.git
+ #git clone https://gitlab.freedesktop.org/mesa/mesa.git
+ git clone git://anongit.freedesktop.org/mesa/mesa
+ # Due to gitlab mesa outage.
+ if [[ "${MESA_DIR}" != "$(pwd)/mesa" ]]; then
+ mv mesa ${MESA_DIR}
+ fi
+fi
pushd .
+cd ${MESA_DIR}
-cd mesa
-
-git checkout mesa-23.2.1
+# Need >= 24 to have llvmpipe for swrast. llvmpipe is needed for GL >= 4.1.
+git checkout mesa-24.2.1
mkdir -p out
+if [[ "$os_name" == "Darwin" ]]; then
+ LOCAL_LDFLAGS="-L/opt/homebrew/opt/llvm@${LLVM_VERSION}/lib"
+ LOCAL_CPPFLAGS="-I/opt/homebrew/opt/llvm@${LLVM_VERSION}/include -I/opt/homebrew/include"
+ LOCAL_PATH=${PATH}:/opt/homebrew/opt/llvm@${LLVM_VERSION}/bin
+
+ # This is necessary to be able to build vk (lavapipe) on macOS. Doesn't seem like a real dependency.
+ sed -I '' "s/error('Vulkan drivers require dri3 for X11 support')//g" meson.build
+fi
+
# -Dosmesa=true => builds OSMesa, which is an offscreen GL context
# -Dgallium-drivers=swrast => builds GL software rasterizer
# -Dvulkan-drivers=swrast => builds VK software rasterizer
-meson setup builddir/ -Dprefix="$(pwd)/out" -Dosmesa=true -Dglx=xlib -Dgallium-drivers=swrast -Dvulkan-drivers=swrast
-meson install -C builddir/
+# -Dgallium-drivers=llvmpipe is needed for GL >= 4.1 pipe-screen (see src/gallium/auxiliary/target-helpers/inline_sw_helper.h)
+CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
+ meson setup --wipe builddir/ -Dprefix="$(pwd)/out" -Dglx=xlib -Dosmesa=true -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast
+CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
+ meson install -C builddir/
popd
diff --git a/web/filament-js/package.json b/web/filament-js/package.json
index 8445d243a7..d739c8380b 100644
--- a/web/filament-js/package.json
+++ b/web/filament-js/package.json
@@ -1,6 +1,6 @@
{
"name": "filament",
- "version": "1.58.0",
+ "version": "1.58.1",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",