diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-10-25 12:53:05 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-10-25 13:08:57 +0000 |
| commit | 7f26e40e0898391a32e6a05d91ef1a217d885668 (patch) | |
| tree | 3236316d1a752e5dbbfae863f8180ff994b31d70 /Common/interface | |
| parent | Merge branch 'master' into ray_tracing (diff) | |
| download | DiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.tar.gz DiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.zip | |
PSO refactoring for ray tracing
Diffstat (limited to 'Common/interface')
| -rw-r--r-- | Common/interface/Align.hpp | 32 | ||||
| -rw-r--r-- | Common/interface/Definitions.hpp | 52 | ||||
| -rw-r--r-- | Common/interface/DynamicLinearAllocator.hpp | 199 | ||||
| -rw-r--r-- | Common/interface/LinearAllocator.hpp | 27 |
4 files changed, 285 insertions, 25 deletions
diff --git a/Common/interface/Align.hpp b/Common/interface/Align.hpp index 658ec7ca..9acb310c 100644 --- a/Common/interface/Align.hpp +++ b/Common/interface/Align.hpp @@ -43,30 +43,38 @@ bool IsPowerOfTwo(T val) return val > 0 && (val & (val - 1)) == 0; } -template <typename T> -inline T Align(T val, T alignment) +template <typename T1, typename T2> +inline typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type Align(T1 val, T2 alignment) { + static_assert(std::is_unsigned<T1>::value == std::is_unsigned<T2>::value, "both types must be signed or unsigned"); + static_assert(!std::is_pointer<T1>::value && !std::is_pointer<T2>::value, "types must not be pointers"); VERIFY(IsPowerOfTwo(alignment), "Alignment (", alignment, ") must be power of 2"); - return (val + (alignment - 1)) & ~(alignment - 1); + + using T = typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type; + return (static_cast<T>(val) + static_cast<T>(alignment - 1)) & ~static_cast<T>(alignment - 1); } -template <typename T> -inline T* Align(T* val, size_t alignment) +template <typename PtrType, typename AlignType> +inline PtrType* Align(PtrType* val, AlignType alignment) { - return reinterpret_cast<T*>(Align(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment))); + return reinterpret_cast<PtrType*>(Align(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment))); } -template <typename T> -inline T AlignDown(T val, T alignment) +template <typename T1, typename T2> +inline typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type AlignDown(T1 val, T2 alignment) { + static_assert(std::is_unsigned<T1>::value == std::is_unsigned<T2>::value, "both types must be signed or unsigned"); + static_assert(!std::is_pointer<T1>::value && !std::is_pointer<T2>::value, "types must not be pointers"); VERIFY(IsPowerOfTwo(alignment), "Alignment (", alignment, ") must be power of 2"); - return val & ~(alignment - 1); + + using T = typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type; + return static_cast<T>(val) & ~static_cast<T>(alignment - 1); } -template <typename T> -inline T* AlignDown(T* val, size_t alignment) +template <typename PtrType, typename AlignType> +inline PtrType* AlignDown(PtrType* val, AlignType alignment) { - return reinterpret_cast<T*>(AlignDown(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment))); + return reinterpret_cast<PtrType*>(AlignDown(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment))); } } // namespace Diligent diff --git a/Common/interface/Definitions.hpp b/Common/interface/Definitions.hpp new file mode 100644 index 00000000..72a09524 --- /dev/null +++ b/Common/interface/Definitions.hpp @@ -0,0 +1,52 @@ +/* + * 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 + +#ifdef _MSC_VER +# if _MSC_VER >= 1917 +# define NDDISCARD [[nodiscard]] +# else +# define NDDISCARD +# endif +#endif // _MSC_VER + +#ifdef __clang__ +# if __has_feature(cxx_attributes) +# define NDDISCARD [[nodiscard]] +# else +# define NDDISCARD +# endif +#endif // __clang__ + +#ifdef __GNUC__ +# if __has_cpp_attribute(nodiscard) +# define NDDISCARD [[nodiscard]] +# else +# define NDDISCARD +# endif +#endif // __GNUC__ diff --git a/Common/interface/DynamicLinearAllocator.hpp b/Common/interface/DynamicLinearAllocator.hpp new file mode 100644 index 00000000..9ddffbb3 --- /dev/null +++ b/Common/interface/DynamicLinearAllocator.hpp @@ -0,0 +1,199 @@ +/* + * 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::DynamicLinearAllocator class + +#include <vector> + +#include "../../Primitives/interface/BasicTypes.h" +#include "../../Primitives/interface/MemoryAllocator.h" +#include "../../Platforms/Basic/interface/DebugUtilities.hpp" +#include "Definitions.hpp" +#include "Align.hpp" + +namespace Diligent +{ + +/// Implementation of a linear allocator on a fixed memory pages +class DynamicLinearAllocator +{ +public: + // clang-format off + DynamicLinearAllocator (const DynamicLinearAllocator&) = delete; + DynamicLinearAllocator (DynamicLinearAllocator&&) = delete; + DynamicLinearAllocator& operator=(const DynamicLinearAllocator&) = delete; + DynamicLinearAllocator& operator=(DynamicLinearAllocator&&) = delete; + // clang-format on + + explicit DynamicLinearAllocator(IMemoryAllocator& Allocator, Uint32 BlockSize = 4 << 10) : + m_pAllocator{&Allocator}, + m_BlockSize{BlockSize} + {} + + ~DynamicLinearAllocator() + { + Free(); + } + + void Free() + { + for (auto& block : m_Blocks) + { + m_pAllocator->Free(block.Page); + } + m_Blocks.clear(); + + m_pAllocator = nullptr; + } + + void Discard() + { + for (auto& block : m_Blocks) + { + block.Size = 0; + } + } + + NDDISCARD void* Allocate(size_t size, size_t align) + { + if (size == 0) + return nullptr; + + for (auto& block : m_Blocks) + { + size_t offset = Align(reinterpret_cast<size_t>(block.Page) + block.Size, align) - reinterpret_cast<size_t>(block.Page); + + if (size <= (block.Capacity - offset)) + { + block.Size = offset + size; + return block.Page + offset; + } + } + + // create new block + size_t BlockSize = m_BlockSize; + BlockSize = size * 2 < BlockSize ? BlockSize : size * 2; + m_Blocks.emplace_back(m_pAllocator->Allocate(BlockSize, "dynamic linear allocator page", __FILE__, __LINE__), 0, BlockSize); + + auto& block = m_Blocks.back(); + size_t offset = Align(reinterpret_cast<size_t>(block.Page), align) - reinterpret_cast<size_t>(block.Page); + block.Size = offset + size; + return block.Page + offset; + } + + template <typename T> + NDDISCARD T* Allocate(size_t count = 1) + { + return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T))); + } + + template <typename T, typename... Args> + NDDISCARD T* Construct(Args&&... args) + { + T* Ptr = Allocate<T>(1); + new (Ptr) T{std::forward<Args>(args)...}; + return Ptr; + } + + template <typename T, typename... Args> + NDDISCARD T* ConstructArray(size_t count, const Args&... args) + { + T* Ptr = Allocate<T>(count); + for (size_t i = 0; i < count; ++i) + { + new (Ptr + i) T{args...}; + } + return Ptr; + } + + template <typename T> + NDDISCARD T* CopyArray(const T* Src, size_t count) + { + T* Dst = Allocate<T>(count); + for (size_t i = 0; i < count; ++i) + { + new (Dst + i) T{Src[i]}; + } + return Dst; + } + + NDDISCARD Char* CopyString(const Char* Str) + { + if (Str == nullptr) + return nullptr; + + size_t len = strlen(Str) + 1; + Char* Dst = Allocate<Char>(len + 1); + std::memcpy(Dst, Str, sizeof(Char) * len); + Dst[len] = 0; + return Dst; + } + + NDDISCARD wchar_t* CopyWString(const char* Str) + { + if (Str == nullptr) + return nullptr; + + size_t len = strlen(Str) + 1; + auto* Dst = Allocate<wchar_t>(len + 1); + for (size_t i = 0; i < len; ++i) + { + Dst[i] = static_cast<wchar_t>(Str[i]); + } + Dst[len] = 0; + return Dst; + } + + NDDISCARD Char* CopyString(const String& Str) + { + size_t len = Str.length() + 1; + Char* Dst = Allocate<Char>(len + 1); + std::memcpy(Dst, Str.c_str(), sizeof(Char) * len); + Dst[len] = 0; + return Dst; + } + +private: + struct Block + { + uint8_t* Page = nullptr; + size_t Size = 0; + size_t Capacity = 0; + + Block(void* _Page, size_t _Size, size_t _Capacity) : + Page{static_cast<uint8_t*>(_Page)}, Size{_Size}, Capacity{_Capacity} {} + }; + + std::vector<Block> m_Blocks; + Uint32 m_BlockSize = 4 << 10; + IMemoryAllocator* m_pAllocator = nullptr; +}; + +} // namespace Diligent diff --git a/Common/interface/LinearAllocator.hpp b/Common/interface/LinearAllocator.hpp index dd137c47..05049dff 100644 --- a/Common/interface/LinearAllocator.hpp +++ b/Common/interface/LinearAllocator.hpp @@ -35,6 +35,7 @@ #include "../../Primitives/interface/BasicTypes.h" #include "../../Primitives/interface/MemoryAllocator.h" #include "../../Platforms/Basic/interface/DebugUtilities.hpp" +#include "Definitions.hpp" #include "Align.hpp" namespace Diligent @@ -80,20 +81,20 @@ public: Reset(); } - void* Release() + NDDISCARD void* Release() { void* Ptr = m_pDataStart; Reset(); return Ptr; } - void* ReleaseOwnership() noexcept + NDDISCARD void* ReleaseOwnership() noexcept { m_pAllocator = nullptr; return GetDataPtr(); } - void* GetDataPtr() const noexcept + NDDISCARD void* GetDataPtr() const noexcept { return m_pDataStart; } @@ -168,7 +169,7 @@ public: m_CurrAlignment = sizeof(void*); } - void* Allocate(size_t size, size_t alignment) + NDDISCARD 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!"); @@ -201,13 +202,13 @@ public: } template <typename T> - T* Allocate(size_t count = 1) + NDDISCARD T* Allocate(size_t count = 1) { return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T))); } template <typename T, typename... Args> - T* Construct(Args&&... args) + NDDISCARD T* Construct(Args&&... args) { T* Ptr = Allocate<T>(); new (Ptr) T{std::forward<Args>(args)...}; @@ -215,7 +216,7 @@ public: } template <typename T, typename... Args> - T* ConstructArray(size_t count, const Args&... args) + NDDISCARD T* ConstructArray(size_t count, const Args&... args) { T* Ptr = Allocate<T>(count); for (size_t i = 0; i < count; ++i) @@ -226,13 +227,13 @@ public: } template <typename T> - T* Copy(const T& Src) + NDDISCARD T* Copy(const T& Src) { return Construct<T>(Src); } template <typename T> - T* CopyArray(const T* Src, size_t count) + NDDISCARD T* CopyArray(const T* Src, size_t count) { T* Dst = Allocate<T>(count); for (size_t i = 0; i < count; ++i) @@ -242,7 +243,7 @@ public: return Dst; } - Char* CopyString(const char* Str) + NDDISCARD Char* CopyString(const char* Str) { if (Str == nullptr) return nullptr; @@ -264,17 +265,17 @@ public: return Ptr; } - Char* CopyString(const std::string& Str) + NDDISCARD Char* CopyString(const std::string& Str) { return CopyString(Str.c_str()); } - size_t GetCurrentSize() const + NDDISCARD size_t GetCurrentSize() const { return static_cast<size_t>(m_pCurrPtr - m_pDataStart); } - size_t GetReservedSize() const + NDDISCARD size_t GetReservedSize() const { return m_ReservedSize; } |
