git.s-ol.nu ~forks/DiligentCore / 2cbe12c
Merge branch 'azhirnov-ray_tracing_2' assiduous 9 months ago
231 changed file(s) with 21007 addition(s) and 3842 deletion(s). Raw diff Collapse all Expand all
1818 interface/FixedBlockMemoryAllocator.hpp
1919 interface/HashUtils.hpp
2020 interface/LockHelper.hpp
21 interface/LinearAllocator.hpp
21 interface/FixedLinearAllocator.hpp
22 interface/DynamicLinearAllocator.hpp
2223 interface/MemoryFileStream.hpp
2324 interface/ObjectBase.hpp
2425 interface/RefCntAutoPtr.hpp
3132 interface/Timer.hpp
3233 interface/UniqueIdentifier.hpp
3334 interface/ValidatedCast.hpp
35 interface/CompilerDefinitions.h
3436 )
3537
3638 set(SOURCE
7878 const Plane3D* Planes = reinterpret_cast<const Plane3D*>(this);
7979 return Planes[static_cast<size_t>(Idx)];
8080 }
81
82 Plane3D& GetPlane(PLANE_IDX Idx)
83 {
84 VERIFY_EXPR(Idx < NUM_PLANES);
85 Plane3D* Planes = reinterpret_cast<Plane3D*>(this);
86 return Planes[static_cast<size_t>(Idx)];
87 }
8188 };
8289
8390 struct ViewFrustumExt : public ViewFrustum
4242 return val > 0 && (val & (val - 1)) == 0;
4343 }
4444
45 template <typename T>
46 inline T Align(T val, T alignment)
45 template <typename T1, typename T2>
46 inline typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type Align(T1 val, T2 alignment)
4747 {
48 static_assert(std::is_unsigned<T1>::value == std::is_unsigned<T2>::value, "both types must be signed or unsigned");
49 static_assert(!std::is_pointer<T1>::value && !std::is_pointer<T2>::value, "types must not be pointers");
4850 VERIFY(IsPowerOfTwo(alignment), "Alignment (", alignment, ") must be power of 2");
49 return (val + (alignment - 1)) & ~(alignment - 1);
51
52 using T = typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type;
53 return (static_cast<T>(val) + static_cast<T>(alignment - 1)) & ~static_cast<T>(alignment - 1);
5054 }
5155
52 template <typename T>
53 inline T* Align(T* val, size_t alignment)
56 template <typename PtrType, typename AlignType>
57 inline PtrType* Align(PtrType* val, AlignType alignment)
5458 {
55 return reinterpret_cast<T*>(Align(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
59 return reinterpret_cast<PtrType*>(Align(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
5660 }
5761
58 template <typename T>
59 inline T AlignDown(T val, T alignment)
62 template <typename T1, typename T2>
63 inline typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type AlignDown(T1 val, T2 alignment)
6064 {
65 static_assert(std::is_unsigned<T1>::value == std::is_unsigned<T2>::value, "both types must be signed or unsigned");
66 static_assert(!std::is_pointer<T1>::value && !std::is_pointer<T2>::value, "types must not be pointers");
6167 VERIFY(IsPowerOfTwo(alignment), "Alignment (", alignment, ") must be power of 2");
62 return val & ~(alignment - 1);
68
69 using T = typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type;
70 return static_cast<T>(val) & ~static_cast<T>(alignment - 1);
6371 }
6472
65 template <typename T>
66 inline T* AlignDown(T* val, size_t alignment)
73 template <typename PtrType, typename AlignType>
74 inline PtrType* AlignDown(PtrType* val, AlignType alignment)
6775 {
68 return reinterpret_cast<T*>(AlignDown(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
76 return reinterpret_cast<PtrType*>(AlignDown(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
6977 }
7078
7179 } // namespace Diligent
971971 1, 0, 0,
972972 0, 1, 0,
973973 0, 0, 1 //
974 };
975 }
976
977 static Matrix3x3 Scale(T x, T y, T z)
978 {
979 return Matrix3x3 //
980 {
981 x, 0, 0,
982 0, y, 0,
983 0, 0, z //
984 };
985 }
986
987 // D3D-style left-handed matrix that rotates a point around the x axis. Angle (in radians)
988 // is measured clockwise when looking along the rotation axis toward the origin:
989 // (x' y' z') = (x y z) * RotationX
990 static Matrix3x3 RotationX(T angleInRadians)
991 {
992 auto s = std::sin(angleInRadians);
993 auto c = std::cos(angleInRadians);
994
995 return Matrix3x3 // clang-format off
996 {
997 1, 0, 0,
998 0, c, s,
999 0, -s, c // clang-format on
1000 };
1001 }
1002
1003 // D3D-style left-handed matrix that rotates a point around the y axis. Angle (in radians)
1004 // is measured clockwise when looking along the rotation axis toward the origin:
1005 // (x' y' z' 1) = (x y z 1) * RotationY
1006 static Matrix3x3 RotationY(T angleInRadians)
1007 {
1008 auto s = std::sin(angleInRadians);
1009 auto c = std::cos(angleInRadians);
1010
1011 return Matrix3x3 // clang-format off
1012 {
1013 c, 0, -s,
1014 0, 1, 0,
1015 s, 0, c // clang-format on
1016 };
1017 }
1018
1019 // D3D-style left-handed matrix that rotates a point around the z axis. Angle (in radians)
1020 // is measured clockwise when looking along the rotation axis toward the origin:
1021 // (x' y' z' 1) = (x y z 1) * RotationZ
1022 static Matrix3x3 RotationZ(T angleInRadians)
1023 {
1024 auto s = std::sin(angleInRadians);
1025 auto c = std::cos(angleInRadians);
1026
1027 return Matrix3x3 // clang-format off
1028 {
1029 c, s, 0,
1030 -s, c, 0,
1031 0, 0, 1 // clang-format on
9741032 };
9751033 }
9761034
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 #ifdef _MSC_VER
30 # if _MSC_VER >= 1917
31 # define NODISCARD [[nodiscard]]
32 # else
33 # define NODISCARD
34 # endif
35 #endif // _MSC_VER
36
37 #ifdef __clang__
38 # if __has_feature(cxx_attributes)
39 # define NODISCARD [[nodiscard]]
40 # else
41 # define NODISCARD
42 # endif
43 #endif // __clang__
44
45 #ifdef __GNUC__
46 # if __has_cpp_attribute(nodiscard)
47 # define NODISCARD [[nodiscard]]
48 # else
49 # define NODISCARD
50 # endif
51 #endif // __GNUC__
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Defines Diligent::DynamicLinearAllocator class
31
32 #include <vector>
33
34 #include "../../Primitives/interface/BasicTypes.h"
35 #include "../../Primitives/interface/MemoryAllocator.h"
36 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
37 #include "CompilerDefinitions.h"
38 #include "Align.hpp"
39
40 namespace Diligent
41 {
42
43 /// Implementation of a linear allocator on fixed memory pages
44 class DynamicLinearAllocator
45 {
46 public:
47 // clang-format off
48 DynamicLinearAllocator (const DynamicLinearAllocator&) = delete;
49 DynamicLinearAllocator (DynamicLinearAllocator&&) = delete;
50 DynamicLinearAllocator& operator=(const DynamicLinearAllocator&) = delete;
51 DynamicLinearAllocator& operator=(DynamicLinearAllocator&&) = delete;
52 // clang-format on
53
54 explicit DynamicLinearAllocator(IMemoryAllocator& Allocator, Uint32 BlockSize = 4 << 10) :
55 m_pAllocator{&Allocator},
56 m_BlockSize{BlockSize}
57 {
58 VERIFY(IsPowerOfTwo(BlockSize), "Block size (", BlockSize, ") is not power of two");
59 }
60
61 ~DynamicLinearAllocator()
62 {
63 Free();
64 }
65
66 void Free()
67 {
68 for (auto& block : m_Blocks)
69 {
70 m_pAllocator->Free(block.Data);
71 }
72 m_Blocks.clear();
73
74 m_pAllocator = nullptr;
75 }
76
77 void Discard()
78 {
79 for (auto& block : m_Blocks)
80 {
81 block.CurrPtr = block.Data;
82 }
83 }
84
85 NODISCARD void* Allocate(size_t size, size_t align)
86 {
87 if (size == 0)
88 return nullptr;
89
90 for (auto& block : m_Blocks)
91 {
92 auto* Ptr = Align(block.CurrPtr, align);
93 if (Ptr + size <= block.Data + block.Size)
94 {
95 block.CurrPtr = Ptr + size;
96 return Ptr;
97 }
98 }
99
100 // Create a new block
101 size_t BlockSize = m_BlockSize;
102 while (BlockSize < size + align - 1)
103 BlockSize *= 2;
104 m_Blocks.emplace_back(m_pAllocator->Allocate(BlockSize, "dynamic linear allocator page", __FILE__, __LINE__), BlockSize);
105
106 auto& block = m_Blocks.back();
107 auto* Ptr = Align(block.Data, align);
108 VERIFY(Ptr + size <= block.Data + block.Size, "Not enough space in the new block - this is a bug");
109 block.CurrPtr = Ptr + size;
110 return Ptr;
111 }
112
113 template <typename T>
114 NODISCARD T* Allocate(size_t count = 1)
115 {
116 return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T)));
117 }
118
119 template <typename T, typename... Args>
120 NODISCARD T* Construct(Args&&... args)
121 {
122 T* Ptr = Allocate<T>(1);
123 new (Ptr) T{std::forward<Args>(args)...};
124 return Ptr;
125 }
126
127 template <typename T, typename... Args>
128 NODISCARD T* ConstructArray(size_t count, const Args&... args)
129 {
130 T* Ptr = Allocate<T>(count);
131 for (size_t i = 0; i < count; ++i)
132 {
133 new (Ptr + i) T{args...};
134 }
135 return Ptr;
136 }
137
138 template <typename T>
139 NODISCARD T* CopyArray(const T* Src, size_t count)
140 {
141 T* Dst = Allocate<T>(count);
142 for (size_t i = 0; i < count; ++i)
143 {
144 new (Dst + i) T{Src[i]};
145 }
146 return Dst;
147 }
148
149 NODISCARD Char* CopyString(const Char* Str, size_t len = 0)
150 {
151 if (Str == nullptr)
152 return nullptr;
153
154 if (len == 0)
155 len = strlen(Str);
156 else
157 VERIFY_EXPR(len <= strlen(Str));
158
159 Char* Dst = Allocate<Char>(len + 1);
160 std::memcpy(Dst, Str, sizeof(Char) * len);
161 Dst[len] = 0;
162 return Dst;
163 }
164
165 NODISCARD wchar_t* CopyWString(const char* Str)
166 {
167 if (Str == nullptr)
168 return nullptr;
169
170 size_t len = strlen(Str);
171 auto* Dst = Allocate<wchar_t>(len + 1);
172 for (size_t i = 0; i < len; ++i)
173 {
174 Dst[i] = static_cast<wchar_t>(Str[i]);
175 }
176 Dst[len] = 0;
177 return Dst;
178 }
179
180 NODISCARD Char* CopyString(const String& Str)
181 {
182 return CopyString(Str.c_str(), Str.length());
183 }
184
185 private:
186 struct Block
187 {
188 uint8_t* const Data = nullptr;
189 size_t const Size = 0;
190 uint8_t* CurrPtr = nullptr;
191
192 Block(void* _Data, size_t _Size) :
193 Data{static_cast<uint8_t*>(_Data)}, Size{_Size}, CurrPtr{Data} {}
194 };
195
196 std::vector<Block> m_Blocks;
197 const Uint32 m_BlockSize = 4 << 10;
198 IMemoryAllocator* m_pAllocator = nullptr;
199 };
200
201 } // namespace Diligent
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Defines Diligent::FixedLinearAllocator class
31
32 #include <vector>
33
34 #include "../../Primitives/interface/BasicTypes.h"
35 #include "../../Primitives/interface/MemoryAllocator.h"
36 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
37 #include "CompilerDefinitions.h"
38 #include "Align.hpp"
39
40 namespace Diligent
41 {
42
43 /// Implementation of a linear allocator on a fixed-size memory page
44 class FixedLinearAllocator
45 {
46 public:
47 // clang-format off
48 FixedLinearAllocator (const FixedLinearAllocator&) = delete;
49 FixedLinearAllocator& operator=(const FixedLinearAllocator&) = delete;
50 FixedLinearAllocator& operator=(FixedLinearAllocator&&) = delete;
51 // clang-format on
52
53 explicit FixedLinearAllocator(IMemoryAllocator& Allocator) noexcept :
54 m_pAllocator{&Allocator}
55 {}
56
57 FixedLinearAllocator(FixedLinearAllocator&& Other) noexcept :
58 // clang-format off
59 m_pDataStart {Other.m_pDataStart },
60 m_pCurrPtr {Other.m_pCurrPtr },
61 m_ReservedSize {Other.m_ReservedSize },
62 m_CurrAlignment{Other.m_CurrAlignment},
63 m_pAllocator {Other.m_pAllocator }
64 // clang-format on
65 {
66 Other.Reset();
67 }
68
69 ~FixedLinearAllocator()
70 {
71 Free();
72 }
73
74 void Free()
75 {
76 if (m_pDataStart != nullptr && m_pAllocator != nullptr)
77 {
78 m_pAllocator->Free(m_pDataStart);
79 }
80 Reset();
81 }
82
83 NODISCARD void* Release()
84 {
85 void* Ptr = m_pDataStart;
86 Reset();
87 return Ptr;
88 }
89
90 NODISCARD void* ReleaseOwnership() noexcept
91 {
92 m_pAllocator = nullptr;
93 return GetDataPtr();
94 }
95
96 NODISCARD void* GetDataPtr() const noexcept
97 {
98 return m_pDataStart;
99 }
100
101 void AddSpace(size_t size, size_t alignment) noexcept
102 {
103 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
104 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
105
106 if (size == 0)
107 return;
108
109 if (m_CurrAlignment == 0)
110 {
111 VERIFY(m_ReservedSize == 0, "This is expected to be a very first time the space is added");
112 m_CurrAlignment = sizeof(void*);
113 }
114
115 if (alignment > m_CurrAlignment)
116 {
117 // Reserve extra space that may be needed for alignment
118 m_ReservedSize += alignment - m_CurrAlignment;
119 }
120 m_CurrAlignment = alignment;
121
122 size = Align(size, alignment);
123 m_ReservedSize += size;
124
125 #if DILIGENT_DEBUG
126 m_DbgAllocations.emplace_back(size, alignment, m_ReservedSize);
127 #endif
128 }
129
130 template <typename T>
131 void AddSpace(size_t count = 1) noexcept
132 {
133 AddSpace(sizeof(T) * count, alignof(T));
134 }
135
136 void AddSpaceForString(const Char* str) noexcept
137 {
138 VERIFY_EXPR(str != nullptr);
139 AddSpace(strlen(str) + 1, 1);
140 }
141
142 void AddSpaceForString(const String& str) noexcept
143 {
144 AddSpaceForString(str.c_str());
145 }
146
147 void Reserve(size_t size)
148 {
149 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
150 VERIFY(m_ReservedSize == 0, "Space has been added to the allocator and will be overriden");
151 m_ReservedSize = size;
152 Reserve();
153 }
154
155 void Reserve()
156 {
157 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
158 VERIFY(m_pAllocator != nullptr, "Allocator must not be null");
159 // Make sure the data size is at least sizeof(void*)-aligned
160 m_ReservedSize = Align(m_ReservedSize, sizeof(void*));
161 if (m_ReservedSize > 0)
162 {
163 m_pDataStart = reinterpret_cast<uint8_t*>(m_pAllocator->Allocate(m_ReservedSize, "Raw memory for linear allocator", __FILE__, __LINE__));
164 VERIFY(m_pDataStart == Align(m_pDataStart, sizeof(void*)), "Memory pointer must be at least sizeof(void*)-aligned");
165
166 m_pCurrPtr = m_pDataStart;
167 }
168 m_CurrAlignment = sizeof(void*);
169 }
170
171 NODISCARD void* Allocate(size_t size, size_t alignment)
172 {
173 VERIFY(size == 0 || m_pDataStart != nullptr, "Memory has not been allocated");
174 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
175
176 if (size == 0)
177 return nullptr;
178
179 size = Align(size, alignment);
180
181 #if DILIGENT_DEBUG
182 VERIFY(m_DbgCurrAllocation < m_DbgAllocations.size(), "Allocation number exceed the number of allocations that were originally reserved.");
183 const auto& CurrAllocation = m_DbgAllocations[m_DbgCurrAllocation++];
184 VERIFY(CurrAllocation.size == size, "Allocation size (", size, ") does not match the initially requested size (", CurrAllocation.size, ")");
185 VERIFY(CurrAllocation.alignment == alignment, "Allocation alignment (", alignment, ") does not match the initially requested alignment (", CurrAllocation.alignment, ")");
186 #endif
187
188 VERIFY(Align(m_pCurrPtr, m_CurrAlignment) == m_pCurrPtr, "Current pointer is not aligned as expected");
189 m_pCurrPtr = Align(m_pCurrPtr, alignment);
190 m_CurrAlignment = alignment;
191
192 VERIFY(m_pCurrPtr + size <= m_pDataStart + CurrAllocation.reserved_size,
193 "Allocation size exceeds the initially reserved space. This is likely a bug.");
194
195 auto* ptr = m_pCurrPtr;
196 m_pCurrPtr += size;
197
198 VERIFY(m_pCurrPtr <= m_pDataStart + m_ReservedSize, "Allocation size exceeds the reserved space");
199
200 return ptr;
201 }
202
203 template <typename T>
204 NODISCARD T* Allocate(size_t count = 1)
205 {
206 return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T)));
207 }
208
209 template <typename T, typename... Args>
210 NODISCARD T* Construct(Args&&... args)
211 {
212 T* Ptr = Allocate<T>();
213 new (Ptr) T{std::forward<Args>(args)...};
214 return Ptr;
215 }
216
217 template <typename T, typename... Args>
218 NODISCARD T* ConstructArray(size_t count, const Args&... args)
219 {
220 T* Ptr = Allocate<T>(count);
221 for (size_t i = 0; i < count; ++i)
222 {
223 new (Ptr + i) T{args...};
224 }
225 return Ptr;
226 }
227
228 template <typename T>
229 NODISCARD T* Copy(const T& Src)
230 {
231 return Construct<T>(Src);
232 }
233
234 template <typename T>
235 NODISCARD T* CopyArray(const T* Src, size_t count)
236 {
237 T* Dst = Allocate<T>(count);
238 for (size_t i = 0; i < count; ++i)
239 {
240 new (Dst + i) T{Src[i]};
241 }
242 return Dst;
243 }
244
245 NODISCARD Char* CopyString(const char* Str)
246 {
247 if (Str == nullptr)
248 return nullptr;
249
250 auto* Ptr = reinterpret_cast<Char*>(Allocate(strlen(Str) + 1, 1));
251 Char* Dst = Ptr;
252
253 const auto* pDataEnd = reinterpret_cast<Char*>(m_pDataStart) + m_ReservedSize;
254 while (*Str != 0 && Dst < pDataEnd)
255 {
256 *(Dst++) = *(Str++);
257 }
258 if (Dst < pDataEnd)
259 *(Dst++) = 0;
260 else
261 UNEXPECTED("Not enough space reserved for the string");
262
263 VERIFY_EXPR(reinterpret_cast<Char*>(m_pCurrPtr) == Dst);
264 return Ptr;
265 }
266
267 NODISCARD Char* CopyString(const std::string& Str)
268 {
269 return CopyString(Str.c_str());
270 }
271
272 NODISCARD size_t GetCurrentSize() const
273 {
274 VERIFY(m_pDataStart != nullptr, "Memory has not been allocated");
275 return static_cast<size_t>(m_pCurrPtr - m_pDataStart);
276 }
277
278 NODISCARD size_t GetReservedSize() const
279 {
280 return m_ReservedSize;
281 }
282
283 private:
284 void Reset()
285 {
286 m_pDataStart = nullptr;
287 m_pCurrPtr = nullptr;
288 m_ReservedSize = 0;
289 m_CurrAlignment = 0;
290 m_pAllocator = nullptr;
291
292 #if DILIGENT_DEBUG
293 m_DbgCurrAllocation = 0;
294 m_DbgAllocations.clear();
295 #endif
296 }
297
298 uint8_t* m_pDataStart = nullptr;
299 uint8_t* m_pCurrPtr = nullptr;
300 size_t m_ReservedSize = 0;
301 size_t m_CurrAlignment = 0;
302 IMemoryAllocator* m_pAllocator = nullptr;
303
304 #if DILIGENT_DEBUG
305 size_t m_DbgCurrAllocation = 0;
306 struct DbgAllocationInfo
307 {
308 const size_t size;
309 const size_t alignment;
310 const size_t reserved_size;
311
312 DbgAllocationInfo(size_t _size, size_t _alignment, size_t _reserved_size) :
313 size{_size},
314 alignment{_alignment},
315 reserved_size{_reserved_size}
316 {
317 }
318 };
319 std::vector<DbgAllocationInfo> m_DbgAllocations;
320 #endif
321 };
322
323 } // namespace Diligent
207207 }
208208 };
209209
210 private:
210 protected:
211211 static constexpr size_t StrOwnershipBit = sizeof(size_t) * 8 - 1;
212212 static constexpr size_t StrOwnershipMask = size_t{1} << StrOwnershipBit;
213213 static constexpr size_t HashMask = ~StrOwnershipMask;
+0
-317
Common/interface/LinearAllocator.hpp less more
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Defines Diligent::LinearAllocator class
31
32 #include <vector>
33
34 #include "../../Primitives/interface/BasicTypes.h"
35 #include "../../Primitives/interface/MemoryAllocator.h"
36 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
37 #include "Align.hpp"
38
39 namespace Diligent
40 {
41
42 /// Implementation of a linear allocator on a fixed-size memory page
43 class LinearAllocator
44 {
45 public:
46 // clang-format off
47 LinearAllocator (const LinearAllocator&) = delete;
48 LinearAllocator& operator=(const LinearAllocator&) = delete;
49 LinearAllocator& operator=(LinearAllocator&&) = delete;
50 // clang-format on
51
52 explicit LinearAllocator(IMemoryAllocator& Allocator) noexcept :
53 m_pAllocator{&Allocator}
54 {}
55
56 LinearAllocator(LinearAllocator&& Other) noexcept :
57 // clang-format off
58 m_pDataStart {Other.m_pDataStart },
59 m_pCurrPtr {Other.m_pCurrPtr },
60 m_ReservedSize {Other.m_ReservedSize },
61 m_CurrAlignment{Other.m_CurrAlignment},
62 m_pAllocator {Other.m_pAllocator }
63 // clang-format on
64 {
65 Other.Reset();
66 }
67
68 ~LinearAllocator()
69 {
70 Free();
71 }
72
73 void Free()
74 {
75 if (m_pDataStart != nullptr && m_pAllocator != nullptr)
76 {
77 m_pAllocator->Free(m_pDataStart);
78 }
79 Reset();
80 }
81
82 void* Release()
83 {
84 void* Ptr = m_pDataStart;
85 Reset();
86 return Ptr;
87 }
88
89 void* ReleaseOwnership() noexcept
90 {
91 m_pAllocator = nullptr;
92 return GetDataPtr();
93 }
94
95 void* GetDataPtr() const noexcept
96 {
97 return m_pDataStart;
98 }
99
100 void AddSpace(size_t size, size_t alignment) noexcept
101 {
102 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
103 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
104
105 if (size == 0)
106 return;
107
108 if (m_CurrAlignment == 0)
109 {
110 VERIFY(m_ReservedSize == 0, "This is expected to be a very first time the space is added");
111 m_CurrAlignment = sizeof(void*);
112 }
113
114 if (alignment > m_CurrAlignment)
115 {
116 // Reserve extra space that may be needed for alignment
117 m_ReservedSize += alignment - m_CurrAlignment;
118 }
119 m_CurrAlignment = alignment;
120
121 size = Align(size, alignment);
122 m_ReservedSize += size;
123
124 #if DILIGENT_DEBUG
125 m_DbgAllocations.emplace_back(size, alignment, m_ReservedSize);
126 #endif
127 }
128
129 template <typename T>
130 void AddSpace(size_t count = 1) noexcept
131 {
132 AddSpace(sizeof(T) * count, alignof(T));
133 }
134
135 void AddSpaceForString(const Char* str) noexcept
136 {
137 VERIFY_EXPR(str != nullptr);
138 AddSpace(strlen(str) + 1, 1);
139 }
140
141 void AddSpaceForString(const String& str) noexcept
142 {
143 AddSpaceForString(str.c_str());
144 }
145
146 void Reserve(size_t size)
147 {
148 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
149 VERIFY(m_ReservedSize == 0, "Space has been added to the allocator and will be overriden");
150 m_ReservedSize = size;
151 Reserve();
152 }
153
154 void Reserve()
155 {
156 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
157 VERIFY(m_pAllocator != nullptr, "Allocator must not be null");
158 // Make sure the data size is at least sizeof(void*)-aligned
159 m_ReservedSize = Align(m_ReservedSize, sizeof(void*));
160 if (m_ReservedSize > 0)
161 {
162 m_pDataStart = reinterpret_cast<uint8_t*>(m_pAllocator->Allocate(m_ReservedSize, "Raw memory for linear allocator", __FILE__, __LINE__));
163 VERIFY(m_pDataStart == Align(m_pDataStart, sizeof(void*)), "Memory pointer must be at least sizeof(void*)-aligned");
164
165 m_pCurrPtr = m_pDataStart;
166 }
167 m_CurrAlignment = sizeof(void*);
168 }
169
170 void* Allocate(size_t size, size_t alignment)
171 {
172 VERIFY(size == 0 || m_pDataStart != nullptr, "Memory has not been allocated");
173 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
174
175 if (size == 0)
176 return nullptr;
177
178 size = Align(size, alignment);
179
180 #if DILIGENT_DEBUG
181 VERIFY(m_DbgCurrAllocation < m_DbgAllocations.size(), "Allocation number exceed the number of allocations that were originally reserved.");
182 const auto& CurrAllocation = m_DbgAllocations[m_DbgCurrAllocation++];
183 VERIFY(CurrAllocation.size == size, "Allocation size (", size, ") does not match the initially requested size (", CurrAllocation.size, ")");
184 VERIFY(CurrAllocation.alignment == alignment, "Allocation alignment (", alignment, ") does not match the initially requested alignment (", CurrAllocation.alignment, ")");
185 #endif
186
187 VERIFY(Align(m_pCurrPtr, m_CurrAlignment) == m_pCurrPtr, "Current pointer is not aligned as expected");
188 m_pCurrPtr = Align(m_pCurrPtr, alignment);
189 m_CurrAlignment = alignment;
190
191 VERIFY(m_pCurrPtr + size <= m_pDataStart + CurrAllocation.reserved_size,
192 "Allocation size exceeds the initially reserved space. This is likely a bug.");
193
194 auto* ptr = m_pCurrPtr;
195 m_pCurrPtr += size;
196
197 VERIFY(m_pCurrPtr <= m_pDataStart + m_ReservedSize, "Allocation size exceeds the reserved space");
198
199 return ptr;
200 }
201
202 template <typename T>
203 T* Allocate(size_t count = 1)
204 {
205 return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T)));
206 }
207
208 template <typename T, typename... Args>
209 T* Construct(Args&&... args)
210 {
211 T* Ptr = Allocate<T>();
212 new (Ptr) T{std::forward<Args>(args)...};
213 return Ptr;
214 }
215
216 template <typename T, typename... Args>
217 T* ConstructArray(size_t count, const Args&... args)
218 {
219 T* Ptr = Allocate<T>(count);
220 for (size_t i = 0; i < count; ++i)
221 {
222 new (Ptr + i) T{args...};
223 }
224 return Ptr;
225 }
226
227 template <typename T>
228 T* Copy(const T& Src)
229 {
230 return Construct<T>(Src);
231 }
232
233 template <typename T>
234 T* CopyArray(const T* Src, size_t count)
235 {
236 T* Dst = Allocate<T>(count);
237 for (size_t i = 0; i < count; ++i)
238 {
239 new (Dst + i) T{Src[i]};
240 }
241 return Dst;
242 }
243
244 Char* CopyString(const char* Str)
245 {
246 if (Str == nullptr)
247 return nullptr;
248
249 auto* Ptr = reinterpret_cast<Char*>(Allocate(strlen(Str) + 1, 1));
250 Char* Dst = Ptr;
251
252 const auto* pDataEnd = reinterpret_cast<Char*>(m_pDataStart) + m_ReservedSize;
253 while (*Str != 0 && Dst < pDataEnd)
254 {
255 *(Dst++) = *(Str++);
256 }
257 if (Dst < pDataEnd)
258 *(Dst++) = 0;
259 else
260 UNEXPECTED("Not enough space reserved for the string");
261
262 VERIFY_EXPR(reinterpret_cast<Char*>(m_pCurrPtr) == Dst);
263 return Ptr;
264 }
265
266 Char* CopyString(const std::string& Str)
267 {
268 return CopyString(Str.c_str());
269 }
270
271 size_t GetCurrentSize() const
272 {
273 return static_cast<size_t>(m_pCurrPtr - m_pDataStart);
274 }
275
276 size_t GetReservedSize() const
277 {
278 return m_ReservedSize;
279 }
280
281 private:
282 void Reset()
283 {
284 m_pDataStart = nullptr;
285 m_pCurrPtr = nullptr;
286 m_ReservedSize = 0;
287 m_CurrAlignment = 0;
288 m_pAllocator = nullptr;
289 }
290
291 uint8_t* m_pDataStart = nullptr;
292 uint8_t* m_pCurrPtr = nullptr;
293 size_t m_ReservedSize = 0;
294 size_t m_CurrAlignment = 0;
295 IMemoryAllocator* m_pAllocator = nullptr;
296
297 #if DILIGENT_DEBUG
298 size_t m_DbgCurrAllocation = 0;
299 struct DbgAllocationInfo
300 {
301 const size_t size;
302 const size_t alignment;
303 const size_t reserved_size;
304
305 DbgAllocationInfo(size_t _size, size_t _alignment, size_t _reserved_size) :
306 size{_size},
307 alignment{_alignment},
308 reserved_size{_reserved_size}
309 {
310 }
311 };
312 std::vector<DbgAllocationInfo> m_DbgAllocations;
313 #endif
314 };
315
316 } // namespace Diligent
6464
6565 ~StringPool()
6666 {
67 Release();
67 Clear();
6868 }
6969
7070 void Reserve(size_t Size, IMemoryAllocator& Allocator)
7171 {
72 Release();
72 Clear();
7373
7474 VERIFY(m_ReservedSize == 0, "Pool is already initialized");
7575 m_pAllocator = &Allocator;
8181 m_pCurrPtr = m_pBuffer;
8282 }
8383
84 void Release()
84 void Clear()
8585 {
8686 if (m_pBuffer != nullptr && m_pAllocator != nullptr)
8787 {
160160 VERIFY(m_pCurrPtr <= m_pBuffer + m_ReservedSize, "Buffer overflow");
161161 return m_pCurrPtr - m_pBuffer;
162162 }
163 size_t GetReservedSize() const
164 {
165 return m_ReservedSize;
166 }
163167
164168 private:
165169 Char* m_pBuffer = nullptr;
4949 m_NumBlocksInPage {NumBlocksInPage }
5050 // clang-format on
5151 {
52 VERIFY_EXPR(BlockSize > 0);
53
5452 // Allocate one page
5553 CreateNewPage();
5654 }
433433 return PlatformMisc::GetLSB(Type);
434434 }
435435
436 static_assert(SHADER_TYPE_LAST == 0x080, "Please add the new shader type index below");
437
438 static constexpr Int32 VSInd = 0;
439 static constexpr Int32 PSInd = 1;
440 static constexpr Int32 GSInd = 2;
441 static constexpr Int32 HSInd = 3;
442 static constexpr Int32 DSInd = 4;
443 static constexpr Int32 CSInd = 5;
444 static constexpr Int32 ASInd = 6;
445 static constexpr Int32 MSInd = 7;
446
447 static constexpr Int32 LastShaderInd = MSInd;
436 static_assert(SHADER_TYPE_LAST == 0x2000, "Please add the new shader type index below");
437
438 static constexpr Int32 VSInd = 0;
439 static constexpr Int32 PSInd = 1;
440 static constexpr Int32 GSInd = 2;
441 static constexpr Int32 HSInd = 3;
442 static constexpr Int32 DSInd = 4;
443 static constexpr Int32 CSInd = 5;
444 static constexpr Int32 ASInd = 6;
445 static constexpr Int32 MSInd = 7;
446 static constexpr Int32 RGSInd = 8;
447 static constexpr Int32 RMSInd = 9;
448 static constexpr Int32 RCHSInd = 10;
449 static constexpr Int32 RAHSInd = 11;
450 static constexpr Int32 RISInd = 12;
451 static constexpr Int32 RCSInd = 13;
452
453 static constexpr Int32 LastShaderInd = RCSInd;
448454
449455 // clang-format off
450 static_assert(SHADER_TYPE_VERTEX == (1 << VSInd), "VSInd is not consistent with SHADER_TYPE_VERTEX");
451 static_assert(SHADER_TYPE_PIXEL == (1 << PSInd), "PSInd is not consistent with SHADER_TYPE_PIXEL");
452 static_assert(SHADER_TYPE_GEOMETRY == (1 << GSInd), "GSInd is not consistent with SHADER_TYPE_GEOMETRY");
453 static_assert(SHADER_TYPE_HULL == (1 << HSInd), "HSInd is not consistent with SHADER_TYPE_HULL");
454 static_assert(SHADER_TYPE_DOMAIN == (1 << DSInd), "DSInd is not consistent with SHADER_TYPE_DOMAIN");
455 static_assert(SHADER_TYPE_COMPUTE == (1 << CSInd), "CSInd is not consistent with SHADER_TYPE_COMPUTE");
456 static_assert(SHADER_TYPE_AMPLIFICATION == (1 << ASInd), "ASInd is not consistent with SHADER_TYPE_AMPLIFICATION");
457 static_assert(SHADER_TYPE_MESH == (1 << MSInd), "MSInd is not consistent with SHADER_TYPE_MESH");
456 static_assert(SHADER_TYPE_VERTEX == (1 << VSInd), "VSInd is not consistent with SHADER_TYPE_VERTEX");
457 static_assert(SHADER_TYPE_PIXEL == (1 << PSInd), "PSInd is not consistent with SHADER_TYPE_PIXEL");
458 static_assert(SHADER_TYPE_GEOMETRY == (1 << GSInd), "GSInd is not consistent with SHADER_TYPE_GEOMETRY");
459 static_assert(SHADER_TYPE_HULL == (1 << HSInd), "HSInd is not consistent with SHADER_TYPE_HULL");
460 static_assert(SHADER_TYPE_DOMAIN == (1 << DSInd), "DSInd is not consistent with SHADER_TYPE_DOMAIN");
461 static_assert(SHADER_TYPE_COMPUTE == (1 << CSInd), "CSInd is not consistent with SHADER_TYPE_COMPUTE");
462 static_assert(SHADER_TYPE_AMPLIFICATION == (1 << ASInd), "ASInd is not consistent with SHADER_TYPE_AMPLIFICATION");
463 static_assert(SHADER_TYPE_MESH == (1 << MSInd), "MSInd is not consistent with SHADER_TYPE_MESH");
464 static_assert(SHADER_TYPE_RAY_GEN == (1 << RGSInd), "RGSInd is not consistent with SHADER_TYPE_RAY_GEN");
465 static_assert(SHADER_TYPE_RAY_MISS == (1 << RMSInd), "RMSInd is not consistent with SHADER_TYPE_RAY_MISS");
466 static_assert(SHADER_TYPE_RAY_CLOSEST_HIT == (1 << RCHSInd), "RCHSInd is not consistent with SHADER_TYPE_RAY_CLOSEST_HIT");
467 static_assert(SHADER_TYPE_RAY_ANY_HIT == (1 << RAHSInd), "RAHSInd is not consistent with SHADER_TYPE_RAY_ANY_HIT");
468 static_assert(SHADER_TYPE_RAY_INTERSECTION == (1 << RISInd), "RISInd is not consistent with SHADER_TYPE_RAY_INTERSECTION");
469 static_assert(SHADER_TYPE_CALLABLE == (1 << RCSInd), "RCSInd is not consistent with SHADER_TYPE_CALLABLE");
458470
459471 static_assert(SHADER_TYPE_LAST == (1 << LastShaderInd), "LastShaderInd is not consistent with SHADER_TYPE_LAST");
460472 // clang-format on
473473
474474 const Char* GetShaderTypeLiteralName(SHADER_TYPE ShaderType)
475475 {
476 static_assert(SHADER_TYPE_LAST == 0x080, "Please handle the new shader type in the switch below");
476 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please handle the new shader type in the switch below");
477477 switch (ShaderType)
478478 {
479479 // clang-format off
480480 #define RETURN_SHADER_TYPE_NAME(ShaderType)\
481481 case ShaderType: return #ShaderType;
482482
483 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_UNKNOWN )
484 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_VERTEX )
485 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_PIXEL )
486 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_GEOMETRY )
487 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_HULL )
488 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_DOMAIN )
489 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_COMPUTE )
490 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_AMPLIFICATION)
491 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_MESH )
483 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_UNKNOWN )
484 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_VERTEX )
485 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_PIXEL )
486 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_GEOMETRY )
487 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_HULL )
488 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_DOMAIN )
489 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_COMPUTE )
490 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_AMPLIFICATION )
491 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_MESH )
492 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_RAY_GEN )
493 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_RAY_MISS )
494 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_RAY_CLOSEST_HIT )
495 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_RAY_ANY_HIT )
496 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_RAY_INTERSECTION)
497 RETURN_SHADER_TYPE_NAME(SHADER_TYPE_CALLABLE )
492498 #undef RETURN_SHADER_TYPE_NAME
493499 // clang-format on
494500
812818
813819 const Char* GetBindFlagString(Uint32 BindFlag)
814820 {
815 VERIFY((BindFlag & (BindFlag - 1)) == 0, "More than one bind flag specified");
821 VERIFY((BindFlag & (BindFlag - 1)) == 0, "More than one bind flag is specified");
822
823 static_assert(BIND_FLAGS_LAST == BIND_RAY_TRACING, "Please handle the new bind flag in the switch below");
816824 switch (BindFlag)
817825 {
818 // clang-format off
819 #define BIND_FLAG_STR_CASE(Flag) case Flag: return #Flag;
820 BIND_FLAG_STR_CASE( BIND_VERTEX_BUFFER )
821 BIND_FLAG_STR_CASE( BIND_INDEX_BUFFER )
822 BIND_FLAG_STR_CASE( BIND_UNIFORM_BUFFER )
823 BIND_FLAG_STR_CASE( BIND_SHADER_RESOURCE )
824 BIND_FLAG_STR_CASE( BIND_STREAM_OUTPUT )
825 BIND_FLAG_STR_CASE( BIND_RENDER_TARGET )
826 BIND_FLAG_STR_CASE( BIND_DEPTH_STENCIL )
827 BIND_FLAG_STR_CASE( BIND_UNORDERED_ACCESS )
828 BIND_FLAG_STR_CASE( BIND_INDIRECT_DRAW_ARGS )
829 #undef BIND_FLAG_STR_CASE
830 // clang-format on
826 #define BIND_FLAG_STR_CASE(Flag) \
827 case Flag: return #Flag;
828 BIND_FLAG_STR_CASE(BIND_VERTEX_BUFFER)
829 BIND_FLAG_STR_CASE(BIND_INDEX_BUFFER)
830 BIND_FLAG_STR_CASE(BIND_UNIFORM_BUFFER)
831 BIND_FLAG_STR_CASE(BIND_SHADER_RESOURCE)
832 BIND_FLAG_STR_CASE(BIND_STREAM_OUTPUT)
833 BIND_FLAG_STR_CASE(BIND_RENDER_TARGET)
834 BIND_FLAG_STR_CASE(BIND_DEPTH_STENCIL)
835 BIND_FLAG_STR_CASE(BIND_UNORDERED_ACCESS)
836 BIND_FLAG_STR_CASE(BIND_INDIRECT_DRAW_ARGS)
837 BIND_FLAG_STR_CASE(BIND_RAY_TRACING)
838 #undef BIND_FLAG_STR_CASE
831839 default: UNEXPECTED("Unexpected bind flag ", BindFlag); return "";
832840 }
833841 }
837845 if (BindFlags == 0)
838846 return "0";
839847 String Str;
840 for (Uint32 Flag = BIND_VERTEX_BUFFER; BindFlags && Flag <= BIND_INDIRECT_DRAW_ARGS; Flag <<= 1)
848 for (Uint32 Flag = 1; BindFlags && Flag <= BIND_FLAGS_LAST; Flag <<= 1)
841849 {
842850 if (BindFlags & Flag)
843851 {
860868 // clang-format off
861869 #define CPU_ACCESS_FLAG_STR_CASE(Flag) case Flag: return #Flag;
862870 CPU_ACCESS_FLAG_STR_CASE( CPU_ACCESS_READ )
863 CPU_ACCESS_FLAG_STR_CASE( CPU_ACCESS_WRITE )
871 CPU_ACCESS_FLAG_STR_CASE( CPU_ACCESS_WRITE )
864872 #undef CPU_ACCESS_FLAG_STR_CASE
865873 // clang-format on
866874 default: UNEXPECTED("Unexpected CPU access flag ", CPUAccessFlag); return "";
10241032 const Char* GetResourceStateFlagString(RESOURCE_STATE State)
10251033 {
10261034 VERIFY((State & (State - 1)) == 0, "Single state is expected");
1027 static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "Please update this function to handle the new resource state");
1035 static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "Please update this function to handle the new resource state");
10281036 switch (State)
10291037 {
10301038 // clang-format off
10461054 case RESOURCE_STATE_RESOLVE_SOURCE: return "RESOLVE_SOURCE";
10471055 case RESOURCE_STATE_INPUT_ATTACHMENT: return "INPUT_ATTACHMENT";
10481056 case RESOURCE_STATE_PRESENT: return "PRESENT";
1057 case RESOURCE_STATE_BUILD_AS_READ: return "BUILD_AS_READ";
1058 case RESOURCE_STATE_BUILD_AS_WRITE: return "BUILD_AS_WRITE";
1059 case RESOURCE_STATE_RAY_TRACING: return "RAY_TRACING";
10491060 // clang-format on
10501061 default:
10511062 UNEXPECTED("Unknown resource state");
10751086
10761087 const char* GetQueryTypeString(QUERY_TYPE QueryType)
10771088 {
1078 // clang-format off
1079 switch(QueryType)
1080 {
1089 static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled");
1090 switch (QueryType)
1091 {
1092 // clang-format off
10811093 case QUERY_TYPE_UNDEFINED: return "QUERY_TYPE_UNDEFINED";
10821094 case QUERY_TYPE_OCCLUSION: return "QUERY_TYPE_OCCLUSION";
10831095 case QUERY_TYPE_BINARY_OCCLUSION: return "QUERY_TYPE_BINARY_OCCLUSION";
10841096 case QUERY_TYPE_TIMESTAMP: return "QUERY_TYPE_TIMESTAMP";
10851097 case QUERY_TYPE_PIPELINE_STATISTICS: return "QUERY_TYPE_PIPELINE_STATISTICS";
10861098 case QUERY_TYPE_DURATION: return "QUERY_TYPE_DURATION";
1087
1088 static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled");
1089
1099 // clang-format on
10901100 default:
10911101 UNEXPECTED("Unepxected query type");
10921102 return "Unknown";
10931103 }
1094 // clang-format on
10951104 }
10961105
10971106 const char* GetSurfaceTransformString(SURFACE_TRANSFORM SrfTransform)
11221131
11231132 const char* GetPipelineTypeString(PIPELINE_TYPE PipelineType)
11241133 {
1125 // clang-format off
1134 static_assert(PIPELINE_TYPE_LAST == PIPELINE_TYPE_RAY_TRACING, "Please update this function to handle the new pipeline type");
11261135 switch (PipelineType)
11271136 {
1128 case PIPELINE_TYPE_COMPUTE: return "compute";
1129 case PIPELINE_TYPE_GRAPHICS: return "graphics";
1130 case PIPELINE_TYPE_MESH: return "mesh";
1131
1137 // clang-format off
1138 case PIPELINE_TYPE_COMPUTE: return "compute";
1139 case PIPELINE_TYPE_GRAPHICS: return "graphics";
1140 case PIPELINE_TYPE_MESH: return "mesh";
1141 case PIPELINE_TYPE_RAY_TRACING: return "ray tracing";
1142 // clang-format on
11321143 default:
11331144 UNEXPECTED("Unexpected pipeline type");
11341145 return "unknown";
11351146 }
1136 // clang-format on
11371147 }
11381148
11391149 const char* GetShaderCompilerTypeString(SHADER_COMPILER Compiler)
11401150 {
1151 static_assert(SHADER_COMPILER_LAST == SHADER_COMPILER_FXC, "Please update this function to handle the new shader compiler");
11411152 switch (Compiler)
11421153 {
1154 // clang-format off
11431155 case SHADER_COMPILER_DEFAULT: return "Default";
11441156 case SHADER_COMPILER_GLSLANG: return "glslang";
1145 case SHADER_COMPILER_DXC: return "DXC";
1146 case SHADER_COMPILER_FXC: return "FXC";
1147
1157 case SHADER_COMPILER_DXC: return "DXC";
1158 case SHADER_COMPILER_FXC: return "FXC";
1159 // clang-format on
11481160 default:
11491161 UNEXPECTED("Unexpected shader compiler");
11501162 return "UNKNOWN";
1151 };
1163 }
11521164 }
11531165
11541166 Uint32 ComputeMipLevelsCount(Uint32 Width)
11751187
11761188 bool VerifyResourceStates(RESOURCE_STATE State, bool IsTexture)
11771189 {
1178 static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "Please update this function to handle the new resource state");
1190 static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "Please update this function to handle the new resource state");
11791191
11801192 // clang-format off
11811193 #define VERIFY_EXCLUSIVE_STATE(ExclusiveState)\
11921204 VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_COPY_DEST);
11931205 VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_RESOLVE_DEST);
11941206 VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_PRESENT);
1207 VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_BUILD_AS_WRITE);
1208 VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_RAY_TRACING);
11951209 #undef VERIFY_EXCLUSIVE_STATE
11961210 // clang-format on
11971211
12871301
12881302 bool IsConsistentShaderType(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineType)
12891303 {
1290 static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type");
1304 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
12911305 switch (PipelineType)
12921306 {
12931307 case PIPELINE_TYPE_GRAPHICS:
13051319 ShaderType == SHADER_TYPE_MESH ||
13061320 ShaderType == SHADER_TYPE_PIXEL;
13071321
1322 case PIPELINE_TYPE_RAY_TRACING:
1323 return ShaderType == SHADER_TYPE_RAY_GEN ||
1324 ShaderType == SHADER_TYPE_RAY_MISS ||
1325 ShaderType == SHADER_TYPE_RAY_CLOSEST_HIT ||
1326 ShaderType == SHADER_TYPE_RAY_ANY_HIT ||
1327 ShaderType == SHADER_TYPE_RAY_INTERSECTION ||
1328 ShaderType == SHADER_TYPE_CALLABLE;
1329
13081330 default:
13091331 UNEXPECTED("Unexpected pipeline type");
13101332 return false;
13171339 " is inconsistent with pipeline type ", GetPipelineTypeString(PipelineType));
13181340 VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified");
13191341
1320 static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type");
1342 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
13211343 switch (ShaderType)
13221344 {
13231345 case SHADER_TYPE_UNKNOWN:
13261348 case SHADER_TYPE_VERTEX: // Graphics
13271349 case SHADER_TYPE_AMPLIFICATION: // Mesh
13281350 case SHADER_TYPE_COMPUTE: // Compute
1351 case SHADER_TYPE_RAY_GEN: // Ray tracing
13291352 return 0;
13301353
1331 case SHADER_TYPE_HULL: // Graphics
1332 case SHADER_TYPE_MESH: // Mesh
1354 case SHADER_TYPE_HULL: // Graphics
1355 case SHADER_TYPE_MESH: // Mesh
1356 case SHADER_TYPE_RAY_MISS: // RayTracing
13331357 return 1;
13341358
1335 case SHADER_TYPE_DOMAIN: // Graphics
1359 case SHADER_TYPE_DOMAIN: // Graphics
1360 case SHADER_TYPE_RAY_CLOSEST_HIT: // Ray tracing
13361361 return 2;
13371362
1338 case SHADER_TYPE_GEOMETRY: // Graphics
1363 case SHADER_TYPE_GEOMETRY: // Graphics
1364 case SHADER_TYPE_RAY_ANY_HIT: // Ray tracing
13391365 return 3;
13401366
1341 case SHADER_TYPE_PIXEL: // Graphics or Mesh
1367 case SHADER_TYPE_PIXEL: // Graphics or Mesh
1368 case SHADER_TYPE_RAY_INTERSECTION: // Ray tracing
13421369 return 4;
1370
1371 case SHADER_TYPE_CALLABLE: // RayTracing
1372 return 5;
13431373
13441374 default:
13451375 UNEXPECTED("Unexpected shader type (", ShaderType, ")");
13491379
13501380 SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineType)
13511381 {
1352 static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type");
1382 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
13531383 switch (PipelineType)
13541384 {
13551385 case PIPELINE_TYPE_GRAPHICS:
13851415
13861416 default:
13871417 UNEXPECTED("Index ", Index, " is not a valid mesh pipeline shader index");
1418 return SHADER_TYPE_UNKNOWN;
1419 }
1420
1421 case PIPELINE_TYPE_RAY_TRACING:
1422 switch (Index)
1423 {
1424 case 0: return SHADER_TYPE_RAY_GEN;
1425 case 1: return SHADER_TYPE_RAY_MISS;
1426 case 2: return SHADER_TYPE_RAY_CLOSEST_HIT;
1427 case 3: return SHADER_TYPE_RAY_ANY_HIT;
1428 case 4: return SHADER_TYPE_RAY_INTERSECTION;
1429 case 5: return SHADER_TYPE_CALLABLE;
1430
1431 default:
1432 UNEXPECTED("Index ", Index, " is not a valid ray tracing pipeline shader index");
13881433 return SHADER_TYPE_UNKNOWN;
13891434 }
13901435
1313 include/EngineMemory.h
1414 include/FenceBase.hpp
1515 include/FramebufferBase.hpp
16 include/pch.h
1716 include/PipelineStateBase.hpp
1817 include/QueryBase.hpp
1918 include/RenderDeviceBase.hpp
2726 include/SwapChainBase.hpp
2827 include/TextureBase.hpp
2928 include/TextureViewBase.hpp
29 include/BottomLevelASBase.hpp
30 include/TopLevelASBase.hpp
31 include/ShaderBindingTableBase.hpp
3032 )
3133
3234 set(INTERFACE
5759 interface/SwapChain.h
5860 interface/Texture.h
5961 interface/TextureView.h
62 interface/BottomLevelAS.h
63 interface/TopLevelAS.h
64 interface/ShaderBindingTable.h
6065 )
6166
6267 set(SOURCE
6368 src/APIInfo.cpp
69 src/BottomLevelASBase.cpp
6470 src/BufferBase.cpp
6571 src/DefaultShaderSourceStreamFactory.cpp
72 src/DeviceContextBase.cpp
6673 src/EngineMemory.cpp
6774 src/FramebufferBase.cpp
6875 src/PipelineStateBase.cpp
6976 src/ResourceMappingBase.cpp
77 src/ShaderBindingTableBase.cpp
7078 src/RenderPassBase.cpp
7179 src/TextureBase.cpp
80 src/TopLevelASBase.cpp
7281 )
7382
7483 add_library(Diligent-GraphicsEngine STATIC ${SOURCE} ${INTERFACE} ${INCLUDE})
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Implementation of the Diligent::BottomLevelASBase template class
31
32 #include <unordered_map>
33 #include <atomic>
34
35 #include "BottomLevelAS.h"
36 #include "DeviceObjectBase.hpp"
37 #include "RenderDeviceBase.hpp"
38 #include "FixedLinearAllocator.hpp"
39 #include "HashUtils.hpp"
40
41 namespace Diligent
42 {
43
44 struct BLASGeomIndex
45 {
46 Uint32 IndexInDesc = INVALID_INDEX; // geometry index in description
47 Uint32 ActualIndex = INVALID_INDEX; // geometry index in build operation
48
49 BLASGeomIndex() {}
50 BLASGeomIndex(Uint32 _IndexInDesc, Uint32 _ActualIndex) :
51 IndexInDesc{_IndexInDesc}, ActualIndex{_ActualIndex} {}
52 };
53 using BLASNameToIndex = std::unordered_map<HashMapStringKey, BLASGeomIndex, HashMapStringKey::Hasher>;
54
55 /// Validates bottom-level AS description and throws and exception in case of an error.
56 void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false);
57
58 /// Copies bottom-level AS geometry description using MemPool to allocate required dynamic space.
59 void CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc,
60 BottomLevelASDesc& DstDesc,
61 FixedLinearAllocator& MemPool,
62 const BLASNameToIndex* pSrcNameToIndex,
63 BLASNameToIndex& DstNameToIndex) noexcept(false);
64
65
66 /// Template class implementing base functionality for a bottom-level acceleration structure object.
67
68 /// \tparam BaseInterface - base interface that this class will inheret
69 /// (Diligent::IBottomLevelASD3D12 or Diligent::IBottomLevelASVk).
70 /// \tparam RenderDeviceImplType - type of the render device implementation
71 /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl)
72 template <class BaseInterface, class RenderDeviceImplType>
73 class BottomLevelASBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, BottomLevelASDesc>
74 {
75 public:
76 using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, BottomLevelASDesc>;
77
78 /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS.
79 /// \param pDevice - pointer to the device.
80 /// \param Desc - BLAS description.
81 /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and
82 /// must not keep a strong reference to the device.
83 BottomLevelASBase(IReferenceCounters* pRefCounters,
84 RenderDeviceImplType* pDevice,
85 const BottomLevelASDesc& Desc,
86 bool bIsDeviceInternal = false) :
87 TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
88 {
89 ValidateBottomLevelASDesc(this->m_Desc);
90
91 if (Desc.CompactedSize > 0)
92 {
93 }
94 else
95 {
96 CopyGeometryDescriptionUnsafe(Desc, nullptr);
97 }
98 }
99
100 ~BottomLevelASBase()
101 {
102 ClearGeometry();
103 }
104
105 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase)
106
107 // Maps geometry that was used in build operation to geometry description.
108 // Returns the geometry index in geometry description.
109 Uint32 UpdateGeometryIndex(const char* Name, Uint32& ActualIndex, bool OnUpdate)
110 {
111 VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
112
113 auto iter = m_NameToIndex.find(Name);
114 if (iter != m_NameToIndex.end())
115 {
116 if (OnUpdate)
117 ActualIndex = iter->second.ActualIndex;
118 else
119 iter->second.ActualIndex = ActualIndex;
120 return iter->second.IndexInDesc;
121 }
122 LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\'');
123 return INVALID_INDEX;
124 }
125
126 virtual Uint32 DILIGENT_CALL_TYPE GetGeometryDescIndex(const char* Name) const override final
127 {
128 VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
129
130 auto iter = m_NameToIndex.find(Name);
131 if (iter != m_NameToIndex.end())
132 return iter->second.IndexInDesc;
133
134 LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\'');
135 return INVALID_INDEX;
136 }
137
138 virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final
139 {
140 VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
141
142 auto iter = m_NameToIndex.find(Name);
143 if (iter != m_NameToIndex.end())
144 {
145 VERIFY(iter->second.ActualIndex != INVALID_INDEX, "Geometry with name '", Name, "', exists but was not enabled during last build");
146 return iter->second.ActualIndex;
147 }
148 LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\'');
149 return INVALID_INDEX;
150 }
151
152 virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
153 {
154 VERIFY(State == RESOURCE_STATE_UNKNOWN || State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE,
155 "Unsupported state for a bottom-level acceleration structure");
156 this->m_State = State;
157 }
158
159 virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final
160 {
161 return this->m_State;
162 }
163
164 /// Implementation of IBottomLevelAS::GetScratchBufferSizes()
165 virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override final
166 {
167 return this->m_ScratchSize;
168 }
169
170 bool IsInKnownState() const
171 {
172 return this->m_State != RESOURCE_STATE_UNKNOWN;
173 }
174
175 bool CheckState(RESOURCE_STATE State) const
176 {
177 VERIFY((State & (State - 1)) == 0, "Single state is expected");
178 VERIFY(IsInKnownState(), "BLAS state is unknown");
179 return (this->m_State & State) == State;
180 }
181
182 #ifdef DILIGENT_DEVELOPMENT
183 void UpdateVersion()
184 {
185 this->m_DbgVersion.fetch_add(1);
186 }
187
188 Uint32 GetVersion() const
189 {
190 return this->m_DbgVersion.load();
191 }
192 #endif // DILIGENT_DEVELOPMENT
193
194 void CopyGeometryDescription(const BottomLevelASBase& SrcBLAS) noexcept
195 {
196 ClearGeometry();
197
198 try
199 {
200 CopyGeometryDescriptionUnsafe(SrcBLAS.GetDesc(), &SrcBLAS.m_NameToIndex);
201 }
202 catch (...)
203 {
204 ClearGeometry();
205 }
206 }
207
208 void SetActualGeometryCount(Uint32 Count)
209 {
210 m_GeometryCount = Count;
211 }
212
213 virtual Uint32 DILIGENT_CALL_TYPE GetActualGeometryCount() const override final
214 {
215 return m_GeometryCount;
216 }
217
218 private:
219 void CopyGeometryDescriptionUnsafe(const BottomLevelASDesc& SrcDesc, const BLASNameToIndex* pSrcNameToIndex) noexcept(false)
220 {
221 FixedLinearAllocator MemPool{GetRawAllocator()};
222 CopyBLASGeometryDesc(SrcDesc, this->m_Desc, MemPool, pSrcNameToIndex, this->m_NameToIndex);
223 this->m_pRawPtr = MemPool.Release();
224 }
225
226 void ClearGeometry() noexcept
227 {
228 if (this->m_pRawPtr != nullptr)
229 {
230 GetRawAllocator().Free(this->m_pRawPtr);
231 this->m_pRawPtr = nullptr;
232 }
233
234 // Keep Name, Flags, CompactedSize, CommandQueueMask
235 this->m_Desc.pTriangles = nullptr;
236 this->m_Desc.TriangleCount = 0;
237 this->m_Desc.pBoxes = nullptr;
238 this->m_Desc.BoxCount = 0;
239
240 m_NameToIndex.clear();
241 }
242
243 protected:
244 RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
245 BLASNameToIndex m_NameToIndex;
246 void* m_pRawPtr = nullptr;
247 Uint32 m_GeometryCount = 0;
248 ScratchBufferSizes m_ScratchSize;
249
250 #ifdef DILIGENT_DEVELOPMENT
251 std::atomic<Uint32> m_DbgVersion{0};
252 #endif
253 };
254
255 } // namespace Diligent
4141 namespace Diligent
4242 {
4343
44 void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData);
45 void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps);
44 /// Validates buffer description and throws an exception in case of an error.
45 void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) noexcept(false);
46
47 /// Validates initial buffer data parameters and throws an exception in case of an error.
48 void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) noexcept(false);
49
50 /// Validates and corrects buffer view description; throws an exception in case of an error.
51 void ValidateAndCorrectBufferViewDesc(const BufferDesc& BuffDesc, BufferViewDesc& ViewDesc) noexcept(false);
52
4653
4754 /// Template class implementing base functionality for a buffer object
4855
9299
93100 /// Implementation of IBuffer::CreateView(); calls CreateViewInternal() virtual function
94101 /// that creates buffer view for the specific engine implementation.
95 virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override;
102 virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override
103 {
104 DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified");
105 if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE)
106 DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag");
107 else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS)
108 DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag");
109 else
110 UNEXPECTED("Unexpected buffer view type");
111
112 CreateViewInternal(ViewDesc, ppView, false);
113 }
114
96115
97116 /// Implementation of IBuffer::GetDefaultView().
98 virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override;
117 virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override
118 {
119 switch (ViewType)
120 {
121 case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get();
122 case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get();
123 default: UNEXPECTED("Unknown view type"); return nullptr;
124 }
125 }
126
99127
100128 /// Creates default buffer views.
101129
104132 /// - Creates default unordered access view addressing the entire buffer if Diligent::BIND_UNORDERED_ACCESS flag is set
105133 ///
106134 /// The function calls CreateViewInternal().
107 void CreateDefaultViews();
135 void CreateDefaultViews()
136 {
137 // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so
138 // cannot create views.
139
140 auto CreateDefaultView = [&](BUFFER_VIEW_TYPE ViewType) //
141 {
142 BufferViewDesc ViewDesc;
143 ViewDesc.ViewType = ViewType;
144
145 std::string ViewName;
146 switch (ViewType)
147 {
148 case BUFFER_VIEW_UNORDERED_ACCESS:
149 ViewName = "Default UAV of buffer '";
150 break;
151
152 case BUFFER_VIEW_SHADER_RESOURCE:
153 ViewName = "Default SRV of buffer '";
154 break;
155
156 default:
157 UNEXPECTED("Unexpected buffer view type");
158 }
159
160 ViewName += this->m_Desc.Name;
161 ViewName += '\'';
162 ViewDesc.Name = ViewName.c_str();
163
164 IBufferView* pView = nullptr;
165 CreateViewInternal(ViewDesc, &pView, true);
166 VERIFY(pView != nullptr, "Failed to create default view for buffer '", this->m_Desc.Name, "'");
167 VERIFY(pView->GetDesc().ViewType == ViewType, "Unexpected view type");
168
169 return static_cast<BufferViewImplType*>(pView);
170 };
171
172 if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW))
173 {
174 m_pDefaultUAV.reset(CreateDefaultView(BUFFER_VIEW_UNORDERED_ACCESS));
175 }
176
177 if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW))
178 {
179 m_pDefaultSRV.reset(CreateDefaultView(BUFFER_VIEW_SHADER_RESOURCE));
180 }
181 }
108182
109183 virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
110184 {
132206 /// Pure virtual function that creates buffer view for the specific engine implementation.
133207 virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) = 0;
134208
135 /// Corrects buffer view description and validates view parameters.
136 void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc);
137
138209 #ifdef DILIGENT_DEBUG
139210 TBuffViewObjAllocator& m_dbgBuffViewAllocator;
140211 #endif
148219 std::unique_ptr<BufferViewImplType, STDDeleter<BufferViewImplType, TBuffViewObjAllocator>> m_pDefaultSRV;
149220 };
150221
151
152
153
154 template <class BaseInterface, class RenderDeviceImplType, class BufferViewImplType, class TBuffViewObjAllocator>
155 void BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffViewObjAllocator>::CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView)
156 {
157 DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified");
158 if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE)
159 DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag");
160 else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS)
161 DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag");
162 else
163 UNEXPECTED("Unexpected buffer view type");
164
165 CreateViewInternal(ViewDesc, ppView, false);
166 }
167
168
169 template <class BaseInterface, class RenderDeviceImplType, class BufferViewImplType, class TBuffViewObjAllocator>
170 void BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffViewObjAllocator>::CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc)
171 {
172 if (ViewDesc.ByteWidth == 0)
173 {
174 DEV_CHECK_ERR(this->m_Desc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", this->m_Desc.uiSizeInBytes, ")");
175 ViewDesc.ByteWidth = this->m_Desc.uiSizeInBytes - ViewDesc.ByteOffset;
176 }
177 if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > this->m_Desc.uiSizeInBytes)
178 LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", this->m_Desc.uiSizeInBytes, ").");
179 if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) ||
180 (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE))
181 {
182 if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED)
183 {
184 VERIFY(this->m_Desc.ElementByteStride != 0, "Element byte stride is zero");
185 if ((ViewDesc.ByteOffset % this->m_Desc.ElementByteStride) != 0)
186 LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ").");
187 if ((ViewDesc.ByteWidth % this->m_Desc.ElementByteStride) != 0)
188 LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ").");
189 }
190
191 if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED)
192 LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer");
193
194 if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED || (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED))
195 {
196 if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4)
197 LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values");
198 if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16)
199 ViewDesc.Format.IsNormalized = false;
200 auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents};
201 if (this->m_Desc.Mode == BUFFER_MODE_RAW && this->m_Desc.ElementByteStride == 0)
202 LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization");
203 if (ViewElementStride != this->m_Desc.ElementByteStride)
204 LOG_ERROR_AND_THROW("Buffer element byte stride (", this->m_Desc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')');
205 }
206
207 if (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED)
208 {
209 if ((ViewDesc.ByteOffset % 16) != 0)
210 LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes");
211 }
212 }
213 }
214
215 template <class BaseInterface, class RenderDeviceImplType, class BufferViewImplType, class TBuffViewObjAllocator>
216 IBufferView* BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffViewObjAllocator>::GetDefaultView(BUFFER_VIEW_TYPE ViewType)
217 {
218 switch (ViewType)
219 {
220 case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get();
221 case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get();
222 default: UNEXPECTED("Unknown view type"); return nullptr;
223 }
224 }
225
226 template <class BaseInterface, class RenderDeviceImplType, class BufferViewImplType, class TBuffViewObjAllocator>
227 void BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffViewObjAllocator>::CreateDefaultViews()
228 {
229 // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so
230 // cannot create views.
231
232 if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW))
233 {
234 BufferViewDesc ViewDesc;
235 ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS;
236 auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\'');
237 ViewDesc.Name = UAVName.c_str();
238
239 IBufferView* pUAV = nullptr;
240 CreateViewInternal(ViewDesc, &pUAV, true);
241 m_pDefaultUAV.reset(static_cast<BufferViewImplType*>(pUAV));
242 VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type");
243 }
244
245 if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW))
246 {
247 BufferViewDesc ViewDesc;
248 ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE;
249 auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\'');
250 ViewDesc.Name = SRVName.c_str();
251
252 IBufferView* pSRV = nullptr;
253 CreateViewInternal(ViewDesc, &pSRV, true);
254 m_pDefaultSRV.reset(static_cast<BufferViewImplType*>(pSRV));
255 VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type");
256 }
257 }
258
259222 } // namespace Diligent
4444 namespace Diligent
4545 {
4646
47 // clang-format off
48 bool VerifyDrawAttribs (const DrawAttribs& Attribs);
49 bool VerifyDrawIndexedAttribs (const DrawIndexedAttribs& Attribs);
50 bool VerifyDrawIndirectAttribs (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
51 bool VerifyDrawIndexedIndirectAttribs(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
52
53 bool VerifyDispatchComputeAttribs (const DispatchComputeAttribs& Attribs);
54 bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
55 // clang-format on
56
57 bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs);
58 bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
59
60 bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs,
61 const TextureDesc& SrcTexDesc,
62 const TextureDesc& DstTexDesc);
63
64 bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs);
65 bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier);
66
67 bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs);
68 bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs);
69 bool VerifyCopyBLASAttribs(const IRenderDevice* pDevice, const CopyBLASAttribs& Attribs);
70 bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs);
71 bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs);
72 bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs);
73 bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs);
74
75
76
4777 /// Describes input vertex stream
4878 template <typename BufferImplType>
4979 struct VertexStreamInfo
5282
5383 /// Strong reference to the buffer object
5484 RefCntAutoPtr<BufferImplType> pBuffer;
55 Uint32 Offset = 0; ///< Offset in bytes
85
86 /// Offset in bytes
87 Uint32 Offset = 0;
5688 };
5789
5890 /// Base implementation of the device context.
6193 /// \tparam ImplementationTraits - implementation traits that define specific implementation details
6294 /// (texture implemenation type, buffer implementation type, etc.)
6395 /// \remarks Device context keeps strong references to all objects currently bound to
64 /// the pipeline: buffers, states, samplers, shaders, etc.
96 /// the pipeline: buffers, tetxures, states, SRBs, etc.
6597 /// The context also keeps strong references to the device and
6698 /// the swap chain.
6799 template <typename BaseInterface, typename ImplementationTraits>
77109 using QueryImplType = typename ImplementationTraits::QueryType;
78110 using FramebufferImplType = typename ImplementationTraits::FramebufferType;
79111 using RenderPassImplType = typename ImplementationTraits::RenderPassType;
80
81 /// \param pRefCounters - reference counters object that controls the lifetime of this device context.
112 using BottomLevelASType = typename ImplementationTraits::BottomLevelASType;
113 using TopLevelASType = typename ImplementationTraits::TopLevelASType;
114
115 /// \param pRefCounters - reference counters object that controls the lifetime of this device context.
82116 /// \param pRenderDevice - render device.
83 /// \param bIsDeferred - flag indicating if this instance is a deferred context
117 /// \param bIsDeferred - flag indicating if this instance is a deferred context
84118 DeviceContextBase(IReferenceCounters* pRefCounters, DeviceImplType* pRenderDevice, bool bIsDeferred) :
85119 // clang-format off
86120 TObjectBase {pRefCounters },
113147 int);
114148
115149 /// Base implementation of IDeviceContext::SetIndexBuffer(); caches the strong reference to the index buffer
116 inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0;
150 inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer,
151 Uint32 ByteOffset,
152 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0;
117153
118154 /// Caches the viewports
119155 inline void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight);
250286
251287 #ifdef DILIGENT_DEVELOPMENT
252288 // clang-format off
253 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const;
254 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const;
255 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const;
256 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
257 bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
258 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
259
260 bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const;
261 bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
262
263 void DvpVerifyRenderTargets()const;
264 void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const;
265 bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const;
266 bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const;
289 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs) const;
290 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs) const;
291 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs) const;
292 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
293 bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
294 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
295
296 bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs) const;
297 bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
298
299 bool DvpVerifyRenderTargets() const;
300 bool DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const;
301 bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const;
302 bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const;
303 bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const;
304 bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const;
267305 #else
268306 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
269307 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
275313 bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;}
276314 bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
277315
278 void DvpVerifyRenderTargets()const {}
279 void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {}
280 bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
281 bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
316 bool DvpVerifyRenderTargets()const {return true;}
317 bool DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {return true;}
318 bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
319 bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
320 bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
321 bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
282322 // clang-format on
283323 #endif
324
325 bool BuildBLAS(const BuildBLASAttribs& Attribs, int) const;
326 bool BuildTLAS(const BuildTLASAttribs& Attribs, int) const;
327 bool CopyBLAS(const CopyBLASAttribs& Attribs, int) const;
328 bool CopyTLAS(const CopyTLASAttribs& Attribs, int) const;
329 bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const;
330 bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const;
331 bool TraceRays(const TraceRaysAttribs& Attribs, int) const;
284332
285333 /// Strong reference to the device.
286334 RefCntAutoPtr<DeviceImplType> m_pDevice;
367415
368416
369417 template <typename BaseInterface, typename ImplementationTraits>
370 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
371 SetVertexBuffers(Uint32 StartSlot,
372 Uint32 NumBuffersSet,
373 IBuffer** ppBuffers,
374 Uint32* pOffsets,
375 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
376 SET_VERTEX_BUFFERS_FLAGS Flags)
418 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetVertexBuffers(
419 Uint32 StartSlot,
420 Uint32 NumBuffersSet,
421 IBuffer** ppBuffers,
422 Uint32* pOffsets,
423 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
424 SET_VERTEX_BUFFERS_FLAGS Flags)
377425 {
378426 #ifdef DILIGENT_DEVELOPMENT
379427 if (StartSlot >= MAX_BUFFER_SLOTS)
428476 }
429477
430478 template <typename BaseInterface, typename ImplementationTraits>
431 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
432 SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/)
479 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetPipelineState(
480 PipelineStateImplType* pPipelineState,
481 int /*Dummy*/)
433482 {
434483 m_pPipelineState = pPipelineState;
435484 }
436485
437486 template <typename BaseInterface, typename ImplementationTraits>
438 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
439 CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int)
487 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::CommitShaderResources(
488 IShaderResourceBinding* pShaderResourceBinding,
489 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
490 int)
440491 {
441492 #ifdef DILIGENT_DEVELOPMENT
442493 VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION),
458509 }
459510 }
460511 #endif
512
461513 return true;
462514 }
463515
471523 }
472524
473525 template <typename BaseInterface, typename ImplementationTraits>
474 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
475 SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
526 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetIndexBuffer(
527 IBuffer* pIndexBuffer,
528 Uint32 ByteOffset,
529 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
476530 {
477531 m_pIndexBuffer = ValidatedCast<BufferImplType>(pIndexBuffer);
478532 m_IndexDataStartOffset = ByteOffset;
537591 }
538592
539593 template <typename BaseInterface, typename ImplementationTraits>
540 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
541 SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight)
594 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetViewports(
595 Uint32 NumViewports,
596 const Viewport* pViewports,
597 Uint32& RTWidth,
598 Uint32& RTHeight)
542599 {
543600 if (RTWidth == 0 || RTHeight == 0)
544601 {
577634 }
578635
579636 template <typename BaseInterface, typename ImplementationTraits>
580 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
581 SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight)
637 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetScissorRects(
638 Uint32 NumRects,
639 const Rect* pRects,
640 Uint32& RTWidth,
641 Uint32& RTHeight)
582642 {
583643 if (RTWidth == 0 || RTHeight == 0)
584644 {
598658 }
599659
600660 template <typename BaseInterface, typename ImplementationTraits>
601 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
602 SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil)
661 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::SetRenderTargets(
662 Uint32 NumRenderTargets,
663 ITextureView* ppRenderTargets[],
664 ITextureView* pDepthStencil)
603665 {
604666 if (NumRenderTargets == 0 && pDepthStencil == nullptr)
605667 {
775837
776838
777839 template <typename BaseInterface, typename ImplementationTraits>
778 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
779 GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV)
840 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::GetRenderTargets(
841 Uint32& NumRenderTargets,
842 ITextureView** ppRTVs,
843 ITextureView** ppDSV)
780844 {
781845 NumRenderTargets = m_NumBoundRenderTargets;
782846
9551019 {
9561020 VERIFY(m_pActiveRenderPass == nullptr, "Attempting to begin render pass while another render pass ('", m_pActiveRenderPass->GetDesc().Name, "') is active.");
9571021 VERIFY(m_pBoundFramebuffer == nullptr, "Attempting to begin render pass while another framebuffer ('", m_pBoundFramebuffer->GetDesc().Name, "') is bound.");
958 VERIFY(Attribs.pRenderPass != nullptr, "Render pass must not be null");
959 VERIFY(Attribs.pFramebuffer != nullptr, "Framebuffer must not be null");
960 #ifdef DILIGENT_DEBUG
961 {
962 const auto& RPDesc = Attribs.pRenderPass->GetDesc();
963
964 Uint32 NumRequiredClearValues = 0;
965 for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i)
966 {
967 const auto& Attchmnt = RPDesc.pAttachments[i];
968 if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR)
969 NumRequiredClearValues = i + 1;
970
971 const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format);
972 if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
973 {
974 if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR)
975 NumRequiredClearValues = i + 1;
976 }
977 }
978 VERIFY(Attribs.ClearValueCount >= NumRequiredClearValues,
979 "Begin render pass operation requiers at least ", NumRequiredClearValues,
980 " clear values, but only ", Attribs.ClearValueCount, " are given.");
981 VERIFY(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr,
982 "pClearValues must not be null when ClearValueCount is not zero");
983 }
984 #endif
1022
1023 VerifyBeginRenderPassAttribs(Attribs);
9851024
9861025 // Reset current render targets (in Vulkan backend, this may end current render pass).
9871026 ResetRenderTargets();
10221061 m_pBoundFramebuffer = pNewFramebuffer;
10231062 m_SubpassIndex = 0;
10241063 m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode;
1064
10251065 UpdateAttachmentStates(m_SubpassIndex);
10261066 SetSubpassRenderTargets();
10271067 }
11961236 return false;
11971237 }
11981238
1239 #ifdef DILIGENT_DEVELOPMENT
11991240 if (m_bIsDeferred)
12001241 {
12011242 LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: Deferred contexts do not support queries");
12071248 LOG_ERROR_MESSAGE("BeginQuery() is disabled for timestamp queries. Call EndQuery() to set the timestamp.");
12081249 return false;
12091250 }
1251 #endif
12101252
12111253 if (!ValidatedCast<QueryImplType>(pQuery)->OnBeginQuery(this))
12121254 return false;
12231265 return false;
12241266 }
12251267
1268 #ifdef DILIGENT_DEVELOPMENT
12261269 if (m_bIsDeferred)
12271270 {
12281271 LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: Deferred contexts do not support queries");
12291272 return false;
12301273 }
1274 #endif
12311275
12321276 if (!ValidatedCast<QueryImplType>(pQuery)->OnEndQuery(this))
12331277 return false;
12361280 }
12371281
12381282 template <typename BaseInterface, typename ImplementationTraits>
1239 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1240 UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
1283 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UpdateBuffer(
1284 IBuffer* pBuffer,
1285 Uint32 Offset,
1286 Uint32 Size,
1287 const void* pData,
1288 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
12411289 {
12421290 VERIFY(pBuffer != nullptr, "Buffer must not be null");
12431291 VERIFY(m_pActiveRenderPass == nullptr, "UpdateBuffer command must be used outside of render pass.");
12521300 }
12531301
12541302 template <typename BaseInterface, typename ImplementationTraits>
1255 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1256 CopyBuffer(IBuffer* pSrcBuffer,
1257 Uint32 SrcOffset,
1258 RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
1259 IBuffer* pDstBuffer,
1260 Uint32 DstOffset,
1261 Uint32 Size,
1262 RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
1303 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBuffer(
1304 IBuffer* pSrcBuffer,
1305 Uint32 SrcOffset,
1306 RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
1307 IBuffer* pDstBuffer,
1308 Uint32 DstOffset,
1309 Uint32 Size,
1310 RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
12631311 {
12641312 VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null");
12651313 VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null");
12751323 }
12761324
12771325 template <typename BaseInterface, typename ImplementationTraits>
1278 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1279 MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
1326 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::MapBuffer(
1327 IBuffer* pBuffer,
1328 MAP_TYPE MapType,
1329 MAP_FLAGS MapFlags,
1330 PVoid& pMappedData)
12801331 {
12811332 VERIFY(pBuffer, "pBuffer must not be null");
12821333
13301381 }
13311382
13321383 template <typename BaseInterface, typename ImplementationTraits>
1333 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1334 UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
1384 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
13351385 {
13361386 VERIFY(pBuffer, "pBuffer must not be null");
13371387 #ifdef DILIGENT_DEBUG
13461396
13471397
13481398 template <typename BaseInterface, typename ImplementationTraits>
1349 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1350 UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
1399 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UpdateTexture(
1400 ITexture* pTexture,
1401 Uint32 MipLevel,
1402 Uint32 Slice,
1403 const Box& DstBox,
1404 const TextureSubResData& SubresData,
1405 RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
1406 RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
13511407 {
13521408 VERIFY(pTexture != nullptr, "pTexture must not be null");
13531409 VERIFY(m_pActiveRenderPass == nullptr, "UpdateTexture command must be used outside of render pass.");
1410
13541411 ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData);
13551412 }
13561413
13571414 template <typename BaseInterface, typename ImplementationTraits>
1358 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1359 CopyTexture(const CopyTextureAttribs& CopyAttribs)
1415 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTexture(const CopyTextureAttribs& CopyAttribs)
13601416 {
13611417 VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null");
13621418 VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null");
13631419 VERIFY(m_pActiveRenderPass == nullptr, "CopyTexture command must be used outside of render pass.");
1420
13641421 ValidateCopyTextureParams(CopyAttribs);
13651422 }
13661423
13671424 template <typename BaseInterface, typename ImplementationTraits>
1368 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1369 MapTextureSubresource(ITexture* pTexture,
1370 Uint32 MipLevel,
1371 Uint32 ArraySlice,
1372 MAP_TYPE MapType,
1373 MAP_FLAGS MapFlags,
1374 const Box* pMapRegion,
1375 MappedTextureSubresource& MappedData)
1425 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::MapTextureSubresource(
1426 ITexture* pTexture,
1427 Uint32 MipLevel,
1428 Uint32 ArraySlice,
1429 MAP_TYPE MapType,
1430 MAP_FLAGS MapFlags,
1431 const Box* pMapRegion,
1432 MappedTextureSubresource& MappedData)
13761433 {
13771434 VERIFY(pTexture, "pTexture must not be null");
13781435 ValidateMapTextureParams(pTexture->GetDesc(), MipLevel, ArraySlice, MapType, MapFlags, pMapRegion);
13791436 }
13801437
13811438 template <typename BaseInterface, typename ImplementationTraits>
1382 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1383 UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice)
1439 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UnmapTextureSubresource(
1440 ITexture* pTexture,
1441 Uint32 MipLevel,
1442 Uint32 ArraySlice)
13841443 {
13851444 VERIFY(pTexture, "pTexture must not be null");
13861445 DEV_CHECK_ERR(MipLevel < pTexture->GetDesc().MipLevels, "Mip level is out of range");
13881447 }
13891448
13901449 template <typename BaseInterface, typename ImplementationTraits>
1391 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1392 GenerateMips(ITextureView* pTexView)
1450 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::GenerateMips(ITextureView* pTexView)
13931451 {
13941452 VERIFY(pTexView != nullptr, "pTexView must not be null");
13951453 VERIFY(m_pActiveRenderPass == nullptr, "GenerateMips command must be used outside of render pass.");
14061464
14071465
14081466 template <typename BaseInterface, typename ImplementationTraits>
1409 void DeviceContextBase<BaseInterface, ImplementationTraits>::
1410 ResolveTextureSubresource(ITexture* pSrcTexture,
1411 ITexture* pDstTexture,
1412 const ResolveTextureSubresourceAttribs& ResolveAttribs)
1413 {
1414 #ifdef DILIGENT_DEVELOPMENT
1467 void DeviceContextBase<BaseInterface, ImplementationTraits>::ResolveTextureSubresource(
1468 ITexture* pSrcTexture,
1469 ITexture* pDstTexture,
1470 const ResolveTextureSubresourceAttribs& ResolveAttribs)
1471 {
1472 #ifdef DILIGENT_DEVELOPMENT
1473 VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass.");
1474
14151475 VERIFY_EXPR(pSrcTexture != nullptr && pDstTexture != nullptr);
14161476 const auto& SrcTexDesc = pSrcTexture->GetDesc();
14171477 const auto& DstTexDesc = pDstTexture->GetDesc();
1418 DEV_CHECK_ERR(SrcTexDesc.SampleCount > 1,
1419 "Source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled");
1420 DEV_CHECK_ERR(DstTexDesc.SampleCount == 1,
1421 "Destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled");
1422 auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel);
1423 auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel);
1424 DEV_CHECK_ERR(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight,
1425 "The size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight,
1426 ") of the source subresource of a resolve operation (texture '",
1427 SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice,
1428 ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight,
1429 ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ",
1430 ResolveAttribs.DstSlice, ")");
1431
1432 const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
1433 const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
1434 const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format);
1435 if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless)
1436 {
1437 DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format,
1438 "Source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name,
1439 ") texture formats of a resolve operation must match exaclty or be compatible typeless formats");
1440 DEV_CHECK_ERR(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation");
1441 }
1442 if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless)
1443 {
1444 DEV_CHECK_ERR(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN,
1445 "Format of a resolve operation must not be unknown when both src and dst texture formats are typeless");
1446 }
1447 if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless)
1448 {
1449 DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless,
1450 "Format of a resolve operation must not be typeless when one of the texture formats is typeless");
1451 }
1452 VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass.");
1453 #endif
1454 }
1455
1456 #ifdef DILIGENT_DEVELOPMENT
1457 template <typename BaseInterface, typename ImplementationTraits>
1458 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1459 DvpVerifyDrawArguments(const DrawAttribs& Attribs) const
1478
1479 VerifyResolveTextureSubresourceAttribs(ResolveAttribs, SrcTexDesc, DstTexDesc);
1480 #endif
1481 }
1482
1483
1484 template <typename BaseInterface, typename ImplementationTraits>
1485 bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BuildBLASAttribs& Attribs, int) const
1486 {
1487 #ifdef DILIGENT_DEVELOPMENT
1488 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1489 {
1490 LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device");
1491 return false;
1492 }
1493
1494 if (m_pActiveRenderPass != nullptr)
1495 {
1496 LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass");
1497 return false;
1498 }
1499
1500 if (!VerifyBuildBLASAttribs(Attribs))
1501 return false;
1502 #endif
1503
1504 return true;
1505 }
1506
1507 template <typename BaseInterface, typename ImplementationTraits>
1508 bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const BuildTLASAttribs& Attribs, int) const
1509 {
1510 #ifdef DILIGENT_DEVELOPMENT
1511 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1512 {
1513 LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device");
1514 return false;
1515 }
1516
1517 if (m_pActiveRenderPass != nullptr)
1518 {
1519 LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass");
1520 return false;
1521 }
1522
1523 if (!VerifyBuildTLASAttribs(Attribs))
1524 return false;
1525 #endif
1526
1527 return true;
1528 }
1529
1530 template <typename BaseInterface, typename ImplementationTraits>
1531 bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) const
1532 {
1533 #ifdef DILIGENT_DEVELOPMENT
1534 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1535 {
1536 LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device");
1537 return false;
1538 }
1539
1540 if (m_pActiveRenderPass != nullptr)
1541 {
1542 LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass");
1543 return false;
1544 }
1545
1546 if (!VerifyCopyBLASAttribs(m_pDevice, Attribs))
1547 return false;
1548 #endif
1549
1550 return true;
1551 }
1552
1553 template <typename BaseInterface, typename ImplementationTraits>
1554 bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) const
1555 {
1556 #ifdef DILIGENT_DEVELOPMENT
1557 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1558 {
1559 LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device");
1560 return false;
1561 }
1562
1563 if (m_pActiveRenderPass != nullptr)
1564 {
1565 LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass");
1566 return false;
1567 }
1568
1569 if (!VerifyCopyTLASAttribs(Attribs))
1570 return false;
1571
1572 if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->ValidateContent())
1573 {
1574 LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid");
1575 return false;
1576 }
1577 #endif
1578
1579 return true;
1580 }
1581
1582 template <typename BaseInterface, typename ImplementationTraits>
1583 bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const
1584 {
1585 #ifdef DILIGENT_DEVELOPMENT
1586 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1587 {
1588 LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device");
1589 return false;
1590 }
1591
1592 if (m_pActiveRenderPass != nullptr)
1593 {
1594 LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass");
1595 return false;
1596 }
1597
1598 if (!VerifyWriteBLASCompactedSizeAttribs(m_pDevice, Attribs))
1599 return false;
1600 #endif
1601
1602 return true;
1603 }
1604
1605 template <typename BaseInterface, typename ImplementationTraits>
1606 bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const
1607 {
1608 #ifdef DILIGENT_DEVELOPMENT
1609 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1610 {
1611 LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device");
1612 return false;
1613 }
1614
1615 if (m_pActiveRenderPass != nullptr)
1616 {
1617 LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass");
1618 return false;
1619 }
1620
1621 if (!VerifyWriteTLASCompactedSizeAttribs(m_pDevice, Attribs))
1622 return false;
1623 #endif
1624
1625 return true;
1626 }
1627
1628 template <typename BaseInterface, typename ImplementationTraits>
1629 bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) const
1630 {
1631 #ifdef DILIGENT_DEVELOPMENT
1632 if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
1633 {
1634 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device");
1635 return false;
1636 }
1637
1638 if (!m_pPipelineState)
1639 {
1640 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound.");
1641 return false;
1642 }
1643
1644 if (!m_pPipelineState->GetDesc().IsRayTracingPipeline())
1645 {
1646 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline.");
1647 return false;
1648 }
1649
1650 if (m_pActiveRenderPass != nullptr && Attribs.SBTTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
1651 {
1652 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command uses resource state transition and must be performed outside of render pass");
1653 return false;
1654 }
1655
1656 if (!VerifyTraceRaysAttribs(Attribs))
1657 return false;
1658
1659 if (m_pPipelineState.RawPtr() != Attribs.pSBT->GetDesc().pPSO)
1660 {
1661 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name,
1662 "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable");
1663 return false;
1664 }
1665
1666 if ((Attribs.DimensionX * Attribs.DimensionY * Attribs.DimensionZ) > m_pDevice->GetProperties().MaxRayGenThreads)
1667 {
1668 LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: the dimension must not exceed the ", m_pDevice->GetProperties().MaxRayGenThreads, " threads");
1669 return false;
1670 }
1671 #endif
1672
1673 return true;
1674 }
1675
1676
1677
1678
1679 #ifdef DILIGENT_DEVELOPMENT
1680
1681 template <typename BaseInterface, typename ImplementationTraits>
1682 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawArguments(const DrawAttribs& Attribs) const
14601683 {
14611684 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
14621685 return true;
14731696 return false;
14741697 }
14751698
1476 if (Attribs.NumVertices == 0)
1477 {
1478 LOG_WARNING_MESSAGE("Draw command arguments are invalid: number of vertices to draw is zero.");
1479 }
1480
1481 return true;
1482 }
1483
1484 template <typename BaseInterface, typename ImplementationTraits>
1485 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1486 DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const
1699 return VerifyDrawAttribs(Attribs);
1700 }
1701
1702 template <typename BaseInterface, typename ImplementationTraits>
1703 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const
14871704 {
14881705 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
14891706 return true;
15011718 return false;
15021719 }
15031720
1504 if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32)
1505 {
1506 LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: IndexType (",
1507 GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
1508 return false;
1509 }
1510
15111721 if (!m_pIndexBuffer)
15121722 {
15131723 LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound.");
15141724 return false;
15151725 }
15161726
1517 if (Attribs.NumIndices == 0)
1518 {
1519 LOG_WARNING_MESSAGE("DrawIndexed command arguments are invalid: number of indices to draw is zero.");
1520 }
1521
1522 return true;
1523 }
1524
1525 template <typename BaseInterface, typename ImplementationTraits>
1526 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1527 DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const
1727 return VerifyDrawIndexedAttribs(Attribs);
1728 }
1729
1730 template <typename BaseInterface, typename ImplementationTraits>
1731 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const
15281732 {
15291733 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
15301734 return true;
15311735
1736 if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
1737 {
1738 LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device");
1739 return false;
1740 }
1741
15321742 if (!m_pPipelineState)
15331743 {
15341744 LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound.");
15421752 return false;
15431753 }
15441754
1545 if (Attribs.ThreadGroupCount == 0)
1546 {
1547 LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero.");
1548 }
1549
1550 return true;
1551 }
1552
1553 template <typename BaseInterface, typename ImplementationTraits>
1554 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1555 DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
1755 return VerifyDrawMeshAttribs(m_pDevice->GetProperties().MaxDrawMeshTasksCount, Attribs);
1756 }
1757
1758 template <typename BaseInterface, typename ImplementationTraits>
1759 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndirectArguments(
1760 const DrawIndirectAttribs& Attribs,
1761 const IBuffer* pAttribsBuffer) const
15561762 {
15571763 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
15581764 return true;
15711777 return false;
15721778 }
15731779
1574 if (pAttribsBuffer != nullptr)
1575 {
1576 if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
1577 {
1578 LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer '",
1579 pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
1580 return false;
1581 }
1582 }
1583 else
1584 {
1585 LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer is null.");
1586 return false;
1587 }
1588
15891780 if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
15901781 {
15911782 LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. "
15931784 return false;
15941785 }
15951786
1596 return true;
1597 }
1598
1599 template <typename BaseInterface, typename ImplementationTraits>
1600 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1601 DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
1787 return VerifyDrawIndirectAttribs(Attribs, pAttribsBuffer);
1788 }
1789
1790 template <typename BaseInterface, typename ImplementationTraits>
1791 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndexedIndirectArguments(
1792 const DrawIndexedIndirectAttribs& Attribs,
1793 const IBuffer* pAttribsBuffer) const
16021794 {
16031795 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
16041796 return true;
16161808 return false;
16171809 }
16181810
1619 if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32)
1620 {
1621 LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: IndexType (",
1622 GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
1623 return false;
1624 }
1625
16261811 if (!m_pIndexBuffer)
16271812 {
16281813 LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound.");
1629 return false;
1630 }
1631
1632 if (pAttribsBuffer != nullptr)
1633 {
1634 if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
1635 {
1636 LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer '",
1637 pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
1638 return false;
1639 }
1640 }
1641 else
1642 {
1643 LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer is null.");
16441814 return false;
16451815 }
16461816
16511821 return false;
16521822 }
16531823
1654 return true;
1655 }
1656
1657 template <typename BaseInterface, typename ImplementationTraits>
1658 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1659 DvpVerifyDrawMeshIndirectArguments(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
1824 return VerifyDrawIndexedIndirectAttribs(Attribs, pAttribsBuffer);
1825 }
1826
1827 template <typename BaseInterface, typename ImplementationTraits>
1828 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawMeshIndirectArguments(
1829 const DrawMeshIndirectAttribs& Attribs,
1830 const IBuffer* pAttribsBuffer) const
16601831 {
16611832 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
16621833 return true;
16631834
1835 if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
1836 {
1837 LOG_ERROR_MESSAGE("DrawMeshIndirect: mesh shaders are not supported by this device");
1838 return false;
1839 }
1840
16641841 if (!m_pPipelineState)
16651842 {
16661843 LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: no pipeline state is bound.");
16741851 return false;
16751852 }
16761853
1677 if (pAttribsBuffer != nullptr)
1678 {
1679 if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
1680 {
1681 LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer '",
1682 pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
1683 return false;
1684 }
1685 }
1686 else
1687 {
1688 LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer is null.");
1689 return false;
1690 }
1691
1692 return true;
1693 }
1694
1695 template <typename BaseInterface, typename ImplementationTraits>
1696 inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
1697 DvpVerifyRenderTargets() const
1854 return VerifyDrawMeshIndirectAttribs(Attribs, pAttribsBuffer);
1855 }
1856
1857 template <typename BaseInterface, typename ImplementationTraits>
1858 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyRenderTargets() const
16981859 {
16991860 if (!m_pPipelineState)
17001861 {
17011862 LOG_ERROR_MESSAGE("No pipeline state is bound");
1702 return;
1863 return false;
17031864 }
17041865
17051866 const auto& PSODesc = m_pPipelineState->GetDesc();
17061867 if (!PSODesc.IsAnyGraphicsPipeline())
17071868 {
17081869 LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline");
1709 return;
1870 return false;
17101871 }
17111872
17121873 TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN};
17481909 "' (", GetTextureFormatAttribs(PSOFmt).Name, ").");
17491910 }
17501911 }
1751 }
1752
1753
1754
1755 template <typename BaseInterface, typename ImplementationTraits>
1756 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1757 DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const
1912
1913 return true;
1914 }
1915
1916
1917
1918 template <typename BaseInterface, typename ImplementationTraits>
1919 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const
17581920 {
17591921 if (!m_pPipelineState)
17601922 {
17751937 return false;
17761938 }
17771939
1778 if (Attribs.ThreadGroupCountX == 0)
1779 LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero.");
1780
1781 if (Attribs.ThreadGroupCountY == 0)
1782 LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountY is zero.");
1783
1784 if (Attribs.ThreadGroupCountZ == 0)
1785 LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountZ is zero.");
1786
1787 return true;
1788 }
1789
1790 template <typename BaseInterface, typename ImplementationTraits>
1791 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1792 DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
1940 return VerifyDispatchComputeAttribs(Attribs);
1941 }
1942
1943 template <typename BaseInterface, typename ImplementationTraits>
1944 inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDispatchIndirectArguments(
1945 const DispatchComputeIndirectAttribs& Attribs,
1946 const IBuffer* pAttribsBuffer) const
17931947 {
17941948 if (!m_pPipelineState)
17951949 {
18101964 return false;
18111965 }
18121966
1813 if (pAttribsBuffer != nullptr)
1814 {
1815 if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
1816 {
1817 LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer '",
1818 pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
1819 return false;
1820 }
1821 }
1822 else
1823 {
1824 LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer is null.");
1825 return false;
1826 }
1827
1828 return true;
1829 }
1830
1831
1832 template <typename BaseInterface, typename ImplementationTraits>
1833 void DeviceContextBase<BaseInterface, ImplementationTraits>::
1834 DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
1835 {
1836 DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null");
1837 DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
1838 RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
1839 if (Barrier.pTexture)
1840 {
1841 const auto& TexDesc = Barrier.pTexture->GetDesc();
1842
1843 DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'");
1844 OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState();
1845 DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN,
1846 "The state of texture '", TexDesc.Name,
1847 "' is unknown to the engine and is not explicitly specified in the barrier");
1848 DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'");
1849
1850 DEV_CHECK_ERR(Barrier.FirstMipLevel < TexDesc.MipLevels, "First mip level (", Barrier.FirstMipLevel,
1851 ") specified by the barrier is out of range. Texture '",
1852 TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
1853 DEV_CHECK_ERR(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels,
1854 "Mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1,
1855 " specified by the barrier is out of range. Texture '",
1856 TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
1857
1858 DEV_CHECK_ERR(Barrier.FirstArraySlice < TexDesc.ArraySize, "First array slice (", Barrier.FirstArraySlice,
1859 ") specified by the barrier is out of range. Array size of texture '",
1860 TexDesc.Name, "' is ", TexDesc.ArraySize);
1861 DEV_CHECK_ERR(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize,
1862 "Array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1,
1863 " specified by the barrier is out of range. Array size of texture '",
1864 TexDesc.Name, "' is ", TexDesc.ArraySize);
1865
1866 auto DevType = m_pDevice->GetDeviceCaps().DevType;
1867 if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN)
1868 {
1869 DEV_CHECK_ERR(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels),
1870 "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
1871 DEV_CHECK_ERR(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize),
1872 "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
1873 }
1874 }
1875 else
1876 {
1877 const auto& BuffDesc = Barrier.pBuffer->GetDesc();
1878 DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'");
1879 OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState();
1880 DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
1881 DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'");
1882 }
1883
1884 if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
1885 {
1886 DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE");
1887 }
1888
1889 if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
1890 {
1891 DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
1892 }
1893 }
1894
1895 template <typename BaseInterface, typename ImplementationTraits>
1896 bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1897 DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const
1967 return VerifyDispatchComputeIndirectAttribs(Attribs, pAttribsBuffer);
1968 }
1969
1970
1971 template <typename BaseInterface, typename ImplementationTraits>
1972 bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
1973 {
1974 return VerifyStateTransitionDesc(m_pDevice, Barrier);
1975 }
1976
1977 template <typename BaseInterface, typename ImplementationTraits>
1978 bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyTextureState(
1979 const TextureImplType& Texture,
1980 RESOURCE_STATE RequiredState,
1981 const char* OperationName) const
18981982 {
18991983 if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState))
19001984 {
19081992 }
19091993
19101994 template <typename BaseInterface, typename ImplementationTraits>
1911 bool DeviceContextBase<BaseInterface, ImplementationTraits>::
1912 DvpVerifyBufferState(const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const
1995 bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyBufferState(
1996 const BufferImplType& Buffer,
1997 RESOURCE_STATE RequiredState,
1998 const char* OperationName) const
19131999 {
19142000 if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState))
19152001 {
19222008 return true;
19232009 }
19242010
2011 template <typename BaseInterface, typename ImplementationTraits>
2012 bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyBLASState(
2013 const BottomLevelASType& BLAS,
2014 RESOURCE_STATE RequiredState,
2015 const char* OperationName) const
2016 {
2017 if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState))
2018 {
2019 LOG_ERROR_MESSAGE(OperationName, " requires BLAS '", BLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
2020 " state. Actual BLAS state: ", GetResourceStateString(BLAS.GetState()),
2021 ". Use appropriate state transiton flags or explicitly transition the BLAS using IDeviceContext::TransitionResourceStates() method.");
2022 return false;
2023 }
2024
2025 return true;
2026 }
2027
2028 template <typename BaseInterface, typename ImplementationTraits>
2029 bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyTLASState(
2030 const TopLevelASType& TLAS,
2031 RESOURCE_STATE RequiredState,
2032 const char* OperationName) const
2033 {
2034 if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState))
2035 {
2036 LOG_ERROR_MESSAGE(OperationName, " requires TLAS '", TLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
2037 " state. Actual TLAS state: ", GetResourceStateString(TLAS.GetState()),
2038 ". Use appropriate state transiton flags or explicitly transition the TLAS using IDeviceContext::TransitionResourceStates() method.");
2039 return false;
2040 }
2041
2042 return true;
2043 }
2044
19252045 #endif // DILIGENT_DEVELOPMENT
19262046
19272047 } // namespace Diligent
3838 namespace Diligent
3939 {
4040
41 void ValidateFramebufferDesc(const FramebufferDesc& Desc);
41 void ValidateFramebufferDesc(const FramebufferDesc& Desc) noexcept(false);
4242
4343 /// Template class implementing base functionality for the framebuffer object.
4444
6565 TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal},
6666 m_pRenderPass{Desc.pRenderPass}
6767 {
68 ValidateFramebufferDesc(Desc);
68 ValidateFramebufferDesc(this->m_Desc);
6969
7070 if (this->m_Desc.AttachmentCount > 0)
7171 {
3131
3232 #include <array>
3333 #include <vector>
34 #include <unordered_map>
35 #include <unordered_set>
3436
3537 #include "PipelineState.h"
3638 #include "DeviceObjectBase.hpp"
3739 #include "STDAllocator.hpp"
3840 #include "EngineMemory.h"
3941 #include "GraphicsAccessories.hpp"
40 #include "LinearAllocator.hpp"
42 #include "FixedLinearAllocator.hpp"