From e1ce742f14f096e9a2e9d0a7af68cca9068f8628 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Wed, 28 Jul 2021 12:30:06 -0600 Subject: [PATCH] Generalize comments pertaining to light data and consolidate inline header Signed-off-by: Jeremy Ong --- .../Atom/Feature/Utils/IndexedDataVector.h | 128 ++++++++++++++++-- .../Atom/Feature/Utils/IndexedDataVector.inl | 113 ---------------- .../Code/atom_feature_common_files.cmake | 1 - 3 files changed, 120 insertions(+), 122 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h index f2a372aca9..a73ba2f16b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h @@ -15,11 +15,15 @@ namespace AZ { namespace Render { + // Growable vector that leverages indirection to support erasure of elements while maintaining + // resident data in a densely packed region of memory. Useful as a backing store for growable + // buffers intended to be uploaded to the GPU for example. template class IndexedDataVector { public: IndexedDataVector(); + explicit IndexedDataVector(size_t initialReservedSize); ~IndexedDataVector() = default; static constexpr IndexType NoFreeSlot = std::numeric_limits::max(); @@ -39,17 +43,125 @@ namespace AZ IndexType GetRawIndex(IndexType index) const; private: + constexpr static size_t InitialReservedSize = 128; - static constexpr size_t InitialReservedCount = 128; - - // stores the index of data vector for respective light, it also include a linked list to flag the free slots + // Stores data indices and an embedded free list AZStd::vector m_indices; - // stores the index of index vector for respective light + // Stores the indirection index AZStd::vector m_dataToIndices; - // stores light data AZStd::vector m_data; }; -#include "IndexedDataVector.inl" - } -} + template + inline IndexedDataVector::IndexedDataVector() + : IndexedDataVector(InitialReservedSize) + { + } + + template + inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) + { + m_dataToIndices.reserve(initialReservedSize); + m_indices.reserve(initialReservedSize); + m_data.reserve(initialReservedSize); + } + + template + inline void IndexedDataVector::Clear() + { + m_dataToIndices.clear(); + m_indices.clear(); + m_data.clear(); + + m_firstFreeSlot = NoFreeSlot; + } + + template + inline IndexType IndexedDataVector::GetFreeSlotIndex() + { + IndexType freeSlotIndex = static_cast(m_indices.size()); + + if (freeSlotIndex == NoFreeSlot) + { + // the vector is full + return NoFreeSlot; + } + + if (m_firstFreeSlot == NoFreeSlot) + { + // If there's no free slot, add on to the end. + m_indices.push_back(freeSlotIndex); + } + else + { + // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. + freeSlotIndex = m_firstFreeSlot; + m_firstFreeSlot = m_indices.at(m_firstFreeSlot); + m_indices.at(freeSlotIndex) = static_cast(m_data.size()); + } + + // The data itself is always packed and m_indices points at it, so push a new entry to the back. + m_data.push_back(DataType()); + m_dataToIndices.push_back(freeSlotIndex); + + return freeSlotIndex; + } + + template + inline void IndexedDataVector::RemoveIndex(IndexType index) + { + IndexType dataIndex = m_indices.at(index); + + // Copy the back light on top of this one. + m_data.at(dataIndex) = m_data.back(); + m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); + + // Update the index of the moved light + m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; + + // Pop the back + m_data.pop_back(); + m_dataToIndices.pop_back(); + + // Use free slot to link to next free slot + m_indices.at(index) = m_firstFreeSlot; + m_firstFreeSlot = index; + } + + template + inline DataType& IndexedDataVector::GetData(IndexType index) + { + return m_data.at(m_indices.at(index)); + } + + template + inline const DataType& IndexedDataVector::GetData(IndexType index) const + { + return m_data.at(m_indices.at(index)); + } + + template + inline size_t IndexedDataVector::GetDataCount() const + { + return m_data.size(); + } + + template + inline AZStd::vector& IndexedDataVector::GetDataVector() + { + return m_data; + } + + template + inline const AZStd::vector& IndexedDataVector::GetDataVector() const + { + return m_data; + } + + template + IndexType IndexedDataVector::GetRawIndex(IndexType index) const + { + return m_indices.at(index); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl deleted file mode 100644 index da10e5a503..0000000000 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -template -inline IndexedDataVector::IndexedDataVector() -{ - m_dataToIndices.reserve(InitialReservedCount); - m_indices.reserve(InitialReservedCount); - m_data.reserve(InitialReservedCount); -} - -template -inline void IndexedDataVector::Clear() -{ - m_dataToIndices.clear(); - m_indices.clear(); - m_data.clear(); - - m_firstFreeSlot = NoFreeSlot; -} - -template -inline IndexType IndexedDataVector::GetFreeSlotIndex() -{ - IndexType freeSlotIndex = static_cast(m_indices.size()); - - if (freeSlotIndex == NoFreeSlot) - { - // the vector is full - return NoFreeSlot; - } - - if (m_firstFreeSlot == NoFreeSlot) - { - // If there's no free slot, add on to the end. - m_indices.push_back(freeSlotIndex); - } - else - { - // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. - freeSlotIndex = m_firstFreeSlot; - m_firstFreeSlot = m_indices.at(m_firstFreeSlot); - m_indices.at(freeSlotIndex) = static_cast(m_data.size()); - } - - // The data itself is always packed and m_indices points at it, so push a new entry to the back. - m_data.push_back(DataType()); - m_dataToIndices.push_back(freeSlotIndex); - - return freeSlotIndex; -} - -template -inline void IndexedDataVector::RemoveIndex(IndexType index) -{ - IndexType dataIndex = m_indices.at(index); - - // Copy the back light on top of this one. - m_data.at(dataIndex) = m_data.back(); - m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); - - // Update the index of the moved light - m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; - - // Pop the back - m_data.pop_back(); - m_dataToIndices.pop_back(); - - // Use free slot to link to next free slot - m_indices.at(index) = m_firstFreeSlot; - m_firstFreeSlot = index; -} - -template -inline DataType& IndexedDataVector::GetData(IndexType index) -{ - return m_data.at(m_indices.at(index)); -} - -template -inline const DataType& IndexedDataVector::GetData(IndexType index) const -{ - return m_data.at(m_indices.at(index)); -} - -template -inline size_t IndexedDataVector::GetDataCount() const -{ - return m_data.size(); -} - -template -inline AZStd::vector& IndexedDataVector::GetDataVector() -{ - return m_data; -} - -template -inline const AZStd::vector& IndexedDataVector::GetDataVector() const -{ - return m_data; -} - -template -IndexType IndexedDataVector::GetRawIndex(IndexType index) const -{ - return m_indices.at(index); -} diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 40188109ca..e4a914ac34 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -38,7 +38,6 @@ set(FILES Include/Atom/Feature/Utils/FrameCaptureBus.h Include/Atom/Feature/Utils/GpuBufferHandler.h Include/Atom/Feature/Utils/IndexedDataVector.h - Include/Atom/Feature/Utils/IndexedDataVector.inl Include/Atom/Feature/Utils/MultiIndexedDataVector.h Include/Atom/Feature/Utils/MultiSparseVector.h Include/Atom/Feature/Utils/ProfilingCaptureBus.h