IndirectRenderingExampleComponent.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/Component/Component.h>
  10. #include <AzCore/Component/TickBus.h>
  11. #include <AzCore/Math/Color.h>
  12. #include <AzCore/std/containers/array.h>
  13. #include <AzFramework/Windowing/WindowBus.h>
  14. #include <AzFramework/Windowing/NativeWindow.h>
  15. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  16. #include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
  17. #include <Atom/RHI/BufferPool.h>
  18. #include <Atom/RHI/DrawItem.h>
  19. #include <Atom/RHI/Device.h>
  20. #include <Atom/RHI/Factory.h>
  21. #include <Atom/RHI/CopyItem.h>
  22. #include <Atom/RHI/FrameScheduler.h>
  23. #include <Atom/RHI/IndirectBufferSignature.h>
  24. #include <Atom/RHI/IndirectBufferWriter.h>
  25. #include <Atom/RHI/PipelineState.h>
  26. #include <Atom/RHI.Reflect/IndirectBufferLayout.h>
  27. #include <RHI/BasicRHIComponent.h>
  28. #include <Utils/ImGuiSidebar.h>
  29. #include <Utils/ImGuiProgressList.h>
  30. #include <Atom/Utils/AssetCollectionAsyncLoader.h>
  31. namespace AtomSampleViewer
  32. {
  33. //! This samples demonstrates the use of indirect rendering.
  34. //! It uses an indirect buffer that contains a list of commands
  35. //! to be executed by the GPU in an indirect manner.
  36. //! The commands are generated at initialization by the CPU. Each frame
  37. //! a compute shader culls the commands that are outside a designated area
  38. //! and the remaining commands are draw using indirect calls.
  39. //! The sample has two user control variables:
  40. //! - The number of primitives to render
  41. //! - The cull area.
  42. //!
  43. //! Depending on the capabilities of the platform the sample can run the following indirect commands:
  44. //! 1) - Inline Constants Command
  45. //! - Set Vertex View Command
  46. //! - Set Index View Command
  47. //! - Draw Indexed Command
  48. //!
  49. //! 2) - Draw Indexed command
  50. //!
  51. //! Depending on capabilities, the samples may use a count buffer.
  52. //! The number of indirect draw calls is also determinate by device capabilities.
  53. //!
  54. class IndirectRenderingExampleComponent final
  55. : public BasicRHIComponent
  56. , public AZ::TickBus::Handler
  57. , public AzFramework::WindowNotificationBus::Handler
  58. , public AZ::RPI::ShaderReloadNotificationBus::MultiHandler
  59. {
  60. public:
  61. AZ_COMPONENT(IndirectRenderingExampleComponent, "{B799BEFC-52AF-47FF-A806-29E38A5BDF12}", AZ::Component);
  62. AZ_DISABLE_COPY(IndirectRenderingExampleComponent);
  63. static void Reflect(AZ::ReflectContext* context);
  64. IndirectRenderingExampleComponent();
  65. ~IndirectRenderingExampleComponent() override = default;
  66. static constexpr char LogName[] = "IndirectRenderingExampleComponent";
  67. static constexpr char IndirectDrawShaderFilePath[] = "Shaders/RHI/IndirectDraw.azshader";
  68. static constexpr char IndirectDispatchShaderFilePath[] = "Shaders/RHI/IndirectDispatch.azshader";
  69. static constexpr char IndirectDrawVariantLabel[] = "IndirectDraw variant";
  70. static constexpr char IndirectDispatchVariantLabel[] = "IndirectDispatch variant";
  71. private:
  72. /// Max number of objects to render.
  73. static const uint32_t s_maxNumberOfObjects = 4096;
  74. /// Data to be use for Input Assembly.
  75. struct BufferData
  76. {
  77. AZStd::array<VertexPosition, 3> m_trianglePositions;
  78. AZStd::array<VertexPosition, 4> m_quadPositions;
  79. AZStd::array<uint16_t, 3> m_triangleIndices;
  80. AZStd::array<uint16_t, 6> m_quadIndices;
  81. AZStd::array<uint32_t, s_maxNumberOfObjects> m_instanceIndices;
  82. };
  83. /// Data specific to an object.
  84. struct InstanceData
  85. {
  86. AZ::Color m_color;
  87. AZ::Vector4 m_offset;
  88. AZ::Vector4 m_scale;
  89. AZ::Vector4 m_velocity;
  90. };
  91. struct ScopeData
  92. {
  93. //UserDataParam - Empty for this samples
  94. };
  95. /// The indirect commands that the indirect buffer will contain.
  96. enum class SequenceType: uint8_t
  97. {
  98. DrawOnly = 0, // The buffer will contain only a draw indexed command.
  99. IARootConstantsDraw, // The buffer will contain a set vertex buffer, set index buffer, set
  100. // root constants and a draw indexed command.
  101. Count
  102. };
  103. static const uint32_t NumSequencesType = static_cast<uint32_t>(SequenceType::Count);
  104. // AZ::Component
  105. void Activate() override;
  106. void Deactivate() override;
  107. // AZ::TickBus::Handler
  108. void OnTick(float deltaTime, AZ::ScriptTimePoint time);
  109. // RHISystemNotificationBus::Handler
  110. void OnFramePrepare(AZ::RHI::FrameGraphBuilder& frameGraphBuilder) override;
  111. // AzFramework::WindowNotificationBus::Handler
  112. void OnWindowResized(uint32_t width, uint32_t height) override;
  113. ///////////////////////////////////////////////////////////////////////
  114. // ShaderReloadNotificationBus overrides
  115. void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override;
  116. ///////////////////////////////////////////////////////////////////////
  117. void InitRequestsForShaderVariants();
  118. void OnAllAssetsReadyActivate();
  119. void InitInputAssemblyResources();
  120. void InitShaderResources();
  121. void InitIndirectRenderingResources();
  122. void InitInstancesDataResources();
  123. void CreateResetCounterBufferScope();
  124. void CreateCullingScope();
  125. void CreateDrawingScope();
  126. void DrawSampleSettings();
  127. void UpdateInstancesData(float deltaTime);
  128. void UpdateIndirectDispatchArguments();
  129. AZ::RHI::InputStreamLayout m_inputStreamLayout;
  130. AZ::RHI::Ptr<AZ::RHI::BufferPool> m_inputAssemblyBufferPool;
  131. AZ::RHI::Ptr<AZ::RHI::BufferPool> m_shaderBufferPool;
  132. AZ::RHI::Ptr<AZ::RHI::BufferPool> m_instancesBufferPool;
  133. AZ::RHI::Ptr<AZ::RHI::BufferPool> m_copyBufferPool;
  134. AZ::RHI::Ptr<AZ::RHI::Buffer> m_inputAssemblyBuffer;
  135. AZ::RHI::Ptr<AZ::RHI::Buffer> m_sourceIndirectBuffer;
  136. AZ::RHI::Ptr<AZ::RHI::Buffer> m_instancesDataBuffer;
  137. AZ::RHI::Ptr<AZ::RHI::Buffer> m_resetCounterBuffer;
  138. AZ::RHI::Ptr<AZ::RHI::Buffer> m_indirectDispatchBuffer;
  139. AZ::RHI::ConstPtr<AZ::RHI::PipelineState> m_drawPipelineState;
  140. AZ::RHI::ConstPtr<AZ::RHI::PipelineState> m_cullPipelineState;
  141. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> m_sceneShaderResourceGroup;
  142. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> m_cullShaderResourceGroup;
  143. AZStd::array<AZ::Data::Instance<AZ::RPI::ShaderResourceGroup>, NumSequencesType> m_indirectCommandsShaderResourceGroups;
  144. AZStd::vector<AZ::RHI::GeometryView> m_geometryViews;
  145. AZStd::array<AZ::RHI::StreamBufferView, 3> m_streamBufferViews;
  146. AZStd::array<AZ::RHI::IndexBufferView, 2> m_indexBufferViews;
  147. AZ::RHI::IndirectBufferView m_indirectDrawBufferView;
  148. AZ::RHI::IndirectBufferView m_indirectDispatchBufferView;
  149. AZ::RHI::Ptr<AZ::RHI::BufferView> m_sourceIndirectBufferView;
  150. AZ::RHI::Ptr<AZ::RHI::BufferView> m_instancesDataBufferView;
  151. AZ::RHI::IndirectBufferLayout m_indirectDrawBufferLayout;
  152. AZ::RHI::IndirectBufferLayout m_indirectDispatchBufferLayout;
  153. AZ::RHI::Ptr<AZ::RHI::IndirectBufferSignature> m_indirectDrawBufferSignature;
  154. AZ::RHI::Ptr<AZ::RHI::IndirectBufferSignature> m_indirectDispatchBufferSignature;
  155. AZ::RHI::ShaderInputBufferIndex m_sceneInstancesDataBufferIndex;
  156. AZ::RHI::ShaderInputConstantIndex m_sceneMatrixInputIndex;
  157. AZ::RHI::ShaderInputBufferIndex m_cullingCountBufferIndex;
  158. AZ::RHI::ShaderInputConstantIndex m_cullingOffsetIndex;
  159. AZ::RHI::ShaderInputConstantIndex m_cullingNumCommandsIndex;
  160. AZ::RHI::ShaderInputConstantIndex m_cullingMaxCommandsIndex;
  161. AZStd::array<AZ::RHI::ShaderInputBufferIndex, NumSequencesType> m_cullingInputIndirectBufferIndices;
  162. AZStd::array<AZ::RHI::ShaderInputBufferIndex, NumSequencesType> m_cullingOutputIndirectBufferIndices;
  163. AZ::RHI::Ptr<AZ::RHI::IndirectBufferWriter> m_indirectDispatchWriter;
  164. AZ::RHI::DrawIndirect m_drawIndirect;
  165. AZ::RHI::CopyBufferDescriptor m_copyDescriptor;
  166. ImGuiSidebar m_imguiSidebar;
  167. float m_cullOffset = 1.0f;
  168. uint32_t m_numObjects = 0;
  169. AZStd::vector<InstanceData> m_instancesData;
  170. SequenceType m_mode = SequenceType::DrawOnly;
  171. bool m_updateIndirectDispatchArguments = false;
  172. bool m_deviceSupportsCountBuffer = false;
  173. // REMARK: This example requires static shader options to run properly.
  174. // We use notifications from ShaderVariantFinderNotificationBus & this flag to get the
  175. // green light to proceed into full activation.
  176. bool m_doneLoadingShaders = false;
  177. AZStd::unique_ptr<AZ::AssetCollectionAsyncLoader> m_assetLoadManager;
  178. ImGuiProgressList m_imguiProgressList;
  179. AZ::Data::Instance<AZ::RPI::Shader> m_indirectDrawShader;
  180. AZ::RPI::ShaderOptionGroup m_indirectDrawShaderOptionGroup;
  181. AZ::RPI::ShaderVariantStableId m_indirectDrawShaderVariantStableId;
  182. AZ::Data::Instance<AZ::RPI::Shader> m_indirectDispatchShader;
  183. AZ::RPI::ShaderOptionGroup m_indirectDispatchShaderOptionGroup;
  184. AZ::RPI::ShaderVariantStableId m_indirectDispatchShaderVariantStableId;
  185. };
  186. } // namespace AtomSampleViewer