summaryrefslogtreecommitdiffstats
path: root/Common/interface
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-25 12:53:05 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-25 13:08:57 +0000
commit7f26e40e0898391a32e6a05d91ef1a217d885668 (patch)
tree3236316d1a752e5dbbfae863f8180ff994b31d70 /Common/interface
parentMerge branch 'master' into ray_tracing (diff)
downloadDiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.tar.gz
DiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.zip
PSO refactoring for ray tracing
Diffstat (limited to 'Common/interface')
-rw-r--r--Common/interface/Align.hpp32
-rw-r--r--Common/interface/Definitions.hpp52
-rw-r--r--Common/interface/DynamicLinearAllocator.hpp199
-rw-r--r--Common/interface/LinearAllocator.hpp27
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;
}