ソースを参照

Buffer/image device masks in RHI Multi-GPU sample. (#687)

Use device resource masks and test the update function.

Signed-off-by: Joerg H. Mueller <[email protected]>
jhmueller-huawei 11 ヶ月 前
コミット
c7423edc59

+ 46 - 57
Gem/Code/Source/RHI/MultiGPUExampleComponent.cpp

@@ -69,7 +69,8 @@ namespace AtomSampleViewer
                 initImageRequest.m_image = m_images[0].get();
                 initImageRequest.m_descriptor = RHI::ImageDescriptor::Create2D(
                     RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite, m_outputWidth, m_outputHeight, m_outputFormat);
-                m_firstDeviceOnlyImagePool->InitImage(initImageRequest);
+                initImageRequest.m_deviceMask = m_deviceMask_1;
+                m_imagePool->InitImage(initImageRequest);
             }
 
             // Image used as color attachment on both devices (rendered on device 1 and copied to device 0 for compositing)
@@ -92,10 +93,29 @@ namespace AtomSampleViewer
                 request.m_buffer = m_stagingBufferToGPU.get();
                 request.m_descriptor = RHI::BufferDescriptor{stagingBufferBindFlags, initialData.size() * sizeof(unsigned int)};
                 request.m_initialData = initialData.data();
-                if (m_stagingBufferPoolToGPU->InitBuffer(request) != RHI::ResultCode::Success)
+
+                // This buffer is only necessary on device 0, but we test UpdateBufferDeviceMask below
+                request.m_deviceMask = RHI::MultiDevice::AllDevices;
+                if (m_stagingBufferPool->InitBuffer(request) != RHI::ResultCode::Success)
                 {
                     AZ_Error("MultiGPUExampleComponent", false, "StagingBufferToGPU was not created");
                 }
+
+                auto bufferViewDescriptor{ RHI::BufferViewDescriptor::CreateRaw(0, request.m_descriptor.m_byteCount) };
+                auto bufferView = m_stagingBufferToGPU->BuildBufferView(bufferViewDescriptor);
+                bufferView->GetDeviceBufferView(0);
+                bufferView->GetDeviceBufferView(1);
+
+                RHI::BufferDeviceMaskRequest updateRequest;
+                updateRequest.m_buffer = m_stagingBufferToGPU.get();
+                updateRequest.m_initialData = initialData.data();
+                updateRequest.m_deviceMask = m_deviceMask_1;
+                if (m_stagingBufferPool->UpdateBufferDeviceMask(updateRequest) != RHI::ResultCode::Success)
+                {
+                    AZ_Error("MultiGPUExampleComponent", false, "StagingBufferToGPU was not created");
+                }
+
+                bufferView->GetDeviceBufferView(0);
             }
 
             {
@@ -104,7 +124,17 @@ namespace AtomSampleViewer
                 request.m_buffer = m_stagingBufferToCPU.get();
                 request.m_descriptor =
                     RHI::BufferDescriptor{ stagingBufferBindFlags, m_outputWidth * m_outputHeight * sizeof(unsigned int) };
-                if (m_stagingBufferPoolToCPU->InitBuffer(request) != RHI::ResultCode::Success)
+                // This buffer is necessary on device 1, but we test UpdateBufferDeviceMask below
+                request.m_deviceMask = RHI::MultiDevice::NoDevices;
+                if (m_stagingBufferPool->InitBuffer(request) != RHI::ResultCode::Success)
+                {
+                    AZ_Error("MultiGPUExampleComponent", false, "StagingBufferToCPU was not created");
+                }
+
+                RHI::BufferDeviceMaskRequest updateRequest;
+                updateRequest.m_buffer = m_stagingBufferToCPU.get();
+                updateRequest.m_deviceMask = m_deviceMask_2;
+                if (m_stagingBufferPool->UpdateBufferDeviceMask(updateRequest) != RHI::ResultCode::Success)
                 {
                     AZ_Error("MultiGPUExampleComponent", false, "StagingBufferToCPU was not created");
                 }
@@ -141,20 +171,20 @@ namespace AtomSampleViewer
 
         RHI::DeviceBufferMapResponse response{};
 
-        m_stagingBufferPoolToCPU->GetDeviceBufferPool(1)->MapBuffer(request, response);
+        m_stagingBufferPool->GetDeviceBufferPool(1)->MapBuffer(request, response);
 
         [[maybe_unused]] uint32_t* source = reinterpret_cast<uint32_t*>(response.m_data);
 
         request.m_buffer = m_stagingBufferToGPU->GetDeviceBuffer(0).get();
 
-        m_stagingBufferPoolToGPU->GetDeviceBufferPool(0)->MapBuffer(request, response);
+        m_stagingBufferPool->GetDeviceBufferPool(0)->MapBuffer(request, response);
 
         uint32_t* destination = reinterpret_cast<uint32_t*>(response.m_data);
 
         memcpy(destination, source, request.m_byteCount);
 
-        m_stagingBufferPoolToCPU->GetDeviceBufferPool(1)->UnmapBuffer(*m_stagingBufferToCPU->GetDeviceBuffer(1));
-        m_stagingBufferPoolToGPU->GetDeviceBufferPool(0)->UnmapBuffer(*m_stagingBufferToGPU->GetDeviceBuffer(0));
+        m_stagingBufferPool->GetDeviceBufferPool(1)->UnmapBuffer(*m_stagingBufferToCPU->GetDeviceBuffer(1));
+        m_stagingBufferPool->GetDeviceBufferPool(0)->UnmapBuffer(*m_stagingBufferToGPU->GetDeviceBuffer(0));
     }
 
     MultiGPUExampleComponent::MultiGPUExampleComponent()
@@ -193,51 +223,20 @@ namespace AtomSampleViewer
             }
         }
 
-        // ImagePool only on first device to render the left half
-        {
-            m_firstDeviceOnlyImagePool = aznew RHI::ImagePool;
-            m_firstDeviceOnlyImagePool->SetName(Name("FirstDeviceImagePool"));
-
-            RHI::ImagePoolDescriptor imagePoolDescriptor{};
-            imagePoolDescriptor.m_bindFlags = imageBindFlags;
-            imagePoolDescriptor.m_deviceMask = m_deviceMask_1;
-
-            if (m_firstDeviceOnlyImagePool->Init(imagePoolDescriptor) != RHI::ResultCode::Success)
-            {
-                AZ_Error("MultiGPUExampleComponent", false, "Failed to initialize first device image pool.");
-                return;
-            }
-        }
-
         RHI::BufferBindFlags stagingBufferBindFlags{ RHI::BufferBindFlags::CopyWrite | RHI::BufferBindFlags::CopyRead };
 
-        // Create staging buffer pool for buffer copy to the GPU
+        // Create staging buffer pool for buffer copy to the CPU and to GPU
         {
-            m_stagingBufferPoolToGPU = aznew RHI::BufferPool;
+            m_stagingBufferPool = aznew RHI::BufferPool;
 
             RHI::BufferPoolDescriptor bufferPoolDesc;
             bufferPoolDesc.m_bindFlags = stagingBufferBindFlags;
             bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
             bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
-            bufferPoolDesc.m_deviceMask = m_deviceMask_1;
-            if (m_stagingBufferPoolToGPU->Init(bufferPoolDesc) != RHI::ResultCode::Success)
-            {
-                AZ_Error("MultiGPUExampleComponent", false, "StagingBufferPoolToGPU was not initialized");
-            }
-        }
-
-        // Create staging buffer pools for buffer copy to the CPU
-        {
-            m_stagingBufferPoolToCPU = aznew RHI::BufferPool;
-
-            RHI::BufferPoolDescriptor bufferPoolDesc;
-            bufferPoolDesc.m_bindFlags = stagingBufferBindFlags;
-            bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
-            bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Read;
-            bufferPoolDesc.m_deviceMask = m_deviceMask_2;
-            if (m_stagingBufferPoolToCPU->Init(bufferPoolDesc) != RHI::ResultCode::Success)
+            bufferPoolDesc.m_deviceMask = m_deviceMask;
+            if (m_stagingBufferPool->Init(bufferPoolDesc) != RHI::ResultCode::Success)
             {
-                AZ_Error("MultiGPUExampleComponent", false, "StagingBufferPoolToCPU was not created");
+                AZ_Error("MultiGPUExampleComponent", false, "StagingBufferPool was not initialized");
             }
         }
 
@@ -257,18 +256,15 @@ namespace AtomSampleViewer
         m_pipelineState = nullptr;
         m_shaderResourceGroupShared = nullptr;
 
-        m_stagingBufferPoolToGPU = nullptr;
+        m_stagingBufferPool = nullptr;
         m_stagingBufferToGPU = nullptr;
-        m_inputAssemblyBufferPoolComposite = nullptr;
+        m_stagingBufferToCPU = nullptr;
         m_inputAssemblyBufferComposite = nullptr;
         m_pipelineStateComposite = nullptr;
         m_shaderResourceGroupComposite = nullptr;
         m_shaderResourceGroupDataComposite = RHI::ShaderResourceGroupData{};
         m_shaderResourceGroupPoolComposite = nullptr;
 
-        m_stagingBufferPoolToCPU = nullptr;
-        m_stagingBufferToCPU = nullptr;
-
         RHI::RHISystemNotificationBus::Handler::BusDisconnect();
         m_windowContext = nullptr;
         m_scopeProducers.clear();
@@ -454,14 +450,6 @@ namespace AtomSampleViewer
 
         // Setup input assembly for fullscreen pass
         {
-            m_inputAssemblyBufferPoolComposite = aznew RHI::BufferPool();
-
-            RHI::BufferPoolDescriptor bufferPoolDesc;
-            bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly;
-            bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
-            bufferPoolDesc.m_deviceMask = m_deviceMask_1;
-            m_inputAssemblyBufferPoolComposite->Init(bufferPoolDesc);
-
             SetFullScreenRect(bufferData.m_positions.data(), bufferData.m_uvs.data(), bufferData.m_indices.data());
 
             m_inputAssemblyBufferComposite = aznew RHI::Buffer;
@@ -470,7 +458,8 @@ namespace AtomSampleViewer
             request.m_buffer = m_inputAssemblyBufferComposite.get();
             request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(bufferData) };
             request.m_initialData = &bufferData;
-            m_inputAssemblyBufferPoolComposite->InitBuffer(request);
+            request.m_deviceMask = m_deviceMask_1;
+            m_inputAssemblyBufferPool->InitBuffer(request);
 
             m_streamBufferViewsComposite[0] = { *m_inputAssemblyBufferComposite,
                                                 offsetof(BufferDataCompositePass, m_positions),

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

@@ -105,10 +105,8 @@ namespace AtomSampleViewer
 
         AZ::RHI::Ptr<AZ::RHI::Device> m_device_1{};
         AZ::RHI::MultiDevice::DeviceMask m_deviceMask_1{};
-        AZ::RHI::Ptr<AZ::RHI::BufferPool> m_stagingBufferPoolToGPU{};
+        AZ::RHI::Ptr<AZ::RHI::BufferPool> m_stagingBufferPool{};
         AZ::RHI::Ptr<AZ::RHI::Buffer> m_stagingBufferToGPU{};
-        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;
         AZ::RHI::ConstPtr<AZ::RHI::PipelineState> m_pipelineStateComposite;
@@ -122,7 +120,6 @@ namespace AtomSampleViewer
 
         AZ::RHI::Ptr<AZ::RHI::Device> m_device_2{};
         AZ::RHI::MultiDevice::DeviceMask m_deviceMask_2{};
-        AZ::RHI::Ptr<AZ::RHI::BufferPool> m_stagingBufferPoolToCPU{};
         AZ::RHI::Ptr<AZ::RHI::Buffer> m_stagingBufferToCPU{};
         AZStd::vector<AZStd::shared_ptr<AZ::RHI::ScopeProducer>> m_secondaryScopeProducers;
     };