diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h index 620d5155ce..93e595243e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h +++ b/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 m_cachedStreamBufferViews; AZStd::vector m_cachedIndexBufferViews; AZStd::vector> m_cachedDrawSrg; - + // structure includes DrawItem and stream and index buffer index - static const uint32_t InvalidIndex = static_cast(-1); + using BufferViewIndexType = uint32_t; + static const BufferViewIndexType InvalidIndex = static_cast(-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 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); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h index 1b3a2248fb..cc2125af95 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h +++ b/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 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 CreateDynamicDrawContext(RenderPipeline* pipeline) = 0; + virtual RHI::Ptr 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 drawPacket) = 0; + + //! Get DrawLists from any DynamicDrawContext which output to the specified RasterPass. + virtual AZStd::vector GetDrawListsForPass(const RasterPass* pass) = 0; }; //! Global function to query the DynamicDrawInterface. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h index 50bf82c79e..4210bca1db 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h @@ -31,14 +31,15 @@ namespace AZ void Shutdown(); // DynamicDrawInterface overrides... - RHI::Ptr CreateDynamicDrawContext(Scene* scene) override; - RHI::Ptr CreateDynamicDrawContext(RenderPipeline* pipeline) override; + RHI::Ptr CreateDynamicDrawContext() override; RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override; void DrawGeometry(Data::Instance material, const GeometryData& geometry, ScenePtr scene) override; void AddDrawPacket(Scene* scene, AZStd::unique_ptr drawPacket) override; + AZStd::vector GetDrawListsForPass(const RasterPass* pass) override; // Submit draw data for selected scene and pipeline void SubmitDrawData(Scene* scene, AZStd::vector views); + protected: void FrameEnd(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h index 05bd34a999..847fe36bd0 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h +++ b/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; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp index cee61e27f3..7ca2bdcee5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -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_drawSrgLayout) + + if (m_drawFinalized) { - AZ_Assert(false, "PerDrawSrg need to be provided since the shader uses it"); + AZ_Assert(false, "Can't add draw calls after draw data was finalized"); + return; + } + + if (m_drawSrgLayout && !drawSrg) + { + 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(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(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 drawSrg) { if (!m_initialized) @@ -496,9 +551,15 @@ namespace AZ return; } - if (!m_drawSrgLayout) + if (m_drawFinalized) { - AZ_Assert(false, "PerDrawSrg need to be provided since the shader uses it"); + AZ_Assert(false, "Can't add draw calls after draw data was finalized"); + return; + } + + if (m_drawSrgLayout && !drawSrg) + { + 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 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() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp index fd568d29f4..c38fbc4480 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp @@ -53,34 +53,14 @@ namespace AZ return m_bufferAlloc->Allocate(size, alignment); } - RHI::Ptr DynamicDrawSystem::CreateDynamicDrawContext(Scene* scene) + RHI::Ptr DynamicDrawSystem::CreateDynamicDrawContext() { - if (!scene) - { - AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input scene is invalid"); - return nullptr; - } RHI::Ptr drawContext = aznew DynamicDrawContext(); - drawContext->m_scene = scene; - AZStd::lock_guard lock(m_mutexDrawContext); m_dynamicDrawContexts.push_back(drawContext); return drawContext; } - RHI::Ptr 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, [[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 DynamicDrawSystem::GetDrawListsForPass(const RasterPass* pass) + { + AZStd::vector result; + AZStd::lock_guard lock(m_mutexDrawContext); + for (RHI::Ptr 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() { { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index 5e5835e39e..8890499cb7 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -7,17 +7,18 @@ */ #include -#include #include - -#include -#include #include +#include + +#include +#include +#include #include #include #include -#include +#include #include namespace AZ @@ -133,10 +134,19 @@ namespace AZ m_viewportState = params.m_viewportState; } - // -- View & DrawList -- - const AZStd::vector& views = m_pipeline->GetViews(GetPipelineViewTag()); - m_drawListView = {}; + UpdateDrawList(); + RenderPass::FrameBeginInternal(params); + } + + void RasterPass::UpdateDrawList() + { + // DrawLists from dynamic draw + AZStd::vector drawLists = DynamicDrawInterface::Get()->GetDrawListsForPass(this); + + // Get DrawList from view + const AZStd::vector& 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 --- diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp index abd8ce9222..414dd7cdf0 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp +++ b/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::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); } diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 3a6fedfb24..9df411f6a3 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/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; diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 05ea22c045..1b85c75ced 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -110,7 +110,7 @@ AZ::RPI::ScenePtr UiRenderer::CreateScene(AZStd::shared_ptr 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(); }