diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/ImGuiUtils.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/ImGuiUtils.h index a200f30c98..52e272a9c4 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/ImGuiUtils.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/ImGuiUtils.h @@ -50,12 +50,12 @@ namespace AZ return scope; } - //! Sets the active context based on the provided PassHierarchyFilter. If the filter doesn't match exactly one pass, then do nothing. - static ImGuiActiveContextScope FromPass(const RPI::PassHierarchyFilter& passHierarchyFilter) + //! Sets the active context based on the provided pass hierarchy filter. If the filter doesn't match exactly one pass, then do nothing. + static ImGuiActiveContextScope FromPass(const AZStd::vector& passHierarchy) { ImGuiActiveContextScope scope; scope.ConnectToImguiNotificationBus(); - ImGuiSystemRequestBus::BroadcastResult(scope.m_isEnabled, &ImGuiSystemRequests::PushActiveContextFromPass, passHierarchyFilter); + ImGuiSystemRequestBus::BroadcastResult(scope.m_isEnabled, &ImGuiSystemRequests::PushActiveContextFromPass, passHierarchy); return scope; } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/SystemBus.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/SystemBus.h index 289cb178d4..78f71b39ba 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/SystemBus.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ImGui/SystemBus.h @@ -15,11 +15,6 @@ namespace AZ { - namespace RPI - { - class PassHierarchyFilter; - } - namespace Render { class ImGuiPass; @@ -51,7 +46,7 @@ namespace AZ //! Pushes whichever ImGui pass is default on the top of the active context stack. Returns true/false for success/fail. virtual bool PushActiveContextFromDefaultPass() = 0; //! Pushes whichever ImGui pass is provided in passHierarchy on the top of the active context stack. Returns true/false for success/fail. - virtual bool PushActiveContextFromPass(const RPI::PassHierarchyFilter& passHierarchy) = 0; + virtual bool PushActiveContextFromPass(const AZStd::vector& passHierarchy) = 0; //! Pops the active context off the top of the active context stack. Returns true if there's a context to pop. virtual bool PopActiveContext() = 0; //! Gets the context at the top of the active context stack. Returns nullptr if the stack is emtpy. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/FrameCaptureBus.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/FrameCaptureBus.h index 93600ec08f..c80926700e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/FrameCaptureBus.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/FrameCaptureBus.h @@ -50,7 +50,7 @@ namespace AZ virtual bool CaptureScreenshotWithPreview(const AZStd::string& outputFilePath) = 0; //! Save a buffer attachment or a image attachment binded to a pass's slot to a data file. - //! @param passHierarchy For finding the pass by using PassHierarchyFilter + //! @param passHierarchy For finding the pass by using a pass hierarchy filter. Check PassFilter::CreateWithPassHierarchy() function for detail //! @param slotName Name of the pass's slot. The attachment bound to this slot will be captured. //! @param option Only valid for an InputOutput attachment. Use PassAttachmentReadbackOption::Input to capture the input state //! and use PassAttachmentReadbackOption::Output to capture the output state diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 6c24b7d35b..b6c6910fd3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -647,54 +647,46 @@ namespace AZ UpdateViewsOfCascadeSegments(); } - void DirectionalLightFeatureProcessor::CacheCascadedShadowmapsPass() { - const AZStd::vector& passes = RPI::PassSystemInterface::Get()->GetPassesForTemplateName(Name("CascadedShadowmapsTemplate")); + void DirectionalLightFeatureProcessor::CacheCascadedShadowmapsPass() + { m_cascadedShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - if (RPI::RenderPipeline* pipeline = pass->GetRenderPipeline()) + + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(Name("CascadedShadowmapsTemplate"), GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { + RPI::RenderPipeline* pipeline = pass->GetRenderPipeline(); const RPI::RenderPipelineId pipelineId = pipeline->GetId(); - // This function can be called when the pipeline is not attached to the scene. - // So we check it is attached to the scene. - if (GetParentScene()->GetRenderPipeline(pipelineId).get() == pipeline) + + CascadedShadowmapsPass* shadowPass = azrtti_cast(pass); + AZ_Assert(shadowPass, "It is not a CascadedShadowmapPass."); + if (pipeline->GetDefaultView()) { - CascadedShadowmapsPass* shadowPass = azrtti_cast(pass); - AZ_Assert(shadowPass, "It is not a CascadedShadowmapPass."); - if (pipeline->GetDefaultView()) - { - m_cascadedShadowmapsPasses[pipelineId].push_back(shadowPass); - } + m_cascadedShadowmapsPasses[pipelineId].push_back(shadowPass); } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void DirectionalLightFeatureProcessor::CacheEsmShadowmapsPass() { - const AZStd::vector& passes = RPI::PassSystemInterface::Get()->GetPassesForTemplateName(Name("EsmShadowmapsTemplate")); m_esmShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - if (RPI::RenderPipeline* pipeline = pass->GetRenderPipeline()) + + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(Name("EsmShadowmapsTemplate"), GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { - const RPI::RenderPipelineId pipelineId = pipeline->GetId(); - // checking the render pipeline is just removed from the scene. - if (GetParentScene()->GetRenderPipeline(pipelineId).get() == pipeline) + const RPI::RenderPipelineId pipelineId = pass->GetRenderPipeline()->GetId(); + + if (m_cascadedShadowmapsPasses.find(pipelineId) != m_cascadedShadowmapsPasses.end()) { - if (m_cascadedShadowmapsPasses.find(pipelineId) != m_cascadedShadowmapsPasses.end()) + EsmShadowmapsPass* esmPass = azrtti_cast(pass); + AZ_Assert(esmPass, "It is not an EsmShadowmapPass."); + if (esmPass->GetLightTypeName() == m_lightTypeName) { - EsmShadowmapsPass* esmPass = azrtti_cast(pass); - AZ_Assert(esmPass, "It is not an EsmShadowmapPass."); - if (m_cascadedShadowmapsPasses.find(esmPass->GetRenderPipeline()->GetId()) != m_cascadedShadowmapsPasses.end() && - esmPass->GetLightTypeName() == m_lightTypeName) - { - m_esmShadowmapsPasses[pipelineId].push_back(esmPass); - } + m_esmShadowmapsPasses[pipelineId].push_back(esmPass); } } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void DirectionalLightFeatureProcessor::PrepareCameraViews() @@ -1063,12 +1055,13 @@ namespace AZ // if the shadow is rendering in an EnvironmentCubeMapPass it also needs to be a ReflectiveCubeMap view, // to filter out shadows from objects that are excluded from the cubemap - RPI::PassClassFilter passFilter; - AZStd::vector cubeMapPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter); - if (!cubeMapPasses.empty()) - { - usageFlags |= RPI::View::UsageReflectiveCubeMap; - } + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass(); + passFilter.SetOwenrScene(GetParentScene()); // only handles passes for this scene + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [&usageFlags]([[maybe_unused]] RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + usageFlags |= RPI::View::UsageReflectiveCubeMap; + return RPI::PassFilterExecutionFlow::StopVisitingPasses; + }); segment.m_view = RPI::View::CreateView(viewName, usageFlags); } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp index c085b26e31..453dbbc0ab 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp @@ -80,35 +80,48 @@ namespace AZ } // update the size multiplier on the DiffuseProbeGridDownsamplePass output - AZStd::vector downsamplePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseProbeGridDownsamplePass") }; - RPI::PassHierarchyFilter downsamplePassFilter(downsamplePassHierarchy); - const AZStd::vector& downsamplePasses = RPI::PassSystemInterface::Get()->FindPasses(downsamplePassFilter); - for (RPI::Pass* pass : downsamplePasses) + // NOTE: The ownerScene wasn't added to both filters. This is because the passes from the non-owner scene may have invalid SRG values which could lead to + // GPU error if the scene doesn't have this feature processor enabled. + // For example, the ASV MultiScene sample may have TDR. { - for (uint32_t outputIndex = 0; outputIndex < pass->GetOutputCount(); ++outputIndex) - { - RPI::Ptr outputAttachment = pass->GetOutputBinding(outputIndex).m_attachment; - RPI::PassAttachmentSizeMultipliers& sizeMultipliers = outputAttachment->m_sizeMultipliers; - - sizeMultipliers.m_widthMultiplier = sizeMultiplier; - sizeMultipliers.m_heightMultiplier = sizeMultiplier; - } - - // set the output scale on the PassSrg - RPI::FullscreenTrianglePass* downsamplePass = static_cast(pass); - auto constantIndex = downsamplePass->GetShaderResourceGroup()->FindShaderInputConstantIndex(Name("m_outputImageScale")); - downsamplePass->GetShaderResourceGroup()->SetConstant(constantIndex, aznumeric_cast(1.0f / sizeMultiplier)); + AZStd::vector downsamplePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseProbeGridDownsamplePass") }; + RPI::PassFilter downsamplePassFilter = RPI::PassFilter::CreateWithPassHierarchy(downsamplePassHierarchy); + RPI::PassSystemInterface::Get()->ForEachPass( + downsamplePassFilter, + [sizeMultiplier](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + for (uint32_t outputIndex = 0; outputIndex < pass->GetOutputCount(); ++outputIndex) + { + RPI::Ptr outputAttachment = pass->GetOutputBinding(outputIndex).m_attachment; + RPI::PassAttachmentSizeMultipliers& sizeMultipliers = outputAttachment->m_sizeMultipliers; + + sizeMultipliers.m_widthMultiplier = sizeMultiplier; + sizeMultipliers.m_heightMultiplier = sizeMultiplier; + } + + // set the output scale on the PassSrg + RPI::FullscreenTrianglePass* downsamplePass = static_cast(pass); + RHI::ShaderInputNameIndex outputImageScaleShaderInput = "m_outputImageScale"; + downsamplePass->GetShaderResourceGroup()->SetConstant( + outputImageScaleShaderInput, aznumeric_cast(1.0f / sizeMultiplier)); + + // handle all downsample passes + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } // update the image scale on the DiffuseComposite pass - AZStd::vector compositePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseCompositePass") }; - RPI::PassHierarchyFilter compositePassFilter(compositePassHierarchy); - const AZStd::vector& compositePasses = RPI::PassSystemInterface::Get()->FindPasses(compositePassFilter); - for (RPI::Pass* pass : compositePasses) { - RPI::FullscreenTrianglePass* compositePass = static_cast(pass); - auto constantIndex = compositePass->GetShaderResourceGroup()->FindShaderInputConstantIndex(Name("m_imageScale")); - compositePass->GetShaderResourceGroup()->SetConstant(constantIndex, aznumeric_cast(1.0f / sizeMultiplier)); + AZStd::vector compositePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseCompositePass") }; + RPI::PassFilter compositePassFilter = RPI::PassFilter::CreateWithPassHierarchy(compositePassHierarchy); + RPI::PassSystemInterface::Get()->ForEachPass(compositePassFilter, [sizeMultiplier](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + RPI::FullscreenTrianglePass* compositePass = static_cast(pass); + RHI::ShaderInputNameIndex imageScaleShaderInput = "m_imageScale"; + compositePass->GetShaderResourceGroup()->SetConstant(imageScaleShaderInput, aznumeric_cast(1.0f / sizeMultiplier)); + + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } } } // namespace Render diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index 4329fd556c..5ea4748fc9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -603,12 +603,12 @@ namespace AZ RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); if (device->GetFeatures().m_rayTracing == false) { - RPI::PassHierarchyFilter updatePassFilter(AZ::Name("DiffuseProbeGridUpdatePass")); - const AZStd::vector& updatePasses = RPI::PassSystemInterface::Get()->FindPasses(updatePassFilter); - for (RPI::Pass* pass : updatePasses) - { - pass->SetEnabled(false); - } + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("DiffuseProbeGridUpdatePass"), GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + pass->SetEnabled(false); + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp index 3ec8840a1c..5b5599383e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp @@ -10,9 +10,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -66,22 +67,14 @@ namespace AZ { // Need to invalidate the CopyToSwapChain pass so that it updates the pipeline state in the event that // the swapchain format changed (for example, moving from LDR to HDR display) - auto* passSystem = RPI::PassSystemInterface::Get(); - const Name fullscreenCopyTemplateName("FullscreenCopyTemplate"); - - if (passSystem->HasPassesForTemplateName(fullscreenCopyTemplateName)) - { - const AZStd::vector& passes = passSystem->GetPassesForTemplateName(fullscreenCopyTemplateName); - for (RPI::Pass* pass : passes) + const Name copyToSwapChainPassName("CopyToSwapChain"); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(copyToSwapChainPassName, GetRenderPipeline()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { - RPI::FullscreenTrianglePass* fullscreenTrianglePass = azrtti_cast(pass); - const Name& passName = fullscreenTrianglePass->GetName(); - if (passName.GetStringView() == "CopyToSwapChain") - { - fullscreenTrianglePass->QueueForInitialization(); - } - } - } + pass->QueueForInitialization(); + return RPI::PassFilterExecutionFlow::StopVisitingPasses; + }); + ConfigureDisplayParameters(); } diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp index 8c0360dec2..ed2d8a1d9f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp @@ -372,29 +372,25 @@ namespace AZ } m_latestCaptureInfo.clear(); - // Find the pass first - RPI::PassClassFilter passFilter; - AZStd::vector foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter); - - if (foundPasses.size() == 0) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass(); + AZ::RPI::ImageAttachmentPreviewPass* previewPass = azrtti_cast(RPI::PassSystemInterface::Get()->FindFirstPass(passFilter)); + if (!previewPass) { - AZ_Warning("FrameCaptureSystemComponent", false, "Failed to find an ImageAttachmentPreviewPass pass "); + AZ_Warning("FrameCaptureSystemComponent", false, "Failed to find an ImageAttachmentPreviewPass"); return false; } - AZ::RPI::ImageAttachmentPreviewPass* previewPass = azrtti_cast(foundPasses[0]); bool result = previewPass->ReadbackOutput(m_readback); if (result) { m_state = State::Pending; m_result = FrameCaptureResult::None; SystemTickBus::Handler::BusConnect(); + return true; } - else - { - AZ_Warning("FrameCaptureSystemComponent", false, "CaptureScreenshotWithPreview. Failed to readback output from the ImageAttachmentPreviewPass");; - } - return result; + + AZ_Warning("FrameCaptureSystemComponent", false, "CaptureScreenshotWithPreview. Failed to readback output from the ImageAttachmentPreviewPass"); + return false; } bool FrameCaptureSystemComponent::CapturePassAttachment(const AZStd::vector& passHierarchy, const AZStd::string& slot, @@ -405,6 +401,12 @@ namespace AZ return false; } + if (passHierarchy.size() == 0) + { + AZ_Warning("FrameCaptureSystemComponent", false, "Empty data in passHierarchy"); + return false; + } + InitReadback(); if (m_state != State::Idle) @@ -426,17 +428,15 @@ namespace AZ } m_latestCaptureInfo.clear(); - // Find the pass first - AZ::RPI::PassHierarchyFilter passFilter(passHierarchy); - AZStd::vector foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassHierarchy(passHierarchy); + RPI::Pass* pass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); - if (foundPasses.size() == 0) + if (!pass) { - AZ_Warning("FrameCaptureSystemComponent", false, "Failed to find pass from %s", passFilter.ToString().c_str()); + AZ_Warning("FrameCaptureSystemComponent", false, "Failed to find pass from %s", passHierarchy[0].c_str()); return false; } - AZ::RPI::Pass* pass = foundPasses[0]; if (pass->ReadbackAttachment(m_readback, Name(slot), option)) { m_state = State::Pending; @@ -444,6 +444,7 @@ namespace AZ SystemTickBus::Handler::BusConnect(); return true; } + AZ_Warning("FrameCaptureSystemComponent", false, "Failed to readback the attachment bound to pass [%s] slot [%s]", pass->GetName().GetCStr(), slot.c_str()); return false; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.cpp index afca20c5cb..3783752e67 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.cpp @@ -109,15 +109,15 @@ namespace AZ void ImGuiSystemComponent::ForAllImGuiPasses(PassFunction func) { ImGuiContext* contextToRestore = ImGui::GetCurrentContext(); - RPI::PassClassFilter filter; - auto imguiPasses = RPI::PassSystemInterface::Get()->FindPasses(filter); - - for (RPI::Pass* pass : imguiPasses) - { - ImGuiPass* imguiPass = azrtti_cast(pass); - ImGui::SetCurrentContext(imguiPass->GetContext()); - func(imguiPass); - } + + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass(); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [func](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + ImGuiPass* imguiPass = azrtti_cast(pass); + ImGui::SetCurrentContext(imguiPass->GetContext()); + func(imguiPass); + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); ImGui::SetCurrentContext(contextToRestore); } @@ -169,29 +169,37 @@ namespace AZ return false; } - bool ImGuiSystemComponent::PushActiveContextFromPass(const RPI::PassHierarchyFilter& passHierarchyFilter) + bool ImGuiSystemComponent::PushActiveContextFromPass(const AZStd::vector& passHierarchyFilter) { - AZStd::vector foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passHierarchyFilter); + if (passHierarchyFilter.size() == 0) + { + AZ_Warning("ImGuiSystemComponent", false, "passHierarchyFilter is empty"); + return false; + } + AZStd::vector foundImGuiPasses; - for (RPI::Pass* pass : foundPasses) - { - ImGuiPass* imGuiPass = azrtti_cast(pass); - if (imGuiPass) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassHierarchy(passHierarchyFilter); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [&foundImGuiPasses](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { - foundImGuiPasses.push_back(imGuiPass); - } - } + ImGuiPass* imGuiPass = azrtti_cast(pass); + if (imGuiPass) + { + foundImGuiPasses.push_back(imGuiPass); + } + + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); if (foundImGuiPasses.size() == 0) { - AZ_Warning("ImGuiSystemComponent", false, "Failed to find ImGui pass to activate from %s", passHierarchyFilter.ToString().c_str()); + AZ_Warning("ImGuiSystemComponent", false, "Failed to find ImGui pass to activate from %s", passHierarchyFilter[0].c_str()); return false; } if (foundImGuiPasses.size() > 1) { - AZ_Warning("ImGuiSystemComponent", false, "Found more than one ImGui pass to activate from %s, only activating first one.", passHierarchyFilter.ToString().c_str()); + AZ_Warning("ImGuiSystemComponent", false, "Found more than one ImGui pass to activate from %s, only activating first one.", passHierarchyFilter[0].c_str()); } ImGuiContext* context = foundImGuiPasses.at(0)->GetContext(); diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.h index 838cf0b3c2..d59124890f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiSystemComponent.h @@ -56,7 +56,7 @@ namespace AZ ImGuiPass* GetDefaultImGuiPass() override; bool PushActiveContextFromDefaultPass() override; - bool PushActiveContextFromPass(const RPI::PassHierarchyFilter& passHierarchy) override; + bool PushActiveContextFromPass(const AZStd::vector& passHierarchy) override; bool PopActiveContext() override; ImGuiContext* GetActiveContext() override; diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/DepthOfField/DepthOfFieldSettings.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/DepthOfField/DepthOfFieldSettings.cpp index fe1ce8a281..98b527868d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/DepthOfField/DepthOfFieldSettings.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/DepthOfField/DepthOfFieldSettings.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -259,24 +260,19 @@ namespace AZ // [GFX TODO][ATOM-3035]This function is temporary and will change with improvement to the draw list tag system void DepthOfFieldSettings::UpdateAutoFocusDepth(bool enabled) - { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); + { const Name TemplateNameReadBackFocusDepth = Name("DepthOfFieldReadBackFocusDepthTemplate"); - if (passSystem->HasPassesForTemplateName(TemplateNameReadBackFocusDepth)) - { - const AZStd::vector& dofPasses = passSystem->GetPassesForTemplateName(TemplateNameReadBackFocusDepth); - for (RPI::Pass* pass : dofPasses) + // [GFX TODO][ATOM-4908] multiple camera should be distingushed. + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(TemplateNameReadBackFocusDepth, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, enabled](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { auto* dofPass = azrtti_cast(pass); - // Check this pass belongs to a render pipeline of the scene. - // [GFX TODO][ATOM-4908] multiple camera should be distingushed. - const RPI::RenderPipelineId pipelineId = dofPass->GetRenderPipeline()->GetId(); - if (enabled && GetParentScene()->GetRenderPipeline(pipelineId)) + if (enabled) { m_normalizedFocusDistanceForAutoFocus = dofPass->GetNormalizedFocusDistanceForAutoFocus(); } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void DepthOfFieldSettings::SetCameraEntityId(EntityId cameraEntityId) diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp index 96ca424307..26c2a61d54 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -188,21 +189,21 @@ namespace AZ void ExposureControlSettings::UpdateLuminanceHeatmap() { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - // [GFX-TODO][ATOM-13194] Support multiple views for the luminance heatmap - // [GFX-TODO][ATOM-13224] Remove UpdateLuminanceHeatmap and UpdateEyeAdaptationPass - const RPI::Ptr luminanceHeatmap = passSystem->GetRootPass()->FindPassByNameRecursive(m_luminanceHeatmapNameId); - if (luminanceHeatmap) - { - luminanceHeatmap->SetEnabled(m_heatmapEnabled); - } - - const RPI::Ptr histogramGenerator = passSystem->GetRootPass()->FindPassByNameRecursive(m_luminanceHistogramGeneratorNameId); - if (histogramGenerator) - { - histogramGenerator->SetEnabled(m_heatmapEnabled); - } + // [GFX-TODO][ATOM-13224] Remove UpdateLuminanceHeatmap and UpdateEyeAdaptationPass + RPI::PassFilter heatmapPassFilter = RPI::PassFilter::CreateWithPassName(m_luminanceHeatmapNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(heatmapPassFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + pass->SetEnabled(m_heatmapEnabled); + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); + + RPI::PassFilter histogramPassFilter = RPI::PassFilter::CreateWithPassName(m_luminanceHistogramGeneratorNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(histogramPassFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + pass->SetEnabled(m_heatmapEnabled); + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void ExposureControlSettings::UpdateBuffer() diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LookModificationCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LookModificationCompositePass.cpp index 85c45de96b..aac3d1d941 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LookModificationCompositePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LookModificationCompositePass.cpp @@ -31,12 +31,14 @@ namespace AZ 0, [](const uint8_t& value) { - auto passes = RPI::PassSystem::Get()->FindPasses(RPI::PassClassFilter()); - for (auto* pass : passes) - { - LookModificationCompositePass* lookModPass = azrtti_cast(pass); - lookModPass->SetSampleQuality(LookModificationCompositePass::SampleQuality(value)); - } + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass(); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [value](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + LookModificationCompositePass* lookModPass = azrtti_cast(pass); + lookModPass->SetSampleQuality(LookModificationCompositePass::SampleQuality(value)); + + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); }, ConsoleFunctorFlags::Null, "This can be increased to deal with particularly tricky luts. Range (0-2). 0 (default) - Standard linear sampling. 1 - 7 tap b-spline sampling. 2 - 19 tap b-spline sampling." diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp index eef0c51e95..ad059fbec0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -71,26 +72,18 @@ namespace AZ void SMAAFeatureProcessor::UpdateConvertToPerceptualPass() { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - - if (passSystem->HasPassesForTemplateName(m_convertToPerceptualColorPassTemplateNameId)) - { - const AZStd::vector& convertToPerceptualColorPasses = passSystem->GetPassesForTemplateName(m_convertToPerceptualColorPassTemplateNameId); - for (RPI::Pass* pass : convertToPerceptualColorPasses) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(m_convertToPerceptualColorPassTemplateNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { pass->SetEnabled(m_data.m_enable); - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void SMAAFeatureProcessor::UpdateEdgeDetectionPass() - { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - - if (passSystem->HasPassesForTemplateName(m_edgeDetectioPassTemplateNameId)) - { - const AZStd::vector& edgeDetectionPasses = passSystem->GetPassesForTemplateName(m_edgeDetectioPassTemplateNameId); - for (RPI::Pass* pass : edgeDetectionPasses) + { + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(m_edgeDetectioPassTemplateNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { auto* edgeDetectionPass = azrtti_cast(pass); @@ -106,18 +99,14 @@ namespace AZ edgeDetectionPass->SetPredicationScale(m_data.m_predicationScale); edgeDetectionPass->SetPredicationStrength(m_data.m_predicationStrength); } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void SMAAFeatureProcessor::UpdateBlendingWeightCalculationPass() { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - - if (passSystem->HasPassesForTemplateName(m_blendingWeightCalculationPassTemplateNameId)) - { - const AZStd::vector& blendingWeightCalculationPasses = passSystem->GetPassesForTemplateName(m_blendingWeightCalculationPassTemplateNameId); - for (RPI::Pass* pass : blendingWeightCalculationPasses) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(m_blendingWeightCalculationPassTemplateNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { auto* blendingWeightCalculationPass = azrtti_cast(pass); @@ -130,18 +119,14 @@ namespace AZ blendingWeightCalculationPass->SetDiagonalDetectionEnable(m_data.m_enableDiagonalDetection); blendingWeightCalculationPass->SetCornerDetectionEnable(m_data.m_enableCornerDetection); } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void SMAAFeatureProcessor::UpdateNeighborhoodBlendingPass() { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - - if (passSystem->HasPassesForTemplateName(m_neighborhoodBlendingPassTemplateNameId)) - { - const AZStd::vector& neighborhoodBlendingPasses = passSystem->GetPassesForTemplateName(m_neighborhoodBlendingPassTemplateNameId); - for (RPI::Pass* pass : neighborhoodBlendingPasses) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(m_neighborhoodBlendingPassTemplateNameId, GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { auto* neighborhoodBlendingPass = azrtti_cast(pass); @@ -153,8 +138,8 @@ namespace AZ { neighborhoodBlendingPass->SetOutputMode(SMAAOutputMode::PassThrough); } - } - } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void SMAAFeatureProcessor::Render([[maybe_unused]] const SMAAFeatureProcessor::RenderPacket& packet) diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 66adfe9985..9bfb2b7e9e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -377,14 +377,7 @@ namespace AZ bool ProfilingCaptureSystemComponent::CapturePassTimestamp(const AZStd::string& outputFilePath) { - // Find the root pass. - AZStd::vector passes = FindPasses({ "Root" }); - if (passes.empty()) - { - return false; - } - - RPI::Pass* root = passes[0]; + RPI::Pass* root = AZ::RPI::PassSystemInterface::Get()->GetRootPass().get(); // Enable all the Timestamp queries in passes. root->SetTimestampQueryEnabled(true); @@ -465,14 +458,7 @@ namespace AZ bool ProfilingCaptureSystemComponent::CapturePassPipelineStatistics(const AZStd::string& outputFilePath) { - // Find the root pass. - AZStd::vector passes = FindPasses({ "Root" }); - if (passes.empty()) - { - return false; - } - - RPI::Pass* root = passes[0]; + RPI::Pass* root = AZ::RPI::PassSystemInterface::Get()->GetRootPass().get(); // Enable all the PipelineStatistics queries in passes. root->SetPipelineStatisticsQueryEnabled(true); @@ -572,19 +558,6 @@ namespace AZ return passes; } - AZStd::vector ProfilingCaptureSystemComponent::FindPasses(AZStd::vector&& passHierarchy) const - { - // Find the pass first. - RPI::PassHierarchyFilter passFilter(passHierarchy); - AZStd::vector foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter); - if (foundPasses.size() == 0) - { - AZ_Warning("ProfilingCaptureSystemComponent", false, "Failed to find pass from %s", passFilter.ToString().c_str()); - } - - return foundPasses; - } - void ProfilingCaptureSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time) { // Update the delayed captures diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h index a9bb8c585f..af1d2f5643 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h @@ -78,8 +78,6 @@ namespace AZ // Recursively collect all the passes from the root pass. AZStd::vector CollectPassesRecursively(const RPI::Pass* root) const; - AZStd::vector FindPasses(AZStd::vector&& passHierarchy) const; - DelayedQueryCaptureHelper m_timestampCapture; DelayedQueryCaptureHelper m_cpuFrameTimeStatisticsCapture; DelayedQueryCaptureHelper m_pipelineStatisticsCapture; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp index 37b1885ee3..a1858a7e9d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp @@ -28,16 +28,17 @@ namespace AZ void ReflectionCopyFrameBufferPass::BuildInternal() { - RPI::PassHierarchyFilter passFilter(AZ::Name("ReflectionScreenSpaceBlurPass")); - const AZStd::vector& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter); - if (!passes.empty()) - { - Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(passes.front()); - Data::Instance& frameBufferAttachment = blurPass->GetFrameBufferImageAttachment(); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceBlurPass"), GetRenderPipeline()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(pass); + Data::Instance& frameBufferAttachment = blurPass->GetFrameBufferImageAttachment(); - RPI::PassAttachmentBinding& outputBinding = GetOutputBinding(0); - AttachImageToSlot(outputBinding.m_name, frameBufferAttachment); - } + RPI::PassAttachmentBinding& outputBinding = GetOutputBinding(0); + AttachImageToSlot(outputBinding.m_name, frameBufferAttachment); + + return RPI::PassFilterExecutionFlow::StopVisitingPasses; + }); FullscreenTrianglePass::BuildInternal(); } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp index 394a6fd406..edd7ad1013 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp @@ -150,7 +150,7 @@ namespace AZ auto transientImageDesc = RHI::ImageDescriptor::Create2D(imageBindFlags, mipSize.m_width, mipSize.m_height, RHI::Format::R16G16B16A16_FLOAT); RPI::PassAttachment* transientPassAttachment = aznew RPI::PassAttachment(); - AZStd::string transientAttachmentName = AZStd::string::format("ReflectionScreenSpace_BlurImage%d", mip); + AZStd::string transientAttachmentName = AZStd::string::format("%s.ReflectionScreenSpace_BlurImage%d", GetPathName().GetCStr(), mip); transientPassAttachment->m_name = transientAttachmentName; transientPassAttachment->m_path = transientAttachmentName; transientPassAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp index 1cf227650c..1362191691 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp @@ -33,20 +33,22 @@ namespace AZ return; } - RPI::PassHierarchyFilter passFilter(AZ::Name("ReflectionScreenSpaceBlurPass")); - const AZStd::vector& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter); - if (!passes.empty()) - { - Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(passes.front()); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceBlurPass"), GetRenderPipeline()); - // compute the max mip level based on the available mips in the previous frame image, and capping it - // to stay within a range that has reasonable data - const uint32_t MaxNumRoughnessMips = 8; - uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1; + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow + { + Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(pass); - auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel")); - m_shaderResourceGroup->SetConstant(constantIndex, maxMipLevel); - } + // compute the max mip level based on the available mips in the previous frame image, and capping it + // to stay within a range that has reasonable data + const uint32_t MaxNumRoughnessMips = 8; + uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1; + + auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel")); + m_shaderResourceGroup->SetConstant(constantIndex, maxMipLevel); + + return RPI::PassFilterExecutionFlow::StopVisitingPasses; + }); FullscreenTrianglePass::CompileResources(context); } diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 7c0b3563c7..70ccaa5702 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -313,52 +313,38 @@ namespace AZ::Render void ProjectedShadowFeatureProcessor::CachePasses() { - const AZStd::vector validPipelineIds = CacheProjectedShadowmapsPass(); - CacheEsmShadowmapsPass(validPipelineIds); + CacheProjectedShadowmapsPass(); + CacheEsmShadowmapsPass(); m_shadowmapPassNeedsUpdate = true; } - AZStd::vector ProjectedShadowFeatureProcessor::CacheProjectedShadowmapsPass() + void ProjectedShadowFeatureProcessor::CacheProjectedShadowmapsPass() { - const AZStd::vector& renderPipelines = GetParentScene()->GetRenderPipelines(); - const auto* passSystem = RPI::PassSystemInterface::Get();; - const AZStd::vector& passes = passSystem->GetPassesForTemplateName(Name("ProjectedShadowmapsTemplate")); - - AZStd::vector validPipelineIds; m_projectedShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - ProjectedShadowmapsPass* shadowPass = static_cast(pass); - for (const RPI::RenderPipelinePtr& pipeline : renderPipelines) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(Name("ProjectedShadowmapsTemplate"), GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { - if (pipeline.get() == shadowPass->GetRenderPipeline()) - { - m_projectedShadowmapsPasses.emplace_back(shadowPass); - validPipelineIds.push_back(shadowPass->GetRenderPipeline()->GetId()); - } - } - } - return validPipelineIds; + ProjectedShadowmapsPass* shadowPass = static_cast(pass); + m_projectedShadowmapsPasses.emplace_back(shadowPass); + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } - void ProjectedShadowFeatureProcessor::CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds) + void ProjectedShadowFeatureProcessor::CacheEsmShadowmapsPass() { const Name LightTypeName = Name("projected"); - - const auto* passSystem = RPI::PassSystemInterface::Get(); - const AZStd::vector passes = passSystem->GetPassesForTemplateName(Name("EsmShadowmapsTemplate")); - + m_esmShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - EsmShadowmapsPass* esmPass = static_cast(pass); - if (esmPass->GetRenderPipeline() && - AZStd::find(validPipelineIds.begin(), validPipelineIds.end(), esmPass->GetRenderPipeline()->GetId()) != validPipelineIds.end() && - esmPass->GetLightTypeName() == LightTypeName) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(Name("EsmShadowmapsTemplate"), GetParentScene()); + RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, LightTypeName](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { - m_esmShadowmapsPasses.emplace_back(esmPass); - } - } + EsmShadowmapsPass* esmPass = static_cast(pass); + if (esmPass->GetLightTypeName() == LightTypeName) + { + m_esmShadowmapsPasses.emplace_back(esmPass); + } + return RPI::PassFilterExecutionFlow::ContinueVisitingPasses; + }); } void ProjectedShadowFeatureProcessor::UpdateFilterParameters() diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index fafcb25a08..8939f1845d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -97,8 +97,8 @@ namespace AZ::Render // Functions for caching the ProjectedShadowmapsPass and EsmShadowmapsPass. void CachePasses(); - AZStd::vector CacheProjectedShadowmapsPass(); - void CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds); + void CacheProjectedShadowmapsPass(); + void CacheEsmShadowmapsPass(); //! Functions to update the parameter of Gaussian filter used in ESM. void UpdateFilterParameters(); diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp index e0209702dc..4c379c4239 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -241,12 +242,12 @@ namespace AZ void SkinnedMeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) { - InitSkinningAndMorphPass(pipeline->GetRootPass()); + InitSkinningAndMorphPass(pipeline.get()); } void SkinnedMeshFeatureProcessor::OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) { - InitSkinningAndMorphPass(renderPipeline->GetRootPass()); + InitSkinningAndMorphPass(renderPipeline); } void SkinnedMeshFeatureProcessor::OnBeginPrepareRender() @@ -289,9 +290,10 @@ namespace AZ return false; } - void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass(const RPI::Ptr pipelineRootPass) + void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass(RPI::RenderPipeline* renderPipeline) { - RPI::Ptr skinningPass = pipelineRootPass->FindPassByNameRecursive(AZ::Name{ "SkinningPass" }); + RPI::PassFilter skinPassFilter = RPI::PassFilter::CreateWithPassName(AZ::Name{ "SkinningPass" }, renderPipeline); + RPI::Ptr skinningPass = RPI::PassSystemInterface::Get()->FindFirstPass(skinPassFilter); if (skinningPass) { SkinnedMeshComputePass* skinnedMeshComputePass = azdynamic_cast(skinningPass.get()); @@ -310,7 +312,8 @@ namespace AZ } } - RPI::Ptr morphTargetPass = pipelineRootPass->FindPassByNameRecursive(AZ::Name{ "MorphTargetPass" }); + RPI::PassFilter morphPassFilter = RPI::PassFilter::CreateWithPassName(AZ::Name{ "MorphTargetPass" }, renderPipeline); + RPI::Ptr morphTargetPass = RPI::PassSystemInterface::Get()->FindFirstPass(morphPassFilter); if (morphTargetPass) { MorphTargetComputePass* morphTargetComputePass = azdynamic_cast(morphTargetPass.get()); diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.h index 2e93acf2cd..5b7ab943e1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.h @@ -66,7 +66,7 @@ namespace AZ private: AZ_DISABLE_COPY_MOVE(SkinnedMeshFeatureProcessor); - void InitSkinningAndMorphPass(const RPI::Ptr pipelineRootPass); + void InitSkinningAndMorphPass(RPI::RenderPipeline* renderPipeline); SkinnedMeshRenderProxyInterfaceHandle AcquireRenderProxyInterface(const SkinnedMeshRenderProxyDesc& desc) override; bool ReleaseRenderProxyInterface(SkinnedMeshRenderProxyInterfaceHandle& handle) override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h index 36994ec03b..6523f0a6d8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h @@ -68,9 +68,6 @@ namespace AZ template Ptr FindChildPass() const; - //! Searches the tree for the first pass that has same pass name (Depth-first search). Return nullptr if none found. - Ptr FindPassByNameRecursive(const Name& passName) const; - //! Gets the list of children. Useful for validating hierarchies AZStd::array_view> GetChildren() const; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h index 34eaae4495..e7b9825ecb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h @@ -139,6 +139,10 @@ namespace AZ //! Returns the number of output attachment bindings uint32_t GetOutputCount() const; + //! Returns the pass template which was used for create this pass. + //! It may return nullptr if the pass wasn't create from a template + const PassTemplate* GetPassTemplate() const; + //! Enable/disable this pass //! If the pass is disabled, it (and any children if it's a ParentPass) won't be rendered. void SetEnabled(bool enabled); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h index c31f353adb..c42991725e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h @@ -16,95 +16,85 @@ namespace AZ { namespace RPI { - // A base class for a filter which can be used to filter passes - class PassFilter - { - public: - //! Whether the input pass matches with the filter - virtual bool Matches(const Pass* pass) const = 0; - - //! Return the pass' name if a pass name is used for the filter. - //! Return nullptr if the filter doesn't have pass name used for matching - virtual const Name* GetPassName() const = 0; + class Scene; + class RenderPipeline; - //! Return this filter's info as a string - virtual AZStd::string ToString() const = 0; - }; - - //! Filter for passes which have a matching name and also with ordered parents. - //! For example, if the filter is initialized with - //! pass name: "ShadowPass1" - //! pass parents names: "MainPipeline", "Shadow" - //! Passes with these names match the filter: - //! "Root.MainPipeline.SwapChainPass.Shadow.ShadowPass1" - //! or "Root.MainPipeline.Shadow.ShadowPass1" - //! or "MainPipeline.Shadow.Group1.ShadowPass1" - //! - //! Passes with these names wont match: - //! "MainPipeline.ShadowPass1" - //! or "Shadow.MainPipeline.ShadowPass1" - class PassHierarchyFilter - : public PassFilter + class PassFilter { public: - AZ_RTTI(PassHierarchyFilter, "{478F169F-BA97-4321-AC34-EDE823997159}", PassFilter); - AZ_CLASS_ALLOCATOR(PassHierarchyFilter, SystemAllocator, 0); - - //! Construct filter with only pass name. - PassHierarchyFilter(const Name& passName); - - virtual ~PassHierarchyFilter() = default; - - //! Construct filter with pass name and its parents' names in the order of the hierarchy - //! This means k-th element is always an ancestor of the (k-1)-th element. - //! And the last element is the pass name. - PassHierarchyFilter(const AZStd::vector& passHierarchy); - PassHierarchyFilter(const AZStd::vector& passHierarchy); - - // PassFilter overrides... - bool Matches(const Pass* pass) const override; - const Name* GetPassName() const override; - AZStd::string ToString() const override; + static PassFilter CreateWithPassName(Name passName, const Scene* scene); + static PassFilter CreateWithPassName(Name passName, const RenderPipeline* renderPipeline); + + //! Create a PassFilter with pass hierarchy information + //! Filter for passes which have a matching name and also with ordered parents. + //! For example, if the filter is initialized with + //! pass name: "ShadowPass1" + //! pass parents names: "MainPipeline", "Shadow" + //! Passes with these names match the filter: + //! "Root.MainPipeline.SwapChainPass.Shadow.ShadowPass1" + //! or "Root.MainPipeline.Shadow.ShadowPass1" + //! or "MainPipeline.Shadow.Group1.ShadowPass1" + //! + //! Passes with these names wont match: + //! "MainPipeline.ShadowPass1" + //! or "Shadow.MainPipeline.ShadowPass1" + static PassFilter CreateWithPassHierarchy(const AZStd::vector& passHierarchy); + static PassFilter CreateWithPassHierarchy(const AZStd::vector& passHierarchy); + static PassFilter CreateWithTemplateName(Name templateName, const Scene* scene); + static PassFilter CreateWithTemplateName(Name templateName, const RenderPipeline* renderPipeline); + template + static PassFilter CreateWithPassClass(); + + enum FilterOptions : uint32_t + { + Empty = 0, + PassName = AZ_BIT(0), + PassTemplateName = AZ_BIT(1), + PassClass = AZ_BIT(2), + PassHierarchy = AZ_BIT(3), + OwnerScene = AZ_BIT(4), + OwnerRenderPipeline = AZ_BIT(5) + }; + + void SetOwenrScene(const Scene* scene); + void SetOwenrRenderPipeline(const RenderPipeline* renderPipeline); + void SetPassName(Name passName); + void SetTemplateName(Name passTemplateName); + void SetPassClass(TypeId passClassTypeId); + + const Name& GetPassName() const; + const Name& GetPassTemplateName() const; + + uint32_t GetEnabledFilterOptions() const; + + //! Return true if the input pass matches the filter + bool Matches(const Pass* pass) const; + + //! Return true if the input pass matches the filter with selected filter options + //! The input filter options should be a subset of options returned by GetEnabledFilterOptions() + //! This function is used to avoid extra checks for passes which was already filtered. + //! Check PassLibrary::ForEachPass() function's implementation for more details + bool Matches(const Pass* pass, uint32_t options) const; private: - PassHierarchyFilter() = delete; + void UpdateFilterOptions(); - AZStd::vector m_parentNames; Name m_passName; + Name m_templateName; + TypeId m_passClassTypeId = TypeId::CreateNull(); + AZStd::vector m_parentNames; + const RenderPipeline* m_ownerRenderPipeline = nullptr; + const Scene* m_ownerScene = nullptr; + uint32_t m_filterOptions = 0; }; - //! Filter for passes based on their class. - template - class PassClassFilter - : public PassFilter - { - public: - AZ_RTTI(PassClassFilter, "{AF6E3AD5-433A-462A-997A-F36D8A551D02}", PassFilter); - AZ_CLASS_ALLOCATOR(PassHierarchyFilter, SystemAllocator, 0); - PassClassFilter() = default; - - // PassFilter overrides... - bool Matches(const Pass* pass) const override; - const Name* GetPassName() const override; - AZStd::string ToString() const override; - }; - - template - bool PassClassFilter::Matches(const Pass* pass) const - { - return pass->RTTI_IsTypeOf(PassClass::RTTI_Type()); - } - - template - const Name* PassClassFilter::GetPassName() const - { - return nullptr; - } - - template - AZStd::string PassClassFilter::ToString() const - { - return AZStd::string::format("PassClassFilter<%s>", PassClass::RTTI_TypeName()); + template + PassFilter PassFilter::CreateWithPassClass() + { + PassFilter filter; + filter.m_passClassTypeId = PassClass::RTTI_Type(); + filter.UpdateFilterOptions(); + return filter; } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassLibrary.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassLibrary.h index 0a4b1c4399..66c3c205ab 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassLibrary.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassLibrary.h @@ -84,8 +84,8 @@ namespace AZ bool LoadPassTemplateMappings(const AZStd::string& templateMappingPath); bool LoadPassTemplateMappings(Data::Asset mappingAsset); - //! Returns a list of passes found in the pass name mapping using the provided pass filter - AZStd::vector FindPasses(const PassFilter& passFilter) const; + //! Visit each pass which matches the filter + void ForEachPass(const PassFilter& passFilter, AZStd::function passFunction); private: diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h index 30fa27e64b..8390b0f7e2 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h @@ -92,13 +92,13 @@ namespace AZ // PassSystemInterface library related functions... bool HasPassesForTemplateName(const Name& templateName) const override; - const AZStd::vector& GetPassesForTemplateName(const Name& templateName) const override; bool AddPassTemplate(const Name& name, const AZStd::shared_ptr& passTemplate) override; const AZStd::shared_ptr GetPassTemplate(const Name& name) const override; void RemovePassFromLibrary(Pass* pass) override; void RegisterPass(Pass* pass) override; void UnregisterPass(Pass* pass) override; - AZStd::vector FindPasses(const PassFilter& passFilter) const override; + void ForEachPass(const PassFilter& filter, AZStd::function passFunction) override; + Pass* FindFirstPass(const PassFilter& filter) override; private: // Returns the root of the pass tree hierarchy diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h index 0e9386f3bb..7f944df88f 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h @@ -75,6 +75,13 @@ namespace AZ u32 m_maxDrawItemsRenderedInAPass = 0; }; + + enum PassFilterExecutionFlow : uint8_t + { + StopVisitingPasses, + ContinueVisitingPasses, + }; + class PassSystemInterface { friend class Pass; @@ -186,9 +193,6 @@ namespace AZ //! Returns true if the pass factory contains passes created with the given template name virtual bool HasPassesForTemplateName(const Name& templateName) const = 0; - //! Get the passes created with the given template name. - virtual const AZStd::vector& GetPassesForTemplateName(const Name& templateName) const = 0; - //! Adds a PassTemplate to the library virtual bool AddPassTemplate(const Name& name, const AZStd::shared_ptr& passTemplate) = 0; @@ -197,9 +201,16 @@ namespace AZ //! Removes all references to the given pass from the pass library virtual void RemovePassFromLibrary(Pass* pass) = 0; - - //! Find matching passes from registered passes with specified filter - virtual AZStd::vector FindPasses(const PassFilter& passFilter) const = 0; + + //! Visit the matching passes from registered passes with specified filter + //! The return value of the passFunction decides if the search continues or not + //! Note: this function will find all the passes which match the pass filter even they are for render pipelines which are not added to a scene + //! This function is fast if a pass name or a pass template name is specified. + virtual void ForEachPass(const PassFilter& filter, AZStd::function passFunction) = 0; + + //! Find the first matching pass from registered passes with specified filter + //! Note: this function SHOULD ONLY be used when you are certain you only need to handle the first pass found + virtual Pass* FindFirstPass(const PassFilter& filter) = 0; private: // These functions are only meant to be used by the Pass class diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp index 36c28877ea..dccf5dbc2e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp @@ -149,29 +149,6 @@ namespace AZ return index.IsValid() ? m_children[index.GetIndex()] : Ptr(nullptr); } - Ptr ParentPass::FindPassByNameRecursive(const Name& passName) const - { - for (const Ptr& child : m_children) - { - if (child->GetName() == passName) - { - return child.get(); - } - - ParentPass* asParent = child->AsParent(); - if (asParent) - { - auto pass = asParent->FindPassByNameRecursive(passName); - if (pass) - { - return pass; - } - } - } - - return nullptr; - } - const Pass* ParentPass::FindPass(RHI::DrawListTag drawListTag) const { if (HasDrawListTag() && GetDrawListTag() == drawListTag) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index a8d94e9a91..3c1de28d6a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -238,6 +238,11 @@ namespace AZ return m_attachmentBindings[bindingIndex]; } + const PassTemplate* Pass::GetPassTemplate() const + { + return m_template.get(); + } + void Pass::AddAttachmentBinding(PassAttachmentBinding attachmentBinding) { // Add the index of the binding to the input, output or input/output list based on the slot type diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp index 7bd1abc0a7..d9e458c615 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp @@ -8,101 +8,264 @@ #include #include +#include namespace AZ { namespace RPI { - PassHierarchyFilter::PassHierarchyFilter(const Name& passName) + PassFilter PassFilter::CreateWithPassName(Name passName, const Scene* scene) { - m_passName = passName; + PassFilter filter; + filter.m_passName = passName; + filter.m_ownerScene = scene; + filter.UpdateFilterOptions(); + return filter; + } + + PassFilter PassFilter::CreateWithPassName(Name passName, const RenderPipeline* renderPipeline) + { + PassFilter filter; + filter.m_passName = passName; + filter.m_ownerRenderPipeline = renderPipeline; + filter.UpdateFilterOptions(); + return filter; } - PassHierarchyFilter::PassHierarchyFilter(const AZStd::vector& passHierarchy) + PassFilter PassFilter::CreateWithTemplateName(Name templateName, const Scene* scene) { + PassFilter filter; + filter.m_templateName = templateName; + filter.m_ownerScene = scene; + filter.UpdateFilterOptions(); + return filter; + } + + PassFilter PassFilter::CreateWithTemplateName(Name templateName, const RenderPipeline* renderPipeline) + { + PassFilter filter; + filter.m_templateName = templateName; + filter.m_ownerRenderPipeline = renderPipeline; + filter.UpdateFilterOptions(); + return filter; + } + + PassFilter PassFilter::CreateWithPassHierarchy(const AZStd::vector& passHierarchy) + { + PassFilter filter; if (passHierarchy.size() == 0) { AZ_Assert(false, "passHierarchy should have at least one element"); - return; + return filter; } - m_passName = Name(passHierarchy.back()); + filter.m_passName = passHierarchy.back(); - m_parentNames.resize(passHierarchy.size() - 1); - for (uint32_t index = 0; index < m_parentNames.size(); index++) + filter.m_parentNames.resize(passHierarchy.size() - 1); + for (uint32_t index = 0; index < filter.m_parentNames.size(); index++) { - m_parentNames[index] = Name(passHierarchy[index]); + filter.m_parentNames[index] = passHierarchy[index]; } + filter.UpdateFilterOptions(); + return filter; } - PassHierarchyFilter::PassHierarchyFilter(const AZStd::vector& passHierarchy) + PassFilter PassFilter::CreateWithPassHierarchy(const AZStd::vector& passHierarchy) { + PassFilter filter; if (passHierarchy.size() == 0) { AZ_Assert(false, "passHierarchy should have at least one element"); - return; + return filter; } - m_passName = passHierarchy.back(); + filter.m_passName = Name(passHierarchy.back()); - m_parentNames.resize(passHierarchy.size() - 1); - for (uint32_t index = 0; index < m_parentNames.size(); index++) + filter.m_parentNames.resize(passHierarchy.size() - 1); + for (uint32_t index = 0; index < filter.m_parentNames.size(); index++) { - m_parentNames[index] = passHierarchy[index]; + filter.m_parentNames[index] = Name(passHierarchy[index]); } + filter.UpdateFilterOptions(); + return filter; + } + + void PassFilter::SetOwenrScene(const Scene* scene) + { + m_ownerScene = scene; + UpdateFilterOptions(); + } + + void PassFilter::SetOwenrRenderPipeline(const RenderPipeline* renderPipeline) + { + m_ownerRenderPipeline = renderPipeline; + UpdateFilterOptions(); } - bool PassHierarchyFilter::Matches(const Pass* pass) const + void PassFilter::SetPassName(Name passName) { - if (pass->GetName() != m_passName) + m_passName = passName; + UpdateFilterOptions(); + } + + void PassFilter::SetTemplateName(Name passTemplateName) + { + m_templateName = passTemplateName; + UpdateFilterOptions(); + } + + void PassFilter::SetPassClass(TypeId passClassTypeId) + { + m_passClassTypeId = passClassTypeId; + UpdateFilterOptions(); + } + + const Name& PassFilter::GetPassName() const + { + return m_passName; + } + + const Name& PassFilter::GetPassTemplateName() const + { + return m_templateName; + } + + uint32_t PassFilter::GetEnabledFilterOptions() const + { + return m_filterOptions; + } + + bool PassFilter::Matches(const Pass* pass) const + { + return Matches(pass, m_filterOptions); + } + + bool PassFilter::Matches(const Pass* pass, uint32_t options) const + { + AZ_Assert( (options&m_filterOptions) == options, "options should be a subset of m_filterOptions"); + + // return false if the pass doesn't have a pass template or the template's name is not matching + if (options & FilterOptions::PassTemplateName && (!pass->GetPassTemplate() || pass->GetPassTemplate()->m_name != m_templateName)) { return false; } - ParentPass* parent = pass->GetParent(); + if ((options & FilterOptions::PassName) && pass->GetName() != m_passName) + { + return false; + } - // search from the back of the array with the most close parent - for (int32_t index = static_cast(m_parentNames.size() - 1); index >= 0; index--) + if ((options & FilterOptions::PassClass) && pass->RTTI_GetType() != m_passClassTypeId) { - const Name& parentName = m_parentNames[index]; - while (parent) + return false; + } + + if ((options & FilterOptions::OwnerRenderPipeline) && m_ownerRenderPipeline != pass->GetRenderPipeline()) + { + return false; + } + + // If the owner render pipeline was checked, the owner scene check can be skipped + if (options & FilterOptions::OwnerScene) + { + if (pass->GetRenderPipeline()) { - if (parent->GetName() == parentName) + // return false if the owner scene doesn't match + if (m_ownerScene != pass->GetRenderPipeline()->GetScene()) { - break; + return false; } - parent = parent->GetParent(); } - - // if parent is nullptr the it didn't find a parent has matching current parentName - if (!parent) + else { + // return false if the pass doesn't have an owner scene return false; } + } + + if ((options & FilterOptions::PassHierarchy)) + { + // Filter for passes which have a matching name and also with ordered parents. + // For example, if the filter is initialized with + // pass name: "ShadowPass1" + // pass parents names: "MainPipeline", "Shadow" + // Passes with these names match the filter: + // "Root.MainPipeline.SwapChainPass.Shadow.ShadowPass1" + // or "Root.MainPipeline.Shadow.ShadowPass1" + // or "MainPipeline.Shadow.Group1.ShadowPass1" + // + // Passes with these names wont match: + // "MainPipeline.ShadowPass1" + // or "Shadow.MainPipeline.ShadowPass1" - // move to next parent - parent = parent->GetParent(); + ParentPass* parent = pass->GetParent(); + + // search from the back of the array with the most close parent + for (int32_t index = static_cast(m_parentNames.size() - 1); index >= 0; index--) + { + const Name& parentName = m_parentNames[index]; + while (parent) + { + if (parent->GetName() == parentName) + { + break; + } + parent = parent->GetParent(); + } + + // if parent is nullptr the it didn't find a parent has matching current parentName + if (!parent) + { + return false; + } + + // move to next parent + parent = parent->GetParent(); + } } return true; } - const Name* PassHierarchyFilter::GetPassName() const + void PassFilter::UpdateFilterOptions() { - return &m_passName; - } - - AZStd::string PassHierarchyFilter::ToString() const - { - AZStd::string result = "PassHierarchyFilter"; - for (uint32_t index = 0; index < m_parentNames.size(); index++) + m_filterOptions = FilterOptions::Empty; + if (!m_passName.IsEmpty()) { - result += AZStd::string::format(" [%s]", m_parentNames[index].GetCStr()); + m_filterOptions |= FilterOptions::PassName; + } + if (!m_templateName.IsEmpty()) + { + m_filterOptions |= FilterOptions::PassTemplateName; + } + if (m_parentNames.size() > 0) + { + m_filterOptions |= FilterOptions::PassHierarchy; + } + if (m_ownerRenderPipeline) + { + m_filterOptions |= FilterOptions::OwnerRenderPipeline; + } + if (m_ownerScene) + { + // If the OwnerRenderPipeline exists, we shouldn't need to filter owner scene + // Validate the owner render pipeline belongs to the owner scene + if (m_filterOptions & FilterOptions::OwnerRenderPipeline) + { + if (m_ownerRenderPipeline->GetScene() != m_ownerScene) + { + AZ_Warning("RPI", false, "The owner scene filter doesn't match owner render pipeline. It will be skipped."); + } + } + else + { + m_filterOptions |= FilterOptions::OwnerScene; + } + } + if (!m_passClassTypeId.IsNull()) + { + m_filterOptions |= FilterOptions::PassClass; } - - result += AZStd::string::format(" [%s]", m_passName.GetCStr()); - return result; } - } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassLibrary.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassLibrary.cpp index c43edafd6b..6a6f5f3ff9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassLibrary.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassLibrary.cpp @@ -85,47 +85,80 @@ namespace AZ return (GetPassesForTemplate(templateName).size() > 0); } - AZStd::vector PassLibrary::FindPasses(const PassFilter& passFilter) const + void PassLibrary::ForEachPass(const PassFilter& passFilter, AZStd::function passFunction) { - const Name* passName = passFilter.GetPassName(); + uint32_t filterOptions = passFilter.GetEnabledFilterOptions(); - AZStd::vector result; - - if (passName) + // A lambda function which visits each pass in a pass list, if the pass matches the pass filter, then call the pass function + auto visitList = [passFilter, passFunction](const AZStd::vector& passList, uint32_t options) -> PassFilterExecutionFlow { - // If the pass' name is known, find passes with matching names first - const auto constItr = m_passNameMapping.find(*passName); - if (constItr == m_passNameMapping.end()) + if (passList.size() == 0) { - return result; + return PassFilterExecutionFlow::ContinueVisitingPasses; } - - const AZStd::vector& passes = constItr->second; - - for (Pass* pass : passes) + // if there is not other filter options enabled, skip the filter and call pass functions directly + if (options == PassFilter::FilterOptions::Empty) { - if (passFilter.Matches(pass)) + for (Pass* pass : passList) { - result.push_back(pass); + // If user want to skip processing, return directly. + if (passFunction(pass) == PassFilterExecutionFlow::StopVisitingPasses) + { + return PassFilterExecutionFlow::StopVisitingPasses; + } } + return PassFilterExecutionFlow::ContinueVisitingPasses; } - } - else - { - // If the filter doesn't know matching pass' name, need to go through all registered passes - for (auto& namePasses : m_passNameMapping) + + // Check with the pass filter and call pass functions + for (Pass* pass : passList) { - for (Pass* pass : namePasses.second) + if (passFilter.Matches(pass, options)) { - if (passFilter.Matches(pass)) + if (passFunction(pass) == PassFilterExecutionFlow::StopVisitingPasses) { - result.push_back(pass); + return PassFilterExecutionFlow::StopVisitingPasses; } } } + return PassFilterExecutionFlow::ContinueVisitingPasses; + }; + + // Check pass template name first + if (filterOptions & PassFilter::FilterOptions::PassTemplateName) + { + auto entry = GetEntry(passFilter.GetPassTemplateName()); + if (!entry) + { + return; + } + + filterOptions &= ~(PassFilter::FilterOptions::PassTemplateName); + visitList(entry->m_passes, filterOptions); + return; + } + else if (filterOptions & PassFilter::FilterOptions::PassName) + { + const auto constItr = m_passNameMapping.find(passFilter.GetPassName()); + if (constItr == m_passNameMapping.end()) + { + return; + } + + filterOptions &= ~(PassFilter::FilterOptions::PassName); + visitList(constItr->second, filterOptions); + return; } - return result; + // check againest every passes. This might be slow + AZ_PROFILE_SCOPE(RPI, "PassLibrary::ForEachPass"); + for (auto& namePasses : m_passNameMapping) + { + if (visitList(namePasses.second, filterOptions) == PassFilterExecutionFlow::StopVisitingPasses) + { + return; + } + } } // Add Functions... @@ -419,3 +452,4 @@ namespace AZ } // namespace RPI } // namespace AZ + diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index f4f51f97b7..7f2948c13a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -456,11 +456,6 @@ namespace AZ return m_passLibrary.HasPassesForTemplate(templateName); } - const AZStd::vector& PassSystem::GetPassesForTemplateName(const Name& templateName) const - { - return m_passLibrary.GetPassesForTemplate(templateName); - } - bool PassSystem::AddPassTemplate(const Name& name, const AZStd::shared_ptr& passTemplate) { return m_passLibrary.AddPassTemplate(name, passTemplate); @@ -487,10 +482,21 @@ namespace AZ RemovePassFromLibrary(pass); --m_passCounter; } + + void PassSystem::ForEachPass(const PassFilter& filter, AZStd::function passFunction) + { + return m_passLibrary.ForEachPass(filter, passFunction); + } - AZStd::vector PassSystem::FindPasses(const PassFilter& passFilter) const + Pass* PassSystem::FindFirstPass(const PassFilter& filter) { - return m_passLibrary.FindPasses(passFilter); + Pass* foundPass = nullptr; + m_passLibrary.ForEachPass(filter, [&foundPass](RPI::Pass* pass) ->PassFilterExecutionFlow + { + foundPass = pass; + return PassFilterExecutionFlow::StopVisitingPasses; + }); + return foundPass; } SwapChainPass* PassSystem::FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const diff --git a/Gems/Atom/RPI/Code/Tests/Pass/PassTests.cpp b/Gems/Atom/RPI/Code/Tests/Pass/PassTests.cpp index 420ab1798a..690f212ec7 100644 --- a/Gems/Atom/RPI/Code/Tests/Pass/PassTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Pass/PassTests.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include #include @@ -573,7 +575,7 @@ namespace UnitTest EXPECT_TRUE(pass != nullptr); } - TEST_F(PassTests, PassHierarchyFilter) + TEST_F(PassTests, PassFilter_PassHierarchy) { m_data->AddPassTemplatesToLibrary(); @@ -587,62 +589,55 @@ namespace UnitTest parent2->AsParent()->AddChild(parent1); parent1->AsParent()->AddChild(pass); - { - // Filter with only pass name - PassHierarchyFilter filter(Name("pass1")); - EXPECT_TRUE(filter.Matches(pass.get())); - } - { // Filter with pass hierarchy which has only one element - PassHierarchyFilter filter({ Name("pass1") }); + PassFilter filter = PassFilter::CreateWithPassHierarchy({Name("pass1")}); EXPECT_TRUE(filter.Matches(pass.get())); } { - // Filter with empty pass hierarchy. Result one assert + // Filter with empty pass hierarchy, triggers one assert AZ_TEST_START_TRACE_SUPPRESSION; - PassHierarchyFilter filter(AZStd::vector{}); + PassFilter filter = PassFilter::CreateWithPassHierarchy(AZStd::vector{}); AZ_TEST_STOP_TRACE_SUPPRESSION(1); - EXPECT_FALSE(filter.Matches(pass.get())); } { // Filters with partial hierarchy by using string vector AZStd::vector passHierarchy1 = { "parent1", "pass1" }; - PassHierarchyFilter filter1(passHierarchy1); + PassFilter filter1 = PassFilter::CreateWithPassHierarchy(passHierarchy1); EXPECT_TRUE(filter1.Matches(pass.get())); AZStd::vector passHierarchy2 = { "parent2", "pass1" }; - PassHierarchyFilter filter2(passHierarchy2); + PassFilter filter2 = PassFilter::CreateWithPassHierarchy(passHierarchy2); EXPECT_TRUE(filter2.Matches(pass.get())); AZStd::vector passHierarchy3 = { "parent3", "parent2", "pass1" }; - PassHierarchyFilter filter3(passHierarchy3); + PassFilter filter3 = PassFilter::CreateWithPassHierarchy(passHierarchy3); EXPECT_TRUE(filter3.Matches(pass.get())); } { // Filters with partial hierarchy by using Name vector AZStd::vector passHierarchy1 = { Name("parent1"), Name("pass1") }; - PassHierarchyFilter filter1(passHierarchy1); + PassFilter filter1 = PassFilter::CreateWithPassHierarchy(passHierarchy1); EXPECT_TRUE(filter1.Matches(pass.get())); AZStd::vector passHierarchy2 = { Name("parent2"), Name("pass1")}; - PassHierarchyFilter filter2(passHierarchy2); + PassFilter filter2 = PassFilter::CreateWithPassHierarchy(passHierarchy2); EXPECT_TRUE(filter2.Matches(pass.get())); AZStd::vector passHierarchy3 = { Name("parent3"), Name("parent2"), Name("pass1") }; - PassHierarchyFilter filter3(passHierarchy3); + PassFilter filter3 = PassFilter::CreateWithPassHierarchy(passHierarchy3); EXPECT_TRUE(filter3.Matches(pass.get())); } { // Find non-leaf pass - PassHierarchyFilter filter1(AZStd::vector{"parent3", "parent1"}); + PassFilter filter1 = PassFilter::CreateWithPassHierarchy(AZStd::vector{"parent3", "parent1"}); EXPECT_TRUE(filter1.Matches(parent1.get())); - - PassHierarchyFilter filter2(Name("parent1")); + + PassFilter filter2 = PassFilter::CreateWithPassHierarchy({ Name("parent1") }); EXPECT_TRUE(filter2.Matches(parent1.get())); EXPECT_FALSE(filter2.Matches(pass.get())); } @@ -650,11 +645,131 @@ namespace UnitTest { // Failed to find pass // Mis-matching hierarchy - PassHierarchyFilter filter1(AZStd::vector{"Parent1", "Parent3", "pass1"}); + PassFilter filter1 = PassFilter::CreateWithPassHierarchy(AZStd::vector{"Parent1", "Parent3", "pass1"}); EXPECT_FALSE(filter1.Matches(pass.get())); // Mis-matching name - PassHierarchyFilter filter2(AZStd::vector{"Parent1", "pass1"}); + PassFilter filter2 = PassFilter::CreateWithPassHierarchy(AZStd::vector{"Parent1", "pass1"}); EXPECT_FALSE(filter2.Matches(parent1.get())); } } + + TEST_F(PassTests, PassFilter_Empty_Success) + { + m_data->AddPassTemplatesToLibrary(); + + // create a pass tree + Ptr pass = m_passSystem->CreatePassFromClass(Name("Pass"), Name("pass1")); + Ptr parent1 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent1")); + Ptr parent2 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent2")); + Ptr parent3 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent3")); + + parent3->AsParent()->AddChild(parent2); + parent2->AsParent()->AddChild(parent1); + parent1->AsParent()->AddChild(pass); + + PassFilter filter; + + // Any pass can match an empty filter + EXPECT_TRUE(filter.Matches(pass.get())); + EXPECT_TRUE(filter.Matches(parent1.get())); + EXPECT_TRUE(filter.Matches(parent2.get())); + EXPECT_TRUE(filter.Matches(parent3.get())); + } + + TEST_F(PassTests, PassFilter_PassClass_Success) + { + m_data->AddPassTemplatesToLibrary(); + + // create a pass tree + Ptr pass = m_passSystem->CreatePassFromClass(Name("Pass"), Name("pass1")); + Ptr depthPass = m_passSystem->CreatePassFromTemplate(Name("DepthPrePass"), Name("depthPass")); + Ptr parent1 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent1")); + + parent1->AsParent()->AddChild(pass); + parent1->AsParent()->AddChild(depthPass); + + PassFilter filter1 = PassFilter::CreateWithPassClass(); + + EXPECT_TRUE(filter1.Matches(pass.get())); + EXPECT_FALSE(filter1.Matches(parent1.get())); + + PassFilter filter2 = PassFilter::CreateWithPassClass(); + EXPECT_FALSE(filter2.Matches(pass.get())); + EXPECT_TRUE(filter2.Matches(parent1.get())); + } + + TEST_F(PassTests, PassFilter_PassTemplate_Success) + { + m_data->AddPassTemplatesToLibrary(); + + // create a pass tree + Ptr childPass = m_passSystem->CreatePassFromClass(Name("Pass"), Name("pass1")); + Ptr parent1 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent1")); + + PassFilter filter1 = PassFilter::CreateWithTemplateName(Name("Pass"), (Scene*) nullptr); + // childPass doesn't have a template + EXPECT_FALSE(filter1.Matches(childPass.get())); + + PassFilter filter2 = PassFilter::CreateWithTemplateName(Name("ParentPass"), (Scene*) nullptr); + EXPECT_TRUE(filter2.Matches(parent1.get())); + } + + TEST_F(PassTests, ForEachPass_PassTemplateFilter_Success) + { + m_data->AddPassTemplatesToLibrary(); + + // create a pass tree + Ptr pass = m_passSystem->CreatePassFromClass(Name("Pass"), Name("pass1")); + Ptr parent1 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent1")); + Ptr parent2 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent2")); + Ptr parent3 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent3")); + + parent3->AsParent()->AddChild(parent2); + parent2->AsParent()->AddChild(parent1); + parent1->AsParent()->AddChild(pass); + + // Create render pipeline + const RPI::PipelineViewTag viewTag{ "viewTag1" }; + RPI::RenderPipelineDescriptor desc; + desc.m_mainViewTagName = viewTag.GetStringView(); + desc.m_name = "TestPipeline"; + RPI::RenderPipelinePtr pipeline = RPI::RenderPipeline::CreateRenderPipeline(desc); + Ptr parent4 = m_passSystem->CreatePassFromTemplate(Name("ParentPass"), Name("parent4")); + pipeline->GetRootPass()->AddChild(parent4); + + Name templateName = Name("ParentPass"); + PassFilter filter1 = PassFilter::CreateWithTemplateName(templateName, (RenderPipeline*)nullptr); + + int count = 0; + m_passSystem->ForEachPass(filter1, [&count, templateName](RPI::Pass* pass) -> PassFilterExecutionFlow + { + EXPECT_TRUE(pass->GetPassTemplate()->m_name == templateName); + count++; + return PassFilterExecutionFlow::ContinueVisitingPasses; + }); + + // three from CreatePassFromTemplate() calls and one from Render Pipeline. + EXPECT_TRUE(count == 4); + + count = 0; + m_passSystem->ForEachPass(filter1, [&count, templateName](RPI::Pass* pass) -> PassFilterExecutionFlow + { + EXPECT_TRUE(pass->GetPassTemplate()->m_name == templateName); + count++; + return PassFilterExecutionFlow::StopVisitingPasses; + }); + EXPECT_TRUE(count == 1); + + PassFilter filter2 = PassFilter::CreateWithTemplateName(templateName, pipeline.get()); + count = 0; + m_passSystem->ForEachPass(filter2, [&count]([[maybe_unused]] RPI::Pass* pass) -> PassFilterExecutionFlow + { + count++; + return PassFilterExecutionFlow::ContinueVisitingPasses; + }); + + // only the ParentPass in the render pipeline was found + EXPECT_TRUE(count == 1); + + } } diff --git a/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.cpp b/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.cpp index a0be18f0e2..161160e16f 100644 --- a/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.cpp +++ b/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -142,12 +143,13 @@ namespace AZ EnablePasses(true); } - void HairFeatureProcessor::EnablePasses([[maybe_unused]] bool enable) + void HairFeatureProcessor::EnablePasses(bool enable) { - RPI::Ptr desiredPass = m_renderPipeline->GetRootPass()->FindPassByNameRecursive(HairParentPassName); - if (desiredPass) + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(HairParentPassName, GetParentScene()); + RPI::Pass* pass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); + if (pass) { - desiredPass->SetEnabled(enable); + pass->SetEnabled(enable); } } @@ -309,10 +311,17 @@ namespace AZ m_forceClearRenderData = true; } + bool HairFeatureProcessor::HasHairParentPass() + { + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(HairParentPassName, GetParentScene()); + RPI::Pass* pass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); + return pass; + } + void HairFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr renderPipeline) { // Proceed only if this is the main pipeline that contains the parent pass - if (!renderPipeline.get()->GetRootPass()->FindPassByNameRecursive(HairParentPassName)) + if (!HasHairParentPass()) { return; } @@ -323,10 +332,10 @@ namespace AZ m_forceRebuildRenderData = true; } - void HairFeatureProcessor::OnRenderPipelineRemoved(RPI::RenderPipeline* renderPipeline) + void HairFeatureProcessor::OnRenderPipelineRemoved([[maybe_unused]] RPI::RenderPipeline* renderPipeline) { // Proceed only if this is the main pipeline that contains the parent pass - if (!renderPipeline->GetRootPass()->FindPassByNameRecursive(HairParentPassName)) + if (!HasHairParentPass()) { return; } @@ -338,7 +347,7 @@ namespace AZ void HairFeatureProcessor::OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) { // Proceed only if this is the main pipeline that contains the parent pass - if (!renderPipeline->GetRootPass()->FindPassByNameRecursive(HairParentPassName)) + if (!HasHairParentPass()) { return; } @@ -457,7 +466,8 @@ namespace AZ { m_computePasses[passName] = nullptr; - RPI::Ptr desiredPass = m_renderPipeline->GetRootPass()->FindPassByNameRecursive(passName); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(passName, m_renderPipeline); + RPI::Ptr desiredPass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); if (desiredPass) { m_computePasses[passName] = static_cast(desiredPass.get()); @@ -478,8 +488,9 @@ namespace AZ bool HairFeatureProcessor::InitPPLLFillPass() { m_hairPPLLRasterPass = nullptr; // reset it to null, just in case it fails to load the assets properly - - RPI::Ptr desiredPass = m_renderPipeline->GetRootPass()->FindPassByNameRecursive(HairPPLLRasterPassName); + + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(HairPPLLRasterPassName, m_renderPipeline); + RPI::Ptr desiredPass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); if (desiredPass) { m_hairPPLLRasterPass = static_cast(desiredPass.get()); @@ -497,7 +508,8 @@ namespace AZ { m_hairPPLLResolvePass = nullptr; // reset it to null, just in case it fails to load the assets properly - RPI::Ptr desiredPass = m_renderPipeline->GetRootPass()->FindPassByNameRecursive(HairPPLLResolvePassName); + RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(HairPPLLResolvePassName, m_renderPipeline); + RPI::Ptr desiredPass = RPI::PassSystemInterface::Get()->FindFirstPass(passFilter); if (desiredPass) { m_hairPPLLResolvePass = static_cast(desiredPass.get()); @@ -518,8 +530,8 @@ namespace AZ m_hairShortCutGeometryDepthAlphaPass = nullptr; m_hairShortCutGeometryShadingPass = nullptr; - m_hairShortCutGeometryDepthAlphaPass = static_cast( - m_renderPipeline->GetRootPass()->FindPassByNameRecursive(HairShortCutGeometryDepthAlphaPassName).get()); + RPI::PassFilter depthAlphaPassFilter = RPI::PassFilter::CreateWithPassName(HairShortCutGeometryDepthAlphaPassName, m_renderPipeline); + m_hairShortCutGeometryDepthAlphaPass = static_cast(RPI::PassSystemInterface::Get()->FindFirstPass(depthAlphaPassFilter)); if (m_hairShortCutGeometryDepthAlphaPass) { m_hairShortCutGeometryDepthAlphaPass->SetFeatureProcessor(this); @@ -530,8 +542,8 @@ namespace AZ return false; } - m_hairShortCutGeometryShadingPass = static_cast( - m_renderPipeline->GetRootPass()->FindPassByNameRecursive(HairShortCutGeometryShadingPassName).get()); + RPI::PassFilter shaderingPassFilter = RPI::PassFilter::CreateWithPassName(HairShortCutGeometryShadingPassName, m_renderPipeline); + m_hairShortCutGeometryShadingPass = static_cast(RPI::PassSystemInterface::Get()->FindFirstPass(shaderingPassFilter)); if (m_hairShortCutGeometryShadingPass) { m_hairShortCutGeometryShadingPass->SetFeatureProcessor(this); diff --git a/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.h b/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.h index 46660a6623..f810967824 100644 --- a/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.h +++ b/Gems/AtomTressFX/Code/Rendering/HairFeatureProcessor.h @@ -165,6 +165,8 @@ namespace AZ void EnablePasses(bool enable); + bool HasHairParentPass(); + //! The following will serve to register the FP in the Thumbnail system AZStd::vector m_hairFeatureProcessorRegistryName;