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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 <Atom/RHI/DrawItem.h>
|
||||
#include <Atom/RHI/TagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
using DrawFilterTagRegistry = TagRegistry<DrawFilterTag, Limits::Pipeline::DrawFilterTagCountMax>;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/Handle.h>
|
||||
#include <Atom/RHI.Reflect/Limits.h>
|
||||
#include <Atom/RHI/StreamBufferView.h>
|
||||
#include <Atom/RHI/IndexBufferView.h>
|
||||
@@ -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<uint8_t>;
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,83 +12,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/DrawList.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
#include <Atom/RHI/TagRegistry.h>
|
||||
|
||||
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<DrawListTagRegistry> 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<Entry, Limits::Pipeline::DrawListTagCountMax> m_entriesByTag;
|
||||
size_t m_allocatedTagCount = 0;
|
||||
};
|
||||
using DrawListTagRegistry = TagRegistry<DrawListTag, Limits::Pipeline::DrawListTagCountMax>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<void(DrawListTag, DrawItemKeyPair)>;
|
||||
|
||||
/// 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;
|
||||
|
||||
|
||||
@@ -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<StreamBufferView> 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<DrawRequest, DrawItemCountMax> m_drawRequests;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace AZ
|
||||
RHI::Ptr<RHI::Device> InitInternalDevice();
|
||||
|
||||
RHI::Ptr<RHI::Device> m_device;
|
||||
RHI::Ptr<RHI::DrawListTagRegistry> m_drawListTagRegistry;
|
||||
RHI::DrawListTagRegistry m_drawListTagRegistry;
|
||||
RHI::Ptr<RHI::PipelineStateCache> m_pipelineStateCache;
|
||||
RHI::FrameScheduler m_frameScheduler;
|
||||
RHI::FrameSchedulerCompileRequest m_compileRequest;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
class Device;
|
||||
class DrawListTagRegistry;
|
||||
class FrameGraphBuilder;
|
||||
class PipelineState;
|
||||
class PipelineStateCache;
|
||||
|
||||
@@ -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 <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
|
||||
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<Integer> 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<typename TagType, size_t MaxTagCount>
|
||||
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<Entry, MaxTagCount> m_entriesByTag;
|
||||
size_t m_allocatedTagCount = 0;
|
||||
};
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
void TagRegistry<TagType, MaxTagCount>::Reset()
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
m_entriesByTag.fill({});
|
||||
m_allocatedTagCount = 0;
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
TagType TagRegistry<TagType, MaxTagCount>::AcquireTag(const Name& tagName)
|
||||
{
|
||||
if (tagName.IsEmpty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
TagType tag;
|
||||
Entry* foundEmptyEntry = nullptr;
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> 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<typename TagType, size_t MaxTagCount>
|
||||
void TagRegistry<TagType, MaxTagCount>::ReleaseTag(TagType tag)
|
||||
{
|
||||
if (tag.IsValid())
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
Entry& entry = m_entriesByTag[tag.GetIndex()];
|
||||
const size_t refCount = --entry.m_refCount;
|
||||
AZ_Assert(
|
||||
refCount != static_cast<size_t>(-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<typename TagType, size_t MaxTagCount>
|
||||
TagType TagRegistry<TagType, MaxTagCount>::FindTag(const Name& tagName) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> 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<typename TagType, size_t MaxTagCount>
|
||||
Name TagRegistry<TagType, MaxTagCount>::GetName(TagType tag) const
|
||||
{
|
||||
if (tag.GetIndex() < m_entriesByTag.size())
|
||||
{
|
||||
return m_entriesByTag[tag.GetIndex()].m_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Name();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
size_t TagRegistry<TagType, MaxTagCount>::GetAllocatedTagCount() const
|
||||
{
|
||||
return m_allocatedTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <Atom/RHI/DrawListTagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
Ptr<DrawListTagRegistry> DrawListTagRegistry::Create()
|
||||
{
|
||||
return aznew DrawListTagRegistry;
|
||||
}
|
||||
|
||||
void DrawListTagRegistry::Reset()
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> 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<AZStd::shared_mutex> 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<AZStd::shared_mutex> lock(m_mutex);
|
||||
Entry& entry = m_entriesByTag[drawListTag.GetIndex()];
|
||||
const size_t refCount = --entry.m_refCount;
|
||||
AZ_Assert(refCount != static_cast<size_t>(-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<AZStd::shared_mutex> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<const DrawPacket*>(p)->m_allocator->DeAllocate(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<RHI::DrawListTagRegistry> m_drawListTagRegistry;
|
||||
RHI::DrawListTagRegistry m_drawListTagRegistry;
|
||||
RHI::DrawListContext m_drawListContext;
|
||||
|
||||
AZStd::unique_ptr<Factory> 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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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<RHI::StreamBufferView> m_cachedStreamBufferViews;
|
||||
AZStd::vector<RHI::IndexBufferView> m_cachedIndexBufferViews;
|
||||
|
||||
@@ -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<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) = 0;
|
||||
|
||||
//! Create a DynamicDrawContext for specified pass
|
||||
virtual RHI::Ptr<DynamicDrawContext> 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<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) = 0;
|
||||
|
||||
//! Get a DynamicBuffer from DynamicDrawSystem.
|
||||
//! The returned buffer will be invalidated every time the RPISystem's RenderTick is called
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
|
||||
// DynamicDrawInterface overrides...
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) override;
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Pass* pass) override;
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) override;
|
||||
RHI::Ptr<DynamicBuffer> GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override;
|
||||
void DrawGeometry(Data::Instance<Material> material, const GeometryData& geometry, ScenePtr scene) override;
|
||||
void AddDrawPacket(Scene* scene, AZStd::unique_ptr<const RHI::DrawPacket> drawPacket) override;
|
||||
|
||||
@@ -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<ViewPtr, RHI::DrawListMask>& 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
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <Atom/RHI/DrawList.h>
|
||||
#include <Atom/RHI/PipelineStateDescriptor.h>
|
||||
#include <Atom/RHI/DrawFilterTagRegistry.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI.Reflect/ShaderResourceGroupLayoutDescriptor.h>
|
||||
#include <Atom/RPI.Reflect/System/SceneDescriptor.h>
|
||||
@@ -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 ---
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicBuffer.h>
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h>
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace AZ
|
||||
|
||||
RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext(Scene* scene)
|
||||
{
|
||||
if (!scene)
|
||||
{
|
||||
AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input scene is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
RHI::Ptr<DynamicDrawContext> drawContext = aznew DynamicDrawContext();
|
||||
drawContext->m_scene = scene;
|
||||
|
||||
@@ -67,11 +72,17 @@ namespace AZ
|
||||
return drawContext;
|
||||
}
|
||||
|
||||
// [GFX TODO][ATOM-13185] Add support for creating DynamicDrawContext for Pass
|
||||
RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext([[maybe_unused]] Pass* pass)
|
||||
RHI::Ptr<DynamicDrawContext> 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user