From 43c3821993cb3d6ec3025fa7156da8544d2a1dac Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 20:30:23 +0300 Subject: D3D12 resource binding refactoring, rename LinearAllocator to FixedLinearAllocator. --- Common/interface/FixedLinearAllocator.hpp | 324 ++++++++++++++++++++++++++++++ Common/interface/LinearAllocator.hpp | 324 ------------------------------ 2 files changed, 324 insertions(+), 324 deletions(-) create mode 100644 Common/interface/FixedLinearAllocator.hpp delete mode 100644 Common/interface/LinearAllocator.hpp (limited to 'Common/interface') diff --git a/Common/interface/FixedLinearAllocator.hpp b/Common/interface/FixedLinearAllocator.hpp new file mode 100644 index 00000000..d9302c5c --- /dev/null +++ b/Common/interface/FixedLinearAllocator.hpp @@ -0,0 +1,324 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::FixedLinearAllocator class + +#include + +#include "../../Primitives/interface/BasicTypes.h" +#include "../../Primitives/interface/MemoryAllocator.h" +#include "../../Platforms/Basic/interface/DebugUtilities.hpp" +#include "CompilerDefinitions.h" +#include "Align.hpp" + +namespace Diligent +{ + +/// Implementation of a linear allocator on a fixed-size memory page +class FixedLinearAllocator +{ +public: + // clang-format off + FixedLinearAllocator (const FixedLinearAllocator&) = delete; + FixedLinearAllocator& operator=(const FixedLinearAllocator&) = delete; + FixedLinearAllocator& operator=(FixedLinearAllocator&&) = delete; + // clang-format on + + explicit FixedLinearAllocator(IMemoryAllocator& Allocator) noexcept : + m_pAllocator{&Allocator} + {} + + FixedLinearAllocator(FixedLinearAllocator&& Other) noexcept : + // clang-format off + m_pDataStart {Other.m_pDataStart }, + m_pCurrPtr {Other.m_pCurrPtr }, + m_ReservedSize {Other.m_ReservedSize }, + m_CurrAlignment{Other.m_CurrAlignment}, + m_pAllocator {Other.m_pAllocator } + // clang-format on + { + Other.Reset(); + } + + ~FixedLinearAllocator() + { + Free(); + } + + void Free() + { + if (m_pDataStart != nullptr && m_pAllocator != nullptr) + { + m_pAllocator->Free(m_pDataStart); + } + Reset(); + } + + NODISCARD void* Release() + { + void* Ptr = m_pDataStart; + Reset(); + return Ptr; + } + + NODISCARD void* ReleaseOwnership() noexcept + { + m_pAllocator = nullptr; + return GetDataPtr(); + } + + NODISCARD void* GetDataPtr() const noexcept + { + return m_pDataStart; + } + + void AddSpace(size_t size, size_t alignment) noexcept + { + VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); + VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!"); + + if (size == 0) + return; + + if (m_CurrAlignment == 0) + { + VERIFY(m_ReservedSize == 0, "This is expected to be a very first time the space is added"); + m_CurrAlignment = sizeof(void*); + } + + if (alignment > m_CurrAlignment) + { + // Reserve extra space that may be needed for alignment + m_ReservedSize += alignment - m_CurrAlignment; + } + m_CurrAlignment = alignment; + + size = Align(size, alignment); + m_ReservedSize += size; + +#if DILIGENT_DEBUG + m_DbgAllocations.emplace_back(size, alignment, m_ReservedSize); +#endif + } + + template + void AddSpace(size_t count = 1) noexcept + { + AddSpace(sizeof(T) * count, alignof(T)); + } + + void AddSpaceForString(const Char* str) noexcept + { + VERIFY_EXPR(str != nullptr); + AddSpace(strlen(str) + 1, 1); + } + + void AddSpaceForString(const String& str) noexcept + { + AddSpaceForString(str.c_str()); + } + + void Reserve(size_t size) + { + VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); + VERIFY(m_ReservedSize == 0, "Space has been added to the allocator and will be overriden"); + m_ReservedSize = size; + Reserve(); + } + + void Reserve() + { + VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); + VERIFY(m_pAllocator != nullptr, "Allocator must not be null"); + // Make sure the data size is at least sizeof(void*)-aligned + m_ReservedSize = Align(m_ReservedSize, sizeof(void*)); + if (m_ReservedSize > 0) + { + m_pDataStart = reinterpret_cast(m_pAllocator->Allocate(m_ReservedSize, "Raw memory for linear allocator", __FILE__, __LINE__)); + VERIFY(m_pDataStart == Align(m_pDataStart, sizeof(void*)), "Memory pointer must be at least sizeof(void*)-aligned"); + + m_pCurrPtr = m_pDataStart; + } + m_CurrAlignment = sizeof(void*); + } + + NODISCARD void* Allocate(size_t size, size_t alignment) + { + VERIFY(size == 0 || m_pDataStart != nullptr, "Memory has not been allocated"); + VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!"); + + if (size == 0) + return nullptr; + + size = Align(size, alignment); + +#if DILIGENT_DEBUG + VERIFY(m_DbgCurrAllocation < m_DbgAllocations.size(), "Allocation number exceed the number of allocations that were originally reserved."); + const auto& CurrAllocation = m_DbgAllocations[m_DbgCurrAllocation++]; + VERIFY(CurrAllocation.size == size, "Allocation size (", size, ") does not match the initially requested size (", CurrAllocation.size, ")"); + VERIFY(CurrAllocation.alignment == alignment, "Allocation alignment (", alignment, ") does not match the initially requested alignment (", CurrAllocation.alignment, ")"); +#endif + + VERIFY(Align(m_pCurrPtr, m_CurrAlignment) == m_pCurrPtr, "Current pointer is not aligned as expected"); + m_pCurrPtr = Align(m_pCurrPtr, alignment); + m_CurrAlignment = alignment; + + VERIFY(m_pCurrPtr + size <= m_pDataStart + CurrAllocation.reserved_size, + "Allocation size exceeds the initially reserved space. This is likely a bug."); + + auto* ptr = m_pCurrPtr; + m_pCurrPtr += size; + + VERIFY(m_pCurrPtr <= m_pDataStart + m_ReservedSize, "Allocation size exceeds the reserved space"); + + return ptr; + } + + template + NODISCARD T* Allocate(size_t count = 1) + { + return reinterpret_cast(Allocate(sizeof(T) * count, alignof(T))); + } + + template + NODISCARD T* Construct(Args&&... args) + { + T* Ptr = Allocate(); + new (Ptr) T{std::forward(args)...}; + return Ptr; + } + + template + NODISCARD T* ConstructArray(size_t count, const Args&... args) + { + T* Ptr = Allocate(count); + for (size_t i = 0; i < count; ++i) + { + new (Ptr + i) T{args...}; + } + return Ptr; + } + + template + NODISCARD T* Copy(const T& Src) + { + return Construct(Src); + } + + template + NODISCARD T* CopyArray(const T* Src, size_t count) + { + T* Dst = Allocate(count); + for (size_t i = 0; i < count; ++i) + { + new (Dst + i) T{Src[i]}; + } + return Dst; + } + + NODISCARD Char* CopyString(const char* Str) + { + if (Str == nullptr) + return nullptr; + + auto* Ptr = reinterpret_cast(Allocate(strlen(Str) + 1, 1)); + Char* Dst = Ptr; + + const auto* pDataEnd = reinterpret_cast(m_pDataStart) + m_ReservedSize; + while (*Str != 0 && Dst < pDataEnd) + { + *(Dst++) = *(Str++); + } + if (Dst < pDataEnd) + *(Dst++) = 0; + else + UNEXPECTED("Not enough space reserved for the string"); + + VERIFY_EXPR(reinterpret_cast(m_pCurrPtr) == Dst); + return Ptr; + } + + NODISCARD Char* CopyString(const std::string& Str) + { + return CopyString(Str.c_str()); + } + + NODISCARD size_t GetCurrentSize() const + { + VERIFY(m_pDataStart != nullptr, "Memory has not been allocated"); + return static_cast(m_pCurrPtr - m_pDataStart); + } + + NODISCARD size_t GetReservedSize() const + { + return m_ReservedSize; + } + +private: + void Reset() + { + m_pDataStart = nullptr; + m_pCurrPtr = nullptr; + m_ReservedSize = 0; + m_CurrAlignment = 0; + m_pAllocator = nullptr; + +#if DILIGENT_DEBUG + m_DbgCurrAllocation = 0; + m_DbgAllocations.clear(); +#endif + } + + uint8_t* m_pDataStart = nullptr; + uint8_t* m_pCurrPtr = nullptr; + size_t m_ReservedSize = 0; + size_t m_CurrAlignment = 0; + IMemoryAllocator* m_pAllocator = nullptr; + +#if DILIGENT_DEBUG + size_t m_DbgCurrAllocation = 0; + struct DbgAllocationInfo + { + const size_t size; + const size_t alignment; + const size_t reserved_size; + + DbgAllocationInfo(size_t _size, size_t _alignment, size_t _reserved_size) : + size{_size}, + alignment{_alignment}, + reserved_size{_reserved_size} + { + } + }; + std::vector m_DbgAllocations; +#endif +}; + +} // namespace Diligent diff --git a/Common/interface/LinearAllocator.hpp b/Common/interface/LinearAllocator.hpp deleted file mode 100644 index 78ee9166..00000000 --- a/Common/interface/LinearAllocator.hpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright 2019-2020 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -/// \file -/// Defines Diligent::LinearAllocator class - -#include - -#include "../../Primitives/interface/BasicTypes.h" -#include "../../Primitives/interface/MemoryAllocator.h" -#include "../../Platforms/Basic/interface/DebugUtilities.hpp" -#include "CompilerDefinitions.h" -#include "Align.hpp" - -namespace Diligent -{ - -/// Implementation of a linear allocator on a fixed-size memory page -class LinearAllocator -{ -public: - // clang-format off - LinearAllocator (const LinearAllocator&) = delete; - LinearAllocator& operator=(const LinearAllocator&) = delete; - LinearAllocator& operator=(LinearAllocator&&) = delete; - // clang-format on - - explicit LinearAllocator(IMemoryAllocator& Allocator) noexcept : - m_pAllocator{&Allocator} - {} - - LinearAllocator(LinearAllocator&& Other) noexcept : - // clang-format off - m_pDataStart {Other.m_pDataStart }, - m_pCurrPtr {Other.m_pCurrPtr }, - m_ReservedSize {Other.m_ReservedSize }, - m_CurrAlignment{Other.m_CurrAlignment}, - m_pAllocator {Other.m_pAllocator } - // clang-format on - { - Other.Reset(); - } - - ~LinearAllocator() - { - Free(); - } - - void Free() - { - if (m_pDataStart != nullptr && m_pAllocator != nullptr) - { - m_pAllocator->Free(m_pDataStart); - } - Reset(); - } - - NODISCARD void* Release() - { - void* Ptr = m_pDataStart; - Reset(); - return Ptr; - } - - NODISCARD void* ReleaseOwnership() noexcept - { - m_pAllocator = nullptr; - return GetDataPtr(); - } - - NODISCARD void* GetDataPtr() const noexcept - { - return m_pDataStart; - } - - void AddSpace(size_t size, size_t alignment) noexcept - { - VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); - VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!"); - - if (size == 0) - return; - - if (m_CurrAlignment == 0) - { - VERIFY(m_ReservedSize == 0, "This is expected to be a very first time the space is added"); - m_CurrAlignment = sizeof(void*); - } - - if (alignment > m_CurrAlignment) - { - // Reserve extra space that may be needed for alignment - m_ReservedSize += alignment - m_CurrAlignment; - } - m_CurrAlignment = alignment; - - size = Align(size, alignment); - m_ReservedSize += size; - -#if DILIGENT_DEBUG - m_DbgAllocations.emplace_back(size, alignment, m_ReservedSize); -#endif - } - - template - void AddSpace(size_t count = 1) noexcept - { - AddSpace(sizeof(T) * count, alignof(T)); - } - - void AddSpaceForString(const Char* str) noexcept - { - VERIFY_EXPR(str != nullptr); - AddSpace(strlen(str) + 1, 1); - } - - void AddSpaceForString(const String& str) noexcept - { - AddSpaceForString(str.c_str()); - } - - void Reserve(size_t size) - { - VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); - VERIFY(m_ReservedSize == 0, "Space has been added to the allocator and will be overriden"); - m_ReservedSize = size; - Reserve(); - } - - void Reserve() - { - VERIFY(m_pDataStart == nullptr, "Memory has already been allocated"); - VERIFY(m_pAllocator != nullptr, "Allocator must not be null"); - // Make sure the data size is at least sizeof(void*)-aligned - m_ReservedSize = Align(m_ReservedSize, sizeof(void*)); - if (m_ReservedSize > 0) - { - m_pDataStart = reinterpret_cast(m_pAllocator->Allocate(m_ReservedSize, "Raw memory for linear allocator", __FILE__, __LINE__)); - VERIFY(m_pDataStart == Align(m_pDataStart, sizeof(void*)), "Memory pointer must be at least sizeof(void*)-aligned"); - - m_pCurrPtr = m_pDataStart; - } - m_CurrAlignment = sizeof(void*); - } - - NODISCARD void* Allocate(size_t size, size_t alignment) - { - VERIFY(size == 0 || m_pDataStart != nullptr, "Memory has not been allocated"); - VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!"); - - if (size == 0) - return nullptr; - - size = Align(size, alignment); - -#if DILIGENT_DEBUG - VERIFY(m_DbgCurrAllocation < m_DbgAllocations.size(), "Allocation number exceed the number of allocations that were originally reserved."); - const auto& CurrAllocation = m_DbgAllocations[m_DbgCurrAllocation++]; - VERIFY(CurrAllocation.size == size, "Allocation size (", size, ") does not match the initially requested size (", CurrAllocation.size, ")"); - VERIFY(CurrAllocation.alignment == alignment, "Allocation alignment (", alignment, ") does not match the initially requested alignment (", CurrAllocation.alignment, ")"); -#endif - - VERIFY(Align(m_pCurrPtr, m_CurrAlignment) == m_pCurrPtr, "Current pointer is not aligned as expected"); - m_pCurrPtr = Align(m_pCurrPtr, alignment); - m_CurrAlignment = alignment; - - VERIFY(m_pCurrPtr + size <= m_pDataStart + CurrAllocation.reserved_size, - "Allocation size exceeds the initially reserved space. This is likely a bug."); - - auto* ptr = m_pCurrPtr; - m_pCurrPtr += size; - - VERIFY(m_pCurrPtr <= m_pDataStart + m_ReservedSize, "Allocation size exceeds the reserved space"); - - return ptr; - } - - template - NODISCARD T* Allocate(size_t count = 1) - { - return reinterpret_cast(Allocate(sizeof(T) * count, alignof(T))); - } - - template - NODISCARD T* Construct(Args&&... args) - { - T* Ptr = Allocate(); - new (Ptr) T{std::forward(args)...}; - return Ptr; - } - - template - NODISCARD T* ConstructArray(size_t count, const Args&... args) - { - T* Ptr = Allocate(count); - for (size_t i = 0; i < count; ++i) - { - new (Ptr + i) T{args...}; - } - return Ptr; - } - - template - NODISCARD T* Copy(const T& Src) - { - return Construct(Src); - } - - template - NODISCARD T* CopyArray(const T* Src, size_t count) - { - T* Dst = Allocate(count); - for (size_t i = 0; i < count; ++i) - { - new (Dst + i) T{Src[i]}; - } - return Dst; - } - - NODISCARD Char* CopyString(const char* Str) - { - if (Str == nullptr) - return nullptr; - - auto* Ptr = reinterpret_cast(Allocate(strlen(Str) + 1, 1)); - Char* Dst = Ptr; - - const auto* pDataEnd = reinterpret_cast(m_pDataStart) + m_ReservedSize; - while (*Str != 0 && Dst < pDataEnd) - { - *(Dst++) = *(Str++); - } - if (Dst < pDataEnd) - *(Dst++) = 0; - else - UNEXPECTED("Not enough space reserved for the string"); - - VERIFY_EXPR(reinterpret_cast(m_pCurrPtr) == Dst); - return Ptr; - } - - NODISCARD Char* CopyString(const std::string& Str) - { - return CopyString(Str.c_str()); - } - - NODISCARD size_t GetCurrentSize() const - { - VERIFY(m_pDataStart != nullptr, "Memory has not been allocated"); - return static_cast(m_pCurrPtr - m_pDataStart); - } - - NODISCARD size_t GetReservedSize() const - { - return m_ReservedSize; - } - -private: - void Reset() - { - m_pDataStart = nullptr; - m_pCurrPtr = nullptr; - m_ReservedSize = 0; - m_CurrAlignment = 0; - m_pAllocator = nullptr; - -#if DILIGENT_DEBUG - m_DbgCurrAllocation = 0; - m_DbgAllocations.clear(); -#endif - } - - uint8_t* m_pDataStart = nullptr; - uint8_t* m_pCurrPtr = nullptr; - size_t m_ReservedSize = 0; - size_t m_CurrAlignment = 0; - IMemoryAllocator* m_pAllocator = nullptr; - -#if DILIGENT_DEBUG - size_t m_DbgCurrAllocation = 0; - struct DbgAllocationInfo - { - const size_t size; - const size_t alignment; - const size_t reserved_size; - - DbgAllocationInfo(size_t _size, size_t _alignment, size_t _reserved_size) : - size{_size}, - alignment{_alignment}, - reserved_size{_reserved_size} - { - } - }; - std::vector m_DbgAllocations; -#endif -}; - -} // namespace Diligent -- cgit v1.2.3