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.main
parent
743d6a511a
commit
12f528d744
@ -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>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue