From 12f528d744d59679f57f904d830cd10c86555ae9 Mon Sep 17 00:00:00 2001 From: qingtao Date: Mon, 26 Apr 2021 13:52:30 -0700 Subject: [PATCH] ATOM-6088 Unified approach to send draws to a single viewport - Created a template class TagRegistery which implements the previous DrawListTagRegistry. The template is used for both DrawListTagRegistry and DrawFilterTagRegistry - Added DrawFilterTag to DrawItemKeyPair - Added DrawFilterMask support in DrawPacket and DrawPacketBuilder - Added CreateDynamicContext for render pipeline which allows draw to selected render pipeline. - Updated RasterPass's BuildCommandListInternal function to filter draw items for its owner RenderPipeline. - Updated RHI unit tests. --- .../Code/Include/Atom/RHI.Reflect/Limits.h | 1 + .../Include/Atom/RHI/DrawFilterTagRegistry.h | 23 +++ .../Atom/RHI/Code/Include/Atom/RHI/DrawItem.h | 20 +- .../Include/Atom/RHI/DrawListTagRegistry.h | 75 +------- .../RHI/Code/Include/Atom/RHI/DrawPacket.h | 52 ++--- .../Code/Include/Atom/RHI/DrawPacketBuilder.h | 18 +- .../RHI/Code/Include/Atom/RHI/RHISystem.h | 2 +- .../Include/Atom/RHI/RHISystemInterface.h | 2 +- .../RHI/Code/Include/Atom/RHI/TagRegistry.h | 177 ++++++++++++++++++ .../Code/Source/RHI/DrawListTagRegistry.cpp | 117 ------------ Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp | 9 +- .../RHI/Code/Source/RHI/DrawPacketBuilder.cpp | 7 + Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 6 +- Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp | 60 +++--- .../Atom/RHI/Code/atom_rhi_public_files.cmake | 3 +- .../DynamicDraw/DynamicDrawContext.h | 4 + .../DynamicDraw/DynamicDrawInterface.h | 7 +- .../DynamicDraw/DynamicDrawSystem.h | 2 +- .../Include/Atom/RPI.Public/RenderPipeline.h | 12 ++ .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 4 + .../DynamicDraw/DynamicDrawContext.cpp | 2 + .../DynamicDraw/DynamicDrawSystem.cpp | 19 +- .../Source/RPI.Public/Pass/RasterPass.cpp | 5 +- .../Code/Source/RPI.Public/RenderPipeline.cpp | 26 +++ .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 4 + 25 files changed, 385 insertions(+), 272 deletions(-) create mode 100644 Gems/Atom/RHI/Code/Include/Atom/RHI/DrawFilterTagRegistry.h create mode 100644 Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h delete mode 100644 Gems/Atom/RHI/Code/Source/RHI/DrawListTagRegistry.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Limits.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Limits.h index 80e8ad268f..1b18ab7671 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Limits.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Limits.h @@ -34,6 +34,7 @@ namespace AZ constexpr uint32_t StreamCountMax = 12; constexpr uint32_t StreamChannelCountMax = 16; constexpr uint32_t DrawListTagCountMax = 64; + constexpr uint32_t DrawFilterTagCountMax = 32; constexpr uint32_t MultiSampleCustomLocationsCountMax = 16; constexpr uint32_t MultiSampleCustomLocationGridSize = 16; constexpr uint32_t SubpassCountMax = 10; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawFilterTagRegistry.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawFilterTagRegistry.h new file mode 100644 index 0000000000..04668b1994 --- /dev/null +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawFilterTagRegistry.h @@ -0,0 +1,23 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include + +namespace AZ +{ + namespace RHI + { + using DrawFilterTagRegistry = TagRegistry; + } +} diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h index 65ca1d3a97..8043e5aa67 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -152,21 +153,31 @@ namespace AZ }; using DrawItemSortKey = int64_t; - + + // A filter associate to a DrawItem which can be used to filter the DrawItem when submitting to command list + using DrawFilterTag = Handle; + using DrawFilterMask = uint32_t; // AZStd::bitset's impelmentation is too expensive. + constexpr uint32_t DrawFilterMaskDefaultValue = uint32_t(-1); // Default all bit to 1. + static_assert(sizeof(DrawFilterMask) * 8 >= Limits::Pipeline::DrawFilterTagCountMax, "DrawFilterMask doesn't have enough bits for maximum tag count"); + struct DrawItemKeyPair { DrawItemKeyPair() = default; - DrawItemKeyPair(const DrawItem* item, DrawItemSortKey sortKey) + DrawItemKeyPair(const DrawItem* item, DrawItemSortKey sortKey = 0, DrawFilterMask filterMask = DrawFilterMaskDefaultValue) : m_item{item} , m_sortKey{sortKey} - {} + , m_drawFilterMask{filterMask} + { + } bool operator == (const DrawItemKeyPair& rhs) const { return m_item == rhs.m_item && m_sortKey == rhs.m_sortKey && - m_depth == rhs.m_depth; + m_depth == rhs.m_depth && + m_drawFilterMask == rhs.m_drawFilterMask + ; } bool operator != (const DrawItemKeyPair& rhs) const @@ -182,6 +193,7 @@ namespace AZ const DrawItem* m_item = nullptr; DrawItemSortKey m_sortKey = 0; float m_depth = 0.0f; + DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; }; } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListTagRegistry.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListTagRegistry.h index 471066a6e2..7c6e9899d8 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListTagRegistry.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListTagRegistry.h @@ -12,83 +12,12 @@ #pragma once #include -#include -#include -#include +#include namespace AZ { namespace RHI { - /** - * Allocates and registers draw list tags by name, allowing the user to acquire and find tags from names. - * The class is designed to map user-friendly tag names defined through content or higher level code to - * low-level tags, which are simple handles. - * - * Some notes about usage and design: - * - DrawListTag values represent indexes into a bitmask, which allows for fast comparison when filtering - * draw items into draw lists (see View::HasDrawListTag()). - * - Tags are reference counted, which means multiple calls to 'Acquire' with the same name will increment - * the internal reference count on the tag. This allows shared ownership between systems, if necessary. - * - FindTag is provided to search for a tag reference without taking ownership. - * - Names are case sensitive. - */ - class DrawListTagRegistry final - : public AZStd::intrusive_base - { - public: - AZ_CLASS_ALLOCATOR(DrawListTagRegistry, AZ::SystemAllocator, 0); - AZ_DISABLE_COPY_MOVE(DrawListTagRegistry); - - static Ptr Create(); - - /** - * Resets the registry back to an empty state. All references are released. - */ - void Reset(); - - /** - * Acquires a draw list tag from the provided name (case sensitive). If the tag already existed, it is ref-counted. - * Returns a valid tag on success; returns a null tag if the registry is at full capacity. You must - * call ReleaseTag() if successful. - */ - DrawListTag AcquireTag(const Name& drawListName); - - /** - * Releases a reference to a tag. Tags are ref-counted, so it's necessary to maintain ownership of the - * tag and release when its no longer needed. - */ - void ReleaseTag(DrawListTag drawListTag); - - /** - * Finds the tag associated with the provided name (case sensitive). If a tag exists with that name, the tag - * is returned. The reference count is NOT incremented on success; ownership is not passed to the user. If - * the tag does not exist, a null tag is returned. - */ - DrawListTag FindTag(const Name& drawListName) const; - - /** - * Returns the name of the given DrawListTag, or empty string if the tag is not registered. - */ - Name GetName(DrawListTag tag) const; - - /** - * Returns the number of allocated tags in the registry. - */ - size_t GetAllocatedTagCount() const; - - private: - DrawListTagRegistry() = default; - - struct Entry - { - Name m_name; - size_t m_refCount = 0; - }; - - mutable AZStd::shared_mutex m_mutex; - AZStd::array m_entriesByTag; - size_t m_allocatedTagCount = 0; - }; + using DrawListTagRegistry = TagRegistry; } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h index 124cbe2c1b..fc7fa90dd6 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h @@ -21,45 +21,48 @@ namespace AZ namespace RHI { - /** - * DrawPacket is a packed data structure (one contiguous allocation) containing a collection of - * DrawItems and their associated array data. Each draw item in the packet is associated - * with a DrawListTag. All draw items in the packet share the same set of shader resource - * groups, index buffer, and draw arguments. - * - * Some notes about design and usage: - * - Draw packets should be used to 'broadcast' variations of the same 'object' to multiple passes. - * For example: 'Shadow', 'Depth', 'Forward'. - * - * - Draw packets can be re-used between different views, scenes, or passes. The embedded shader resource groups - * should represent only the local data necessary to describe the 'object', not the full context including - * scene / view / pass specific state. They serve as a 'template'. - * - * - The packet is self-contained and does not reference external memory. Use DrawPacketBuilder to construct - * an instance and either store in an RHI::Ptr or call 'delete' to release. - */ + //! + //! DrawPacket is a packed data structure (one contiguous allocation) containing a collection of + //! DrawItems and their associated array data. Each draw item in the packet is associated + //! with a DrawListTag. All draw items in the packet share the same set of shader resource + //! groups, index buffer, and draw arguments. + //! + //! Some notes about design and usage: + //! - Draw packets should be used to 'broadcast' variations of the same 'object' to multiple passes. + //! For example: 'Shadow', 'Depth', 'Forward'. + //! + //! - Draw packets can be re-used between different views, scenes, or passes. The embedded shader resource groups + //! should represent only the local data necessary to describe the 'object', not the full context including + //! scene / view / pass specific state. They serve as a 'template'. + //! + //! - The packet is self-contained and does not reference external memory. Use DrawPacketBuilder to construct + //! an instance and either store in an RHI::Ptr or call 'delete' to release. + //! class DrawPacket final : public AZStd::intrusive_base { friend class DrawPacketBuilder; public: using DrawItemVisitor = AZStd::function; - /// Draw packets cannot be move constructed or copied, as they contain an additional memory payload. + //! Draw packets cannot be move constructed or copied, as they contain an additional memory payload. AZ_DISABLE_COPY_MOVE(DrawPacket); - /// Returns the mask representing all the draw lists affected by the packet. + //! Returns the mask representing all the draw lists affected by the packet. DrawListMask GetDrawListMask() const; - /// Returns the number of draw items stored in the packet. + //! Returns the number of draw items stored in the packet. size_t GetDrawItemCount() const; - /// Returns the draw item / sort key associated with the provided index. + //! Returns the draw item / sort key associated with the provided index. DrawItemKeyPair GetDrawItem(size_t index) const; - /// Returns the draw list tag associated with the provided index. + //! Returns the draw list tag associated with the provided index. DrawListTag GetDrawListTag(size_t index) const; - /// Overloaded operator delete for freeing a draw packet. + //! Returns the draw filter mask which applied to all the draw items. + DrawFilterMask GetDrawFilterMask() const; + + //! Overloaded operator delete for freeing a draw packet. void operator delete(void* p, size_t size); private: @@ -72,6 +75,9 @@ namespace AZ // The bit-mask of all active filter tags. DrawListMask m_drawListMask = 0; + // The draw filter applies to each draw item + DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; + // The index buffer view used when the draw call is indexed. IndexBufferView m_indexBufferView; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h index 9a091980bc..5d475d2ccb 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h @@ -29,23 +29,26 @@ namespace AZ { DrawRequest() = default; - /// The filter tag used to direct the draw item. + //! The filter tag used to direct the draw item. DrawListTag m_listTag; - /// The stencil ref value used for this draw item. + //! The stencil ref value used for this draw item. uint8_t m_stencilRef = 0; - /// The array of stream buffers to bind for this draw item. + //! The array of stream buffers to bind for this draw item. AZStd::array_view m_streamBufferViews; - /// Shader resource group unique for this draw request + //! Shader resource group unique for this draw request const ShaderResourceGroup* m_uniqueShaderResourceGroup = nullptr; - /// The pipeline state assigned to this draw item. + //! The pipeline state assigned to this draw item. const PipelineState* m_pipelineState = nullptr; - /// The sort key assigned to this draw item. + //! The sort key assigned to this draw item. DrawItemSortKey m_sortKey = 0; + + //! The filter associates to this draw item. + DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; }; // NOTE: This is configurable; just used to control the amount of memory held by the builder. @@ -69,6 +72,8 @@ namespace AZ void AddShaderResourceGroup(const ShaderResourceGroup* shaderResourceGroup); + void SetDrawFilterMask(DrawFilterMask filterMask); + void AddDrawItem(const DrawRequest& request); const DrawPacket* End(); @@ -79,6 +84,7 @@ namespace AZ IAllocatorAllocate* m_allocator = nullptr; DrawArguments m_drawArguments; DrawListMask m_drawListMask = 0; + DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; size_t m_streamBufferViewCount = 0; IndexBufferView m_indexBufferView; AZStd::fixed_vector m_drawRequests; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h index ccfaff3f11..efaaad1967 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h @@ -65,7 +65,7 @@ namespace AZ RHI::Ptr InitInternalDevice(); RHI::Ptr m_device; - RHI::Ptr m_drawListTagRegistry; + RHI::DrawListTagRegistry m_drawListTagRegistry; RHI::Ptr m_pipelineStateCache; RHI::FrameScheduler m_frameScheduler; RHI::FrameSchedulerCompileRequest m_compileRequest; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h index e7aea89993..784f9344b4 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h @@ -15,13 +15,13 @@ #include #include #include +#include namespace AZ { namespace RHI { class Device; - class DrawListTagRegistry; class FrameGraphBuilder; class PipelineState; class PipelineStateCache; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h new file mode 100644 index 0000000000..277afdd1e3 --- /dev/null +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h @@ -0,0 +1,177 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include +#include + +namespace AZ +{ + namespace RHI + { + //! + //! Allocates and registers tags by name, allowing the user to acquire and find tags from names. + //! The class is designed to map user-friendly tag names defined through content or higher level code to + //! low-level tags, which are simple handles. + //! + //! Some notes about usage and design: + //! - TagType need to be a Handle type. + //! - Tags are reference counted, which means multiple calls to 'Acquire' with the same name will increment + //! the internal reference count on the tag. This allows shared ownership between systems, if necessary. + //! - FindTag is provided to search for a tag reference without taking ownership. + //! - Names are case sensitive. + //! + template + class TagRegistry final + : public AZStd::intrusive_base + { + public: + + //! Resets the registry back to an empty state. All references are released. + void Reset(); + + //! Acquires a tag from the provided name (case sensitive). If the tag already existed, it is ref-counted. + //! Returns a valid tag on success; returns a null tag if the registry is at full capacity. You must + //! call ReleaseTag() if successful. + TagType AcquireTag(const Name& drawListName); + + //! Releases a reference to a tag. Tags are ref-counted, so it's necessary to maintain ownership of the + //! tag and release when its no longer needed. + void ReleaseTag(TagType drawListTag); + + //! Finds the tag associated with the provided name (case sensitive). If a tag exists with that name, the tag + //! is returned. The reference count is NOT incremented on success; ownership is not passed to the user. If + //! the tag does not exist, a null tag is returned. + TagType FindTag(const Name& drawListName) const; + + //! Returns the name of the given DrawListTag, or empty string if the tag is not registered. + Name GetName(TagType tag) const; + + //! Returns the number of allocated tags in the registry. + size_t GetAllocatedTagCount() const; + + private: + + struct Entry + { + Name m_name; + size_t m_refCount = 0; + }; + + mutable AZStd::shared_mutex m_mutex; + AZStd::array m_entriesByTag; + size_t m_allocatedTagCount = 0; + }; + + template + void TagRegistry::Reset() + { + AZStd::unique_lock lock(m_mutex); + m_entriesByTag.fill({}); + m_allocatedTagCount = 0; + } + + template + TagType TagRegistry::AcquireTag(const Name& tagName) + { + if (tagName.IsEmpty()) + { + return {}; + } + + TagType tag; + Entry* foundEmptyEntry = nullptr; + + AZStd::unique_lock lock(m_mutex); + for (size_t i = 0; i < m_entriesByTag.size(); ++i) + { + Entry& entry = m_entriesByTag[i]; + + // Found an empty entry. Cache off the tag and pointer, but keep searching to find if + // another entry holds the same name. + if (entry.m_refCount == 0 && !foundEmptyEntry) + { + foundEmptyEntry = &entry; + tag = TagType(i); + } + else if (entry.m_name == tagName) + { + entry.m_refCount++; + return TagType(i); + } + } + + // No other entry holds the name, so allocate the empty entry. + if (foundEmptyEntry) + { + foundEmptyEntry->m_refCount = 1; + foundEmptyEntry->m_name = tagName; + ++m_allocatedTagCount; + } + + return tag; + } + + template + void TagRegistry::ReleaseTag(TagType tag) + { + if (tag.IsValid()) + { + AZStd::unique_lock lock(m_mutex); + Entry& entry = m_entriesByTag[tag.GetIndex()]; + const size_t refCount = --entry.m_refCount; + AZ_Assert( + refCount != static_cast(-1), "Attempted to forfeit a tag that is not valid. Tag{%d},Name{'%s'}", tag, + entry.m_name.GetCStr()); + if (refCount == 0) + { + entry.m_name = Name(); + --m_allocatedTagCount; + } + } + } + + template + TagType TagRegistry::FindTag(const Name& tagName) const + { + AZStd::shared_lock lock(m_mutex); + for (size_t i = 0; i < m_entriesByTag.size(); ++i) + { + if (m_entriesByTag[i].m_name == tagName) + { + return TagType(i); + } + } + return {}; + } + + template + Name TagRegistry::GetName(TagType tag) const + { + if (tag.GetIndex() < m_entriesByTag.size()) + { + return m_entriesByTag[tag.GetIndex()].m_name; + } + else + { + return Name(); + } + } + + template + size_t TagRegistry::GetAllocatedTagCount() const + { + return m_allocatedTagCount; + } + } +} diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawListTagRegistry.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawListTagRegistry.cpp deleted file mode 100644 index 14d517962a..0000000000 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawListTagRegistry.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include - -namespace AZ -{ - namespace RHI - { - Ptr DrawListTagRegistry::Create() - { - return aznew DrawListTagRegistry; - } - - void DrawListTagRegistry::Reset() - { - AZStd::unique_lock lock(m_mutex); - m_entriesByTag.fill({}); - m_allocatedTagCount = 0; - } - - DrawListTag DrawListTagRegistry::AcquireTag(const Name& drawListName) - { - if (drawListName.IsEmpty()) - { - return {}; - } - - DrawListTag drawListTag; - Entry* foundEmptyEntry = nullptr; - - AZStd::unique_lock lock(m_mutex); - for (size_t i = 0; i < m_entriesByTag.size(); ++i) - { - Entry& entry = m_entriesByTag[i]; - - // Found an empty entry. Cache off the tag and pointer, but keep searching to find if - // another entry holds the same name. - if (entry.m_refCount == 0 && !foundEmptyEntry) - { - foundEmptyEntry = &entry; - drawListTag = DrawListTag(i); - } - else if (entry.m_name == drawListName) - { - entry.m_refCount++; - return DrawListTag(i); - } - } - - // No other entry holds the name, so allocate the empty entry. - if (foundEmptyEntry) - { - foundEmptyEntry->m_refCount = 1; - foundEmptyEntry->m_name = drawListName; - ++m_allocatedTagCount; - } - - return drawListTag; - } - - void DrawListTagRegistry::ReleaseTag(DrawListTag drawListTag) - { - if (drawListTag.IsValid()) - { - AZStd::unique_lock lock(m_mutex); - Entry& entry = m_entriesByTag[drawListTag.GetIndex()]; - const size_t refCount = --entry.m_refCount; - AZ_Assert(refCount != static_cast(-1), "Attempted to forfeit a tag that is not valid. Tag{%d},Name{'%s'}", drawListTag, entry.m_name.GetCStr()); - if (refCount == 0) - { - entry.m_name = Name(); - --m_allocatedTagCount; - } - } - } - - DrawListTag DrawListTagRegistry::FindTag(const Name& drawListName) const - { - AZStd::shared_lock lock(m_mutex); - for (size_t i = 0; i < m_entriesByTag.size(); ++i) - { - if (m_entriesByTag[i].m_name == drawListName) - { - return DrawListTag(i); - } - } - return {}; - } - - Name DrawListTagRegistry::GetName(DrawListTag tag) const - { - if (tag.GetIndex() < m_entriesByTag.size()) - { - return m_entriesByTag[tag.GetIndex()].m_name; - } - else - { - return Name(); - } - } - - size_t DrawListTagRegistry::GetAllocatedTagCount() const - { - return m_allocatedTagCount; - } - } -} diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp index 391bcf3d99..5fa5c563bd 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp @@ -27,7 +27,7 @@ namespace AZ DrawItemKeyPair DrawPacket::GetDrawItem(size_t index) const { AZ_Assert(index < GetDrawItemCount(), "Out of bounds array access!"); - return DrawItemKeyPair(&m_drawItems[index], m_drawItemSortKeys[index]); + return DrawItemKeyPair(&m_drawItems[index], m_drawItemSortKeys[index], m_drawFilterMask); } DrawListTag DrawPacket::GetDrawListTag(size_t index) const @@ -36,6 +36,11 @@ namespace AZ return m_drawListTags[index]; } + DrawFilterMask DrawPacket::GetDrawFilterMask() const + { + return m_drawFilterMask; + } + DrawListMask DrawPacket::GetDrawListMask() const { return m_drawListMask; @@ -46,4 +51,4 @@ namespace AZ reinterpret_cast(p)->m_allocator->DeAllocate(p); } } -} \ No newline at end of file +} diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawPacketBuilder.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawPacketBuilder.cpp index 203818b166..45732e66a7 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawPacketBuilder.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/DrawPacketBuilder.cpp @@ -82,6 +82,11 @@ namespace AZ } } + void DrawPacketBuilder::SetDrawFilterMask(DrawFilterMask filterMask) + { + m_drawFilterMask = filterMask; + } + void DrawPacketBuilder::AddDrawItem(const DrawRequest& request) { if (request.m_listTag.IsValid()) @@ -165,6 +170,7 @@ namespace AZ drawPacket->m_allocator = m_allocator; drawPacket->m_indexBufferView = m_indexBufferView; drawPacket->m_drawListMask = m_drawListMask; + drawPacket->m_drawFilterMask = m_drawFilterMask; if (shaderResourceGroupsOffset.IsValid()) { @@ -288,6 +294,7 @@ namespace AZ m_rootConstants = {}; m_scissors.clear(); m_viewports.clear(); + m_drawFilterMask = DrawFilterMaskDefaultValue; } } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 067090e909..550a7765bf 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -61,7 +61,6 @@ namespace AZ return; } - m_drawListTagRegistry = RHI::DrawListTagRegistry::Create(); m_pipelineStateCache = RHI::PipelineStateCache::Create(*m_device); frameSchedulerDescriptor.m_transientAttachmentPoolDescriptor.m_renderTargetBudgetInBytes = m_platformLimitsDescriptor->m_transientAttachmentPoolBudgets.m_renderTargetBudgetInBytes; @@ -107,7 +106,7 @@ namespace AZ // Register draw list tags declared from content. for (const Name& drawListName : descriptor.m_drawListTags) { - RHI::DrawListTag drawListTag = m_drawListTagRegistry->AcquireTag(drawListName); + RHI::DrawListTag drawListTag = m_drawListTagRegistry.AcquireTag(drawListName); AZ_Warning("RHISystem", drawListTag.IsValid(), "Failed to register draw list tag '%s'. Registry at capacity.", drawListName.GetCStr()); } @@ -199,7 +198,6 @@ namespace AZ m_frameScheduler.Shutdown(); m_platformLimitsDescriptor = nullptr; - m_drawListTagRegistry = nullptr; m_pipelineStateCache = nullptr; m_device->PreShutdown(); AZ_Assert(m_device->use_count()==1, "The ref count for Device is %i but it should be 1 here to ensure all the resources are released", m_device->use_count()); @@ -252,7 +250,7 @@ namespace AZ RHI::DrawListTagRegistry* RHISystem::GetDrawListTagRegistry() { - return m_drawListTagRegistry.get(); + return &m_drawListTagRegistry; } const RHI::FrameSchedulerCompileRequest& RHISystem::GetFrameSchedulerCompileRequest() const diff --git a/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp b/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp index 75a9081100..47830dfa2b 100644 --- a/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp @@ -170,12 +170,10 @@ namespace UnitTest RHITestFixture::SetUp(); m_factory.reset(aznew Factory()); - m_drawListTagRegistry = RHI::DrawListTagRegistry::Create(); } void TearDown() override { - m_drawListTagRegistry = nullptr; m_factory.reset(); RHITestFixture::TearDown(); @@ -184,7 +182,7 @@ namespace UnitTest protected: static const uint32_t s_randomSeed = 1234; - RHI::Ptr m_drawListTagRegistry; + RHI::DrawListTagRegistry m_drawListTagRegistry; RHI::DrawListContext m_drawListContext; AZStd::unique_ptr m_factory; @@ -192,12 +190,12 @@ namespace UnitTest TEST_F(DrawPacketTest, TestDrawListTagRegistryNullCase) { - RHI::DrawListTag nullTag = m_drawListTagRegistry->AcquireTag(Name()); + RHI::DrawListTag nullTag = m_drawListTagRegistry.AcquireTag(Name()); EXPECT_TRUE(nullTag.IsNull()); - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), 0); - m_drawListTagRegistry->ReleaseTag(nullTag); - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0); + m_drawListTagRegistry.ReleaseTag(nullTag); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), 0); } TEST_F(DrawPacketTest, TestDrawListTagRegistrySimple) @@ -205,39 +203,39 @@ namespace UnitTest const Name forwardName1("Forward"); const Name forwardName2("forward"); - RHI::DrawListTag forwardTag1 = m_drawListTagRegistry->AcquireTag(forwardName1); - RHI::DrawListTag forwardTag2 = m_drawListTagRegistry->AcquireTag(forwardName2); + RHI::DrawListTag forwardTag1 = m_drawListTagRegistry.AcquireTag(forwardName1); + RHI::DrawListTag forwardTag2 = m_drawListTagRegistry.AcquireTag(forwardName2); EXPECT_FALSE(forwardTag1.IsNull()); EXPECT_FALSE(forwardTag2.IsNull()); EXPECT_NE(forwardTag1, forwardTag2); - RHI::DrawListTag forwardTag3 = m_drawListTagRegistry->AcquireTag(forwardName1); + RHI::DrawListTag forwardTag3 = m_drawListTagRegistry.AcquireTag(forwardName1); EXPECT_EQ(forwardTag1, forwardTag3); - m_drawListTagRegistry->ReleaseTag(forwardTag1); - m_drawListTagRegistry->ReleaseTag(forwardTag2); - m_drawListTagRegistry->ReleaseTag(forwardTag3); + m_drawListTagRegistry.ReleaseTag(forwardTag1); + m_drawListTagRegistry.ReleaseTag(forwardTag2); + m_drawListTagRegistry.ReleaseTag(forwardTag3); - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), 0); } TEST_F(DrawPacketTest, TestDrawListTagRegistryDeAllocateAssert) { AZ_TEST_START_ASSERTTEST; - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), 0); const Name tagName{"Test"}; - RHI::DrawListTag tag = m_drawListTagRegistry->AcquireTag(tagName); - m_drawListTagRegistry->AcquireTag(tagName); - m_drawListTagRegistry->AcquireTag(tagName); - m_drawListTagRegistry->ReleaseTag(tag); - m_drawListTagRegistry->ReleaseTag(tag); - m_drawListTagRegistry->ReleaseTag(tag); + RHI::DrawListTag tag = m_drawListTagRegistry.AcquireTag(tagName); + m_drawListTagRegistry.AcquireTag(tagName); + m_drawListTagRegistry.AcquireTag(tagName); + m_drawListTagRegistry.ReleaseTag(tag); + m_drawListTagRegistry.ReleaseTag(tag); + m_drawListTagRegistry.ReleaseTag(tag); // One additional forfeit should assert. - m_drawListTagRegistry->ReleaseTag(tag); + m_drawListTagRegistry.ReleaseTag(tag); AZ_TEST_STOP_ASSERTTEST(1); } @@ -256,15 +254,15 @@ namespace UnitTest // Acquire if (random.GetRandom() % 2) { - RHI::DrawListTag tag = m_drawListTagRegistry->AcquireTag(tagNameUnique); + RHI::DrawListTag tag = m_drawListTagRegistry.AcquireTag(tagNameUnique); if (tag.IsNull()) { - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax); } else { - EXPECT_LT(m_drawListTagRegistry->GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax); + EXPECT_LT(m_drawListTagRegistry.GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax); acquiredTags.emplace_back(tag); } } @@ -276,26 +274,26 @@ namespace UnitTest RHI::DrawListTag tag = acquiredTags[tagIndex]; - size_t allocationCountBefore = m_drawListTagRegistry->GetAllocatedTagCount(); - m_drawListTagRegistry->ReleaseTag(tag); - size_t allocationCountAfter = m_drawListTagRegistry->GetAllocatedTagCount(); + size_t allocationCountBefore = m_drawListTagRegistry.GetAllocatedTagCount(); + m_drawListTagRegistry.ReleaseTag(tag); + size_t allocationCountAfter = m_drawListTagRegistry.GetAllocatedTagCount(); EXPECT_EQ(allocationCountBefore - allocationCountAfter, 1); acquiredTags.erase(acquiredTags.begin() + tagIndex); } - EXPECT_EQ(acquiredTags.size(), m_drawListTagRegistry->GetAllocatedTagCount()); + EXPECT_EQ(acquiredTags.size(), m_drawListTagRegistry.GetAllocatedTagCount()); } // Erase all references, make sure the registry is empty again. for (RHI::DrawListTag tag : acquiredTags) { - m_drawListTagRegistry->ReleaseTag(tag); + m_drawListTagRegistry.ReleaseTag(tag); } acquiredTags.clear(); - EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0); + EXPECT_EQ(m_drawListTagRegistry.GetAllocatedTagCount(), 0); } TEST_F(DrawPacketTest, DrawPacketEmpty) diff --git a/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake b/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake index 79239e2c09..d39c3cb6df 100644 --- a/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake +++ b/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake @@ -36,6 +36,7 @@ set(FILES Include/Atom/RHI/CopyItem.h Include/Atom/RHI/ConstantsData.h Include/Atom/RHI/DispatchItem.h + Include/Atom/RHI/DrawFilterTagRegistry.h Include/Atom/RHI/DrawItem.h Include/Atom/RHI/DrawList.h Include/Atom/RHI/DrawListTagRegistry.h @@ -48,7 +49,6 @@ set(FILES Source/RHI/ConstantsData.cpp Source/RHI/DrawList.cpp Source/RHI/DrawListContext.cpp - Source/RHI/DrawListTagRegistry.cpp Source/RHI/DrawPacket.cpp Source/RHI/DrawPacketBuilder.cpp Include/Atom/RHI/Device.h @@ -201,4 +201,5 @@ set(FILES Include/Atom/RHI/CpuProfiler.h Include/Atom/RHI/CpuProfilerImpl.h Source/RHI/CpuProfilerImpl.cpp + Include/Atom/RHI/TagRegistry.h ) 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 3393f6af5c..789717cabe 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 @@ -214,6 +214,10 @@ namespace AZ Scene* m_scene = nullptr; RHI::DrawListTag m_drawListTag; + // 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; + // Cached draw data AZStd::vector m_cachedStreamBufferViews; AZStd::vector m_cachedIndexBufferViews; 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 cd7f9d1bb6..ce686f5c00 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 @@ -56,9 +56,10 @@ namespace AZ //! Draw calls which are made to this DynamicDrawContext will only be submitted for this scene. //! The created DynamicDrawContext is managed by dynamic draw system. virtual RHI::Ptr CreateDynamicDrawContext(Scene* scene) = 0; - - //! Create a DynamicDrawContext for specified pass - virtual RHI::Ptr CreateDynamicDrawContext(Pass* pass = nullptr) = 0; + + //! Create a DynamicDrawContext for specified render pipeline + //! This allows draw calls are only submitted to selected render pipeline (viewport) + virtual RHI::Ptr CreateDynamicDrawContext(RenderPipeline* pipeline) = 0; //! Get a DynamicBuffer from DynamicDrawSystem. //! The returned buffer will be invalidated every time the RPISystem's RenderTick is called 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 07cbed7e72..21c0078374 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 @@ -36,7 +36,7 @@ namespace AZ // DynamicDrawInterface overrides... RHI::Ptr CreateDynamicDrawContext(Scene* scene) override; - RHI::Ptr CreateDynamicDrawContext(Pass* pass) override; + RHI::Ptr CreateDynamicDrawContext(RenderPipeline* pipeline) 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; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h index b81aa84c20..d82e575493 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -184,6 +184,11 @@ namespace AZ //! Get current render mode RenderMode GetRenderMode() const; + //! Get draw filter tag + RHI::DrawFilterTag GetDrawFilterTag() const; + + RHI::DrawFilterMask GetDrawFilterMask() const; + private: RenderPipeline() = default; @@ -211,6 +216,8 @@ namespace AZ // if the view already exists in map, its DrawListMask will be combined to the existing one's void CollectPersistentViews(AZStd::map& outViewMasks) const; + void SetDrawFilterTag(RHI::DrawFilterTag); + // End of functions accessed by Scene class ////////////////////////////////////////////////// @@ -250,6 +257,11 @@ namespace AZ // Original settings from RenderPipelineDescriptor, used to revert active render settings to original settings from RenderPipelineDescriptor PipelineRenderSettings m_originalRenderSettings; + + // A tag to filter draw items submitted by passes of this render pipeline. + // This tag is allocated when it's added to a scene. It's set to invalid when it's removed to the scene. + RHI::DrawFilterTag m_drawFilterTag; + RHI::DrawFilterMask m_drawFilterMask = 0; // The corresponding mask of the m_drawFilterTag }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h index aac6f4fb97..fd80ea4f74 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -234,6 +235,9 @@ namespace AZ // reference of dynamic draw system (from RPISystem) DynamicDrawSystem* m_dynamicDrawSystem = nullptr; + + // Registry which allocates draw filter tag for RenderPipeline + RHI::DrawFilterTagRegistry m_drawFilterTagRegistry; }; // --- Template functions --- 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 5117c3d9dd..78b06aedf8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -604,6 +605,7 @@ namespace AZ RHI::DrawItemKeyPair drawItemKeyPair; drawItemKeyPair.m_sortKey = sortKey; drawItemKeyPair.m_item = &drawItemInfo.m_drawItem; + drawItemKeyPair.m_drawFilterMask = m_drawFilter; view->AddDrawItem(m_drawListTag, drawItemKeyPair); sortKey++; } 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 d7c459cbde..35b5fb205c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawSystem.cpp @@ -59,6 +59,11 @@ namespace AZ RHI::Ptr DynamicDrawSystem::CreateDynamicDrawContext(Scene* scene) { + 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; @@ -67,11 +72,17 @@ namespace AZ return drawContext; } - // [GFX TODO][ATOM-13185] Add support for creating DynamicDrawContext for Pass - RHI::Ptr DynamicDrawSystem::CreateDynamicDrawContext([[maybe_unused]] Pass* pass) + RHI::Ptr DynamicDrawSystem::CreateDynamicDrawContext(RenderPipeline* pipeline) { - AZ_Error("RPI", false, "Unimplemented function"); - return nullptr; + 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 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 84d1499602..1ff6c8ea14 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -197,7 +197,10 @@ namespace AZ for (const RHI::DrawItemKeyPair& drawItemKeyPair : drawListViewPartition) { - commandList->Submit(*drawItemKeyPair.m_item); + if (drawItemKeyPair.m_drawFilterMask & m_pipeline->GetDrawFilterMask()) + { + commandList->Submit(*drawItemKeyPair.m_item); + } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp index 20b6674fb9..cc0cefd082 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp @@ -300,6 +300,9 @@ namespace AZ m_scene = nullptr; m_rootPass->SetEnabled(false); m_rootPass->QueueForRemoval(); + + m_drawFilterTag.Reset(); + m_drawFilterMask = 0; } void RenderPipeline::OnPassModified() @@ -506,5 +509,28 @@ namespace AZ { return m_renderMode != RenderMode::NoRender; } + + RHI::DrawFilterTag RenderPipeline::GetDrawFilterTag() const + { + return m_drawFilterTag; + } + + RHI::DrawFilterMask RenderPipeline::GetDrawFilterMask() const + { + return m_drawFilterMask; + } + + void RenderPipeline::SetDrawFilterTag(RHI::DrawFilterTag tag) + { + m_drawFilterTag = tag; + if (m_drawFilterTag.IsValid()) + { + m_drawFilterMask = 1 << tag.GetIndex(); + } + else + { + m_drawFilterMask = 0; + } + } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 00054881a1..2d9b5f035a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -269,6 +269,8 @@ namespace AZ return; } + pipeline->SetDrawFilterTag(m_drawFilterTagRegistry.AcquireTag(pipelineId)); + m_pipelines.push_back(pipeline); // Set this pipeline as default if the default pipeline was empty. This pipeline should be the first pipeline be added to the scene @@ -303,6 +305,8 @@ namespace AZ m_defaultPipeline = nullptr; } + m_drawFilterTagRegistry.ReleaseTag(pipelineToRemove->GetDrawFilterTag()); + pipelineToRemove->OnRemovedFromScene(this); m_pipelines.erase(it);