From 2d518b5fd1384d321ebbdf75631c19dcc7c78930 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Thu, 31 Jul 2025 15:52:21 -0700 Subject: [PATCH] ppm: ensure a renderable descriptor set is bound - We set a dummy set at the renderable bind point for post-processing passes, since it is not used. --- filament/src/PostProcessManager.cpp | 77 ++++++++++++++++++++++++++++- filament/src/PostProcessManager.h | 7 +++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 76ab875a3e..c830fdd5b7 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -252,6 +252,11 @@ void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const n mPostProcessDescriptorSet.bind(driver); } +void PostProcessManager::bindPerRenderableDescriptorSet(DriverApi& driver) noexcept { + driver.bindDescriptorSet(mDummyPerRenderableDsh, +DescriptorSetBindingPoints::PER_RENDERABLE, + { { 0, 0 }, driver }); +} + UTILS_NOINLINE void PostProcessManager::registerPostProcessMaterial(std::string_view const name, StaticMaterialInfo const& info) { @@ -315,6 +320,32 @@ void PostProcessManager::init() noexcept { mFullScreenQuadVbih = engine.getFullScreenVertexBuffer()->getVertexBufferInfoHandle(); mPerRenderableDslh = engine.getPerRenderableDescriptorSetLayout().getHandle(); + mDummyPerRenderableDsh = driver.createDescriptorSet(mPerRenderableDslh); + + driver.updateDescriptorSetBuffer(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::OBJECT_UNIFORMS, engine.getDummyUniformBuffer(), 0, + sizeof(PerRenderableUib)); + + driver.updateDescriptorSetBuffer(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::BONES_UNIFORMS, engine.getDummyUniformBuffer(), 0, + sizeof(PerRenderableBoneUib)); + + driver.updateDescriptorSetBuffer(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::MORPHING_UNIFORMS, engine.getDummyUniformBuffer(), 0, + sizeof(PerRenderableMorphingUib)); + + driver.updateDescriptorSetTexture(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS, + engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {}); + + driver.updateDescriptorSetTexture(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS, + engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {}); + + driver.updateDescriptorSetTexture(mDummyPerRenderableDsh, + +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS, engine.getZeroTextureArray(), + {}); + mSsrPassDescriptorSet.init(engine); mPostProcessDescriptorSet.init(engine); mStructureDescriptorSet.init(engine); @@ -385,6 +416,8 @@ void PostProcessManager::terminate(DriverApi& driver) noexcept { FEngine& engine = mEngine; driver.destroyTexture(mStarburstTexture); + driver.destroyDescriptorSet(mDummyPerRenderableDsh); + // Must destroy the instances before the materials mMaterialInstanceManager.terminate(engine); @@ -553,6 +586,7 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph // bind the per-view descriptorSet that is used for the structure pass getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); passBuilder.renderFlags(structureRenderFlags); passBuilder.variant(structureVariant); @@ -590,7 +624,8 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph } }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { - getStructureDescriptorSet().bind(driver); + getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); auto in = resources.getTexture(data.depth); auto& material = getPostProcessMaterial("mipmapDepth"); @@ -661,6 +696,7 @@ FrameGraphId PostProcessManager::transparentPicking(FrameGrap // bind the per-view descriptorSet that is used for the structure pass getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); auto [target, params] = resources.getRenderPassInfo(); passBuilder.renderFlags(structureRenderFlags); @@ -751,6 +787,8 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, mSsrPassDescriptorSet.bind(driver); + bindPerRenderableDescriptorSet(driver); + auto const out = resources.getRenderPassInfo(); // Remove the HAS_SHADOWING RenderFlags, since it's irrelevant when rendering reflections @@ -918,6 +956,7 @@ FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion( [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { // bind the per-view descriptorSet that is used for the structure pass getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); auto depth = resources.getTexture(data.depth); auto ssao = resources.getRenderPassInfo(); @@ -1112,6 +1151,7 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph auto const& data, DriverApi& driver) { // TODO: the structure descriptor set might not be the best fit. getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); auto ssao = resources.getTexture(data.input); auto blurred = resources.getRenderPassInfo(); @@ -1278,6 +1318,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); // don't use auto for those, b/c the ide can't resolve them using FGTD = FrameGraphTexture::Descriptor; @@ -1754,6 +1795,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto color = resources.getTexture(data.color); auto depth = resources.getTexture(data.depth); @@ -1813,6 +1856,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto desc = resources.getDescriptor(data.inOutColor); auto inOutColor = resources.getTexture(data.inOutColor); @@ -1890,6 +1934,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto const& inputDesc = resources.getDescriptor(data.inCocMinMax); auto const& out = resources.getRenderPassInfo(); auto inCocMinMax = resources.getTexture(data.inCocMinMax); @@ -1927,6 +1972,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto inTilesCocMinMax = resources.getTexture(data.inTilesCocMinMax); auto const& material = getPostProcessMaterial("dofDilate"); @@ -1981,6 +2028,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto color = resources.getTexture(data.color); @@ -2045,6 +2094,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto inColor = resources.getTexture(data.inColor); @@ -2093,6 +2144,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto color = resources.getTexture(data.color); @@ -2130,6 +2183,8 @@ FrameGraphId PostProcessManager::downscalePass(FrameGraph& fg [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); + auto const& out = resources.getRenderPassInfo(); auto const& material = getPostProcessMaterial("bloomDownsample2x"); FMaterialInstance* const mi = getMaterialInstance(mEngine, material); @@ -2263,6 +2318,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); // TODO: if downsampling is not exactly a multiple of two, use the 13 samples // filter. This is generally the accepted solution, however, the 13 samples @@ -2318,6 +2374,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto hwOut = resources.getTexture(data.out); auto const& outDesc = resources.getDescriptor(data.out); @@ -2379,6 +2436,7 @@ FrameGraphId PostProcessManager::flarePass(FrameGraph& fg, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto in = resources.getTexture(data.in); auto const out = resources.getRenderPassInfo(0); const float aspectRatio = float(width) / float(height); @@ -2457,6 +2515,7 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, ColorGradingConfig const& colorGradingConfig) noexcept { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); PostProcessVariant const variant = colorGradingConfig.translucent ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; @@ -2488,6 +2547,7 @@ void PostProcessManager::customResolvePrepareSubpass(DriverApi& driver, CustomRe void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); FEngine const& engine = mEngine; Handle const& fullScreenRenderPrimitive = engine.getFullScreenRenderPrimitive(); @@ -2522,6 +2582,7 @@ FrameGraphId PostProcessManager::customResolveUncompressPass( auto out = resources.getRenderPassInfo(); out.params.subpassMask = 1; bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); driver.beginRenderPass(out.target, out.params); customResolveSubpass(driver); driver.endRenderPass(); @@ -2596,6 +2657,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto colorTexture = resources.getTexture(data.input); auto bloomTexture = @@ -2691,6 +2753,7 @@ FrameGraphId PostProcessManager::fxaa(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto const& inDesc = resources.getDescriptor(data.input); auto const& texture = resources.getTexture(data.input); auto const& out = resources.getRenderPassInfo(); @@ -2909,6 +2972,7 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, }, [=, ¤t](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); constexpr mat4f normalizedToClip{mat4f::row_major_init{ 2, 0, 0, -1, @@ -3051,6 +3115,7 @@ FrameGraphId PostProcessManager::rcas( [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto const input = resources.getTexture(data.input); auto const out = resources.getRenderPassInfo(); @@ -3122,6 +3187,7 @@ FrameGraphId PostProcessManager::upscaleBilinear(FrameGraph& [this, vp, filter](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto color = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); @@ -3187,6 +3253,7 @@ FrameGraphId PostProcessManager::upscaleSGSR1(FrameGraph& fg, [this, vp, sourceHasLuminance](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto color = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); @@ -3274,6 +3341,7 @@ FrameGraphId PostProcessManager::upscaleFSR1(FrameGraph& fg, [this, twoPassesEASU, dsrOptions, vp](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); // helper to set the EASU uniforms auto setEasuUniforms = [vp, backend = mEngine.getBackend()](FMaterialInstance* mi, @@ -3404,6 +3472,7 @@ FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool co [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto color = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); auto out = resources.getRenderPassInfo(); @@ -3505,6 +3574,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { getStructureDescriptorSet().bind(driver); + bindPerRenderableDescriptorSet(driver); auto depth = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); auto const out = resources.getRenderPassInfo(); @@ -3623,6 +3693,7 @@ FrameGraphId PostProcessManager::resolveDepth(FrameGraph& fg, }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto const& input = resources.getTexture(data.input); auto const& material = getPostProcessMaterial("resolveDepth"); FMaterialInstance* const mi = @@ -3661,6 +3732,7 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto in = driver.createTextureView(resources.getTexture(data.in), level, 1); auto out = resources.getRenderPassInfo(); @@ -3717,6 +3789,7 @@ FrameGraphId PostProcessManager::debugShadowCascades(FrameGra }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto color = resources.getTexture(data.color); auto depth = resources.getTexture(data.depth); auto const out = resources.getRenderPassInfo(); @@ -3763,6 +3836,7 @@ FrameGraphId PostProcessManager::debugCombineArrayTexture(Fra }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto color = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); auto out = resources.getRenderPassInfo(); @@ -3845,6 +3919,7 @@ FrameGraphId PostProcessManager::debugDisplayShadowTexture( }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); + bindPerRenderableDescriptorSet(driver); auto const out = resources.getRenderPassInfo(); auto in = resources.getTexture(data.depth); auto const& material = getPostProcessMaterial("shadowmap"); diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index ccfdb590fb..1d49cf0f60 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -395,6 +395,8 @@ public: private: static void unbindAllDescriptorSets(backend::DriverApi& driver) noexcept; + void bindPerRenderableDescriptorSet(backend::DriverApi& driver) noexcept; + // Helper to get a MaterialInstance from a FMaterial // This currently just call FMaterial::getDefaultInstance(). FMaterialInstance* getMaterialInstance(FMaterial const* ma) { @@ -412,6 +414,11 @@ private: backend::VertexBufferInfoHandle mFullScreenQuadVbih; backend::DescriptorSetLayoutHandle mPerRenderableDslh; + // We need to have a dummy descriptor set because each post processing pass is expected to have + // a descriptor set bound at the renderable bind point. But the set itself contains dummy + // values. + backend::DescriptorSetHandle mDummyPerRenderableDsh; + FEngine& mEngine; mutable SsrPassDescriptorSet mSsrPassDescriptorSet;