Browse Source

Merge branch 'development' into Prefab/ClearEntityMapsTogether

Signed-off-by: srikappa-amzn <[email protected]>
srikappa-amzn 4 years ago
parent
commit
ef68a07a40

+ 1 - 1
Code/Editor/EditorViewportWidget.cpp

@@ -103,7 +103,7 @@
 AZ_CVAR(
     bool, ed_visibility_logTiming, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Output the timing of the new IVisibilitySystem query");
 AZ_CVAR(bool, ed_useNewCameraSystem, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Editor camera system");
-AZ_CVAR(bool, ed_showCursorCameraLook, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Show the cursor when using free look with the new camera system");
+AZ_CVAR(bool, ed_showCursorCameraLook, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Show the cursor when using free look with the new camera system");
 
 namespace SandboxEditor
 {

+ 48 - 17
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h

@@ -18,6 +18,10 @@ namespace AZ
 {
     namespace RPI
     {
+        class Scene;
+        class RenderPipeline;
+        class RasterPass;
+
         //! This class helps setup dynamic draw data as well as provide draw functions to draw dynamic items.
         //! The draw calls added to the context are only valid for one frame.
         //! DynamicDrawContext is only associated with
@@ -80,17 +84,20 @@ namespace AZ
             //! This function can only be called before EndInit() is called
             void AddDrawStateOptions(DrawStateOptions options);
 
+            //! Call any one of these functions to decide which scope this DynamicDrawContext may draw to.
+            //! One of the function has to be called once before EndInit() is called.
+            //! After DynamicDrawContext is initialized, the output scope can be changed. 
+            //! But it has to be called after existing draw calls are submitted.
+            //! @Param scene Draw calls made with this DynamicDrawContext will be submit to this scene
+            //! @Param pipeline Draw calls made with this DynamicDrawContext will be submit to this render pipeline
+            //! @Param pass Draw calls made with this DynamicDrawContext will only be submit to this pass
+            void SetOutputScope(Scene* scene);
+            void SetOutputScope(RenderPipeline* pipeline);
+            void SetOutputScope(RasterPass* pass);
+
             //! Finalize and validate initialization. Any initialization functions should be called before EndInit is called. 
             void EndInit();
 
-            //! Set up the DynamicDrawContext for the input Scene.
-            //! This should be called after the last frame is done and before any draw calls.
-            void SetScene(Scene* scene);
-
-            //! Set up the DynamicDrawContext for the input RenderPipeline.
-            //! This should be called after the last frame is done and before any draw calls.
-            void SetRenderPipeline(RenderPipeline* pipeline);
-
             //! Return if this DynamicDrawContext is ready to add draw calls
             bool IsReady();
 
@@ -177,14 +184,21 @@ namespace AZ
             DynamicDrawContext() = default;
 
             // Submit draw items to a view
-            void SubmitDrawData(ViewPtr view);
+            void SubmitDrawList(ViewPtr view);
+
+            // Finalize the draw list for all submiited draws.
+            void FinalizeDrawList();
+
+            RHI::DrawListView GetDrawList();
             
             // Reset cached draw data when frame is end (draw data was submitted)
             void FrameEnd();
 
+            void ReInit();
+
             // Get rhi pipeline state which matches current states
             const RHI::PipelineState* GetCurrentPipelineState();
-
+                        
             struct MultiStates
             {
                 // states available for change 
@@ -230,10 +244,22 @@ namespace AZ
             // Draw variations allowed in this DynamicDrawContext
             DrawStateOptions m_drawStateOptions;
 
-            // For generate output attachment layout and filter draw items
-            Scene* m_scene = nullptr;
+            // DrawListTag used to help setup PipelineState's output
+            // and also for submitting draw items to views 
             RHI::DrawListTag m_drawListTag;
 
+            // Output scope related
+            enum class OutputScopeType
+            {
+                Unset,
+                Scene,
+                RenderPipeline,
+                RasterPass
+            };
+            Scene* m_scene = nullptr;
+            RasterPass* m_pass = nullptr;
+            OutputScopeType m_outputScope = OutputScopeType::Unset;
+
             // All draw items use this filter when submit them to views
             // It's set to RenderPipeline's draw filter mask if the DynamicDrawContext was created for a render pipeline.
             RHI::DrawFilterMask m_drawFilter = RHI::DrawFilterMaskDefaultValue;
@@ -242,19 +268,22 @@ namespace AZ
             AZStd::vector<RHI::StreamBufferView> m_cachedStreamBufferViews;
             AZStd::vector<RHI::IndexBufferView> m_cachedIndexBufferViews;
             AZStd::vector<Data::Instance<ShaderResourceGroup>> m_cachedDrawSrg;
-
+            
             // structure includes DrawItem and stream and index buffer index
-            static const uint32_t InvalidIndex = static_cast<uint32_t>(-1);
+            using BufferViewIndexType = uint32_t;
+            static const BufferViewIndexType InvalidIndex = static_cast<BufferViewIndexType>(-1);
             struct DrawItemInfo
             {
                 RHI::DrawItem m_drawItem;
                 RHI::DrawItemSortKey m_sortKey;
-                uint32_t m_vertexBufferViewIndex = InvalidIndex;
-                uint32_t m_indexBufferViewIndex = InvalidIndex;
+                BufferViewIndexType m_vertexBufferViewIndex = InvalidIndex;
+                BufferViewIndexType m_indexBufferViewIndex = InvalidIndex;
             };
-
             AZStd::vector<DrawItemInfo> m_cachedDrawItems;
 
+            // Cached draw list for render to rasterpass
+            RHI::DrawList m_cachedDrawList;
+
             // Flags if this DynamicDrawContext can change shader variants
             bool m_supportShaderVariants = false;
             ShaderVariantId m_currentShaderVariantId;
@@ -266,6 +295,8 @@ namespace AZ
             bool m_initialized = false;
 
             RHI::DrawItemSortKey m_sortKey = 0;
+
+            bool m_drawFinalized = false;
         };
 
         AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::RPI::DynamicDrawContext::DrawStateOptions);

+ 5 - 8
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h

@@ -48,15 +48,9 @@ namespace AZ
 
             AZ_DISABLE_COPY_MOVE(DynamicDrawInterface);
 
-            //! Create a DynamicDrawContext for specified scene (and render pipeline).
-            //! Draw calls which are made to this DynamicDrawContext will only be submitted for this scene.
+            //! Create a DynamicDrawContext
             //! The created DynamicDrawContext is managed by dynamic draw system.
-            virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) = 0;
-                                    
-            //! Create a DynamicDrawContext for specified render pipeline
-            //! Draw calls submitted through the context created by this function are only submitted
-            //! to the supplied render pipeline (viewport)
-            virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) = 0;
+            virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext() = 0;
 
             //! Get a DynamicBuffer from DynamicDrawSystem.
             //! The returned buffer will be invalidated every time the RPISystem's RenderTick is called
@@ -69,6 +63,9 @@ namespace AZ
             //! Note that ownership of the DrawPacket pointer is passed to the dynamic draw system.
             //! (it will be cleaned up correctly since the DrawPacket keeps track of the allocator that was used when it was built)
             virtual void AddDrawPacket(Scene* scene, AZStd::unique_ptr<const RHI::DrawPacket> drawPacket) = 0;
+
+            //! Get DrawLists from any DynamicDrawContext which output to the specified RasterPass.
+            virtual AZStd::vector<RHI::DrawListView> GetDrawListsForPass(const RasterPass* pass) = 0;
         };
 
         //! Global function to query the DynamicDrawInterface.

+ 3 - 2
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h

@@ -31,14 +31,15 @@ namespace AZ
             void Shutdown();
 
             // DynamicDrawInterface overrides...
-            RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) override;
-            RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) override;
+            RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext() override;
             RHI::Ptr<DynamicBuffer> GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override;
             void DrawGeometry(Data::Instance<Material> material, const GeometryData& geometry, ScenePtr scene) override;
             void AddDrawPacket(Scene* scene, AZStd::unique_ptr<const RHI::DrawPacket> drawPacket) override;
+            AZStd::vector<RHI::DrawListView> GetDrawListsForPass(const RasterPass* pass) override;
 
             // Submit draw data for selected scene and pipeline
             void SubmitDrawData(Scene* scene, AZStd::vector<ViewPtr> views);
+
         protected:
 
             void FrameEnd();

+ 8 - 1
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h

@@ -55,6 +55,9 @@ namespace AZ
             void CompileResources(const RHI::FrameGraphCompileContext& context) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
 
+            // Retrieve draw lists from view and dynamic draw system and generate final draw list
+            void UpdateDrawList();
+
             // The draw list tag used to fetch the draw list from the views
             RHI::DrawListTag m_drawListTag;
 
@@ -62,8 +65,12 @@ namespace AZ
             // This is the index of the pipeline state data that corresponds to this pass in the array of pipeline state data
             RHI::Handle<> m_pipelineStateDataIndex;
 
-            // The draw list returned from the view
+            // The reference of the draw list to be drawn
             RHI::DrawListView m_drawListView;
+
+            // If there are more than one draw lists from different source: View, DynamicDrawSystem,
+            // we need to creates a combined draw list which combines all the draw lists to one and cache it until they are submitted. 
+            RHI::DrawList m_combinedDrawList;
             
             RHI::Scissor m_scissorState;
             RHI::Viewport m_viewportState;

+ 117 - 35
Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp

@@ -13,6 +13,7 @@
 #include <Atom/RPI.Public/DynamicDraw/DynamicBuffer.h>
 #include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h>
 #include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
+#include <Atom/RPI.Public/Pass/RasterPass.h>
 #include <Atom/RPI.Public/RenderPipeline.h>
 
 #include <Atom/RPI.Public/View.h>
@@ -173,9 +174,7 @@ namespace AZ
 
         void DynamicDrawContext::EndInit()
         {
-            AZ_Assert(m_scene != nullptr, "DynamicDrawContext should always belong to a scene");
-
-            AZ_Warning("RPI", m_pipelineState, "Failed to initialized shader for DynamicDrawContext");
+            AZ_Warning("RPI", m_pipelineState, "Failed to initialize shader for DynamicDrawContext");
             AZ_Warning("RPI", m_drawListTag.IsValid(), "DynamicDrawContext doesn't have a valid DrawListTag");
 
             if (!m_drawListTag.IsValid() || m_pipelineState == nullptr)
@@ -183,8 +182,27 @@ namespace AZ
                 return;
             }
 
-            m_pipelineState->SetOutputFromScene(m_scene, m_drawListTag);
-            m_pipelineState->Finalize();
+            if (m_outputScope == OutputScopeType::RenderPipeline || m_outputScope == OutputScopeType::Scene)
+            {
+                m_pipelineState->SetOutputFromScene(m_scene, m_drawListTag);
+            }
+            else if (m_outputScope == OutputScopeType::RasterPass)
+            {
+                m_pipelineState->SetOutputFromPass(m_pass);
+            }
+            else
+            {                
+                AZ_Assert(false, "DynamicDrawContext need to set output scope before end initialization");
+                return;
+            }
+
+            m_rhiPipelineState = m_pipelineState->Finalize();
+
+            if (!m_rhiPipelineState)
+            {
+                AZ_Warning("RPI", false, "Failed to initialize PipelineState for DynamicDrawContext");
+                return;
+            }
             m_initialized = true;
 
             // Acquire MultiStates from m_pipelineState
@@ -199,16 +217,58 @@ namespace AZ
             m_rhiPipelineState = m_pipelineState->GetRHIPipelineState();
         }
 
-        void DynamicDrawContext::SetScene(Scene* scene)
+        void DynamicDrawContext::SetOutputScope(Scene* scene)
         {
-            AZ_Assert(scene, "SetScene called with an invalid scene");
-            if (!scene || m_scene == scene)
+            AZ_Assert(scene, "SetOutputScope was called with an invalid Scene");
+            if (!scene)
             {
                 return;
             }
+
+            m_outputScope = OutputScopeType::Scene;
             m_scene = scene;
+            m_pass = nullptr;
             m_drawFilter = RHI::DrawFilterMaskDefaultValue;
-            // Reinitialize if it was initialized
+                        
+            ReInit();
+        }
+
+        void DynamicDrawContext::SetOutputScope(RenderPipeline* pipeline)
+        {
+            AZ_Assert(pipeline, "SetOutputScope was called with an invalid RenderPipeline");
+            AZ_Assert(pipeline->GetScene(), "SetOutputScope called with a RenderPipeline without adding to a scene");
+            if (!pipeline || !pipeline->GetScene())
+            {
+                return;
+            }
+            
+            m_outputScope = OutputScopeType::RenderPipeline;
+            m_scene = pipeline->GetScene();
+            m_pass = nullptr;
+            m_drawFilter = pipeline->GetDrawFilterMask();
+            
+            ReInit();
+        }
+
+        void DynamicDrawContext::SetOutputScope(RasterPass* pass)
+        {
+            AZ_Assert(pass, "SetOutputScope was called with an invalid RasterPass");
+            if (!pass)
+            {
+                return;
+            }
+
+            m_outputScope = OutputScopeType::RasterPass;
+            m_scene = nullptr;
+            m_pass = pass;
+            m_drawFilter = RHI::DrawFilterMaskDefaultValue;
+
+            ReInit();
+        }
+        
+        void DynamicDrawContext::ReInit()
+        {
+         // Reinitialize if it was initialized
             if (m_initialized)
             {
                 // Report warning if there were some draw data
@@ -224,17 +284,6 @@ namespace AZ
             }
         }
 
-        void DynamicDrawContext::SetRenderPipeline(RenderPipeline* pipeline)
-        {
-            AZ_Assert(pipeline, "SetRenderPipeline called with an invalid pipeline");
-            if (!pipeline)
-            {
-                return;
-            }
-            SetScene(pipeline->GetScene());
-            m_drawFilter = pipeline->GetDrawFilterMask();
-        }
-
         bool DynamicDrawContext::IsReady()
         {
             return m_initialized;
@@ -402,10 +451,16 @@ namespace AZ
                 AZ_Assert(false, "DynamicDrawContext isn't initialized");
                 return;
             }
+            
+            if (m_drawFinalized)
+            {
+                AZ_Assert(false, "Can't add draw calls after draw data was finalized");
+                return;
+            }
 
-            if (!m_drawSrgLayout)
+            if (m_drawSrgLayout && !drawSrg)
             {
-                AZ_Assert(false, "PerDrawSrg need to be provided since the shader uses it");
+                AZ_Assert(false, "drawSrg need to be provided since the shader requires it");
                 return;
             }
 
@@ -446,12 +501,12 @@ namespace AZ
             vertexBuffer->Write(vertexData, vertexDataSize);
             m_cachedStreamBufferViews.push_back(vertexBuffer->GetStreamBufferView(m_perVertexDataSize));
             drawItem.m_streamBufferViewCount = 1;
-            drawItemInfo.m_vertexBufferViewIndex = uint32_t(m_cachedStreamBufferViews.size() - 1);
+            drawItemInfo.m_vertexBufferViewIndex = static_cast<BufferViewIndexType>(m_cachedStreamBufferViews.size() - 1);
 
             // Write data to index buffer and set up index buffer view for DrawItem
             indexBuffer->Write(indexData, indexDataSize);
             m_cachedIndexBufferViews.push_back(indexBuffer->GetIndexBufferView(indexFormat));
-            drawItemInfo.m_indexBufferViewIndex = uint32_t(m_cachedIndexBufferViews.size() - 1);
+            drawItemInfo.m_indexBufferViewIndex = static_cast<BufferViewIndexType>(m_cachedIndexBufferViews.size() - 1);
 
             // Setup per context srg if it exists
             if (m_srgPerContext)
@@ -487,7 +542,7 @@ namespace AZ
             drawItemInfo.m_sortKey = m_sortKey++;
             m_cachedDrawItems.emplace_back(drawItemInfo);
         }
-                
+
         void DynamicDrawContext::DrawLinear(const void* vertexData, uint32_t vertexCount, Data::Instance<ShaderResourceGroup> drawSrg)
         {
             if (!m_initialized)
@@ -496,9 +551,15 @@ namespace AZ
                 return;
             }
 
-            if (!m_drawSrgLayout)
+            if (m_drawFinalized)
+            {
+                AZ_Assert(false, "Can't add draw calls after draw data was finalized");
+                return;
+            }
+            
+            if (m_drawSrgLayout && !drawSrg)
             {
-                AZ_Assert(false, "PerDrawSrg need to be provided since the shader uses it");
+                AZ_Assert(false, "drawSrg need to be provided since the shader requires it");
                 return;
             }
 
@@ -569,7 +630,6 @@ namespace AZ
             m_cachedDrawItems.emplace_back(drawItemInfo);
         }
 
-
         Data::Instance<ShaderResourceGroup> DynamicDrawContext::NewDrawSrg()
         {
             if (!m_drawSrgLayout)
@@ -626,18 +686,14 @@ namespace AZ
             return m_sortKey;
         }
 
-        void DynamicDrawContext::SubmitDrawData(ViewPtr view)
+        void DynamicDrawContext::FinalizeDrawList()
         {
-            if (!m_initialized)
+            if (m_drawFinalized)
             {
                 return;
             }
+            AZ_Assert(m_cachedDrawList.size() == 0, "m_cachedDrawList should be cleared ine the end of last frame ");
 
-            if (!view->HasDrawListTag(m_drawListTag))
-            {
-                return;
-            }
- 
             for (auto& drawItemInfo : m_cachedDrawItems)
             {
                 if (drawItemInfo.m_indexBufferViewIndex != InvalidIndex)
@@ -654,10 +710,34 @@ namespace AZ
                 drawItemProperties.m_sortKey = drawItemInfo.m_sortKey;
                 drawItemProperties.m_item = &drawItemInfo.m_drawItem;
                 drawItemProperties.m_drawFilterMask = m_drawFilter;
+                m_cachedDrawList.emplace_back(drawItemProperties);
+            }
+            m_drawFinalized = true;
+        }
+
+        void DynamicDrawContext::SubmitDrawList(ViewPtr view)
+        {
+            if (!m_initialized || m_outputScope == OutputScopeType::RasterPass)
+            {
+                return;
+            }
+
+            if (!view->HasDrawListTag(m_drawListTag))
+            {
+                return;
+            }
+
+            for (auto& drawItemProperties : m_cachedDrawList)
+            {                
                 view->AddDrawItem(m_drawListTag, drawItemProperties);
             }
         }
 
+        RHI::DrawListView DynamicDrawContext::GetDrawList()
+        {
+            return m_cachedDrawList;
+        }
+        
         void DynamicDrawContext::FrameEnd()
         {
             m_sortKey = 0;
@@ -665,6 +745,8 @@ namespace AZ
             m_cachedStreamBufferViews.clear();
             m_cachedIndexBufferViews.clear();
             m_cachedDrawSrg.clear();
+            m_cachedDrawList.clear();
+            m_drawFinalized = false;
         }
 
         const RHI::PipelineState* DynamicDrawContext::GetCurrentPipelineState()

+ 22 - 22
Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp

@@ -53,34 +53,14 @@ namespace AZ
             return m_bufferAlloc->Allocate(size, alignment);
         }
 
-        RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext(Scene* scene)
+        RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext()
         {
-            if (!scene)
-            {
-                AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input scene is invalid");
-                return nullptr;
-            }
             RHI::Ptr<DynamicDrawContext> drawContext = aznew DynamicDrawContext();
-            drawContext->m_scene = scene;
-
             AZStd::lock_guard<AZStd::mutex> lock(m_mutexDrawContext);
             m_dynamicDrawContexts.push_back(drawContext);
             return drawContext;
         }
 
-        RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext(RenderPipeline* pipeline)
-        {
-            if (!pipeline || !pipeline->GetScene())
-            {
-                AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input RenderPipeline is invalid or wasn't added to a Scene");
-                return nullptr;
-            }
-
-            auto context = CreateDynamicDrawContext(pipeline->GetScene());
-            context->m_drawFilter = pipeline->GetDrawFilterMask();
-            return context;
-        }
-
         // [GFX TODO][ATOM-13184] Add support of draw geometry with material for DynamicDrawSystemInterface
         void DynamicDrawSystem::DrawGeometry([[maybe_unused]] Data::Instance<Material> material, [[maybe_unused]] const GeometryData& geometry, [[maybe_unused]] ScenePtr scene)
         {
@@ -101,9 +81,10 @@ namespace AZ
                 {
                     if (drawContext->m_scene == scene)
                     {
+                        drawContext->FinalizeDrawList();
                         for (auto& view : views)
                         {
-                            drawContext->SubmitDrawData(view);
+                            drawContext->SubmitDrawList(view);
                         }
                     }
                 }
@@ -121,6 +102,25 @@ namespace AZ
             }
         }
 
+        AZStd::vector<RHI::DrawListView> DynamicDrawSystem::GetDrawListsForPass(const RasterPass* pass)
+        {
+            AZStd::vector<RHI::DrawListView> result;
+            AZStd::lock_guard<AZStd::mutex> lock(m_mutexDrawContext);
+            for (RHI::Ptr<DynamicDrawContext> drawContext : m_dynamicDrawContexts)
+            {
+                if (drawContext->m_pass == pass)
+                {
+                    drawContext->FinalizeDrawList();
+                    auto drawListView = drawContext->GetDrawList();
+                    if (drawListView.size() > 0)
+                    {
+                        result.push_back(drawListView);
+                    }
+                }
+            }
+            return result;
+        }
+
         void DynamicDrawSystem::FrameEnd()
         {
             {

+ 49 - 10
Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp

@@ -7,17 +7,18 @@
  */
 
 #include <Atom/RHI/CommandList.h>
-#include <Atom/RHI/ShaderResourceGroup.h>
 #include <Atom/RHI/DrawListTagRegistry.h>
+#include <Atom/RHI/RHISystemInterface.h>
+#include <Atom/RHI/ShaderResourceGroup.h>
 
-#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
+#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
+#include <Atom/RPI.Public/Pass/RasterPass.h>
 #include <Atom/RPI.Public/RenderPipeline.h>
-#include <Atom/RHI/RHISystemInterface.h>
 #include <Atom/RPI.Public/RPISystemInterface.h>
 #include <Atom/RPI.Public/Scene.h>
 #include <Atom/RPI.Public/View.h>
-#include <Atom/RPI.Public/Pass/RasterPass.h>
 
+#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
 #include <Atom/RPI.Reflect/Pass/RasterPassData.h>
 
 namespace AZ
@@ -133,10 +134,19 @@ namespace AZ
                 m_viewportState = params.m_viewportState;
             }
 
-            // -- View & DrawList --
-            const AZStd::vector<ViewPtr>& views = m_pipeline->GetViews(GetPipelineViewTag());
-            m_drawListView = {};
+            UpdateDrawList();
+
+            RenderPass::FrameBeginInternal(params);
+        }
+
+        void RasterPass::UpdateDrawList()
+        {
+             // DrawLists from dynamic draw
+            AZStd::vector<RHI::DrawListView> drawLists = DynamicDrawInterface::Get()->GetDrawListsForPass(this);
 
+            // Get DrawList from view
+            const AZStd::vector<ViewPtr>& views = m_pipeline->GetViews(GetPipelineViewTag());
+            RHI::DrawListView viewDrawList;
             if (!views.empty())
             {
                 const ViewPtr& view = views.front();
@@ -144,11 +154,40 @@ namespace AZ
                 // Assert the view has our draw list (the view's DrawlistTags are collected from passes using its viewTag)
                 AZ_Assert(view->HasDrawListTag(m_drawListTag), "View's DrawListTags out of sync with pass'. ");
 
-                // Draw List 
-                m_drawListView = view->GetDrawList(m_drawListTag);
+                viewDrawList = view->GetDrawList(m_drawListTag);
             }
 
-            RenderPass::FrameBeginInternal(params);
+            // clean up data
+            m_drawListView = {};
+            m_combinedDrawList.clear();
+
+            // draw list from view was sorted and if it's the only draw list then we can use it directly
+            if (viewDrawList.size() > 0 && drawLists.size() == 0)
+            {
+                m_drawListView = viewDrawList;
+                return;
+            }
+
+            // add view's draw list to drawLists too
+            drawLists.push_back(viewDrawList);
+
+            // combine draw items from mutiple draw lists to one draw list and sort it.
+            size_t itemCount = 0;
+            for (auto drawList : drawLists)
+            {
+                itemCount += drawList.size();
+            }
+            m_combinedDrawList.resize(itemCount);
+            RHI::DrawItemProperties* currentBuffer = m_combinedDrawList.data();
+            for (auto drawList : drawLists)
+            {
+                memcpy(currentBuffer, drawList.data(), drawList.size()*sizeof(RHI::DrawItemProperties));
+                currentBuffer += drawList.size();
+            }
+            SortDrawList(m_combinedDrawList);
+
+            // have the final draw list point to the combined draw list.
+            m_drawListView = m_combinedDrawList;
         }
 
         // --- DrawList and PipelineView Tags ---

+ 3 - 2
Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp

@@ -83,7 +83,7 @@ namespace AZ::AtomBridge
                 ViewportData& viewportData = m_viewportData[viewportId];
                 for (auto& context : viewportData.m_dynamicDrawContexts)
                 {
-                    context.second->SetRenderPipeline(pipeline.get());
+                    context.second->SetOutputScope(pipeline.get());
                 }
             });
             viewportData.m_viewportDestroyedHandler = AZ::Event<AzFramework::ViewportId>::Handler([this, viewportId](AzFramework::ViewportId id)
@@ -106,7 +106,8 @@ namespace AZ::AtomBridge
             {
                 return nullptr;
             }
-            context = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(pipeline);
+            context = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
+            context->SetOutputScope(pipeline);
             contextFactoryIt->second(context);
         }
 

+ 2 - 1
Gems/LyShine/Code/Source/Draw2d.cpp

@@ -96,7 +96,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc
     AZ_Assert(scene != nullptr, "Attempting to create a DynamicDrawContext for a viewport context that has not been associated with a scene yet.");
 
     // Create and initialize a DynamicDrawContext for 2d drawing
-    m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene.get());
+    m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
     AZ::RPI::ShaderOptionList shaderOptions;
     shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true")));
     shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("false")));
@@ -107,6 +107,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc
         {"TEXCOORD0", AZ::RHI::Format::R32G32_FLOAT} });
     m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::PrimitiveType
         | AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode);
+    m_dynamicDraw->SetOutputScope(scene.get());
     m_dynamicDraw->EndInit();
 
     AZ::RHI::TargetBlendState targetBlendState;

+ 2 - 1
Gems/LyShine/Code/Source/UiRenderer.cpp

@@ -110,7 +110,7 @@ AZ::RPI::ScenePtr UiRenderer::CreateScene(AZStd::shared_ptr<AZ::RPI::ViewportCon
 
 void UiRenderer::CreateDynamicDrawContext(AZ::RPI::ScenePtr scene, AZ::Data::Instance<AZ::RPI::Shader> uiShader)
 {
-    m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene.get());
+    m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
 
     // Initialize the dynamic draw context
     m_dynamicDraw->InitShader(uiShader);
@@ -122,6 +122,7 @@ void UiRenderer::CreateDynamicDrawContext(AZ::RPI::ScenePtr scene, AZ::Data::Ins
     );
     m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::StencilState
         | AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode);
+    m_dynamicDraw->SetOutputScope(scene.get());
     m_dynamicDraw->EndInit();
 }
 

+ 2 - 1
Gems/PhysX/Code/Editor/DocumentationLinkWidget.cpp

@@ -21,8 +21,9 @@ namespace PhysX
             setTextInteractionFlags(Qt::TextBrowserInteraction);
             setOpenExternalLinks(true);
             setAlignment(Qt::AlignCenter);
-            setContentsMargins(60, 15, 60, 15);
+            setContentsMargins(60, 7, 60, 7);
             setWordWrap(true);
+            setStyleSheet(QString::fromUtf8("background-color: rgb(51, 51, 51);"));
         }
     }
 }