From 12f528d744d59679f57f904d830cd10c86555ae9 Mon Sep 17 00:00:00 2001 From: qingtao Date: Mon, 26 Apr 2021 13:52:30 -0700 Subject: [PATCH 1/2] 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); From 60db6b55d065ddd34efea67d09307cdfe7e40c80 Mon Sep 17 00:00:00 2001 From: qingtao Date: Tue, 27 Apr 2021 13:26:43 -0700 Subject: [PATCH 2/2] Address feedback of PR for ATOM-6088. * Rename DrawItemKeyPair to DrawItemProperties. * Switch back to use Ptr instead of DrawListTagRegistry * Updated some comment. --- .../Atom/RHI/Code/Include/Atom/RHI/DrawItem.h | 18 +++-- .../Atom/RHI/Code/Include/Atom/RHI/DrawList.h | 4 +- .../Code/Include/Atom/RHI/DrawListContext.h | 2 +- .../RHI/Code/Include/Atom/RHI/DrawPacket.h | 8 +-- .../Code/Include/Atom/RHI/DrawPacketBuilder.h | 2 +- .../RHI/Code/Include/Atom/RHI/RHISystem.h | 2 +- .../RHI/Code/Include/Atom/RHI/TagRegistry.h | 19 ++++-- Gems/Atom/RHI/Code/Source/RHI/DrawList.cpp | 12 ++-- .../RHI/Code/Source/RHI/DrawListContext.cpp | 6 +- Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp | 4 +- Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 7 +- Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp | 66 ++++++++++--------- .../DynamicDraw/DynamicDrawInterface.h | 3 +- .../Include/Atom/RPI.Public/RenderPipeline.h | 5 +- .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 2 +- .../RPI/Code/Include/Atom/RPI.Public/View.h | 2 +- .../DynamicDraw/DynamicDrawContext.cpp | 10 +-- .../Source/RPI.Public/Pass/RasterPass.cpp | 6 +- .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 5 +- Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp | 4 +- 20 files changed, 104 insertions(+), 83 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h index 8043e5aa67..23fa2e691c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawItem.h @@ -160,18 +160,18 @@ namespace AZ 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 + struct DrawItemProperties { - DrawItemKeyPair() = default; + DrawItemProperties() = default; - DrawItemKeyPair(const DrawItem* item, DrawItemSortKey sortKey = 0, DrawFilterMask filterMask = DrawFilterMaskDefaultValue) + DrawItemProperties(const DrawItem* item, DrawItemSortKey sortKey = 0, DrawFilterMask filterMask = DrawFilterMaskDefaultValue) : m_item{item} , m_sortKey{sortKey} , m_drawFilterMask{filterMask} { } - bool operator == (const DrawItemKeyPair& rhs) const + bool operator==(const DrawItemProperties& rhs) const { return m_item == rhs.m_item && m_sortKey == rhs.m_sortKey && @@ -180,19 +180,25 @@ namespace AZ ; } - bool operator != (const DrawItemKeyPair& rhs) const + bool operator!=(const DrawItemProperties& rhs) const { return !(*this == rhs); } - bool operator < (const DrawItemKeyPair& rhs) const + bool operator<(const DrawItemProperties& rhs) const { return m_sortKey < rhs.m_sortKey; } + //! A pointer to the draw item const DrawItem* m_item = nullptr; + //! A sorting key of this draw item which is used for sorting draw items in DrawList + // Check RHI::SortDrawList() function for detail DrawItemSortKey m_sortKey = 0; + //! A depth value this draw item which is used for sorting draw items in DrawList + //! Check RHI::SortDrawList() function for detail float m_depth = 0.0f; + //! A filter mask which helps decide whether to submit this draw item to a Scope's command list or not DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; }; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawList.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawList.h index 71c1cc026c..e232b1cf07 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawList.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawList.h @@ -39,8 +39,8 @@ namespace AZ using DrawListTag = Handle; using DrawListMask = AZStd::bitset; - using DrawList = AZStd::vector; - using DrawListView = AZStd::array_view; + using DrawList = AZStd::vector; + using DrawListView = AZStd::array_view; /// Contains a table of draw lists, indexed by the tag. using DrawListsByTag = AZStd::array; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListContext.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListContext.h index 00514ef3ef..c8f792ac49 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListContext.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawListContext.h @@ -53,7 +53,7 @@ namespace AZ /// Adds an individual draw item to the draw list associated with the provided tag. This will /// no-op if the tag is not present in the internal draw list mask. - void AddDrawItem(DrawListTag drawListTag, DrawItemKeyPair drawItemKeyPair); + void AddDrawItem(DrawListTag drawListTag, DrawItemProperties drawItemProperties); /// Coalesces the draw lists in preparation for access via GetList. This should /// be called from a single thread as a sync point between the append / consume phases. diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h index fc7fa90dd6..988c3a73dd 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacket.h @@ -25,7 +25,7 @@ namespace AZ //! 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. + //! groups, index buffer, one DrawFilterMask, and draw arguments. //! //! Some notes about design and usage: //! - Draw packets should be used to 'broadcast' variations of the same 'object' to multiple passes. @@ -42,7 +42,7 @@ namespace AZ { friend class DrawPacketBuilder; public: - using DrawItemVisitor = AZStd::function; + using DrawItemVisitor = AZStd::function; //! Draw packets cannot be move constructed or copied, as they contain an additional memory payload. AZ_DISABLE_COPY_MOVE(DrawPacket); @@ -53,8 +53,8 @@ namespace AZ //! 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. - DrawItemKeyPair GetDrawItem(size_t index) const; + //! Returns the draw item and its properties associated with the provided index. + DrawItemProperties GetDrawItem(size_t index) const; //! Returns the draw list tag associated with the provided index. DrawListTag GetDrawListTag(size_t index) const; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h index 5d475d2ccb..15303158f9 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/DrawPacketBuilder.h @@ -47,7 +47,7 @@ namespace AZ //! The sort key assigned to this draw item. DrawItemSortKey m_sortKey = 0; - //! The filter associates to this draw item. + //! The filter associated to this draw item. DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue; }; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h index efaaad1967..ccfaff3f11 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::DrawListTagRegistry m_drawListTagRegistry; + RHI::Ptr m_drawListTagRegistry; RHI::Ptr m_pipelineStateCache; RHI::FrameScheduler m_frameScheduler; RHI::FrameSchedulerCompileRequest m_compileRequest; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h index 277afdd1e3..429a49657b 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/TagRegistry.h @@ -36,6 +36,10 @@ namespace AZ : public AZStd::intrusive_base { public: + AZ_CLASS_ALLOCATOR(TagRegistry, AZ::SystemAllocator, 0); + AZ_DISABLE_COPY_MOVE(TagRegistry); + + static Ptr Create(); //! Resets the registry back to an empty state. All references are released. void Reset(); @@ -43,24 +47,25 @@ namespace AZ //! 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); + TagType AcquireTag(const Name& tagName); //! 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); + void ReleaseTag(TagType tagName); //! 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; + TagType FindTag(const Name& tagName) const; - //! Returns the name of the given DrawListTag, or empty string if the tag is not registered. + //! Returns the name of the given tag, 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: + TagRegistry() = default; struct Entry { @@ -73,6 +78,12 @@ namespace AZ size_t m_allocatedTagCount = 0; }; + template + Ptr> TagRegistry::Create() + { + return aznew TagRegistry(); + } + template void TagRegistry::Reset() { diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawList.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawList.cpp index 518ec59ac5..c50255224f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawList.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/DrawList.cpp @@ -35,8 +35,7 @@ namespace AZ switch (sortType) { case DrawListSortType::KeyThenDepth: - AZStd::sort(drawList.begin(), drawList.end(), - [](const DrawItemKeyPair& a, const DrawItemKeyPair& b) + AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b) { if (a.m_sortKey != b.m_sortKey) { @@ -48,8 +47,7 @@ namespace AZ break; case DrawListSortType::KeyThenReverseDepth: - AZStd::sort(drawList.begin(), drawList.end(), - [](const DrawItemKeyPair& a, const DrawItemKeyPair& b) + AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b) { if (a.m_sortKey != b.m_sortKey) { @@ -61,8 +59,7 @@ namespace AZ break; case DrawListSortType::DepthThenKey: - AZStd::sort(drawList.begin(), drawList.end(), - [](const DrawItemKeyPair& a, const DrawItemKeyPair& b) + AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b) { if (a.m_depth != b.m_depth) { @@ -74,8 +71,7 @@ namespace AZ break; case DrawListSortType::ReverseDepthThenKey: - AZStd::sort(drawList.begin(), drawList.end(), - [](const DrawItemKeyPair& a, const DrawItemKeyPair& b) + AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b) { if (a.m_depth != b.m_depth) { diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawListContext.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawListContext.cpp index dbd06c6969..8cec5ba39b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawListContext.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/DrawListContext.cpp @@ -63,14 +63,14 @@ namespace AZ if (m_drawListMask[drawListTag.GetIndex()]) { - DrawItemKeyPair drawItem = drawPacket->GetDrawItem(i); + DrawItemProperties drawItem = drawPacket->GetDrawItem(i); drawItem.m_depth = depth; threadListsByTag[drawListTag.GetIndex()].push_back(drawItem); } } } - void DrawListContext::AddDrawItem(DrawListTag drawListTag, DrawItemKeyPair drawItemKeyPair) + void DrawListContext::AddDrawItem(DrawListTag drawListTag, DrawItemProperties drawItemProperties) { if (Validation::IsEnabled()) { @@ -84,7 +84,7 @@ namespace AZ if (m_drawListMask[drawListTag.GetIndex()]) { DrawListsByTag& drawListsByTag = m_threadListsByTag.GetStorage(); - drawListsByTag[drawListTag.GetIndex()].push_back(drawItemKeyPair); + drawListsByTag[drawListTag.GetIndex()].push_back(drawItemProperties); } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp b/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp index 5fa5c563bd..85580fdc84 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/DrawPacket.cpp @@ -24,10 +24,10 @@ namespace AZ return m_drawItemCount; } - DrawItemKeyPair DrawPacket::GetDrawItem(size_t index) const + DrawItemProperties DrawPacket::GetDrawItem(size_t index) const { AZ_Assert(index < GetDrawItemCount(), "Out of bounds array access!"); - return DrawItemKeyPair(&m_drawItems[index], m_drawItemSortKeys[index], m_drawFilterMask); + return DrawItemProperties(&m_drawItems[index], m_drawItemSortKeys[index], m_drawFilterMask); } DrawListTag DrawPacket::GetDrawListTag(size_t index) const diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 550a7765bf..f92d2621b1 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -60,7 +60,8 @@ namespace AZ AZ_Assert(false, "RHISystem", "Unable to initialize RHI! \n"); return; } - + + m_drawListTagRegistry = RHI::DrawListTagRegistry::Create(); m_pipelineStateCache = RHI::PipelineStateCache::Create(*m_device); frameSchedulerDescriptor.m_transientAttachmentPoolDescriptor.m_renderTargetBudgetInBytes = m_platformLimitsDescriptor->m_transientAttachmentPoolBudgets.m_renderTargetBudgetInBytes; @@ -106,7 +107,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()); } @@ -250,7 +251,7 @@ namespace AZ RHI::DrawListTagRegistry* RHISystem::GetDrawListTagRegistry() { - return &m_drawListTagRegistry; + return m_drawListTagRegistry.get(); } 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 47830dfa2b..7fc393cd0c 100644 --- a/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/DrawPacketTests.cpp @@ -80,11 +80,11 @@ namespace UnitTest m_indexBufferView = RHI::IndexBufferView(*m_bufferEmpty, random.GetRandom(), random.GetRandom(), RHI::IndexFormat::Uint16); } - void ValidateDrawItem(const DrawItemData& drawItemData, RHI::DrawItemKeyPair itemKeyPair) const + void ValidateDrawItem(const DrawItemData& drawItemData, RHI::DrawItemProperties itemProperties) const { - const RHI::DrawItem* drawItem = itemKeyPair.m_item; + const RHI::DrawItem* drawItem = itemProperties.m_item; - EXPECT_EQ(itemKeyPair.m_sortKey, drawItemData.m_sortKey); + EXPECT_EQ(itemProperties.m_sortKey, drawItemData.m_sortKey); EXPECT_EQ(drawItem->m_stencilRef, drawItemData.m_stencilRef); EXPECT_EQ(drawItem->m_pipelineState, drawItemData.m_pipelineState); @@ -170,10 +170,12 @@ 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(); @@ -182,7 +184,7 @@ namespace UnitTest protected: static const uint32_t s_randomSeed = 1234; - RHI::DrawListTagRegistry m_drawListTagRegistry; + RHI::Ptr m_drawListTagRegistry; RHI::DrawListContext m_drawListContext; AZStd::unique_ptr m_factory; @@ -190,12 +192,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) @@ -203,39 +205,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); } @@ -254,15 +256,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); } } @@ -274,26 +276,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/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h index ce686f5c00..50b13277af 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 @@ -58,7 +58,8 @@ namespace AZ virtual RHI::Ptr CreateDynamicDrawContext(Scene* scene) = 0; //! Create a DynamicDrawContext for specified render pipeline - //! This allows draw calls are only submitted to selected render pipeline (viewport) + //! 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; //! Get a DynamicBuffer from DynamicDrawSystem. 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 d82e575493..5595c1d2ac 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -187,6 +187,7 @@ namespace AZ //! Get draw filter tag RHI::DrawFilterTag GetDrawFilterTag() const; + //! Get draw filter mask RHI::DrawFilterMask GetDrawFilterMask() const; private: @@ -261,7 +262,9 @@ namespace AZ // 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 + // A mask to filter draw items submitted by passes of this render pipeline. + // This mask is created from the value of m_drawFilterTag. + RHI::DrawFilterMask m_drawFilterMask = 0; }; } // 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 fd80ea4f74..3238785d81 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -237,7 +237,7 @@ namespace AZ DynamicDrawSystem* m_dynamicDrawSystem = nullptr; // Registry which allocates draw filter tag for RenderPipeline - RHI::DrawFilterTagRegistry m_drawFilterTagRegistry; + RHI::Ptr m_drawFilterTagRegistry; }; // --- Template functions --- diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h index ba652a2b94..f64983126d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h @@ -75,7 +75,7 @@ namespace AZ void AddDrawPacket(const RHI::DrawPacket* drawPacket, Vector3 worldPosition); //! Add a draw item to this view with its associated draw list tag - void AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemKeyPair& drawItemKeyPair); + void AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemProperties& drawItemProperties); //! Sets the worldToView matrix and recalculates the other matrices. void SetWorldToViewMatrix(const AZ::Matrix4x4& worldToView); 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 78b06aedf8..65b698f9ac 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -602,11 +602,11 @@ namespace AZ drawItemInfo.m_drawItem.m_streamBufferViews = &m_cachedStreamBufferViews[drawItemInfo.m_vertexBufferViewIndex]; } - RHI::DrawItemKeyPair drawItemKeyPair; - drawItemKeyPair.m_sortKey = sortKey; - drawItemKeyPair.m_item = &drawItemInfo.m_drawItem; - drawItemKeyPair.m_drawFilterMask = m_drawFilter; - view->AddDrawItem(m_drawListTag, drawItemKeyPair); + RHI::DrawItemProperties drawItemProperties; + drawItemProperties.m_sortKey = sortKey; + drawItemProperties.m_item = &drawItemInfo.m_drawItem; + drawItemProperties.m_drawFilterMask = m_drawFilter; + view->AddDrawItem(m_drawListTag, drawItemProperties); sortKey++; } } 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 1ff6c8ea14..baf1d22da5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -195,11 +195,11 @@ namespace AZ SetSrgsForDraw(commandList); } - for (const RHI::DrawItemKeyPair& drawItemKeyPair : drawListViewPartition) + for (const RHI::DrawItemProperties& drawItemProperties : drawListViewPartition) { - if (drawItemKeyPair.m_drawFilterMask & m_pipeline->GetDrawFilterMask()) + if (drawItemProperties.m_drawFilterMask & m_pipeline->GetDrawFilterMask()) { - commandList->Submit(*drawItemKeyPair.m_item); + commandList->Submit(*drawItemProperties.m_item); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 2d9b5f035a..2c11ef9a41 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -87,6 +87,7 @@ namespace AZ m_id = Uuid::CreateRandom(); m_cullingScene = aznew CullingScene(); SceneRequestBus::Handler::BusConnect(m_id); + m_drawFilterTagRegistry = RHI::DrawFilterTagRegistry::Create(); } Scene::~Scene() @@ -269,7 +270,7 @@ namespace AZ return; } - pipeline->SetDrawFilterTag(m_drawFilterTagRegistry.AcquireTag(pipelineId)); + pipeline->SetDrawFilterTag(m_drawFilterTagRegistry->AcquireTag(pipelineId)); m_pipelines.push_back(pipeline); @@ -305,7 +306,7 @@ namespace AZ m_defaultPipeline = nullptr; } - m_drawFilterTagRegistry.ReleaseTag(pipelineToRemove->GetDrawFilterTag()); + m_drawFilterTagRegistry->ReleaseTag(pipelineToRemove->GetDrawFilterTag()); pipelineToRemove->OnRemovedFromScene(this); m_pipelines.erase(it); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index 4fe9843534..8a8f27b4b5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -90,9 +90,9 @@ namespace AZ AddDrawPacket(drawPacket, depth); } - void View::AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemKeyPair& drawItemKeyPair) + void View::AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemProperties& drawItemProperties) { - m_drawListContext.AddDrawItem(drawListTag, drawItemKeyPair); + m_drawListContext.AddDrawItem(drawListTag, drawItemProperties); } void View::SetWorldToViewMatrix(const AZ::Matrix4x4& worldToView)