ImGuiPass.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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/TickBus.h>
  10. #include <AzFramework/Input/Events/InputTextEventListener.h>
  11. #include <AzFramework/Input/Events/InputChannelEventListener.h>
  12. #include <Atom/RHI/DevicePipelineState.h>
  13. #include <Atom/RHI/StreamBufferView.h>
  14. #include <Atom/RPI.Public/Image/StreamingImage.h>
  15. #include <Atom/RPI.Public/Pass/RenderPass.h>
  16. #include <Atom/RPI.Public/PipelineState.h>
  17. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  18. #include <Atom/RPI.Public/Shader/Shader.h>
  19. #include <Atom/RPI.Reflect/Pass/RasterPassData.h>
  20. #include <imgui/imgui.h>
  21. namespace AZ
  22. {
  23. namespace Render
  24. {
  25. //! Custom data for the ImGuiPassData.
  26. struct ImGuiPassData
  27. : public RPI::RasterPassData
  28. {
  29. AZ_RTTI(ImGuiPassData, "{3E96AF5F-DE1E-4B3B-9833-7164AEAB7C28}", RPI::RasterPassData);
  30. AZ_CLASS_ALLOCATOR(ImGuiPassData, SystemAllocator);
  31. ImGuiPassData() = default;
  32. virtual ~ImGuiPassData() = default;
  33. static void Reflect(ReflectContext* context)
  34. {
  35. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  36. {
  37. serializeContext->Class<ImGuiPassData, RPI::RasterPassData>()
  38. ->Version(1)
  39. ->Field("isDefaultImGui", &ImGuiPassData::m_isDefaultImGui)
  40. ;
  41. }
  42. }
  43. bool m_isDefaultImGui = false;
  44. };
  45. //! This pass owns and manages activation of an Imgui context.
  46. class ImGuiPass
  47. : public RPI::RenderPass
  48. , private AzFramework::InputChannelEventListener
  49. , private AzFramework::InputTextEventListener
  50. {
  51. using Base = RPI::RenderPass;
  52. AZ_RPI_PASS(ImGuiPass);
  53. public:
  54. AZ_RTTI(ImGuiPass, "{44EC7CFB-860B-40C8-922D-D54F971E049F}", Base);
  55. AZ_CLASS_ALLOCATOR(ImGuiPass, SystemAllocator);
  56. //! Creates a new ImGuiPass
  57. static RPI::Ptr<ImGuiPass> Create(const RPI::PassDescriptor& descriptor);
  58. ~ImGuiPass();
  59. //! Gets the underlying ImGui context.
  60. ImGuiContext* GetContext();
  61. //! Allows draw data from other imgui contexts to be rendered on this context.
  62. void RenderImguiDrawData(const ImDrawData& drawData);
  63. // AzFramework::InputTextEventListener overrides...
  64. bool OnInputTextEventFiltered(const AZStd::string& textUTF8) override;
  65. // AzFramework::InputChannelEventListener overrides...
  66. bool OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel) override;
  67. protected:
  68. explicit ImGuiPass(const RPI::PassDescriptor& descriptor);
  69. // Pass Behaviour Overrides...
  70. void InitializeInternal() override;
  71. void FrameBeginInternal(FramePrepareParams params) override;
  72. // Scope producer functions
  73. void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
  74. void CompileResources(const RHI::FrameGraphCompileContext& context) override;
  75. void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
  76. private:
  77. static const int MaxUserTextures = 15;
  78. //! Class which connects to the tick handler using the tick order required at the start of an ImGui frame.
  79. class TickHandlerFrameStart : protected TickBus::Handler
  80. {
  81. public:
  82. TickHandlerFrameStart(ImGuiPass& imGuiPass);
  83. protected:
  84. // TickBus::Handler overrides...
  85. int GetTickOrder() override;
  86. void OnTick(float deltaTime, AZ::ScriptTimePoint timePoint) override;
  87. private:
  88. ImGuiPass& m_imGuiPass;
  89. };
  90. //! Class which connects to the tick handler using the tick order required at the end of an ImGui frame.
  91. class TickHandlerFrameEnd : protected TickBus::Handler
  92. {
  93. public:
  94. TickHandlerFrameEnd(ImGuiPass& imGuiPass);
  95. protected:
  96. // TickBus::Handler overrides...
  97. int GetTickOrder() override;
  98. void OnTick(float deltaTime, AZ::ScriptTimePoint timePoint) override;
  99. private:
  100. ImGuiPass& m_imGuiPass;
  101. };
  102. struct DrawInfo
  103. {
  104. RHI::DrawInstanceArguments m_drawInstanceArgs;
  105. RHI::GeometryView m_geometryView;
  106. RHI::Scissor m_scissor;
  107. };
  108. // Wrapper around AZStd::vector<DrawInfo> to implement double/triple buffering
  109. struct BufferedDrawInfos
  110. {
  111. static constexpr u32 DrawInfoBuffering = 2;
  112. AZStd::vector<DrawInfo> m_drawInfos[DrawInfoBuffering];
  113. u8 m_currentIndex = 0;
  114. // Move to the next DrawInfo list in a ring buffer fashion
  115. void NextBuffer() { m_currentIndex = (m_currentIndex + 1) % DrawInfoBuffering; }
  116. // Get the current DrawInfo list
  117. AZStd::vector<DrawInfo>& Get() { return m_drawInfos[m_currentIndex]; }
  118. };
  119. //! Updates the index and vertex buffers, and returns the total number of draw items.
  120. uint32_t UpdateImGuiResources();
  121. // Initializes ImGui related data in the pass. Called during the pass's initialization phase.
  122. void InitializeImGui();
  123. ImGuiContext* m_imguiContext = nullptr;
  124. TickHandlerFrameStart m_tickHandlerFrameStart;
  125. TickHandlerFrameEnd m_tickHandlerFrameEnd;
  126. RHI::Ptr<RPI::PipelineStateForDraw> m_pipelineState;
  127. Data::Instance<RPI::Shader> m_shader;
  128. Data::Instance<RPI::ShaderResourceGroup> m_resourceGroup;
  129. RHI::ShaderInputNameIndex m_texturesIndex = "m_textures";
  130. RHI::ShaderInputNameIndex m_projectionMatrixIndex = "m_projectionMatrix";
  131. RHI::Viewport m_viewportState;
  132. RHI::IndexBufferView m_indexBufferView;
  133. AZStd::array<RHI::StreamBufferView, 2> m_vertexBufferView; // For vertex buffer and instance data
  134. // List of DrawInfos that can be double or triple buffered
  135. BufferedDrawInfos m_drawInfos;
  136. Data::Instance<RPI::StreamingImage> m_fontAtlas;
  137. AZStd::vector<ImDrawData> m_drawData;
  138. bool m_isDefaultImGuiPass = false;
  139. // Whether the pass data indicated that the pass should be used as the default ImGui pass
  140. bool m_requestedAsDefaultImguiPass = false;
  141. // ImGui processes mouse wheel movement on NewFrame(), which could be before input events
  142. // happen, so save the value to apply the most recent value right before NewFrame().
  143. float m_lastFrameMouseWheel = 0.0;
  144. uint32_t m_viewportWidth = 0;
  145. uint32_t m_viewportHeight = 0;
  146. AZStd::unordered_map<Data::Instance<RPI::StreamingImage>, uint32_t> m_userTextures;
  147. Data::Instance<RPI::Buffer> m_instanceBuffer;
  148. RHI::StreamBufferView m_instanceBufferView;
  149. // cache the font text id
  150. void* m_imguiFontTexId = nullptr;
  151. // Whether the pass has already initialized it's ImGui related data.
  152. bool m_imguiInitialized = false;
  153. };
  154. } // namespace RPI
  155. } // namespace AZ