Browse Source

MultiGPU samples cleanup (#682)

* MultiGPU samples cleanup

Signed-off-by: Joerg H. Mueller <[email protected]>
jhmueller-huawei 1 năm trước cách đây
mục cha
commit
388f4e516e

+ 0 - 20
Gem/Code/Source/MultiGPURPIExampleComponent.cpp

@@ -66,13 +66,6 @@ namespace AtomSampleViewer
 
         AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusConnect();
 
-        // preload assets
-        AZStd::vector<AssetCollectionAsyncLoader::AssetToLoadInfo> assetList = {
-            {CubeModelFilePath, azrtti_typeid<RPI::ModelAsset>()}
-        };
-
-        PreloadAssets(assetList);
-
         // save original render pipeline first and remove it from the scene
         m_originalPipeline = m_scene->GetDefaultRenderPipeline();
         m_scene->RemoveRenderPipeline(m_originalPipeline->GetId());
@@ -165,19 +158,6 @@ namespace AtomSampleViewer
         }
     }
 
-    void MultiGPURPIExampleComponent::OnAllAssetsReadyActivate()
-    {
-        auto meshFeatureProcessor = GetMeshFeatureProcessor();
-
-        auto asset = RPI::AssetUtils::LoadAssetByProductPath<RPI::ModelAsset>(CubeModelFilePath,
-                                                                              RPI::AssetUtils::TraceLevel::Assert);
-        m_meshHandle = meshFeatureProcessor->AcquireMesh(Render::MeshHandleDescriptor(asset));
-
-        const Vector3 translation{ 0.f, 0.f, -1.0f };
-        Transform transform = Transform::CreateTranslation(translation);
-        meshFeatureProcessor->SetTransform(m_meshHandle, transform);
-    }
-
     void MultiGPURPIExampleComponent::DefaultWindowCreated()
     {
         AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext,

+ 0 - 3
Gem/Code/Source/MultiGPURPIExampleComponent.h

@@ -59,9 +59,6 @@ namespace AtomSampleViewer
         // AZ::TickBus::Handler overrides ...
         void OnTick(float deltaTime, AZ::ScriptTimePoint timePoint) override;
 
-        // CommonSampleComponentBase overrides...
-        void OnAllAssetsReadyActivate() override;
-
         // DefaultWindowNotificationBus::Handler overrides...
         void DefaultWindowCreated() override;
 

+ 42 - 40
Gem/Code/Source/RHI/MultiGPUExampleComponent.cpp

@@ -62,25 +62,24 @@ namespace AtomSampleViewer
     {
         if (m_outputWidth != m_imageWidth || m_outputHeight != m_imageHeight)
         {
-            // Image used as color attachment
+            // Image used as color attachment only on first device
             {
-                m_image = aznew RHI::Image;
+                m_images[0] = aznew RHI::Image;
                 RHI::ImageInitRequest initImageRequest;
-                initImageRequest.m_image = m_image.get();
+                initImageRequest.m_image = m_images[0].get();
                 initImageRequest.m_descriptor = RHI::ImageDescriptor::Create2D(
-                    RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, m_outputWidth, m_outputHeight, m_outputFormat);
-                m_imagePool->InitImage(initImageRequest);
+                    RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite, m_outputWidth, m_outputHeight, m_outputFormat);
+                m_firstDeviceOnlyImagePool->InitImage(initImageRequest);
             }
 
-            // Image holds rendered texture from GPU1 (on GPU0)
+            // Image used as color attachment on both devices (rendered on device 1 and copied to device 0 for compositing)
             {
-                m_transferImage = aznew RHI::Image;
+                m_images[1] = aznew RHI::Image;
                 RHI::ImageInitRequest initImageRequest;
-                initImageRequest.m_image = m_transferImage.get();
+                initImageRequest.m_image = m_images[1].get();
                 initImageRequest.m_descriptor = RHI::ImageDescriptor::Create2D(
-                    RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderRead | RHI::ImageBindFlags::CopyWrite, m_outputWidth, m_outputHeight,
-                    m_outputFormat);
-                m_transferImagePool->InitImage(initImageRequest);
+                    RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::CopyWrite, m_outputWidth, m_outputHeight, m_outputFormat);
+                m_imagePool->InitImage(initImageRequest);
             }
 
             RHI::BufferBindFlags stagingBufferBindFlags{ RHI::BufferBindFlags::CopyWrite | RHI::BufferBindFlags::CopyRead };
@@ -92,7 +91,6 @@ namespace AtomSampleViewer
                 RHI::BufferInitRequest request;
                 request.m_buffer = m_stagingBufferToGPU.get();
                 request.m_descriptor = RHI::BufferDescriptor{stagingBufferBindFlags, initialData.size() * sizeof(unsigned int)};
-                //? Check BindFlags
                 request.m_initialData = initialData.data();
                 if (m_stagingBufferPoolToGPU->InitBuffer(request) != RHI::ResultCode::Success)
                 {
@@ -105,7 +103,7 @@ namespace AtomSampleViewer
                 RHI::BufferInitRequest request;
                 request.m_buffer = m_stagingBufferToCPU.get();
                 request.m_descriptor =
-                    RHI::BufferDescriptor{ stagingBufferBindFlags, m_outputWidth * m_outputHeight * sizeof(unsigned int) }; //? Check BindFlags
+                    RHI::BufferDescriptor{ stagingBufferBindFlags, m_outputWidth * m_outputHeight * sizeof(unsigned int) };
                 if (m_stagingBufferPoolToCPU->InitBuffer(request) != RHI::ResultCode::Success)
                 {
                     AZ_Error("MultiGPUExampleComponent", false, "StagingBufferToCPU was not created");
@@ -126,16 +124,16 @@ namespace AtomSampleViewer
         }
 
         frameGraphBuilder.GetAttachmentDatabase().ImportImage(
-            m_imageAttachmentIds[0], m_image);
+            m_imageAttachmentIds[0], m_images[0]);
 
         frameGraphBuilder.GetAttachmentDatabase().ImportImage(
-            m_imageAttachmentIds[1], m_transferImage);
+            m_imageAttachmentIds[1], m_images[1]);
 
         frameGraphBuilder.GetAttachmentDatabase().ImportBuffer(
-            m_bufferAttachmentIds[0], m_stagingBufferToGPU);
+            m_bufferAttachmentIds[0], m_stagingBufferToCPU);
 
         frameGraphBuilder.GetAttachmentDatabase().ImportBuffer(
-            m_bufferAttachmentIds[1], m_stagingBufferToCPU);
+            m_bufferAttachmentIds[1], m_stagingBufferToGPU);
 
         RHI::DeviceBufferMapRequest request{};
         request.m_buffer = m_stagingBufferToCPU->GetDeviceBuffer(1).get();
@@ -177,14 +175,15 @@ namespace AtomSampleViewer
 
         // Create multi-device resources
 
-        // ImagePool for the render target texture
+        RHI::ImageBindFlags imageBindFlags{ RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::CopyWrite };
+
+        // ImagePool for both devices
         {
             m_imagePool = aznew RHI::ImagePool;
-            m_imagePool->SetName(Name("RenderTexturePool"));
+            m_imagePool->SetName(Name("MultiDeviceTexturePool"));
 
             RHI::ImagePoolDescriptor imagePoolDescriptor{};
-            imagePoolDescriptor.m_bindFlags =
-                RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::CopyWrite;
+            imagePoolDescriptor.m_bindFlags = imageBindFlags;
 
             if (m_imagePool->Init(m_deviceMask, imagePoolDescriptor) != RHI::ResultCode::Success)
             {
@@ -193,18 +192,17 @@ namespace AtomSampleViewer
             }
         }
 
-        // ImagePool used to transfer the rendered texture from GPU 1 -> GPU 0
+        // ImagePool only on first device to render the left half
         {
-            m_transferImagePool = aznew RHI::ImagePool;
-            m_transferImagePool->SetName(Name("TransferImagePool"));
+            m_firstDeviceOnlyImagePool = aznew RHI::ImagePool;
+            m_firstDeviceOnlyImagePool->SetName(Name("FirstDeviceImagePool"));
 
             RHI::ImagePoolDescriptor imagePoolDescriptor{};
-            imagePoolDescriptor.m_bindFlags =
-                RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::CopyWrite;
+            imagePoolDescriptor.m_bindFlags = imageBindFlags;
 
-            if (m_transferImagePool->Init(m_deviceMask_1, imagePoolDescriptor) != RHI::ResultCode::Success)
+            if (m_firstDeviceOnlyImagePool->Init(m_deviceMask_1, imagePoolDescriptor) != RHI::ResultCode::Success)
             {
-                AZ_Error("MultiGPUExampleComponent", false, "Failed to initialize transfer image pool.");
+                AZ_Error("MultiGPUExampleComponent", false, "Failed to initialize first device image pool.");
                 return;
             }
         }
@@ -372,7 +370,7 @@ namespace AtomSampleViewer
             }
         }
 
-        // Creates a scope for rendering the triangle.
+        // Creates two scopes for rendering the halves of the triangle.
         {
             struct ScopeData
             {
@@ -381,9 +379,9 @@ namespace AtomSampleViewer
 
             const auto prepareFunction = [this](RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
             {
-                // Binds the swap chain as a color attachment. Clears it to white.
+                // Binds the swap chain as a color attachment. Clears it to black.
                 RHI::ImageScopeAttachmentDescriptor descriptor;
-                descriptor.m_attachmentId = m_imageAttachmentIds[0];
+                descriptor.m_attachmentId = m_imageAttachmentIds[scopeData.second];
                 descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
                 descriptor.m_loadStoreAction.m_storeAction = RHI::AttachmentStoreAction::Store;
                 descriptor.m_loadStoreAction.m_clearValue.m_vector4Uint = {0, 0, 0, 0};
@@ -564,9 +562,6 @@ namespace AtomSampleViewer
                 }
 
                 frameGraph.SetEstimatedItemCount(1);
-
-                frameGraph.ExecuteAfter(RHI::ScopeId{ "MultiGPUTriangle0" });
-                frameGraph.ExecuteAfter(RHI::ScopeId{ "MultiGPUCopyToGPU" });
             };
 
             const auto compileFunction = [this](const RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData)
@@ -628,6 +623,15 @@ namespace AtomSampleViewer
 
         const auto prepareFunction = [this]([[maybe_unused]] RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
         {
+            {
+                RHI::BufferScopeAttachmentDescriptor descriptor{};
+                descriptor.m_attachmentId = m_bufferAttachmentIds[1];
+                descriptor.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, static_cast<uint32_t>(m_stagingBufferToGPU->GetDescriptor().m_byteCount));
+                descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
+                descriptor.m_loadStoreAction.m_storeAction = RHI::AttachmentStoreAction::DontCare;
+                frameGraph.UseCopyAttachment(descriptor, RHI::ScopeAttachmentAccess::Read);
+            }
+
             {
                 RHI::ImageScopeAttachmentDescriptor descriptor{};
                 descriptor.m_attachmentId = m_imageAttachmentIds[1];
@@ -649,7 +653,7 @@ namespace AtomSampleViewer
             copyDescriptor.m_sourceBytesPerRow = m_imageWidth * sizeof(uint32_t);
             copyDescriptor.m_sourceBytesPerImage = static_cast<uint32_t>(m_stagingBufferToGPU->GetDescriptor().m_byteCount);
             copyDescriptor.m_sourceSize = RHI::Size{ m_imageWidth, m_imageHeight, 1 };
-            copyDescriptor.m_destinationImage = m_transferImage->GetDeviceImage(context.GetDeviceIndex()).get();
+            copyDescriptor.m_destinationImage = m_images[1]->GetDeviceImage(context.GetDeviceIndex()).get();
 
             RHI::DeviceCopyItem copyItem(copyDescriptor);
             context.GetCommandList()->Submit(copyItem);
@@ -670,7 +674,7 @@ namespace AtomSampleViewer
         {
             {
                 RHI::BufferScopeAttachmentDescriptor descriptor{};
-                descriptor.m_attachmentId = m_bufferAttachmentIds[1];
+                descriptor.m_attachmentId = m_bufferAttachmentIds[0];
                 descriptor.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, static_cast<uint32_t>(m_stagingBufferToCPU->GetDescriptor().m_byteCount));
                 descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
                 descriptor.m_loadStoreAction.m_storeAction = RHI::AttachmentStoreAction::Store;
@@ -679,13 +683,11 @@ namespace AtomSampleViewer
 
             {
                 RHI::ImageScopeAttachmentDescriptor descriptor{};
-                descriptor.m_attachmentId = m_imageAttachmentIds[0];
+                descriptor.m_attachmentId = m_imageAttachmentIds[1];
                 descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
                 descriptor.m_loadStoreAction.m_storeAction = RHI::AttachmentStoreAction::DontCare;
                 frameGraph.UseCopyAttachment(descriptor, RHI::ScopeAttachmentAccess::Read);
             }
-
-            frameGraph.ExecuteAfter(RHI::ScopeId{ "MultiGPUTriangle1" });
         };
 
         const auto compileFunction = []([[maybe_unused]] const RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData)
@@ -695,7 +697,7 @@ namespace AtomSampleViewer
         const auto executeFunction = [this](const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
         {
             RHI::DeviceCopyImageToBufferDescriptor copyDescriptor{};
-            copyDescriptor.m_sourceImage = m_image->GetDeviceImage(context.GetDeviceIndex()).get();
+            copyDescriptor.m_sourceImage = m_images[1]->GetDeviceImage(context.GetDeviceIndex()).get();
             copyDescriptor.m_sourceSize = RHI::Size{ m_imageWidth, m_imageHeight, 1 };
             copyDescriptor.m_destinationBuffer = m_stagingBufferToCPU->GetDeviceBuffer(context.GetDeviceIndex()).get();
             copyDescriptor.m_destinationOffset = 0;

+ 4 - 5
Gem/Code/Source/RHI/MultiGPUExampleComponent.h

@@ -79,11 +79,11 @@ namespace AtomSampleViewer
         AZStd::array<AZ::RHI::StreamBufferView, 2> m_streamBufferViews;
 
         AZ::RHI::Ptr<AZ::RHI::ImagePool> m_imagePool{};
-        AZ::RHI::Ptr<AZ::RHI::Image> m_image{};
+        AZStd::array<AZ::RHI::Ptr<AZ::RHI::Image>, 2> m_images;
         AZStd::array<AZ::RHI::AttachmentId, 2> m_imageAttachmentIds = { { AZ::RHI::AttachmentId("MultiGPURenderTexture1"),
                                                                           AZ::RHI::AttachmentId("MultiGPURenderTexture2") } };
-        AZStd::array<AZ::RHI::AttachmentId, 2> m_bufferAttachmentIds = { { AZ::RHI::AttachmentId("MultiGPUBufferToGPU"),
-                                                                          AZ::RHI::AttachmentId("MultiGPUBufferToCPU") } };
+        AZStd::array<AZ::RHI::AttachmentId, 2> m_bufferAttachmentIds = { { AZ::RHI::AttachmentId("MultiGPUBufferToCPU"),
+                                                                           AZ::RHI::AttachmentId("MultiGPUBufferToGPU") } };
         uint32_t m_imageWidth{0};
         uint32_t m_imageHeight{0};
 
@@ -107,8 +107,7 @@ namespace AtomSampleViewer
         AZ::RHI::MultiDevice::DeviceMask m_deviceMask_1{};
         AZ::RHI::Ptr<AZ::RHI::BufferPool> m_stagingBufferPoolToGPU{};
         AZ::RHI::Ptr<AZ::RHI::Buffer> m_stagingBufferToGPU{};
-        AZ::RHI::Ptr<AZ::RHI::ImagePool> m_transferImagePool{};
-        AZ::RHI::Ptr<AZ::RHI::Image> m_transferImage{};
+        AZ::RHI::Ptr<AZ::RHI::ImagePool> m_firstDeviceOnlyImagePool{};
         AZ::RHI::Ptr<AZ::RHI::BufferPool> m_inputAssemblyBufferPoolComposite{};
         AZ::RHI::Ptr<AZ::RHI::Buffer> m_inputAssemblyBufferComposite{};
         AZStd::array<AZ::RHI::StreamBufferView, 2> m_streamBufferViewsComposite;

+ 2 - 2
Passes/MultiGPUCopyTestPipeline.pass

@@ -160,7 +160,7 @@
                     ],
                     "PassData": {
                         "$type": "CopyPassData",
-                        "CloneInput": true,
+                        "CloneInput": false,
                         "SourceDeviceIndex": 0,
                         "DestinationDeviceIndex": 1
                     }
@@ -296,4 +296,4 @@
             ]
         }
     }
-}
+}

+ 4 - 0
atomsampleviewer_asset_files.cmake

@@ -18,6 +18,10 @@ set(FILES
     Passes/Fullscreen.pass
     Passes/FullscreenPipeline.pass
     Passes/MultiGPUPipeline.pass
+    Passes/MultiGPUCopyBufferToBuffer.pass
+    Passes/MultiGPUCopyBufferToImage.pass
+    Passes/MultiGPUCopyImageToBuffer.pass
+    Passes/MultiGPUCopyTestPipeline.pass
     Passes/MultiGPUCompositePass.pass
     Passes/MultiGPUTrianglePass.pass
     Passes/RayTracingAmbientOcclusion.pass