/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AtomSampleViewer { // MultiGPU RHI example. // Renders a rotating triangle to the screen similar to the TriangleExampleComponent, except, the left half of the screen is rendered by // GPU 0 and the right half by GPU 1, which is then copied to GPU 0 to composite and show the final output on GPU 0. // At least two devices need to be initialized (by passing "--device-count 2") to run this example. class MultiGPUExampleComponent final : public BasicRHIComponent { public: AZ_COMPONENT(MultiGPUExampleComponent, "{BBA75A38-F111-4F52-AD5E-334B6DD58827}", AZ::Component); AZ_DISABLE_COPY(MultiGPUExampleComponent); static void Reflect(AZ::ReflectContext* context); MultiGPUExampleComponent(); ~MultiGPUExampleComponent() override = default; protected: // AZ::Component void Activate() override; void Deactivate() override; void FrameBeginInternal(AZ::RHI::FrameGraphBuilder& frameGraphBuilder) override; // RHISystemNotificationBus::Handler void OnFramePrepare(AZ::RHI::FrameGraphBuilder& frameGraphBuilder) override; private: ///////////////////////////////////////////////////////////////////////// //! Shared Resources void CreateRenderScopeProducer(); AZ::RHI::MultiDevice::DeviceMask m_deviceMask; AZ::RHI::Ptr m_inputAssemblyBufferPool; AZ::RHI::Ptr m_inputAssemblyBuffer; AZ::RHI::ConstPtr m_pipelineState; AZ::Data::Instance m_shaderResourceGroupShared; AZ::RHI::ShaderInputConstantIndex m_objectMatrixConstantIndex; struct BufferDataTrianglePass { AZStd::array m_positions; AZStd::array m_colors; AZStd::array m_indices; }; AZStd::array m_streamBufferViews; AZ::RHI::Ptr m_imagePool{}; AZStd::array, 2> m_images; AZStd::array m_imageAttachmentIds = { { AZ::RHI::AttachmentId("MultiGPURenderTexture1"), AZ::RHI::AttachmentId("MultiGPURenderTexture2") } }; AZStd::array m_bufferAttachmentIds = { { AZ::RHI::AttachmentId("MultiGPUBufferToCPU"), AZ::RHI::AttachmentId("MultiGPUBufferToGPU") } }; uint32_t m_imageWidth{0}; uint32_t m_imageHeight{0}; ///////////////////////////////////////////////////////////////////////// //! First device methods and members void CreateCopyToGPUScopeProducer(); void CreateCopyToCPUScopeProducer(); void CreateCompositeScopeProducer(); struct BufferDataCompositePass { AZStd::array m_positions; AZStd::array m_uvs; AZStd::array m_indices; }; AZStd::array m_textureInputIndices; AZ::RHI::Ptr m_device_1{}; AZ::RHI::MultiDevice::DeviceMask m_deviceMask_1{}; AZ::RHI::Ptr m_stagingBufferPoolToGPU{}; AZ::RHI::Ptr m_stagingBufferToGPU{}; AZ::RHI::Ptr m_firstDeviceOnlyImagePool{}; AZ::RHI::Ptr m_inputAssemblyBufferPoolComposite{}; AZ::RHI::Ptr m_inputAssemblyBufferComposite{}; AZStd::array m_streamBufferViewsComposite; AZ::RHI::ConstPtr m_pipelineStateComposite; AZ::RHI::Ptr m_shaderResourceGroupPoolComposite; AZ::RHI::Ptr m_shaderResourceGroupComposite; AZ::RHI::ShaderResourceGroupData m_shaderResourceGroupDataComposite; AZStd::array m_scissors{}; ///////////////////////////////////////////////////////////////////////// //! Second device methods and members AZ::RHI::Ptr m_device_2{}; AZ::RHI::MultiDevice::DeviceMask m_deviceMask_2{}; AZ::RHI::Ptr m_stagingBufferPoolToCPU{}; AZ::RHI::Ptr m_stagingBufferToCPU{}; AZStd::vector> m_secondaryScopeProducers; }; } // namespace AtomSampleViewer