2
0
Эх сурвалжийг харах

Make it possible to have a morph target and skinning pass per device

Signed-off-by: Martin Sattlecker <[email protected]>
Martin Sattlecker 5 сар өмнө
parent
commit
904fa67f54

+ 18 - 11
Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetComputePass.cpp

@@ -6,10 +6,10 @@
  *
  *
  */
  */
 
 
-
+#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
+#include <Atom/RPI.Public/Scene.h>
 #include <MorphTargets/MorphTargetComputePass.h>
 #include <MorphTargets/MorphTargetComputePass.h>
 #include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
 #include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
-#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
 
 
 #include <Atom/RPI.Public/Shader/Shader.h>
 #include <Atom/RPI.Public/Shader/Shader.h>
 
 
@@ -35,11 +35,6 @@ namespace AZ
             return m_shader;
             return m_shader;
         }
         }
 
 
-        void MorphTargetComputePass::SetFeatureProcessor(SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor)
-        {
-            m_skinnedMeshFeatureProcessor = skinnedMeshFeatureProcessor;
-        }
-
         void MorphTargetComputePass::BuildInternal()
         void MorphTargetComputePass::BuildInternal()
         {
         {
             // The same buffer that skinning writes to is used to manage the computed vertex deltas that are passed from the
             // The same buffer that skinning writes to is used to manage the computed vertex deltas that are passed from the
@@ -49,9 +44,9 @@ namespace AZ
 
 
         void MorphTargetComputePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
         void MorphTargetComputePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
         {
         {
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
             {
             {
-                m_skinnedMeshFeatureProcessor->SetupMorphTargetScope(frameGraph);
+                featureProcessor->SetupMorphTargetScope(frameGraph, Pass::GetDeviceIndex());
             }
             }
 
 
             ComputePass::SetupFrameGraphDependencies(frameGraph);
             ComputePass::SetupFrameGraphDependencies(frameGraph);
@@ -59,12 +54,24 @@ namespace AZ
 
 
         void MorphTargetComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
         void MorphTargetComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
         {
         {
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
             {
             {
                 SetSrgsForDispatch(context);
                 SetSrgsForDispatch(context);
 
 
-                m_skinnedMeshFeatureProcessor->SubmitMorphTargetDispatchItems(context, context.GetSubmitRange().m_startIndex, context.GetSubmitRange().m_endIndex);
+                featureProcessor->SubmitMorphTargetDispatchItems(
+                    context, context.GetSubmitRange().m_startIndex, context.GetSubmitRange().m_endIndex);
+            }
+        }
+
+        SkinnedMeshFeatureProcessor* MorphTargetComputePass::GetSkinnedMeshFeatureProcessor()
+        {
+            AZ::RPI::Scene* scene{ GetScene() };
+            if (!scene)
+            {
+                return nullptr;
             }
             }
+            auto result = scene->GetFeatureProcessor<SkinnedMeshFeatureProcessor>();
+            return result;
         }
         }
     }   // namespace Render
     }   // namespace Render
 }   // namespace AZ
 }   // namespace AZ

+ 1 - 2
Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetComputePass.h

@@ -31,13 +31,12 @@ namespace AZ
 
 
             Data::Instance<RPI::Shader> GetShader() const;
             Data::Instance<RPI::Shader> GetShader() const;
 
 
-            void SetFeatureProcessor(SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor);
         private:
         private:
             void BuildInternal() override;
             void BuildInternal() override;
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
 
 
-            SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
+            SkinnedMeshFeatureProcessor* GetSkinnedMeshFeatureProcessor();
         };
         };
     }
     }
 }
 }

+ 40 - 22
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp

@@ -27,7 +27,8 @@ namespace AZ
     {
     {
         RPI::Ptr<RayTracingAccelerationStructurePass> RayTracingAccelerationStructurePass::Create(const RPI::PassDescriptor& descriptor)
         RPI::Ptr<RayTracingAccelerationStructurePass> RayTracingAccelerationStructurePass::Create(const RPI::PassDescriptor& descriptor)
         {
         {
-            RPI::Ptr<RayTracingAccelerationStructurePass> rayTracingAccelerationStructurePass = aznew RayTracingAccelerationStructurePass(descriptor);
+            RPI::Ptr<RayTracingAccelerationStructurePass> rayTracingAccelerationStructurePass =
+                aznew RayTracingAccelerationStructurePass(descriptor);
             return AZStd::move(rayTracingAccelerationStructurePass);
             return AZStd::move(rayTracingAccelerationStructurePass);
         }
         }
 
 
@@ -95,8 +96,7 @@ namespace AZ
                     break;
                     break;
                 case RPI::ScopeQueryType::PipelineStatistics:
                 case RPI::ScopeQueryType::PipelineStatistics:
                     query = RPI::GpuQuerySystemInterface::Get()->CreateQuery(
                     query = RPI::GpuQuerySystemInterface::Get()->CreateQuery(
-                        RHI::QueryType::PipelineStatistics, RHI::QueryPoolScopeAttachmentType::Global,
-                        RHI::ScopeAttachmentAccess::Write);
+                        RHI::QueryType::PipelineStatistics, RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
                     break;
                     break;
                 }
                 }
 
 
@@ -161,19 +161,22 @@ namespace AZ
                         AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId();
                         AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId();
                         if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId) == false)
                         if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId) == false)
                         {
                         {
-                            [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer);
+                            [[maybe_unused]] RHI::ResultCode result =
+                                frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer);
                             AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result);
                             AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result);
                         }
                         }
 
 
                         uint32_t tlasBufferByteCount = aznumeric_cast<uint32_t>(rayTracingTlasBuffer->GetDescriptor().m_byteCount);
                         uint32_t tlasBufferByteCount = aznumeric_cast<uint32_t>(rayTracingTlasBuffer->GetDescriptor().m_byteCount);
-                        RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount);
+                        RHI::BufferViewDescriptor tlasBufferViewDescriptor =
+                            RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount);
 
 
                         RHI::BufferScopeAttachmentDescriptor desc;
                         RHI::BufferScopeAttachmentDescriptor desc;
                         desc.m_attachmentId = tlasAttachmentId;
                         desc.m_attachmentId = tlasAttachmentId;
                         desc.m_bufferViewDescriptor = tlasBufferViewDescriptor;
                         desc.m_bufferViewDescriptor = tlasBufferViewDescriptor;
                         desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare;
                         desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare;
 
 
-                        frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write, RHI::ScopeAttachmentStage::RayTracingShader);
+                        frameGraph.UseShaderAttachment(
+                            desc, RHI::ScopeAttachmentAccess::Write, RHI::ScopeAttachmentStage::RayTracingShader);
                     }
                     }
                 }
                 }
 
 
@@ -181,10 +184,24 @@ namespace AZ
                 // the skinning pass has finished. We assume that the pipeline has a skinning pass with this output available.
                 // the skinning pass has finished. We assume that the pipeline has a skinning pass with this output available.
                 if (rayTracingFeatureProcessor->GetSkinnedMeshCount() > 0)
                 if (rayTracingFeatureProcessor->GetSkinnedMeshCount() > 0)
                 {
                 {
-                    auto skinningPassPtr = FindAdjacentPass(AZ::Name("SkinningPass"));
+                    RHI::Ptr<RPI::Pass> skinningPassPtr;
+                    for (const auto& sibling : m_parent->GetChildren())
+                    {
+                        if (sibling->GetPassTemplate() && sibling->GetPassTemplate()->m_name == AZ::Name{ "SkinningPassTemplate" } &&
+                            sibling->GetDeviceIndex() == Pass::GetDeviceIndex())
+                        {
+                            skinningPassPtr = sibling;
+                            break;
+                        }
+                    }
+                    AZ_Assert(skinningPassPtr, "Failed to find SkinningPass");
                     auto skinnedMeshOutputStreamBindingPtr = skinningPassPtr->FindAttachmentBinding(AZ::Name("SkinnedMeshOutputStream"));
                     auto skinnedMeshOutputStreamBindingPtr = skinningPassPtr->FindAttachmentBinding(AZ::Name("SkinnedMeshOutputStream"));
-                    [[maybe_unused]] auto result = frameGraph.UseShaderAttachment(skinnedMeshOutputStreamBindingPtr->m_unifiedScopeDesc.GetAsBuffer(), RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::RayTracingShader);
-                    AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to attach SkinnedMeshOutputStream buffer with error %d", result);
+                    [[maybe_unused]] auto result = frameGraph.UseShaderAttachment(
+                        skinnedMeshOutputStreamBindingPtr->m_unifiedScopeDesc.GetAsBuffer(),
+                        RHI::ScopeAttachmentAccess::Read,
+                        RHI::ScopeAttachmentStage::RayTracingShader);
+                    AZ_Assert(
+                        result == AZ::RHI::ResultCode::Success, "Failed to attach SkinnedMeshOutputStream buffer with error %d", result);
                 }
                 }
 
 
                 AddScopeQueryToFrameGraph(frameGraph);
                 AddScopeQueryToFrameGraph(frameGraph);
@@ -348,7 +365,7 @@ namespace AZ
         {
         {
             const auto addToFrameGraph = [&frameGraph](RHI::Ptr<RPI::Query> query)
             const auto addToFrameGraph = [&frameGraph](RHI::Ptr<RPI::Query> query)
             {
             {
-              query->AddToFrameGraph(frameGraph);
+                query->AddToFrameGraph(frameGraph);
             };
             };
 
 
             ExecuteOnTimestampQuery(addToFrameGraph);
             ExecuteOnTimestampQuery(addToFrameGraph);
@@ -359,15 +376,16 @@ namespace AZ
         {
         {
             const auto beginQuery = [&context, this](RHI::Ptr<RPI::Query> query)
             const auto beginQuery = [&context, this](RHI::Ptr<RPI::Query> query)
             {
             {
-              if (query->BeginQuery(context) == RPI::QueryResultCode::Fail)
-              {
-                  AZ_UNUSED(this); // Prevent unused warning in release builds
-                  AZ_WarningOnce(
-                      "RayTracingAccelerationStructurePass", false,
-                      "BeginScopeQuery failed. Make sure AddScopeQueryToFrameGraph was called in SetupFrameGraphDependencies"
-                      " for this pass: %s",
-                      this->RTTI_GetTypeName());
-              }
+                if (query->BeginQuery(context) == RPI::QueryResultCode::Fail)
+                {
+                    AZ_UNUSED(this); // Prevent unused warning in release builds
+                    AZ_WarningOnce(
+                        "RayTracingAccelerationStructurePass",
+                        false,
+                        "BeginScopeQuery failed. Make sure AddScopeQueryToFrameGraph was called in SetupFrameGraphDependencies"
+                        " for this pass: %s",
+                        this->RTTI_GetTypeName());
+                }
             };
             };
 
 
             ExecuteOnTimestampQuery(beginQuery);
             ExecuteOnTimestampQuery(beginQuery);
@@ -378,7 +396,7 @@ namespace AZ
         {
         {
             const auto endQuery = [&context](const RHI::Ptr<RPI::Query>& query)
             const auto endQuery = [&context](const RHI::Ptr<RPI::Query>& query)
             {
             {
-              query->EndQuery(context);
+                query->EndQuery(context);
             };
             };
 
 
             // This scope query implementation should be replaced by the feature linked below on GitHub:
             // This scope query implementation should be replaced by the feature linked below on GitHub:
@@ -406,5 +424,5 @@ namespace AZ
                     query->GetLatestResult(&m_statisticsResult, sizeof(RPI::PipelineStatisticsResult), m_lastDeviceIndex);
                     query->GetLatestResult(&m_statisticsResult, sizeof(RPI::PipelineStatisticsResult), m_lastDeviceIndex);
                 });
                 });
         }
         }
-    }   // namespace RPI
-}   // namespace AZ
+    } // namespace Render
+} // namespace AZ

+ 22 - 15
Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.cpp

@@ -6,10 +6,10 @@
  *
  *
  */
  */
 
 
-
+#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
+#include <Atom/RPI.Public/Scene.h>
 #include <SkinnedMesh/SkinnedMeshComputePass.h>
 #include <SkinnedMesh/SkinnedMeshComputePass.h>
 #include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
 #include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
-#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
 
 
 #include <Atom/RPI.Public/Shader/Shader.h>
 #include <Atom/RPI.Public/Shader/Shader.h>
 
 
@@ -35,16 +35,11 @@ namespace AZ
             return m_shader;
             return m_shader;
         }
         }
 
 
-        void SkinnedMeshComputePass::SetFeatureProcessor(SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor)
-        {
-            m_skinnedMeshFeatureProcessor = skinnedMeshFeatureProcessor;
-        }
-
         void SkinnedMeshComputePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
         void SkinnedMeshComputePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
         {
         {
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
             {
             {
-                m_skinnedMeshFeatureProcessor->SetupSkinningScope(frameGraph);
+                featureProcessor->SetupSkinningScope(frameGraph, Pass::GetDeviceIndex());
             }
             }
 
 
             ComputePass::SetupFrameGraphDependencies(frameGraph);
             ComputePass::SetupFrameGraphDependencies(frameGraph);
@@ -52,30 +47,42 @@ namespace AZ
 
 
         void SkinnedMeshComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
         void SkinnedMeshComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
         {
         {
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
             {
             {
                 SetSrgsForDispatch(context);
                 SetSrgsForDispatch(context);
 
 
-                m_skinnedMeshFeatureProcessor->SubmitSkinningDispatchItems(context, context.GetSubmitRange().m_startIndex, context.GetSubmitRange().m_endIndex);
+                featureProcessor->SubmitSkinningDispatchItems(
+                    context, context.GetSubmitRange().m_startIndex, context.GetSubmitRange().m_endIndex);
             }
             }
         }
         }
 
 
         void SkinnedMeshComputePass::OnShaderReinitialized(const RPI::Shader& shader)
         void SkinnedMeshComputePass::OnShaderReinitialized(const RPI::Shader& shader)
         {
         {
             ComputePass::OnShaderReinitialized(shader);
             ComputePass::OnShaderReinitialized(shader);
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
             {
             {
-                m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
+                featureProcessor->OnSkinningShaderReinitialized(m_shader);
             }
             }
         }
         }
 
 
         void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant)
         void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant)
         {
         {
             ComputePass::OnShaderVariantReinitialized(shaderVariant);
             ComputePass::OnShaderVariantReinitialized(shaderVariant);
-            if (m_skinnedMeshFeatureProcessor)
+            if (auto featureProcessor = GetSkinnedMeshFeatureProcessor())
+            {
+                featureProcessor->OnSkinningShaderReinitialized(m_shader);
+            }
+        }
+
+        SkinnedMeshFeatureProcessor* SkinnedMeshComputePass::GetSkinnedMeshFeatureProcessor()
+        {
+            AZ::RPI::Scene* scene{ GetScene() };
+            if (!scene)
             {
             {
-                m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
+                return nullptr;
             }
             }
+            auto result = scene->GetFeatureProcessor<SkinnedMeshFeatureProcessor>();
+            return result;
         }
         }
     }   // namespace Render
     }   // namespace Render
 }   // namespace AZ
 }   // namespace AZ

+ 1 - 3
Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.h

@@ -33,8 +33,6 @@ namespace AZ
 
 
             Data::Instance<RPI::Shader> GetShader() const;
             Data::Instance<RPI::Shader> GetShader() const;
 
 
-            void SetFeatureProcessor(SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor);
-
         private:
         private:
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
@@ -43,7 +41,7 @@ namespace AZ
             void OnShaderReinitialized(const RPI::Shader& shader) override;
             void OnShaderReinitialized(const RPI::Shader& shader) override;
             void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
             void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
 
 
-            SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
+            SkinnedMeshFeatureProcessor* GetSkinnedMeshFeatureProcessor();
         };
         };
     }
     }
 }
 }

+ 11 - 12
Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp

@@ -309,8 +309,8 @@ namespace AZ
             m_skinningDispatches.clear();
             m_skinningDispatches.clear();
             m_morphTargetDispatches.clear();
             m_morphTargetDispatches.clear();
 
 
-            m_alreadyCreatedSkinningScopeThisFrame = false;
-            m_alreadyCreatedMorphTargetScopeThisFrame = false;
+            m_alreadyCreatedSkinningScopeThisFrame = {};
+            m_alreadyCreatedMorphTargetScopeThisFrame = {};
         }
         }
 
 
         SkinnedMeshFeatureProcessor::SkinnedMeshHandle SkinnedMeshFeatureProcessor::AcquireSkinnedMesh(const SkinnedMeshHandleDescriptor& desc)
         SkinnedMeshFeatureProcessor::SkinnedMeshHandle SkinnedMeshFeatureProcessor::AcquireSkinnedMesh(const SkinnedMeshHandleDescriptor& desc)
@@ -370,12 +370,11 @@ namespace AZ
 
 
         void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass(RPI::RenderPipeline* renderPipeline)
         void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass(RPI::RenderPipeline* renderPipeline)
         {
         {
-            RPI::PassFilter skinPassFilter = RPI::PassFilter::CreateWithPassName(AZ::Name{ "SkinningPass" }, renderPipeline);
+            RPI::PassFilter skinPassFilter = RPI::PassFilter::CreateWithTemplateName(AZ::Name{ "SkinningPassTemplate" }, renderPipeline);
             RPI::Ptr<RPI::Pass> skinningPass = RPI::PassSystemInterface::Get()->FindFirstPass(skinPassFilter);
             RPI::Ptr<RPI::Pass> skinningPass = RPI::PassSystemInterface::Get()->FindFirstPass(skinPassFilter);
             if (skinningPass)
             if (skinningPass)
             {
             {
                 SkinnedMeshComputePass* skinnedMeshComputePass = azdynamic_cast<SkinnedMeshComputePass*>(skinningPass.get());
                 SkinnedMeshComputePass* skinnedMeshComputePass = azdynamic_cast<SkinnedMeshComputePass*>(skinningPass.get());
-                skinnedMeshComputePass->SetFeatureProcessor(this);
 
 
                 // There may be multiple skinning passes in the scene due to multiple pipelines, but there is only one skinning shader
                 // There may be multiple skinning passes in the scene due to multiple pipelines, but there is only one skinning shader
                 m_skinningShader = skinnedMeshComputePass->GetShader();
                 m_skinningShader = skinnedMeshComputePass->GetShader();
@@ -390,12 +389,12 @@ namespace AZ
                 }
                 }
             }
             }
 
 
-            RPI::PassFilter morphPassFilter = RPI::PassFilter::CreateWithPassName(AZ::Name{ "MorphTargetPass" }, renderPipeline);
+            RPI::PassFilter morphPassFilter =
+                RPI::PassFilter::CreateWithTemplateName(AZ::Name{ "MorphTargetPassTemplate" }, renderPipeline);
             RPI::Ptr<RPI::Pass> morphTargetPass = RPI::PassSystemInterface::Get()->FindFirstPass(morphPassFilter);
             RPI::Ptr<RPI::Pass> morphTargetPass = RPI::PassSystemInterface::Get()->FindFirstPass(morphPassFilter);
             if (morphTargetPass)
             if (morphTargetPass)
             {
             {
                 MorphTargetComputePass* morphTargetComputePass = azdynamic_cast<MorphTargetComputePass*>(morphTargetPass.get());
                 MorphTargetComputePass* morphTargetComputePass = azdynamic_cast<MorphTargetComputePass*>(morphTargetPass.get());
-                morphTargetComputePass->SetFeatureProcessor(this);
 
 
                 // There may be multiple morph target passes in the scene due to multiple pipelines, but there is only one morph target shader
                 // There may be multiple morph target passes in the scene due to multiple pipelines, but there is only one morph target shader
                 m_morphTargetShader = morphTargetComputePass->GetShader();
                 m_morphTargetShader = morphTargetComputePass->GetShader();
@@ -419,29 +418,29 @@ namespace AZ
             m_cachedSkinningShaderOptions.SetShader(m_skinningShader);
             m_cachedSkinningShaderOptions.SetShader(m_skinningShader);
         }
         }
 
 
-        void SkinnedMeshFeatureProcessor::SetupSkinningScope(RHI::FrameGraphInterface frameGraph)
+        void SkinnedMeshFeatureProcessor::SetupSkinningScope(RHI::FrameGraphInterface frameGraph, int deviceIndex)
         {
         {
-            if (m_alreadyCreatedSkinningScopeThisFrame)
+            if (RHI::CheckBit(m_alreadyCreatedSkinningScopeThisFrame, deviceIndex))
             {
             {
                 frameGraph.SetEstimatedItemCount(0);
                 frameGraph.SetEstimatedItemCount(0);
             }
             }
             else
             else
             {
             {
                 frameGraph.SetEstimatedItemCount((u32)m_skinningDispatches.size());
                 frameGraph.SetEstimatedItemCount((u32)m_skinningDispatches.size());
-                m_alreadyCreatedSkinningScopeThisFrame = true;
+                RHI::SetBit(m_alreadyCreatedSkinningScopeThisFrame, deviceIndex);
             }
             }
         }
         }
 
 
-        void SkinnedMeshFeatureProcessor::SetupMorphTargetScope(RHI::FrameGraphInterface frameGraph)
+        void SkinnedMeshFeatureProcessor::SetupMorphTargetScope(RHI::FrameGraphInterface frameGraph, int deviceIndex)
         {
         {
-            if (m_alreadyCreatedMorphTargetScopeThisFrame)
+            if (RHI::CheckBit(m_alreadyCreatedMorphTargetScopeThisFrame, deviceIndex))
             {
             {
                 frameGraph.SetEstimatedItemCount(0);
                 frameGraph.SetEstimatedItemCount(0);
             }
             }
             else
             else
             {
             {
                 frameGraph.SetEstimatedItemCount((u32)m_morphTargetDispatches.size());
                 frameGraph.SetEstimatedItemCount((u32)m_morphTargetDispatches.size());
-                m_alreadyCreatedMorphTargetScopeThisFrame = true;
+                RHI::SetBit(m_alreadyCreatedMorphTargetScopeThisFrame, deviceIndex);
             }
             }
         }
         }
 
 

+ 4 - 4
Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.h

@@ -68,11 +68,11 @@ namespace AZ
             RPI::ShaderOptionGroup CreateSkinningShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler);
             RPI::ShaderOptionGroup CreateSkinningShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler);
             void OnSkinningShaderReinitialized(const Data::Instance<RPI::Shader> skinningShader);
             void OnSkinningShaderReinitialized(const Data::Instance<RPI::Shader> skinningShader);
             void SubmitSkinningDispatchItems(const RHI::FrameGraphExecuteContext& context, uint32_t startIndex, uint32_t endIndex);
             void SubmitSkinningDispatchItems(const RHI::FrameGraphExecuteContext& context, uint32_t startIndex, uint32_t endIndex);
-            void SetupSkinningScope(RHI::FrameGraphInterface frameGraph);
+            void SetupSkinningScope(RHI::FrameGraphInterface frameGraph, int deviceIndex);
 
 
             Data::Instance<RPI::Shader> GetMorphTargetShader() const;
             Data::Instance<RPI::Shader> GetMorphTargetShader() const;
             void SubmitMorphTargetDispatchItems(const RHI::FrameGraphExecuteContext& context, uint32_t startIndex, uint32_t endIndex);
             void SubmitMorphTargetDispatchItems(const RHI::FrameGraphExecuteContext& context, uint32_t startIndex, uint32_t endIndex);
-            void SetupMorphTargetScope(RHI::FrameGraphInterface frameGraph);
+            void SetupMorphTargetScope(RHI::FrameGraphInterface frameGraph, int deviceIndex);
 
 
         private:
         private:
             AZ_DISABLE_COPY_MOVE(SkinnedMeshFeatureProcessor);
             AZ_DISABLE_COPY_MOVE(SkinnedMeshFeatureProcessor);
@@ -91,10 +91,10 @@ namespace AZ
             AZStd::unique_ptr<SkinnedMeshStatsCollector> m_statsCollector;
             AZStd::unique_ptr<SkinnedMeshStatsCollector> m_statsCollector;
 
 
             AZStd::unordered_set<const RHI::DispatchItem*> m_skinningDispatches;
             AZStd::unordered_set<const RHI::DispatchItem*> m_skinningDispatches;
-            bool m_alreadyCreatedSkinningScopeThisFrame = false;
+            RHI::MultiDevice::DeviceMask m_alreadyCreatedSkinningScopeThisFrame;
 
 
             AZStd::unordered_set<const RHI::DispatchItem*> m_morphTargetDispatches;
             AZStd::unordered_set<const RHI::DispatchItem*> m_morphTargetDispatches;
-            bool m_alreadyCreatedMorphTargetScopeThisFrame = false;
+            RHI::MultiDevice::DeviceMask m_alreadyCreatedMorphTargetScopeThisFrame;
 
 
             AZStd::mutex m_dispatchItemMutex;
             AZStd::mutex m_dispatchItemMutex;