瀏覽代碼

Avoid a crash with the DebugRayTracingPass with terrain rendering (#18754)

Signed-off-by: Karl Haubenwallner <[email protected]>
Karl Haubenwallner 4 月之前
父節點
當前提交
4f465b1675

+ 36 - 22
Gems/Atom/Feature/Common/Code/Source/Debug/RayTracingDebugFeatureProcessor.cpp

@@ -8,6 +8,7 @@
 
 #include <Atom/RPI.Public/RenderPipeline.h>
 #include <Atom/RPI.Public/Scene.h>
+#include <Atom/RPI.Public/Pass/PassFilter.h>
 #include <Debug/RayTracingDebugFeatureProcessor.h>
 #include <RayTracing/RayTracingFeatureProcessor.h>
 
@@ -34,7 +35,8 @@ namespace AZ::Render
     {
         if (m_debugComponentCount == 0)
         {
-            AddDebugPass();
+            // force a rebuild, so we get a chance to add our debug-pass
+            MarkPipelineNeedsRebuild();
         }
         m_debugComponentCount++;
     }
@@ -44,7 +46,8 @@ namespace AZ::Render
         m_debugComponentCount--;
         if (m_debugComponentCount == 0)
         {
-            RemoveDebugPass();
+            // force a rebuild during which we won't add our debug-pass
+            MarkPipelineNeedsRebuild();
         }
     }
 
@@ -65,22 +68,46 @@ namespace AZ::Render
         m_settings.reset();
     }
 
+    void RayTracingDebugFeatureProcessor::OnRenderPipelineChanged(RPI::RenderPipeline* pipeline, [[maybe_unused]] RPI::SceneNotification::RenderPipelineChangeType changeType)
+    {
+        m_pipeline = pipeline;
+    }
+
     void RayTracingDebugFeatureProcessor::AddRenderPasses(RPI::RenderPipeline* pipeline)
     {
         m_pipeline = pipeline;
+        if (m_debugComponentCount > 0)
+        {
+            auto pass = RPI::PassSystemInterface::Get()->CreatePassFromTemplate(Name{ "DebugRayTracingPassTemplate" }, Name{ "DebugRayTracingPass" });
+            if (!pass)
+            {
+                AZ_Assert(false, "Failed to create DebugRayTracingPass");
+                return;
+            }
+            m_pipeline->AddPassAfter(pass, Name{ "AuxGeomPass" });
+            m_isEnabled = m_settings->GetEnabled();
+            pass->SetEnabled(m_isEnabled);
+        }
         FeatureProcessor::AddRenderPasses(pipeline);
     }
 
     void RayTracingDebugFeatureProcessor::Render(const RPI::FeatureProcessor::RenderPacket& packet)
     {
-        if (!m_rayTracingPass)
+        if (m_debugComponentCount == 0)
         {
             return;
         }
-
-        if (m_rayTracingPass->IsEnabled() != m_settings->GetEnabled())
+        if (m_settings->GetEnabled() != m_isEnabled)
         {
-            m_rayTracingPass->SetEnabled(m_settings->GetEnabled());
+            m_isEnabled = m_settings->GetEnabled();
+            auto filter = AZ::RPI::PassFilter::CreateWithTemplateName(Name{ "DebugRayTracingPassTemplate" }, m_pipeline);
+            AZ::RPI::PassSystemInterface::Get()->ForEachPass(
+                filter,
+                [&](AZ::RPI::Pass* pass)
+                {
+                    pass->SetEnabled(m_isEnabled);
+                    return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
+                });
         }
 
         if (!m_sceneSrg && m_settings->GetEnabled())
@@ -103,24 +130,11 @@ namespace AZ::Render
         FeatureProcessor::Render(packet);
     }
 
-    void RayTracingDebugFeatureProcessor::AddDebugPass()
-    {
-        m_rayTracingPass =
-            RPI::PassSystemInterface::Get()->CreatePassFromTemplate(Name{ "DebugRayTracingPassTemplate" }, Name{ "DebugRayTracingPass" });
-        if (!m_rayTracingPass)
-        {
-            AZ_Assert(false, "Failed to create DebugRayTracingPass");
-            return;
-        }
-        m_pipeline->AddPassAfter(m_rayTracingPass, Name{ "AuxGeomPass" });
-    }
-
-    void RayTracingDebugFeatureProcessor::RemoveDebugPass()
+    void RayTracingDebugFeatureProcessor::MarkPipelineNeedsRebuild()
     {
-        if (m_rayTracingPass)
+        if (m_pipeline)
         {
-            m_rayTracingPass->QueueForRemoval();
-            m_rayTracingPass.reset();
+            m_pipeline->MarkPipelinePassChanges(RPI::PipelinePassChanges::PipelineChangedByFeatureProcessor);
         }
     }
 } // namespace AZ::Render

+ 8 - 7
Gems/Atom/Feature/Common/Code/Source/Debug/RayTracingDebugFeatureProcessor.h

@@ -29,6 +29,9 @@ namespace AZ::Render
         void OnRayTracingDebugComponentAdded() override;
         void OnRayTracingDebugComponentRemoved() override;
 
+        // SceneNotificationBus overrides
+        void OnRenderPipelineChanged(RPI::RenderPipeline* pipeline, RPI::SceneNotification::RenderPipelineChangeType changeType) override;
+
         // FeatureProcessor overrides
         void Activate() override;
         void Deactivate() override;
@@ -36,17 +39,15 @@ namespace AZ::Render
         void Render(const RenderPacket& packet) override;
 
     private:
-        // Adds the debug ray tracing pass to the pipeline (The debug ray tracing pass is not part of the main pipeline and is only added if
-        // a "Debug Ray Tracing" level component is added to the scene).
-        void AddDebugPass();
-
-        // Removes the debug ray tracing pass from the pipeline.
-        void RemoveDebugPass();
+        // Forces a rebuild of the pipeline so the FeatureProcessor can add the debug ray tracing pass to the pipeline.
+        // The debug ray tracing pass is not generally part of the main pipeline and is only added if
+        // a "Debug Ray Tracing" level component is added to the scene.
+        void MarkPipelineNeedsRebuild();
 
         AZStd::unique_ptr<RayTracingDebugSettings> m_settings;
         Data::Instance<RPI::ShaderResourceGroup> m_sceneSrg; // The ray tracing scene SRG (RayTracingSceneSrg)
         RPI::RenderPipeline* m_pipeline{ nullptr };
-        RPI::Ptr<RPI::Pass> m_rayTracingPass;
+        bool m_isEnabled{ false };
         int m_debugComponentCount{ 0 };
         RHI::ShaderInputNameIndex m_debugOptionsIndex{ "m_debugViewMode" };
     };

+ 5 - 0
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp

@@ -246,6 +246,11 @@ namespace AZ
                 return false;
             }
 
+            if (m_pipeline == nullptr)
+            {
+                return false;
+            }
+
             RPI::Scene* scene = m_pipeline->GetScene();
             if (!scene)
             {