From 6b0dc7babe9e871c125489bb8d511fd94d20a3ef Mon Sep 17 00:00:00 2001 From: Eliza Velasquez Date: Mon, 9 Mar 2026 16:34:29 +0900 Subject: [PATCH] wip --- filament/src/PostProcessManager.cpp | 97 ++++++++++++++++------------- filament/src/PostProcessManager.h | 46 +++++++++----- filament/src/RenderPass.cpp | 6 +- 3 files changed, 89 insertions(+), 60 deletions(-) diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 7cf355ba28..128f33c665 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -184,13 +184,10 @@ void PostProcessManager::PostProcessMaterial::loadMaterial(FEngine& engine) cons } UTILS_NOINLINE -FMaterial* PostProcessManager::PostProcessMaterial::getMaterial(FEngine& engine, - DriverApi& driver, Variant::type_t const variant) const noexcept { +FMaterial* PostProcessManager::PostProcessMaterial::getMaterial(FEngine& engine) const noexcept { if (UTILS_UNLIKELY(mSize)) { loadMaterial(engine); } - mMaterial->getDefaultInstance()->prepareProgram(driver, Variant{ variant }, - CompilerPriorityQueue::CRITICAL); return mMaterial; } @@ -248,6 +245,20 @@ void PostProcessManager::bindPerRenderableDescriptorSet(DriverApi& driver) const { { 0, 0 }, driver }); } +FMaterialInstance* PostProcessManager::getMaterialInstance(backend::DriverApi& driver, + FMaterial const* ma, Variant::type_t variant) const { + FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma); + mi->prepareProgram(driver, Variant{ variant }, backend::CompilerPriorityQueue::CRITICAL); + return mi; +} + +FMaterialInstance* PostProcessManager::getMaterialInstanceWithTag(backend::DriverApi& driver, + FMaterial const* ma, uint32_t tag, Variant::type_t variant) const { + FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma, tag); + mi->prepareProgram(driver, Variant { variant }, backend::CompilerPriorityQueue::CRITICAL); + return mi; +} + UboManager* PostProcessManager::getUboManager() const noexcept { return mEngine.getUboManager(); } @@ -633,8 +644,8 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph auto in = resources.getTexture(data.depth); auto& material = getPostProcessMaterial("mipmapDepth"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); - FMaterialInstance* const mi = getMaterialInstance(ma); + FMaterial const* const ma = material.getMaterial(mEngine); + FMaterialInstance* const mi = getMaterialInstance(driver, ma); // Only the depth texture is changing in the material instance (no UBO updates), // we do not move getMaterialInstance() inside the loop. @@ -998,14 +1009,13 @@ FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion( #endif auto& material = getPostProcessMaterial(materialName); - FMaterial* ma = material.getMaterial(mEngine, driver); + FMaterial* ma = material.getMaterial(mEngine); ma->getPrograms().setConstants({ { "useVisibilityBitmasks", options.gtao.useVisibilityBitmasks }, { "linearThickness", options.gtao.linearThickness }, }); - ma = material.getMaterial(mEngine, driver); - FMaterialInstance* const mi = getMaterialInstance(ma); + FMaterialInstance* const mi = getMaterialInstance(driver, ma); // Set AO type specific material parameters switch (aoType) { @@ -1191,8 +1201,8 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph auto& material = config.bentNormals ? getPostProcessMaterial("bilateralBlurBentNormals") : getPostProcessMaterial("bilateralBlur"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); - FMaterialInstance* const mi = getMaterialInstance(ma); + FMaterial const* const ma = material.getMaterial(mEngine); + FMaterialInstance* const mi = getMaterialInstance(driver, ma); mi->setParameter("ssao", ssao, { /* only reads level 0 */ }); mi->setParameter("axis", axis / float2{desc.width, desc.height}); mi->setParameter("kernel", kGaussianSamples, kGaussianCount); @@ -1360,7 +1370,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& "separableGaussianBlur4L"sv : "separableGaussianBlur4"sv; break; } auto const& separableGaussianBlur = getPostProcessMaterial(materialName); - auto ma = separableGaussianBlur.getMaterial(mEngine, driver); + auto ma = separableGaussianBlur.getMaterial(mEngine); const size_t kernelStorageSize = ma->reflect("kernel")->size; float2 kernel[64]; @@ -1876,8 +1886,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, auto inOutCoc = resources.getTexture(data.inOutCoc); auto const& material = getPostProcessMaterial("dofMipmap"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); - FMaterialInstance* const mi = getMaterialInstance(ma); + FMaterial const* const ma = material.getMaterial(mEngine); + FMaterialInstance* const mi = getMaterialInstance(driver, ma); auto const pipeline = getPipelineState(mi, variant); @@ -1887,7 +1897,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, auto const& out = resources.getRenderPassInfo(data.rp[level]); auto inColor = driver.createTextureView(inOutColor, level, 1); auto inCoc = driver.createTextureView(inOutCoc, level, 1); - FMaterialInstance* const mi = getMaterialInstance(ma); + // FIXME: is this necessary? + FMaterialInstance* const mi = getMaterialInstance(driver, ma); mi->setParameter("color", inColor, SamplerParams{ .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST }); @@ -2404,9 +2415,9 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, auto const& outDesc = resources.getDescriptor(data.out); auto const& material = getPostProcessMaterial("bloomUpsample"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); + FMaterial const* const ma = material.getMaterial(mEngine); - auto pipeline = getPipelineState(getMaterialInstance(ma)); + auto pipeline = getPipelineState(getMaterialInstance(driver, ma)); pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE; pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE; @@ -2414,7 +2425,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, // Note that we wouldn't want to use the same instance for each pass since that // would imply using the same UBOs, which implies synchronization across the // passes. - FMaterialInstance* mi = getMaterialInstance(ma); + FMaterialInstance* mi = getMaterialInstance(driver, ma); auto hwDstRT = resources.getRenderPassInfo(data.outRT[i - 1]); hwDstRT.params.flags.discardStart = TargetBufferFlags::NONE; // b/c we'll blend hwDstRT.params.flags.discardEnd = TargetBufferFlags::NONE; @@ -2547,9 +2558,10 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; auto const& material = getPostProcessMaterial("colorGradingAsSubpass"); - FMaterial const* const ma = material.getMaterial(mEngine, driver, variant); + FMaterial const* const ma = material.getMaterial(mEngine); // the UBO has been set and committed in colorGradingPrepareSubpass() - FMaterialInstance const* mi = mMaterialInstanceManager.getMaterialInstance(ma, colorGradingConfig.translucent); + FMaterialInstance const* mi = + getMaterialInstanceWithTag(driver, ma, colorGradingConfig.translucent, variant); mi->use(driver); auto const pipeline = getPipelineState(mi, variant); driver.nextSubpass(); @@ -2559,8 +2571,8 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, void PostProcessManager::customResolvePrepareSubpass(DriverApi& driver, CustomResolveOp const op) noexcept { auto const& material = getPostProcessMaterial("customResolveAsSubpass"); - auto const ma = material.getMaterial(mEngine, driver, PostProcessVariant::OPAQUE); - auto* const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0); + auto const ma = material.getMaterial(mEngine); + auto* const mi = getMaterialInstance(driver, ma, 0); mi->setParameter("direction", op == CustomResolveOp::COMPRESS ? 1.0f : -1.0f), mi->commit(driver, getUboManager()); } @@ -2570,9 +2582,9 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept { bindPerRenderableDescriptorSet(driver); auto const& material = getPostProcessMaterial("customResolveAsSubpass"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); + FMaterial const* const ma = material.getMaterial(mEngine); // the UBO has been set and committed in customResolvePrepareSubpass() - FMaterialInstance const* mi = mMaterialInstanceManager.getMaterialInstance(ma, 0); + FMaterialInstance const* mi = getMaterialInstance(driver, ma, 0); mi->use(driver); auto const pipeline = getPipelineState(mi); @@ -2611,8 +2623,8 @@ FrameGraphId PostProcessManager::customResolveUncompressPass( void PostProcessManager::clearAncillaryBuffersPrepare(DriverApi& driver, Variant::type_t variant) noexcept { auto const& material = getPostProcessMaterial("clearDepth"); - auto const ma = material.getMaterial(mEngine, driver, variant); - auto const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0); + auto const ma = material.getMaterial(mEngine); + auto const mi = getMaterialInstanceWithTag(driver, ma, 0, variant); mi->commit(driver, getUboManager()); } @@ -2627,10 +2639,10 @@ void PostProcessManager::clearAncillaryBuffers(DriverApi& driver, bindPerRenderableDescriptorSet(driver); auto const& material = getPostProcessMaterial("clearDepth"); - FMaterial const* const ma = material.getMaterial(mEngine, driver, variant); + FMaterial const* const ma = material.getMaterial(mEngine); // the UBO has been set and committed in clearAncillaryBuffersPrepare() - FMaterialInstance const* const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0); + FMaterialInstance const* const mi = getMaterialInstanceWithTag(driver, ma, 0, variant); mi->use(driver); auto pipeline = getPipelineState(mi, variant); @@ -2643,7 +2655,7 @@ void PostProcessManager::clearAncillaryBuffers(DriverApi& driver, void PostProcessManager::fogPrepare(DriverApi& driver) noexcept { // ensures the material is loaded and material instance created auto const& material = getPostProcessMaterial("fog"); - FMaterial const* const ma = material.getMaterial(mEngine, driver, PostProcessVariant::OPAQUE); + FMaterial const* const ma = material.getMaterial(mEngine); FMaterialInstance const* mi = ma->getDefaultInstance(); mi->commit(driver, getUboManager()); } @@ -2654,7 +2666,7 @@ void PostProcessManager::fog(DriverApi& driver) noexcept { bindPerRenderableDescriptorSet(driver); auto const& material = getPostProcessMaterial("fog"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); + FMaterial const* const ma = material.getMaterial(mEngine); FMaterialInstance const* mi = ma->getDefaultInstance(); mi->use(driver); @@ -2915,7 +2927,7 @@ void PostProcessManager::TaaJitterCamera( void PostProcessManager::configureTemporalAntiAliasingMaterial(backend::DriverApi& driver, TemporalAntiAliasingOptions const& taaOptions) noexcept { - FMaterial* const ma = getPostProcessMaterial("taa").getMaterial(mEngine, driver); + FMaterial* const ma = getPostProcessMaterial("taa").getMaterial(mEngine); ma->getPrograms().setConstants({ { "upscaling", taaOptions.upscaling > 1.0f }, { "historyReprojection", taaOptions.historyReprojection }, @@ -2934,7 +2946,7 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial(backend::Dr PostProcessMaterial const& material, FColorGrading const* colorGrading, ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions, uint32_t const width, uint32_t const height) noexcept { - FMaterial* ma = material.getMaterial(mEngine, driver); + FMaterial* ma = material.getMaterial(mEngine); ma->getPrograms().setConstants({ { "isOneDimensional", colorGrading->isOneDimensional() }, { "isLDR", colorGrading->isLDR() }, @@ -2943,8 +2955,9 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial(backend::Dr PostProcessVariant const variant = colorGradingConfig.translucent ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; - ma = material.getMaterial(mEngine, driver, variant); - FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma, colorGradingConfig.translucent); + ma = material.getMaterial(mEngine); + FMaterialInstance* mi = + getMaterialInstanceWithTag(driver, ma, colorGradingConfig.translucent, variant); const SamplerParams params = SamplerParams{ .filterMag = SamplerMagFilter::LINEAR, @@ -3056,9 +3069,9 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, PostProcessVariant const variant = colorGradingConfig.translucent ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; - FMaterial const* const ma = material.getMaterial(mEngine, driver, variant); + FMaterial const* const ma = material.getMaterial(mEngine); - FMaterialInstance* mi = getMaterialInstance(ma); + FMaterialInstance* mi = getMaterialInstance(driver, ma); mi->setParameter("color", color, SamplerParams{}); // nearest mi->setParameter("depth", depth, SamplerParams{}); // nearest mi->setParameter("history", history, SamplerParams{ @@ -3547,8 +3560,8 @@ FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool co PostProcessMaterial const& material = getPostProcessMaterial(layer ? "blitArray" : "blitLow"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); - auto* mi = getMaterialInstance(ma); + FMaterial const* const ma = material.getMaterial(mEngine); + auto* mi = getMaterialInstance(driver, ma); mi->setParameter("color", color, SamplerParams{ .filterMag = filterMag, .filterMin = filterMin @@ -3806,8 +3819,8 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg uint32_t const dim = std::max(1u, width >> (level + 1)); auto& material = getPostProcessMaterial("vsmMipmap"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); - FMaterialInstance* const mi = getMaterialInstance(ma); + FMaterial const* const ma = material.getMaterial(mEngine); + FMaterialInstance* const mi = getMaterialInstance(driver, ma); auto const pipeline = getPipelineState(mi); backend::Viewport const scissor = { 0, 0, dim, dim }; @@ -3906,10 +3919,10 @@ FrameGraphId PostProcessManager::debugCombineArrayTexture(Fra // set uniforms PostProcessMaterial const& material = getPostProcessMaterial("blitArray"); - FMaterial const* const ma = material.getMaterial(mEngine, driver); + FMaterial const* const ma = material.getMaterial(mEngine); // It should be ok to not move this getMaterialInstance to inside the loop, since // this is a pass meant for debug. - auto* mi = getMaterialInstance(ma); + auto* mi = getMaterialInstance(driver, ma); mi->setParameter("color", color, SamplerParams{ .filterMag = filterMag, .filterMin = filterMin diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 3c4a96f84d..22c5049ee3 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -357,13 +357,7 @@ public: void terminate(FEngine& engine) noexcept; - FMaterial* getMaterial(FEngine& engine, backend::DriverApi& driver, - Variant::type_t variant) const noexcept; - - FMaterial* getMaterial(FEngine& engine, backend::DriverApi& driver, - PostProcessVariant variant = PostProcessVariant::OPAQUE) const noexcept { - return getMaterial(engine, driver, Variant::type_t(variant)); - } + FMaterial* getMaterial(FEngine& engine) const noexcept; private: void loadMaterial(FEngine& engine) const noexcept; @@ -428,17 +422,37 @@ private: void bindPerRenderableDescriptorSet(backend::DriverApi& driver) const noexcept; - // Helper to get a MaterialInstance from a FMaterial - // This currently just call FMaterial::getDefaultInstance(). - FMaterialInstance* getMaterialInstance(FMaterial const* ma) { - return mMaterialInstanceManager.getMaterialInstance(ma); + // Helpers to get MaterialInstances. + // + // These funcions additionally ensure that the necessary shader programs are compiled via + // prepareProgram(). + FMaterialInstance* getMaterialInstance(backend::DriverApi& driver, FMaterial const* ma, + Variant::type_t variant) const; + + FMaterialInstance* getMaterialInstance(backend::DriverApi& driver, FMaterial const* ma, + PostProcessVariant variant = PostProcessVariant::OPAQUE) const { + return getMaterialInstance(driver, ma, Variant::type_t(variant)); } - // Helper to get a MaterialInstance from a PostProcessMaterial. - FMaterialInstance* getMaterialInstance(FEngine& engine, backend::DriverApi& driver, PostProcessMaterial const& material, - PostProcessVariant variant = PostProcessVariant::OPAQUE) { - FMaterial const* ma = material.getMaterial(engine, driver, variant); - return getMaterialInstance(ma); + FMaterialInstance* getMaterialInstance(FEngine& engine, backend::DriverApi& driver, + PostProcessMaterial const& material, + PostProcessVariant variant = PostProcessVariant::OPAQUE) const { + return getMaterialInstance(driver, material.getMaterial(engine), Variant::type_t(variant)); + } + + FMaterialInstance* getMaterialInstanceWithTag(backend::DriverApi& driver, FMaterial const* ma, + uint32_t tag, Variant::type_t variant) const; + + FMaterialInstance* getMaterialInstanceWithTag(backend::DriverApi& driver, FMaterial const* ma, + uint32_t tag, PostProcessVariant variant = PostProcessVariant::OPAQUE) const { + return getMaterialInstanceWithTag(driver, ma, tag, Variant::type_t(variant)); + } + + FMaterialInstance* getMaterialInstanceWithTag(FEngine& engine, backend::DriverApi& driver, + PostProcessMaterial const& material, uint32_t tag, + PostProcessVariant variant = PostProcessVariant::OPAQUE) const { + return getMaterialInstanceWithTag(driver, material.getMaterial(engine), tag, + Variant::type_t(variant)); } UboManager* getUboManager() const noexcept; diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index 7a87ebc964..0b37bf5e8c 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -426,16 +426,18 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant, bool const isBlendingCommand = !hasScreenSpaceRefraction && (blendingMode != BlendingMode::OPAQUE && blendingMode != BlendingMode::MASKED); + RasterState rasterState = mi->getRasterState(); + uint64_t keyDraw = cmdDraw.key; keyDraw &= ~(PASS_MASK | BLENDING_MASK | MATERIAL_MASK); keyDraw |= uint64_t(hasScreenSpaceRefraction ? Pass::REFRACT : Pass::COLOR); keyDraw |= uint64_t(CustomCommand::PASS); keyDraw |= mi->getSortingKey(); // already all set-up for direct or'ing keyDraw |= makeField(variant.key, MATERIAL_VARIANT_KEY_MASK, MATERIAL_VARIANT_KEY_SHIFT); - keyDraw |= makeField(ma->getRasterState().alphaToCoverage, BLENDING_MASK, BLENDING_SHIFT); + keyDraw |= makeField(rasterState.alphaToCoverage, BLENDING_MASK, BLENDING_SHIFT); cmdDraw.key = isBlendingCommand ? keyBlending : keyDraw; - cmdDraw.info.rasterState = mi->getRasterState(); + cmdDraw.info.rasterState = rasterState; // for SSR pass, the blending mode of opaques (including MASKED) must be off // see Material.cpp.