From 9e6cf3c876f51b4159ce8f8f8e011de1a8ab88de Mon Sep 17 00:00:00 2001 From: alizahlalani <39961857+alizahlalani@users.noreply.github.com> Date: Tue, 18 Mar 2025 19:46:31 -0400 Subject: [PATCH 01/18] Refactored external image handling in PlatformEGLAndroid (#8512) --- .../backend/platforms/PlatformEGLAndroid.h | 34 ++++- .../opengl/platforms/PlatformEGLAndroid.cpp | 128 ++++++++++++++++-- filament/src/details/Texture.cpp | 7 +- 3 files changed, 150 insertions(+), 19 deletions(-) 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/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/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); From 4db3cc521b5be240b861ef127150a50299d90fca Mon Sep 17 00:00:00 2001 From: Doris Wu Date: Wed, 19 Mar 2025 13:42:34 +0800 Subject: [PATCH 02/18] Move includes outside fgviewer namespace (#8543) --- libs/fgviewer/src/DebugServer.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/fgviewer/src/DebugServer.cpp b/libs/fgviewer/src/DebugServer.cpp index a68413bdad..7457e24603 100644 --- a/libs/fgviewer/src/DebugServer.cpp +++ b/libs/fgviewer/src/DebugServer.cpp @@ -28,29 +28,38 @@ #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 = From 67f05c15d01b94b0bf97837fab544a4030cb751a Mon Sep 17 00:00:00 2001 From: Syed Idris Shah Date: Wed, 19 Mar 2025 12:59:00 -0400 Subject: [PATCH 03/18] Fix WebGPU compilation error WebGPU is broken because of 3abddc4584d63ce72bb8e2ccb11d41af490c0cc8 change --- filament/backend/src/webgpu/WebGPUDriver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; } From 4fbfd1b8c1157ed6ba3fd35eea6febf3241a537b Mon Sep 17 00:00:00 2001 From: Eliza Velasquez Date: Thu, 13 Mar 2025 17:54:29 -0700 Subject: [PATCH 04/18] Generate 1D LUTs for color grading when possible This introduces two new methods to `ToneMapper`: `isOneDimensional()` and `isLDR()`. `ColorGrading` references these values along with other parameters passed to the builder to determine if we can get away with only generating a one-dimensional LUT. Meanwhile, `PostProcessManager` takes care of setting the new spec constants and uniforms for `colorGrading.mat` and `colorGradingAsSubpass.mat`. --- NEW_RELEASE_NOTES.md | 2 + .../google/android/filament/ColorGrading.java | 17 +- filament/include/filament/ColorGrading.h | 15 +- filament/include/filament/ToneMapper.h | 31 ++ filament/src/PostProcessManager.cpp | 131 ++++--- filament/src/PostProcessManager.h | 7 + filament/src/details/ColorGrading.cpp | 359 ++++++++++-------- filament/src/details/ColorGrading.h | 5 +- .../materials/colorGrading/colorGrading.fs | 25 +- .../materials/colorGrading/colorGrading.mat | 17 +- .../colorGrading/colorGradingAsSubpass.mat | 17 +- 11 files changed, 392 insertions(+), 234 deletions(-) diff --git a/NEW_RELEASE_NOTES.md b/NEW_RELEASE_NOTES.md index 4a1a9c7fa7..961c2b9387 100644 --- a/NEW_RELEASE_NOTES.md +++ b/NEW_RELEASE_NOTES.md @@ -7,3 +7,5 @@ for next branch cut* header. appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md). ## Release notes for next branch cut + +- engine: Generate 1D instead of 3D LUTs for color grading whenever possible. 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..884fbeca1b 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,11 @@ 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. * + * When color grading can be implemented using a 1D LUT, this setting only affects the + * resolution of the LUT, using the same values as in 3D (i.e. 16, 32, 64). + * + * 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 +179,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. @@ -187,8 +193,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(). + * When color grading is implemented using a LUT, this sets the dimension of the LUT. This + * overrides the value set by quality(). * * The default is 32 * @@ -616,4 +622,3 @@ public class ColorGrading { private static native long nBuilderBuild(long nativeBuilder, long nativeEngine); } - diff --git a/filament/include/filament/ColorGrading.h b/filament/include/filament/ColorGrading.h index e5c8f3cae3..e21bfa413d 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,10 @@ 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. + * + * When color grading can be implemented using a 1D LUT, this setting only affects the + * resolution of the LUT, using the same values as in 3D (i.e. 16, 32, 64). + * * This overrides the values set by format() and dimensions(). * * The default quality is medium. @@ -169,6 +172,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. @@ -178,8 +183,8 @@ public: Builder& format(LutFormat format) noexcept; /** - * When color grading is implemented using a 3D LUT, this sets the dimension of the LUT. - * This overrides the value set by quality(). + * When color grading is implemented using a LUT, this sets the dimension of the LUT. This + * overrides the value set by quality(). * * The default is 32 * 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..029ea26df0 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); } ); @@ -2697,6 +2654,70 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial( } } +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 si 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 + }; + if (colorGrading->isOneDimensional()) { + mi->setParameter("lut1d", colorGrading->getHwHandle(), params); + mi->setParameter("lut", mEngine.getZeroTexture(), params); + } else { + mi->setParameter("lut", colorGrading->getHwHandle(), params); + mi->setParameter("lut1d", mEngine.getZeroTexture(), 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..29ecee14e0 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::R8, PixelDataFormat::R, PixelDataType::UBYTE }; + } // We use RGBA16F for high quality modes instead of RGB16F because RGB16F // is not supported everywhere switch (lutFormat) { @@ -658,27 +660,28 @@ 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); - } + const Config config = { + builder->dimension, + adaptationTransform(builder->whiteBalance), + selectColorGradingTransformIn(builder->toneMapping), + selectColorGradingTransformOut(builder->toneMapping), + selectColorGradingLuminance(builder->toneMapping), + selectOETF(builder->outputColorSpace), + }; - mDimension = c.lutDimension; + mDimension = config.lutDimension; + mIsOneDimensional = !builder->hasAdjustments && !builder->luminanceScaling + && builder->toneMapper->isOneDimensional(); + mIsLDR = mIsOneDimensional && builder->toneMapper->isLDR(); - size_t lutElementCount = c.lutDimension * c.lutDimension * c.lutDimension; - size_t elementSize = sizeof(half4); + size_t lutElementCount = mIsOneDimensional + ? config.lutDimension + : (config.lutDimension * config.lutDimension * config.lutDimension); + size_t elementSize = mIsOneDimensional ? sizeof(uint8_t) : 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 +691,206 @@ 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) { + uint8_t* UTILS_RESTRICT p = (uint8_t*) data; + for (size_t rgb = 0; rgb < config.lutDimension; rgb++) { + float s; + if (mIsLDR) { + float3 v = float3(rgb) * (1.0f / float(config.lutDimension - 1u)); + + v = (*builder->toneMapper)(float3(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); + + s = v.r; + } else { + s = hdrColorAt(rgb, rgb, rgb).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); + *p++ = uint8_t(std::floor(s * 255.0f + 0.5f)); + } + } 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. + backend::SamplerType target; + uint32_t width; + uint32_t height; + uint32_t depth; + + if (mIsOneDimensional) { + target = SamplerType::SAMPLER_2D; + width = config.lutDimension; + height = 1; + depth = 1; + } else { + target = SamplerType::SAMPLER_3D; + width = config.lutDimension; + height = config.lutDimension; + depth = config.lutDimension; + } + + mLutHandle = driver.createTexture(target, 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/materials/colorGrading/colorGrading.fs b/filament/src/materials/colorGrading/colorGrading.fs index 2b2000142d..7ebeebb19f 100644 --- a/filament/src/materials/colorGrading/colorGrading.fs +++ b/filament/src/materials/colorGrading/colorGrading.fs @@ -1,13 +1,28 @@ -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(const vec3 v) { + return textureLod(materialParams_lut, v, 0.0).rgb; +} - return textureLod(lut, logc, 0.0).rgb; +vec3 colorGrade1D(const vec3 v) { + return vec3( + textureLod(materialParams_lut1d, vec2(v.r, 0.5), 0.0).r, + textureLod(materialParams_lut1d, vec2(v.g, 0.5), 0.0).r, + textureLod(materialParams_lut1d, vec2(v.b, 0.5), 0.0).r); +} + +vec3 colorGrade(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(v) : colorGrade3D(v); } diff --git a/filament/src/materials/colorGrading/colorGrading.mat b/filament/src/materials/colorGrading/colorGrading.mat index 20315b5a62..a6d71510cf 100644 --- a/filament/src/materials/colorGrading/colorGrading.mat +++ b/filament/src/materials/colorGrading/colorGrading.mat @@ -11,6 +11,11 @@ material { name : lut, precision: medium }, + { + type : sampler2d, + name : lut1d, + precision: medium + }, { type : float2, name : lutSize @@ -66,6 +71,16 @@ material { precision : high } ], + constants : [ + { + type : bool, + name : isOneDimensional + }, + { + type : bool, + name : isLDR + } + ], variables : [ vertex ], @@ -154,7 +169,7 @@ void postProcess(inout PostProcessInputs postProcess) { } // Color grading - color.rgb = colorGrade(materialParams_lut, color.rgb); + color.rgb = colorGrade(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..4dec51bf81 100644 --- a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat +++ b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat @@ -6,6 +6,11 @@ material { name : lut, precision: medium }, + { + type : sampler2d, + name : lut1d, + precision: medium + }, { type : float2, name : lutSize @@ -32,6 +37,16 @@ material { name : vignetteColor } ], + constants : [ + { + type : bool, + name : isOneDimensional + }, + { + type : bool, + name : isLDR + } + ], subpasses : [ { type : subpassInput, @@ -103,7 +118,7 @@ void postProcess(inout PostProcessInputs postProcess) { } // Color grading - color.rgb = colorGrade(materialParams_lut, color.rgb); + color.rgb = colorGrade(color.rgb); // output in premultiplied alpha #if !POST_PROCESS_OPAQUE From daa359717b2d7a768369074c5e7a03f70ab31e05 Mon Sep 17 00:00:00 2001 From: Eliza Velasquez Date: Mon, 17 Mar 2025 13:55:57 -0700 Subject: [PATCH 05/18] 1dlut: mathias feedback --- .../google/android/filament/ColorGrading.java | 9 +-- filament/include/filament/ColorGrading.h | 9 +-- filament/src/PostProcessManager.cpp | 13 ++-- filament/src/details/ColorGrading.cpp | 72 +++++++++---------- .../materials/colorGrading/colorGrading.fs | 17 ++--- .../materials/colorGrading/colorGrading.mat | 7 +- .../colorGrading/colorGradingAsSubpass.mat | 7 +- 7 files changed, 58 insertions(+), 76 deletions(-) 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 884fbeca1b..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 @@ -159,8 +159,7 @@ 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. * - * When color grading can be implemented using a 1D LUT, this setting only affects the - * resolution of the LUT, using the same values as in 3D (i.e. 16, 32, 64). + * This setting has no effect if generating a 1D LUT. * * This overrides the values set by format() and dimensions(). * @@ -193,8 +192,10 @@ public class ColorGrading { } /** - * When color grading is implemented using a LUT, this sets the dimension of the LUT. This - * overrides the value set by quality(). + * 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 * diff --git a/filament/include/filament/ColorGrading.h b/filament/include/filament/ColorGrading.h index e21bfa413d..3e4916fbb2 100644 --- a/filament/include/filament/ColorGrading.h +++ b/filament/include/filament/ColorGrading.h @@ -155,8 +155,7 @@ public: * 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. * - * When color grading can be implemented using a 1D LUT, this setting only affects the - * resolution of the LUT, using the same values as in 3D (i.e. 16, 32, 64). + * This setting has no effect if generating a 1D LUT. * * This overrides the values set by format() and dimensions(). * @@ -183,8 +182,10 @@ public: Builder& format(LutFormat format) noexcept; /** - * When color grading is implemented using a LUT, this sets the dimension of the LUT. This - * overrides the value set by quality(). + * 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 * diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 029ea26df0..78b78e770a 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -2649,7 +2649,7 @@ 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 } } @@ -2676,7 +2676,7 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial( 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 } @@ -2693,13 +2693,8 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial( .wrapR = SamplerWrapMode::CLAMP_TO_EDGE, .anisotropyLog2 = 0 }; - if (colorGrading->isOneDimensional()) { - mi->setParameter("lut1d", colorGrading->getHwHandle(), params); - mi->setParameter("lut", mEngine.getZeroTexture(), params); - } else { - mi->setParameter("lut", colorGrading->getHwHandle(), params); - mi->setParameter("lut1d", mEngine.getZeroTexture(), params); - } + + mi->setParameter("lut", colorGrading->getHwHandle(), params); const float lutDimension = float(colorGrading->getDimension()); mi->setParameter("lutSize", float2{ diff --git a/filament/src/details/ColorGrading.cpp b/filament/src/details/ColorGrading.cpp index 29ecee14e0..439086409d 100644 --- a/filament/src/details/ColorGrading.cpp +++ b/filament/src/details/ColorGrading.cpp @@ -583,7 +583,7 @@ static float3 luminanceScaling(float3 x, static std::tuple selectLutTextureParams( ColorGrading::LutFormat const lutFormat, const bool isOneDimensional) noexcept { if (isOneDimensional) { - return { TextureFormat::R8, PixelDataFormat::R, PixelDataType::UBYTE }; + return { TextureFormat::R16F, PixelDataFormat::R, PixelDataType::HALF }; } // We use RGBA16F for high quality modes instead of RGB16F because RGB16F // is not supported everywhere @@ -660,8 +660,15 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { DriverApi& driver = engine.getDriverApi(); + // 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 = { - builder->dimension, + mIsOneDimensional ? 512u : builder->dimension, adaptationTransform(builder->whiteBalance), selectColorGradingTransformIn(builder->toneMapping), selectColorGradingTransformOut(builder->toneMapping), @@ -670,14 +677,22 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { }; mDimension = config.lutDimension; - mIsOneDimensional = !builder->hasAdjustments && !builder->luminanceScaling - && builder->toneMapper->isOneDimensional(); - mIsLDR = mIsOneDimensional && builder->toneMapper->isLDR(); - size_t lutElementCount = mIsOneDimensional - ? config.lutDimension - : (config.lutDimension * config.lutDimension * config.lutDimension); - size_t elementSize = mIsOneDimensional ? sizeof(uint8_t) : sizeof(half4); + 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; + } + + size_t lutElementCount = width * height * depth; + size_t elementSize = mIsOneDimensional ? sizeof(half) : sizeof(half4); void* data = malloc(lutElementCount * elementSize); auto [textureFormat, format, type] = @@ -784,29 +799,25 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { //auto now = std::chrono::steady_clock::now(); if (mIsOneDimensional) { - uint8_t* UTILS_RESTRICT p = (uint8_t*) data; - for (size_t rgb = 0; rgb < config.lutDimension; rgb++) { - float s; - if (mIsLDR) { + 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)); - // 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); - s = v.r; - } else { - s = hdrColorAt(rgb, rgb, rgb).r; + *p++ = half{v.r}; + } + } else { + for (size_t rgb = 0; rgb < config.lutDimension; rgb++) { + *p = half{hdrColorAt(rgb, rgb, rgb).r}; } - *p++ = uint8_t(std::floor(s * 255.0f + 0.5f)); } } else { // Multithreadedly generate the tone mapping 3D look-up table using 32 jobs @@ -864,24 +875,7 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { } // Create texture. - backend::SamplerType target; - uint32_t width; - uint32_t height; - uint32_t depth; - - if (mIsOneDimensional) { - target = SamplerType::SAMPLER_2D; - width = config.lutDimension; - height = 1; - depth = 1; - } else { - target = SamplerType::SAMPLER_3D; - width = config.lutDimension; - height = config.lutDimension; - depth = config.lutDimension; - } - - mLutHandle = driver.createTexture(target, 1, textureFormat, 1, + mLutHandle = driver.createTexture(SamplerType::SAMPLER_3D, 1, textureFormat, 1, width, height, depth, TextureUsage::DEFAULT); driver.update3DImage(mLutHandle, 0, diff --git a/filament/src/materials/colorGrading/colorGrading.fs b/filament/src/materials/colorGrading/colorGrading.fs index 7ebeebb19f..195b3ff749 100644 --- a/filament/src/materials/colorGrading/colorGrading.fs +++ b/filament/src/materials/colorGrading/colorGrading.fs @@ -7,22 +7,23 @@ vec3 LogC_to_linear(const vec3 x) { return c * log2(a * x + b) + d; } -vec3 colorGrade3D(const vec3 v) { - return textureLod(materialParams_lut, v, 0.0).rgb; +vec3 colorGrade3D(mediump sampler3D lut, const vec3 v) { + return textureLod(lut, v, 0.0).rgb; } -vec3 colorGrade1D(const vec3 v) { +vec3 colorGrade1D(mediump sampler3D lut, const vec3 v) { return vec3( - textureLod(materialParams_lut1d, vec2(v.r, 0.5), 0.0).r, - textureLod(materialParams_lut1d, vec2(v.g, 0.5), 0.0).r, - textureLod(materialParams_lut1d, vec2(v.b, 0.5), 0.0).r); + 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(vec3 v) { +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(v) : colorGrade3D(v); + 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 a6d71510cf..8c14501771 100644 --- a/filament/src/materials/colorGrading/colorGrading.mat +++ b/filament/src/materials/colorGrading/colorGrading.mat @@ -11,11 +11,6 @@ material { name : lut, precision: medium }, - { - type : sampler2d, - name : lut1d, - precision: medium - }, { type : float2, name : lutSize @@ -169,7 +164,7 @@ void postProcess(inout PostProcessInputs postProcess) { } // Color grading - color.rgb = colorGrade(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 4dec51bf81..49992f78ca 100644 --- a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat +++ b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat @@ -6,11 +6,6 @@ material { name : lut, precision: medium }, - { - type : sampler2d, - name : lut1d, - precision: medium - }, { type : float2, name : lutSize @@ -118,7 +113,7 @@ void postProcess(inout PostProcessInputs postProcess) { } // Color grading - color.rgb = colorGrade(color.rgb); + color.rgb = colorGrade(materialParams_lut, color.rgb); // output in premultiplied alpha #if !POST_PROCESS_OPAQUE From 1f169d7e754ec3200abc3a6f2062a5f5f23afe46 Mon Sep 17 00:00:00 2001 From: Eliza Velasquez Date: Mon, 17 Mar 2025 14:03:51 -0700 Subject: [PATCH 06/18] 1dlut: fix iOS build --- filament/src/details/ColorGrading.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/filament/src/details/ColorGrading.cpp b/filament/src/details/ColorGrading.cpp index 439086409d..aca98a9314 100644 --- a/filament/src/details/ColorGrading.cpp +++ b/filament/src/details/ColorGrading.cpp @@ -812,11 +812,11 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { // Apply OETF v = config.oetf(v); - *p++ = half{v.r}; + *p++ = half(v.r); } } else { for (size_t rgb = 0; rgb < config.lutDimension; rgb++) { - *p = half{hdrColorAt(rgb, rgb, rgb).r}; + *p = half(hdrColorAt(rgb, rgb, rgb).r); } } } else { From 65861b85cf69192097fc36b657ad25ac901776e1 Mon Sep 17 00:00:00 2001 From: Eliza Velasquez Date: Wed, 19 Mar 2025 11:59:33 -0700 Subject: [PATCH 07/18] 1dlut: fix psychadelic lookup tables --- .../src/main/java/com/google/android/filament/ToneMapper.java | 2 -- filament/src/details/ColorGrading.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) 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/filament/src/details/ColorGrading.cpp b/filament/src/details/ColorGrading.cpp index aca98a9314..939f0cbbbc 100644 --- a/filament/src/details/ColorGrading.cpp +++ b/filament/src/details/ColorGrading.cpp @@ -816,7 +816,7 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { } } else { for (size_t rgb = 0; rgb < config.lutDimension; rgb++) { - *p = half(hdrColorAt(rgb, rgb, rgb).r); + *p++ = half(hdrColorAt(rgb, rgb, rgb).r); } } } else { From ea0bbad63695c9eb1ea6f3727c717b083148bece Mon Sep 17 00:00:00 2001 From: rafadevai Date: Wed, 19 Mar 2025 13:41:44 -0700 Subject: [PATCH 08/18] vk: Refactor Vulkan android into its own class (#8538) --- .../backend/platforms/VulkanPlatform.h | 13 +++- .../backend/platforms/VulkanPlatformAndroid.h | 48 ++++++++---- filament/backend/src/PlatformFactory.cpp | 12 ++- .../src/vulkan/platform/VulkanPlatform.cpp | 9 +++ .../vulkan/platform/VulkanPlatformAndroid.cpp | 73 +++++++++++-------- .../vulkan/platform/VulkanPlatformApple.mm | 4 +- .../platform/VulkanPlatformLinuxWindows.cpp | 4 +- 7 files changed, 110 insertions(+), 53 deletions(-) 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..9d8e49323b 100644 --- a/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h +++ b/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h @@ -17,27 +17,45 @@ #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: + 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; + }; + + Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer, + bool sRGB) noexcept; + + virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage); + + using ImageData = VulkanPlatform::ImageData; + virtual ImageData createExternalImageData(ExternalImageHandleRef externalImage, + const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, + VkImageUsageFlags usage); protected: - ~ExternalImageVulkanAndroid() override; + 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..bb48a7f778 100644 --- a/filament/backend/src/PlatformFactory.cpp +++ b/filament/backend/src/PlatformFactory.cpp @@ -55,7 +55,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) @@ -104,7 +108,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 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..1813f57473 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,10 @@ Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer, return Platform::ExternalImageHandle{}; } -} // namespace fvkandroid - -VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl( - ExternalImageHandleRef externalImage, VkDevice device) { +VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::getExternalImageMetadata( + ExternalImageHandleRef externalImage) { auto const* fvkExternalImage = - static_cast(externalImage.get()); + static_cast(externalImage.get()); ExternalImageMetadata metadata; AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer; @@ -245,7 +240,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 +251,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 +266,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 +392,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 +411,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; From 6066e3a461910e8a22b306a217e7ba067e607544 Mon Sep 17 00:00:00 2001 From: Benjamin Doherty Date: Wed, 19 Mar 2025 16:17:12 -0700 Subject: [PATCH 09/18] Release Filament 1.58.1 --- NEW_RELEASE_NOTES.md | 2 -- README.md | 4 ++-- RELEASE_NOTES.md | 4 ++++ android/gradle.properties | 2 +- ios/CocoaPods/Filament.podspec | 4 ++-- web/filament-js/package.json | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/NEW_RELEASE_NOTES.md b/NEW_RELEASE_NOTES.md index 961c2b9387..4a1a9c7fa7 100644 --- a/NEW_RELEASE_NOTES.md +++ b/NEW_RELEASE_NOTES.md @@ -7,5 +7,3 @@ for next branch cut* header. appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md). ## Release notes for next branch cut - -- engine: Generate 1D instead of 3D LUTs for color grading whenever possible. 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/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/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/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", From de5d0e55afbb272fc4281d321ff09541894ca685 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Thu, 20 Mar 2025 13:57:49 -0700 Subject: [PATCH 10/18] webgpu: enable webgpu build for test on linux (#8549) --- .github/workflows/presubmit.yml | 8 ++++---- build/linux/ci-common.sh | 2 +- filament/backend/src/PlatformFactory.cpp | 8 +++++--- .../backend/src/webgpu/platform/WebGPUPlatformLinux.cpp | 6 +++++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index ae7efb2ebe..a409d0f746 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -106,13 +106,13 @@ jobs: 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 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/filament/backend/src/PlatformFactory.cpp b/filament/backend/src/PlatformFactory.cpp index bb48a7f778..c12feabbdc 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) @@ -69,9 +74,6 @@ filament::backend::Platform* createDefaultMetalPlatform(); #endif #include "noop/PlatformNoop.h" -#if defined(FILAMENT_SUPPORTS_WEBGPU) - #include "backend/platforms/WebGPUPlatform.h" -#endif namespace filament::backend { 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" From 6b91f303891983ef1e5ce520f81c57859f33fd60 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 20 Mar 2025 14:03:52 -0700 Subject: [PATCH 11/18] Materials can now specify a shadow attenuation factor (#8540) * Materials can now specify a shadow strength factor Materials have a new property: shadowStrength that can be used to attenuate all shadows received by this material. e.g.: ``` void material(inout MaterialInputs material) { prepareMaterial(material); material. shadowStrength = 0.1; } ``` FIXES=[391663042] Co-authored-by: Powei Feng --------- Co-authored-by: Powei Feng --- docs/Materials.md.html | 27 ++++++++++--------- .../include/filament/MaterialEnums.h | 3 ++- libs/filamat/src/Enums.cpp | 3 ++- libs/filamat/src/shaders/CodeGenerator.cpp | 1 + libs/filamat/tests/test_filamat.cpp | 19 +++++++++++++ shaders/src/surface_light_directional.fs | 3 +++ shaders/src/surface_light_punctual.fs | 3 +++ shaders/src/surface_material_inputs.fs | 7 +++++ shaders/src/surface_shading_unlit.fs | 3 +++ shaders/src/surface_shadowing.fs | 6 +++++ 10 files changed, 60 insertions(+), 15 deletions(-) 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/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, From 8c396caba0772c261f2c6944872aeb07ec7e2c61 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Thu, 20 Mar 2025 15:03:08 -0700 Subject: [PATCH 12/18] vk: removing caching/ directory (#8553) Move the files out of that directory for consistency. (Should have never created the directory in the first place). Also did some small clean-ups of removing old comments and no longer needed includes. --- filament/backend/CMakeLists.txt | 8 ++-- ...nager.cpp => VulkanDescriptorSetCache.cpp} | 41 +++++++++---------- ...etManager.h => VulkanDescriptorSetCache.h} | 18 ++++---- filament/backend/src/vulkan/VulkanDriver.cpp | 23 +++++------ filament/backend/src/vulkan/VulkanDriver.h | 6 +-- .../src/vulkan/VulkanPipelineCache.cpp | 3 -- .../VulkanPipelineLayoutCache.cpp | 0 .../{caching => }/VulkanPipelineLayoutCache.h | 3 +- 8 files changed, 46 insertions(+), 56 deletions(-) rename filament/backend/src/vulkan/{caching/VulkanDescriptorSetManager.cpp => VulkanDescriptorSetCache.cpp} (93%) rename filament/backend/src/vulkan/{caching/VulkanDescriptorSetManager.h => VulkanDescriptorSetCache.h} (82%) rename filament/backend/src/vulkan/{caching => }/VulkanPipelineLayoutCache.cpp (100%) rename filament/backend/src/vulkan/{caching => }/VulkanPipelineLayoutCache.h (98%) diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index 6f66f1f457..b96be62d1e 100644 --- a/filament/backend/CMakeLists.txt +++ b/filament/backend/CMakeLists.txt @@ -173,10 +173,10 @@ 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/VulkanPipelineLayoutCache.cpp + src/vulkan/VulkanPipelineLayoutCache.h src/vulkan/memory/ResourceManager.cpp src/vulkan/memory/ResourceManager.h src/vulkan/memory/ResourcePointer.h diff --git a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp similarity index 93% rename from filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp rename to filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp index 570dcc5df2..946ebb8833 100644 --- a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp +++ b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp @@ -14,20 +14,17 @@ * 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 { @@ -36,7 +33,7 @@ namespace { using BitmaskGroup = VulkanDescriptorSetLayout::Bitmask; using DescriptorCount = VulkanDescriptorSetLayout::Count; -using DescriptorSetLayoutArray = VulkanDescriptorSetManager::DescriptorSetLayoutArray; +using DescriptorSetLayoutArray = VulkanDescriptorSetCache::DescriptorSetLayoutArray; using BitmaskGroupHashFn = utils::hash::MurmurHashFn; struct BitmaskGroupEqual { bool operator()(BitmaskGroup const& k1, BitmaskGroup const& k2) const { @@ -264,7 +261,7 @@ inline VkDescriptorSetLayout createLayout(VkDevice device, BitmaskGroup const& b // 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,7 +316,7 @@ private: std::vector> mPools; }; -class VulkanDescriptorSetManager::DescriptorSetLayoutManager { +class VulkanDescriptorSetCache::DescriptorSetLayoutManager { public: DescriptorSetLayoutManager(VkDevice device) : mDevice(device) {} @@ -345,16 +342,16 @@ private: 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{ +void VulkanDescriptorSetCache::terminate() noexcept{ mLayoutManager.reset(); mDescriptorPool.reset(); clearHistory(); @@ -362,18 +359,18 @@ void VulkanDescriptorSetManager::terminate() noexcept{ // 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 +409,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 +435,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 +467,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 } -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 +489,12 @@ fvkmemory::resource_ptr VulkanDescriptorSetManager::createS }); } -void VulkanDescriptorSetManager::initVkLayout( +void VulkanDescriptorSetCache::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 82% rename from filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h rename to filament/backend/src/vulkan/VulkanDescriptorSetCache.h index 87aa076213..d55a5f2a0b 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 { +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; @@ -99,4 +95,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/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index eb6629bafa..d04618b1c3 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" @@ -219,7 +218,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex mSamplerCache(mPlatform->getDevice()), mBlitter(mPlatform->getPhysicalDevice(), &mCommands), mReadPixels(mPlatform->getDevice()), - mDescriptorSetManager(mPlatform->getDevice(), &mResourceManager), + mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager), mQueryManager(mPlatform->getDevice()), mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported), mStereoscopicType(driverConfig.stereoscopicType) { @@ -329,7 +328,7 @@ void VulkanDriver::terminate() { mPipelineCache.terminate(); mFramebufferCache.reset(); mSamplerCache.terminate(); - mDescriptorSetManager.terminate(); + mDescriptorSetCache.terminate(); mPipelineLayoutCache.terminate(); // Before terminating ResourceManager, we must make sure all of the resource_ptrs have been unset. @@ -365,7 +364,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 +407,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 +420,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) { @@ -779,7 +778,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); + mDescriptorSetCache.initVkLayout(layout); layout.inc(); } @@ -788,7 +787,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 +1492,7 @@ void VulkanDriver::nextSubpass(int) { if (mCurrentRenderPass.params.subpassMask & 0x1) { VulkanAttachment& subpassInput = renderTarget->getColor0(); - mDescriptorSetManager.updateInputAttachment({}, subpassInput); + mDescriptorSetCache.updateInputAttachment({}, subpassInput); } } @@ -1820,9 +1819,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 +1829,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..0974da35d4 100644 --- a/filament/backend/src/vulkan/VulkanDriver.h +++ b/filament/backend/src/vulkan/VulkanDriver.h @@ -27,8 +27,8 @@ #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/VulkanPipelineLayoutCache.h" #include "vulkan/memory/ResourceManager.h" #include "vulkan/memory/ResourcePointer.h" #include "vulkan/utils/Definitions.h" @@ -137,7 +137,7 @@ private: VulkanSamplerCache mSamplerCache; VulkanBlitter mBlitter; VulkanReadPixels mReadPixels; - VulkanDescriptorSetManager mDescriptorSetManager; + 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 From df897b3fb29a964f301239b114da63426ac19fe5 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Thu, 20 Mar 2025 15:37:23 -0700 Subject: [PATCH 13/18] osmesa: Enable Mesa/OSMesa rendering for mac (#8530) This commit enables local running of the renderdiff tests and also for github workflows. --- .github/workflows/presubmit.yml | 18 ++- CMakeLists.txt | 18 ++- filament/backend/CMakeLists.txt | 17 ++- .../backend/platforms/PlatformOSMesa.h | 5 + filament/backend/src/PlatformFactory.cpp | 12 +- .../src/opengl/platforms/PlatformOSMesa.cpp | 39 ++++-- libs/bluegl/CMakeLists.txt | 18 ++- ...BlueGLLinuxOSMesa.cpp => BlueGLOSMesa.cpp} | 42 ++++-- test/renderdiff/src/run.py | 7 +- test/renderdiff/test.sh | 12 +- test/renderdiff/tests/presubmit.json | 3 +- test/utils/get_mesa.sh | 122 +++++++++++++----- 12 files changed, 232 insertions(+), 81 deletions(-) rename libs/bluegl/src/{BlueGLLinuxOSMesa.cpp => BlueGLOSMesa.cpp} (78%) diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index a409d0f746..9745f29131 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -92,15 +92,21 @@ 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 @@ -115,4 +121,4 @@ jobs: - name: Run build script 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/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index b96be62d1e..d9e5aa13e8 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) @@ -416,9 +420,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/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/src/PlatformFactory.cpp b/filament/backend/src/PlatformFactory.cpp index c12feabbdc..d5055daee5 100644 --- a/filament/backend/src/PlatformFactory.cpp +++ b/filament/backend/src/PlatformFactory.cpp @@ -35,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) @@ -142,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/opengl/platforms/PlatformOSMesa.cpp b/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp index 831e30cc62..3e152b709f 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"); } @@ -103,12 +114,22 @@ private: Driver* PlatformOSMesa::createDriver(void* const 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/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/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 From 5e9be5dd2d325853472c35f1b34d5d0376419b6e Mon Sep 17 00:00:00 2001 From: Doris Wu Date: Fri, 21 Mar 2025 10:10:05 +0800 Subject: [PATCH 14/18] Remove trailing whitespace (#8556) --- libs/fgviewer/README.md | 2 +- libs/fgviewer/include/fgviewer/FrameGraphInfo.h | 2 +- libs/fgviewer/web/app.js | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) 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/web/app.js b/libs/fgviewer/web/app.js index ccc2c01bb4..fa527088ba 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` -
    ${fgid === this.selectedFrameGraph ? '● ' : ''}${name}
    @@ -440,12 +440,12 @@ class FrameGraphTable extends LitElement { return html` - ${hasSubresources + ${hasSubresources ? html` ${isExpanded ? '▼' : '▶'} - ` + ` : nothing} ${resource.name} ${hasSubresources && isExpanded ? nothing : html`(${subresourceIds.length})`} @@ -592,12 +592,12 @@ class FrameGraphViewer extends LitElement { return html` - `; From d2d5d62a205b76b5a61343c580b6f2b2cf73783e Mon Sep 17 00:00:00 2001 From: Doris Wu Date: Sat, 22 Mar 2025 00:17:22 +0800 Subject: [PATCH 15/18] Some cleanups (#8558) * Clean up includes * Fix the logic --- libs/fgviewer/src/ApiHandler.cpp | 8 ++++++++ libs/fgviewer/src/DebugServer.cpp | 6 +++--- libs/fgviewer/src/FrameGraphInfo.cpp | 5 +++++ libs/fgviewer/src/JsonWriter.cpp | 8 ++++++-- libs/fgviewer/web/app.js | 2 +- 5 files changed, 23 insertions(+), 6 deletions(-) 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 7457e24603..159578ed6e 100644 --- a/libs/fgviewer/src/DebugServer.cpp +++ b/libs/fgviewer/src/DebugServer.cpp @@ -21,15 +21,15 @@ #include -#include -#include #include +#include +#include +#include #include #include - // 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 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 fa527088ba..071a33e479 100644 --- a/libs/fgviewer/web/app.js +++ b/libs/fgviewer/web/app.js @@ -448,7 +448,7 @@ class FrameGraphTable extends LitElement { ` : nothing} ${resource.name} - ${hasSubresources && isExpanded ? nothing : html`(${subresourceIds.length})`} + ${hasSubresources && !isExpanded ? html`(${subresourceIds.length})` : nothing} ${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR)} From 625603d8d415a60d0e37de617e007d34af3d33ad Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Fri, 21 Mar 2025 09:33:35 -0700 Subject: [PATCH 16/18] vk: split layout cache from descriptorSet cache (#8554) This is just splitting the layout cache into its own class and files. --- filament/backend/CMakeLists.txt | 2 + .../src/vulkan/VulkanDescriptorSetCache.cpp | 101 +--------------- .../src/vulkan/VulkanDescriptorSetCache.h | 6 +- .../vulkan/VulkanDescriptorSetLayoutCache.cpp | 110 ++++++++++++++++++ .../vulkan/VulkanDescriptorSetLayoutCache.h | 63 ++++++++++ filament/backend/src/vulkan/VulkanDriver.cpp | 8 +- filament/backend/src/vulkan/VulkanDriver.h | 2 + 7 files changed, 182 insertions(+), 110 deletions(-) create mode 100644 filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.cpp create mode 100644 filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.h diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index d9e5aa13e8..24c7a15587 100644 --- a/filament/backend/CMakeLists.txt +++ b/filament/backend/CMakeLists.txt @@ -179,6 +179,8 @@ if (FILAMENT_SUPPORTS_VULKAN) include/backend/platforms/VulkanPlatform.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 diff --git a/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp index 946ebb8833..eb89ad8eab 100644 --- a/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp +++ b/filament/backend/src/vulkan/VulkanDescriptorSetCache.cpp @@ -31,15 +31,8 @@ namespace filament::backend { namespace { -using BitmaskGroup = VulkanDescriptorSetLayout::Bitmask; using DescriptorCount = VulkanDescriptorSetLayout::Count; using DescriptorSetLayoutArray = VulkanDescriptorSetCache::DescriptorSetLayoutArray; -using BitmaskGroupHashFn = utils::hash::MurmurHashFn; -struct BitmaskGroupEqual { - bool operator()(BitmaskGroup const& k1, BitmaskGroup const& k2) const { - return k1 == k2; - } -}; // We create a pool for each layout as defined by the number of descriptors of each type. For // example, a layout of @@ -196,66 +189,6 @@ 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 @@ -316,43 +249,16 @@ private: std::vector> mPools; }; -class VulkanDescriptorSetCache::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; -}; VulkanDescriptorSetCache::VulkanDescriptorSetCache(VkDevice device, fvkmemory::ResourceManager* resourceManager) : mDevice(device), mResourceManager(resourceManager), - mLayoutManager(std::make_unique(device)), mDescriptorPool(std::make_unique(device)) {} VulkanDescriptorSetCache::~VulkanDescriptorSetCache() = default; void VulkanDescriptorSetCache::terminate() noexcept{ - mLayoutManager.reset(); mDescriptorPool.reset(); clearHistory(); } @@ -470,7 +376,7 @@ void VulkanDescriptorSetCache::updateSampler(fvkmemory::resource_ptr set, VulkanAttachment const& attachment) noexcept { - // TOOD: fill-in this region + // TOOD: fill this in. } fvkmemory::resource_ptr VulkanDescriptorSetCache::createSet( @@ -489,11 +395,6 @@ fvkmemory::resource_ptr VulkanDescriptorSetCache::createSet }); } -void VulkanDescriptorSetCache::initVkLayout( - fvkmemory::resource_ptr layout) { - layout->setVkLayout(mLayoutManager->getVkLayout(layout->bitmask)); -} - void VulkanDescriptorSetCache::clearHistory() { mStashedSets = {}; } diff --git a/filament/backend/src/vulkan/VulkanDescriptorSetCache.h b/filament/backend/src/vulkan/VulkanDescriptorSetCache.h index d55a5f2a0b..898b314be9 100644 --- a/filament/backend/src/vulkan/VulkanDescriptorSetCache.h +++ b/filament/backend/src/vulkan/VulkanDescriptorSetCache.h @@ -34,7 +34,7 @@ namespace filament::backend { -// Abstraction over the pool and the layout cache. +// Abstraction over the descriptor set pool. class VulkanDescriptorSetCache { public: static constexpr uint8_t UNIQUE_DESCRIPTOR_SET_COUNT = @@ -68,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 = @@ -81,7 +78,6 @@ private: VkDevice mDevice; fvkmemory::ResourceManager* mResourceManager; - std::unique_ptr mLayoutManager; std::unique_ptr mDescriptorPool; std::pair mInputAttachment; DescriptorSetArray mStashedSets = {}; 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 d04618b1c3..8cfadd3728 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -34,7 +34,6 @@ #include #include -#include #include #ifndef NDEBUG @@ -43,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. @@ -218,6 +215,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex mSamplerCache(mPlatform->getDevice()), mBlitter(mPlatform->getPhysicalDevice(), &mCommands), mReadPixels(mPlatform->getDevice()), + mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager), mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager), mQueryManager(mPlatform->getDevice()), mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported), @@ -328,6 +326,7 @@ void VulkanDriver::terminate() { mPipelineCache.terminate(); mFramebufferCache.reset(); mSamplerCache.terminate(); + mDescriptorSetLayoutCache.terminate(); mDescriptorSetCache.terminate(); mPipelineLayoutCache.terminate(); @@ -777,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); - mDescriptorSetCache.initVkLayout(layout); + auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info)); layout.inc(); } diff --git a/filament/backend/src/vulkan/VulkanDriver.h b/filament/backend/src/vulkan/VulkanDriver.h index 0974da35d4..613e4d5a6c 100644 --- a/filament/backend/src/vulkan/VulkanDriver.h +++ b/filament/backend/src/vulkan/VulkanDriver.h @@ -28,6 +28,7 @@ #include "VulkanStagePool.h" #include "VulkanQueryManager.h" #include "vulkan/VulkanDescriptorSetCache.h" +#include "vulkan/VulkanDescriptorSetLayoutCache.h" #include "vulkan/VulkanPipelineLayoutCache.h" #include "vulkan/memory/ResourceManager.h" #include "vulkan/memory/ResourcePointer.h" @@ -137,6 +138,7 @@ private: VulkanSamplerCache mSamplerCache; VulkanBlitter mBlitter; VulkanReadPixels mReadPixels; + VulkanDescriptorSetLayoutCache mDescriptorSetLayoutCache; VulkanDescriptorSetCache mDescriptorSetCache; VulkanQueryManager mQueryManager; From 7f7bceb970650e04e2663db3617ee8096f3449f1 Mon Sep 17 00:00:00 2001 From: rafadevai Date: Fri, 21 Mar 2025 10:09:29 -0700 Subject: [PATCH 17/18] vk: New method to describe external image in Vulkan Android (#8551) To match the GL platform add a new function to describe an external image. Also make `ExternalImageVulkanAndroid` and `getExternalImageMetadata` protected, so only the backend has access to it. --- .../backend/platforms/VulkanPlatformAndroid.h | 18 ++++++++++++++---- .../vulkan/platform/VulkanPlatformAndroid.cpp | 13 +++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h b/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h index 9d8e49323b..f08ff384cc 100644 --- a/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h +++ b/filament/backend/include/backend/platforms/VulkanPlatformAndroid.h @@ -26,6 +26,20 @@ namespace filament::backend { 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: struct ExternalImageVulkanAndroid : public Platform::ExternalImage { AHardwareBuffer* aHardwareBuffer = nullptr; bool sRGB = false; @@ -38,9 +52,6 @@ public: ~ExternalImageVulkanAndroid() override; }; - Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer, - bool sRGB) noexcept; - virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage); using ImageData = VulkanPlatform::ImageData; @@ -48,7 +59,6 @@ public: const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage); -protected: virtual ExtensionSet getSwapchainInstanceExtensions() const; using SurfaceBundle = VulkanPlatform::SurfaceBundle; diff --git a/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp b/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp index 1813f57473..441004e995 100644 --- a/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp +++ b/filament/backend/src/vulkan/platform/VulkanPlatformAndroid.cpp @@ -223,6 +223,19 @@ Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage( return Platform::ExternalImageHandle{}; } +VulkanPlatformAndroid::ExternalImageDescAndroid VulkanPlatformAndroid::getExternalImageDesc( + ExternalImageHandleRef externalImage) const noexcept { + auto const* fvkExternalImage = + 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 = From af079b42a65c46ea33b1eb795a4483e3aeb85323 Mon Sep 17 00:00:00 2001 From: Syed Idris Shah Date: Thu, 20 Mar 2025 16:33:35 -0400 Subject: [PATCH 18/18] Make decl/def of createDriver api consistent Replace "void* const" with "void*" as const here serves no purpose because of following reasons: 1. void* const in function parameter has a limited and local effect on the code. 2. clang tidy would complain and report error if const is added to the function declaration. 3. const is dropped later in the call stack making the code incosistent. --- filament/backend/src/noop/PlatformNoop.cpp | 2 +- filament/backend/src/opengl/OpenGLDriver.cpp | 12 ++++++------ .../src/opengl/platforms/PlatformCocoaTouchGL.mm | 2 +- .../backend/src/opengl/platforms/PlatformGLX.cpp | 2 +- .../backend/src/opengl/platforms/PlatformOSMesa.cpp | 2 +- .../backend/src/opengl/platforms/PlatformWGL.cpp | 2 +- .../backend/src/opengl/platforms/PlatformWebGL.cpp | 2 +- .../backend/src/webgpu/platform/WebGPUPlatform.cpp | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) 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/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 3e152b709f..16d52de0d2 100644 --- a/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp +++ b/filament/backend/src/opengl/platforms/PlatformOSMesa.cpp @@ -112,7 +112,7 @@ private: }// anonymous namespace -Driver* PlatformOSMesa::createDriver(void* const sharedGLContext, +Driver* PlatformOSMesa::createDriver(void* sharedGLContext, const DriverConfig& driverConfig) noexcept { OSMesaAPI* api = new OSMesaAPI(); 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/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 "