1 #ifndef _VKRAYTRACINGUTIL_HPP
2 #define _VKRAYTRACINGUTIL_HPP
3 /*-------------------------------------------------------------------------
4 * Vulkan CTS Framework
5 * --------------------
6 *
7 * Copyright (c) 2020 The Khronos Group Inc.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Vulkan ray tracing utility.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vkDefs.hpp"
27 #include "vkRef.hpp"
28 #include "vkMemUtil.hpp"
29 #include "vkBufferWithMemory.hpp"
30
31 #include "deFloat16.h"
32
33 #include "tcuVector.hpp"
34 #include "tcuVectorType.hpp"
35
36 #include <vector>
37
38 namespace vk
39 {
40 const VkTransformMatrixKHR identityMatrix3x4 = { { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } } };
41
42 template<typename T>
makeVkSharedPtr(Move<T> move)43 inline de::SharedPtr<Move<T>> makeVkSharedPtr(Move<T> move)
44 {
45 return de::SharedPtr<Move<T>>(new Move<T>(move));
46 }
47
48 template<typename T>
makeVkSharedPtr(de::MovePtr<T> movePtr)49 inline de::SharedPtr<de::MovePtr<T> > makeVkSharedPtr(de::MovePtr<T> movePtr)
50 {
51 return de::SharedPtr<de::MovePtr<T> >(new de::MovePtr<T>(movePtr));
52 }
53
54 template<typename T>
dataOrNullPtr(const std::vector<T> & v)55 inline const T* dataOrNullPtr(const std::vector<T>& v)
56 {
57 return (v.empty() ? DE_NULL : v.data());
58 }
59
60 template<typename T>
dataOrNullPtr(std::vector<T> & v)61 inline T* dataOrNullPtr(std::vector<T>& v)
62 {
63 return (v.empty() ? DE_NULL : v.data());
64 }
65
updateRayTracingGLSL(const std::string & str)66 inline std::string updateRayTracingGLSL (const std::string& str)
67 {
68 return str;
69 }
70
71 std::string getCommonRayGenerationShader (void);
72
73 // Get lowercase version of the format name with no VK_FORMAT_ prefix.
74 std::string getFormatSimpleName (vk::VkFormat format);
75
76 // Checks the given vertex buffer format is valid for acceleration structures.
77 // Note: VK_KHR_get_physical_device_properties2 and VK_KHR_acceleration_structure are supposed to be supported.
78 void checkAccelerationStructureVertexBufferFormat (const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice, vk::VkFormat format);
79
80 class RaytracedGeometryBase
81 {
82 public:
83 RaytracedGeometryBase () = delete;
84 RaytracedGeometryBase (const RaytracedGeometryBase& geometry) = delete;
85 RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType);
86 virtual ~RaytracedGeometryBase ();
87
getGeometryType(void) const88 inline VkGeometryTypeKHR getGeometryType (void) const { return m_geometryType; }
isTrianglesType(void) const89 inline bool isTrianglesType (void) const { return m_geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR; }
getVertexFormat(void) const90 inline VkFormat getVertexFormat (void) const { return m_vertexFormat; }
getIndexType(void) const91 inline VkIndexType getIndexType (void) const { return m_indexType; }
usesIndices(void) const92 inline bool usesIndices (void) const { return m_indexType != VK_INDEX_TYPE_NONE_KHR; }
getGeometryFlags(void) const93 inline VkGeometryFlagsKHR getGeometryFlags (void) const { return m_geometryFlags; }
setGeometryFlags(const VkGeometryFlagsKHR geometryFlags)94 inline void setGeometryFlags (const VkGeometryFlagsKHR geometryFlags) { m_geometryFlags = geometryFlags; }
95 virtual deUint32 getVertexCount (void) const = 0;
96 virtual const deUint8* getVertexPointer (void) const = 0;
97 virtual VkDeviceSize getVertexStride (void) const = 0;
98 virtual VkDeviceSize getAABBStride (void) const = 0;
99 virtual size_t getVertexByteSize (void) const = 0;
100 virtual deUint32 getIndexCount (void) const = 0;
101 virtual const deUint8* getIndexPointer (void) const = 0;
102 virtual VkDeviceSize getIndexStride (void) const = 0;
103 virtual size_t getIndexByteSize (void) const = 0;
104 virtual deUint32 getPrimitiveCount (void) const = 0;
105 virtual void addVertex (const tcu::Vec3& vertex) = 0;
106 virtual void addIndex (const deUint32& index) = 0;
107 private:
108 VkGeometryTypeKHR m_geometryType;
109 VkFormat m_vertexFormat;
110 VkIndexType m_indexType;
111 VkGeometryFlagsKHR m_geometryFlags;
112 };
113
114 template <typename T>
convertSatRte(float f)115 inline T convertSatRte (float f)
116 {
117 // \note Doesn't work for 64-bit types
118 DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64));
119 DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
120
121 deInt64 minVal = std::numeric_limits<T>::min();
122 deInt64 maxVal = std::numeric_limits<T>::max();
123 float q = deFloatFrac(f);
124 deInt64 intVal = (deInt64)(f-q);
125
126 // Rounding.
127 if (q == 0.5f)
128 {
129 if (intVal % 2 != 0)
130 intVal++;
131 }
132 else if (q > 0.5f)
133 intVal++;
134 // else Don't add anything
135
136 // Saturate.
137 intVal = de::max(minVal, de::min(maxVal, intVal));
138
139 return (T)intVal;
140 }
141
142 // Converts float to signed integer with variable width.
143 // Source float is assumed to be in the [-1, 1] range.
144 template <typename T>
deFloat32ToSNorm(float src)145 inline T deFloat32ToSNorm (float src)
146 {
147 DE_STATIC_ASSERT(std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed);
148 const T range = std::numeric_limits<T>::max();
149 const T intVal = convertSatRte<T>(src * static_cast<float>(range));
150 return de::clamp<T>(intVal, -range, range);
151 }
152
153 typedef tcu::Vector<deFloat16, 2> Vec2_16;
154 typedef tcu::Vector<deFloat16, 3> Vec3_16;
155 typedef tcu::Vector<deFloat16, 4> Vec4_16;
156 typedef tcu::Vector<deInt16, 2> Vec2_16SNorm;
157 typedef tcu::Vector<deInt16, 3> Vec3_16SNorm;
158 typedef tcu::Vector<deInt16, 4> Vec4_16SNorm;
159 typedef tcu::Vector<deInt8, 2> Vec2_8SNorm;
160 typedef tcu::Vector<deInt8, 3> Vec3_8SNorm;
161 typedef tcu::Vector<deInt8, 4> Vec4_8SNorm;
162
163 template<typename V> VkFormat vertexFormatFromType ();
vertexFormatFromType()164 template<> inline VkFormat vertexFormatFromType<tcu::Vec2> () { return VK_FORMAT_R32G32_SFLOAT; }
vertexFormatFromType()165 template<> inline VkFormat vertexFormatFromType<tcu::Vec3> () { return VK_FORMAT_R32G32B32_SFLOAT; }
vertexFormatFromType()166 template<> inline VkFormat vertexFormatFromType<tcu::Vec4> () { return VK_FORMAT_R32G32B32A32_SFLOAT; }
vertexFormatFromType()167 template<> inline VkFormat vertexFormatFromType<Vec2_16> () { return VK_FORMAT_R16G16_SFLOAT; }
vertexFormatFromType()168 template<> inline VkFormat vertexFormatFromType<Vec3_16> () { return VK_FORMAT_R16G16B16_SFLOAT; }
vertexFormatFromType()169 template<> inline VkFormat vertexFormatFromType<Vec4_16> () { return VK_FORMAT_R16G16B16A16_SFLOAT; }
vertexFormatFromType()170 template<> inline VkFormat vertexFormatFromType<Vec2_16SNorm> () { return VK_FORMAT_R16G16_SNORM; }
vertexFormatFromType()171 template<> inline VkFormat vertexFormatFromType<Vec3_16SNorm> () { return VK_FORMAT_R16G16B16_SNORM; }
vertexFormatFromType()172 template<> inline VkFormat vertexFormatFromType<Vec4_16SNorm> () { return VK_FORMAT_R16G16B16A16_SNORM; }
vertexFormatFromType()173 template<> inline VkFormat vertexFormatFromType<tcu::DVec2> () { return VK_FORMAT_R64G64_SFLOAT; }
vertexFormatFromType()174 template<> inline VkFormat vertexFormatFromType<tcu::DVec3> () { return VK_FORMAT_R64G64B64_SFLOAT; }
vertexFormatFromType()175 template<> inline VkFormat vertexFormatFromType<tcu::DVec4> () { return VK_FORMAT_R64G64B64A64_SFLOAT; }
vertexFormatFromType()176 template<> inline VkFormat vertexFormatFromType<Vec2_8SNorm> () { return VK_FORMAT_R8G8_SNORM; }
vertexFormatFromType()177 template<> inline VkFormat vertexFormatFromType<Vec3_8SNorm> () { return VK_FORMAT_R8G8B8_SNORM; }
vertexFormatFromType()178 template<> inline VkFormat vertexFormatFromType<Vec4_8SNorm> () { return VK_FORMAT_R8G8B8A8_SNORM; }
179
180 struct EmptyIndex {};
181 template<typename I> VkIndexType indexTypeFromType ();
indexTypeFromType()182 template<> inline VkIndexType indexTypeFromType<deUint16> () { return VK_INDEX_TYPE_UINT16; }
indexTypeFromType()183 template<> inline VkIndexType indexTypeFromType<deUint32> () { return VK_INDEX_TYPE_UINT32; }
indexTypeFromType()184 template<> inline VkIndexType indexTypeFromType<EmptyIndex> () { return VK_INDEX_TYPE_NONE_KHR; }
185
186 template<typename V> V convertFloatTo (const tcu::Vec3& vertex);
convertFloatTo(const tcu::Vec3 & vertex)187 template<> inline tcu::Vec2 convertFloatTo<tcu::Vec2> (const tcu::Vec3& vertex) { return tcu::Vec2(vertex.x(), vertex.y()); }
convertFloatTo(const tcu::Vec3 & vertex)188 template<> inline tcu::Vec3 convertFloatTo<tcu::Vec3> (const tcu::Vec3& vertex) { return vertex; }
convertFloatTo(const tcu::Vec3 & vertex)189 template<> inline tcu::Vec4 convertFloatTo<tcu::Vec4> (const tcu::Vec3& vertex) { return tcu::Vec4(vertex.x(), vertex.y(), vertex.z(), 0.0f); }
convertFloatTo(const tcu::Vec3 & vertex)190 template<> inline Vec2_16 convertFloatTo<Vec2_16> (const tcu::Vec3& vertex) { return Vec2_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)191 template<> inline Vec3_16 convertFloatTo<Vec3_16> (const tcu::Vec3& vertex) { return Vec3_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)192 template<> inline Vec4_16 convertFloatTo<Vec4_16> (const tcu::Vec3& vertex) { return Vec4_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z()), deFloat32To16(0.0f)); }
convertFloatTo(const tcu::Vec3 & vertex)193 template<> inline Vec2_16SNorm convertFloatTo<Vec2_16SNorm> (const tcu::Vec3& vertex) { return Vec2_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)194 template<> inline Vec3_16SNorm convertFloatTo<Vec3_16SNorm> (const tcu::Vec3& vertex) { return Vec3_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y()), deFloat32ToSNorm<deInt16>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)195 template<> inline Vec4_16SNorm convertFloatTo<Vec4_16SNorm> (const tcu::Vec3& vertex) { return Vec4_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y()), deFloat32ToSNorm<deInt16>(vertex.z()), deFloat32ToSNorm<deInt16>(0.0f)); }
convertFloatTo(const tcu::Vec3 & vertex)196 template<> inline tcu::DVec2 convertFloatTo<tcu::DVec2> (const tcu::Vec3& vertex) { return tcu::DVec2(static_cast<double>(vertex.x()), static_cast<double>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)197 template<> inline tcu::DVec3 convertFloatTo<tcu::DVec3> (const tcu::Vec3& vertex) { return tcu::DVec3(static_cast<double>(vertex.x()), static_cast<double>(vertex.y()), static_cast<double>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)198 template<> inline tcu::DVec4 convertFloatTo<tcu::DVec4> (const tcu::Vec3& vertex) { return tcu::DVec4(static_cast<double>(vertex.x()), static_cast<double>(vertex.y()), static_cast<double>(vertex.z()), 0.0); }
convertFloatTo(const tcu::Vec3 & vertex)199 template<> inline Vec2_8SNorm convertFloatTo<Vec2_8SNorm> (const tcu::Vec3& vertex) { return Vec2_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)200 template<> inline Vec3_8SNorm convertFloatTo<Vec3_8SNorm> (const tcu::Vec3& vertex) { return Vec3_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y()), deFloat32ToSNorm<deInt8>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)201 template<> inline Vec4_8SNorm convertFloatTo<Vec4_8SNorm> (const tcu::Vec3& vertex) { return Vec4_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y()), deFloat32ToSNorm<deInt8>(vertex.z()), deFloat32ToSNorm<deInt8>(0.0f)); }
202
203 template<typename V> V convertIndexTo (deUint32 index);
convertIndexTo(deUint32 index)204 template<> inline EmptyIndex convertIndexTo<EmptyIndex> (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Cannot add empty index"); }
convertIndexTo(deUint32 index)205 template<> inline deUint16 convertIndexTo<deUint16> (deUint32 index) { return static_cast<deUint16>(index); }
convertIndexTo(deUint32 index)206 template<> inline deUint32 convertIndexTo<deUint32> (deUint32 index) { return index; }
207
208 template<typename V, typename I>
209 class RaytracedGeometry : public RaytracedGeometryBase
210 {
211 public:
212 RaytracedGeometry () = delete;
213 RaytracedGeometry (const RaytracedGeometry& geometry) = delete;
214 RaytracedGeometry (VkGeometryTypeKHR geometryType, deUint32 paddingBlocks = 0u);
215 RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices = std::vector<I>(), deUint32 paddingBlocks = 0u);
216
217 deUint32 getVertexCount (void) const override;
218 const deUint8* getVertexPointer (void) const override;
219 VkDeviceSize getVertexStride (void) const override;
220 VkDeviceSize getAABBStride (void) const override;
221 size_t getVertexByteSize (void) const override;
222 deUint32 getIndexCount (void) const override;
223 const deUint8* getIndexPointer (void) const override;
224 VkDeviceSize getIndexStride (void) const override;
225 size_t getIndexByteSize (void) const override;
226 deUint32 getPrimitiveCount (void) const override;
227
228 void addVertex (const tcu::Vec3& vertex) override;
229 void addIndex (const deUint32& index) override;
230
231 private:
232 void init (); // To be run in constructors.
233 void checkGeometryType () const; // Checks geometry type is valid.
234 void calcBlockSize (); // Calculates and saves vertex buffer block size.
235 size_t getBlockSize () const; // Return stored vertex buffer block size.
236 void addNativeVertex (const V& vertex); // Adds new vertex in native format.
237
238 // The implementation below stores vertices as byte blocks to take the requested padding into account. m_vertices is the array
239 // of bytes containing vertex data.
240 //
241 // For triangles, the padding block has a size that is a multiple of the vertex size and each vertex is stored in a byte block
242 // equivalent to:
243 //
244 // struct Vertex
245 // {
246 // V vertex;
247 // deUint8 padding[m_paddingBlocks * sizeof(V)];
248 // };
249 //
250 // For AABBs, the padding block has a size that is a multiple of kAABBPadBaseSize (see below) and vertices are stored in pairs
251 // before the padding block. This is equivalent to:
252 //
253 // struct VertexPair
254 // {
255 // V vertices[2];
256 // deUint8 padding[m_paddingBlocks * kAABBPadBaseSize];
257 // };
258 //
259 // The size of each pseudo-structure above is saved to one of the correspoding union members below.
260 union BlockSize
261 {
262 size_t trianglesBlockSize;
263 size_t aabbsBlockSize;
264 };
265
266 const deUint32 m_paddingBlocks;
267 size_t m_vertexCount;
268 std::vector<deUint8> m_vertices; // Vertices are stored as byte blocks.
269 std::vector<I> m_indices; // Indices are stored natively.
270 BlockSize m_blockSize; // For m_vertices.
271
272 // Data sizes.
273 static constexpr size_t kVertexSize = sizeof(V);
274 static constexpr size_t kIndexSize = sizeof(I);
275 static constexpr size_t kAABBPadBaseSize = 8; // As required by the spec.
276 };
277
278 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,deUint32 paddingBlocks)279 RaytracedGeometry<V, I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, deUint32 paddingBlocks)
280 : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
281 , m_paddingBlocks(paddingBlocks)
282 , m_vertexCount(0)
283 {
284 init();
285 }
286
287 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,const std::vector<V> & vertices,const std::vector<I> & indices,deUint32 paddingBlocks)288 RaytracedGeometry<V,I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices, deUint32 paddingBlocks)
289 : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
290 , m_paddingBlocks(paddingBlocks)
291 , m_vertexCount(0)
292 , m_vertices()
293 , m_indices(indices)
294 {
295 init();
296 for (const auto& vertex : vertices)
297 addNativeVertex(vertex);
298 }
299
300 template<typename V, typename I>
getVertexCount(void) const301 deUint32 RaytracedGeometry<V,I>::getVertexCount (void) const
302 {
303 return (isTrianglesType() ? static_cast<deUint32>(m_vertexCount) : 0u);
304 }
305
306 template<typename V, typename I>
getVertexPointer(void) const307 const deUint8* RaytracedGeometry<V, I>::getVertexPointer (void) const
308 {
309 DE_ASSERT(!m_vertices.empty());
310 return reinterpret_cast<const deUint8*>(m_vertices.data());
311 }
312
313 template<typename V, typename I>
getVertexStride(void) const314 VkDeviceSize RaytracedGeometry<V,I>::getVertexStride (void) const
315 {
316 return ((!isTrianglesType()) ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
317 }
318
319 template<typename V, typename I>
getAABBStride(void) const320 VkDeviceSize RaytracedGeometry<V, I>::getAABBStride (void) const
321 {
322 return (isTrianglesType() ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
323 }
324
325 template<typename V, typename I>
getVertexByteSize(void) const326 size_t RaytracedGeometry<V, I>::getVertexByteSize (void) const
327 {
328 return m_vertices.size();
329 }
330
331 template<typename V, typename I>
getIndexCount(void) const332 deUint32 RaytracedGeometry<V, I>::getIndexCount (void) const
333 {
334 return static_cast<deUint32>(isTrianglesType() ? m_indices.size() : 0);
335 }
336
337 template<typename V, typename I>
getIndexPointer(void) const338 const deUint8* RaytracedGeometry<V, I>::getIndexPointer (void) const
339 {
340 const auto indexCount = getIndexCount();
341 DE_UNREF(indexCount); // For release builds.
342 DE_ASSERT(indexCount > 0u);
343
344 return reinterpret_cast<const deUint8*>(m_indices.data());
345 }
346
347 template<typename V, typename I>
getIndexStride(void) const348 VkDeviceSize RaytracedGeometry<V, I>::getIndexStride (void) const
349 {
350 return static_cast<VkDeviceSize>(kIndexSize);
351 }
352
353 template<typename V, typename I>
getIndexByteSize(void) const354 size_t RaytracedGeometry<V, I>::getIndexByteSize (void) const
355 {
356 const auto indexCount = getIndexCount();
357 DE_ASSERT(indexCount > 0u);
358
359 return (indexCount * kIndexSize);
360 }
361
362 template<typename V, typename I>
getPrimitiveCount(void) const363 deUint32 RaytracedGeometry<V,I>::getPrimitiveCount (void) const
364 {
365 return static_cast<deUint32>(isTrianglesType() ? (usesIndices() ? m_indices.size() / 3 : m_vertexCount / 3) : (m_vertexCount / 2));
366 }
367
368 template<typename V, typename I>
addVertex(const tcu::Vec3 & vertex)369 void RaytracedGeometry<V, I>::addVertex (const tcu::Vec3& vertex)
370 {
371 addNativeVertex(convertFloatTo<V>(vertex));
372 }
373
374 template<typename V, typename I>
addNativeVertex(const V & vertex)375 void RaytracedGeometry<V, I>::addNativeVertex (const V& vertex)
376 {
377 const auto oldSize = m_vertices.size();
378 const auto blockSize = getBlockSize();
379
380 if (isTrianglesType())
381 {
382 // Reserve new block, copy vertex at the beginning of the new block.
383 m_vertices.resize(oldSize + blockSize, deUint8{0});
384 deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
385 }
386 else // AABB
387 {
388 if (m_vertexCount % 2 == 0)
389 {
390 // New block needed.
391 m_vertices.resize(oldSize + blockSize, deUint8{0});
392 deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
393 }
394 else
395 {
396 // Insert in the second position of last existing block.
397 //
398 // Vertex Size
399 // +-------+
400 // +-------------+------------+----------------------------------------+
401 // | | | ... | vertex vertex padding |
402 // +-------------+------------+----------------+-----------------------+
403 // +-----------------------+
404 // Block Size
405 // +-------------------------------------------------------------------+
406 // Old Size
407 //
408 deMemcpy(&m_vertices[oldSize - blockSize + kVertexSize], &vertex, kVertexSize);
409 }
410 }
411
412 ++m_vertexCount;
413 }
414
415 template<typename V, typename I>
addIndex(const deUint32 & index)416 void RaytracedGeometry<V, I>::addIndex (const deUint32& index)
417 {
418 m_indices.push_back(convertIndexTo<I>(index));
419 }
420
421 template<typename V, typename I>
init()422 void RaytracedGeometry<V, I>::init ()
423 {
424 checkGeometryType();
425 calcBlockSize();
426 }
427
428 template<typename V, typename I>
checkGeometryType() const429 void RaytracedGeometry<V, I>::checkGeometryType () const
430 {
431 const auto geometryType = getGeometryType();
432 DE_UNREF(geometryType); // For release builds.
433 DE_ASSERT(geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
434 }
435
436 template<typename V, typename I>
calcBlockSize()437 void RaytracedGeometry<V, I>::calcBlockSize ()
438 {
439 if (isTrianglesType())
440 m_blockSize.trianglesBlockSize = kVertexSize * static_cast<size_t>(1u + m_paddingBlocks);
441 else
442 m_blockSize.aabbsBlockSize = 2 * kVertexSize + m_paddingBlocks * kAABBPadBaseSize;
443 }
444
445 template<typename V, typename I>
getBlockSize() const446 size_t RaytracedGeometry<V, I>::getBlockSize () const
447 {
448 return (isTrianglesType() ? m_blockSize.trianglesBlockSize : m_blockSize.aabbsBlockSize);
449 }
450
451 de::SharedPtr<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType, bool padVertices = false);
452
453 VkDeviceAddress getBufferDeviceAddress ( const DeviceInterface& vkd,
454 const VkDevice device,
455 const VkBuffer buffer,
456 VkDeviceSize offset );
457
458 class SerialStorage
459 {
460 public:
461 enum
462 {
463 DE_SERIALIZED_FIELD(DRIVER_UUID, VK_UUID_SIZE), // VK_UUID_SIZE bytes of data matching VkPhysicalDeviceIDProperties::driverUUID
464 DE_SERIALIZED_FIELD(COMPAT_UUID, VK_UUID_SIZE), // VK_UUID_SIZE bytes of data identifying the compatibility for comparison using vkGetDeviceAccelerationStructureCompatibilityKHR
465 DE_SERIALIZED_FIELD(SERIALIZED_SIZE, sizeof(deUint64)), // A 64-bit integer of the total size matching the value queried using VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
466 DE_SERIALIZED_FIELD(DESERIALIZED_SIZE, sizeof(deUint64)), // A 64-bit integer of the deserialized size to be passed in to VkAccelerationStructureCreateInfoKHR::size
467 DE_SERIALIZED_FIELD(HANDLES_COUNT, sizeof(deUint64)), // A 64-bit integer of the count of the number of acceleration structure handles following. This will be zero for a bottom-level acceleration structure.
468 SERIAL_STORAGE_SIZE_MIN
469 };
470
471 SerialStorage () = delete;
472 SerialStorage (const DeviceInterface& vk,
473 const VkDevice device,
474 Allocator& allocator,
475 const VkAccelerationStructureBuildTypeKHR buildType,
476 const VkDeviceSize storageSize);
477
478 VkDeviceOrHostAddressKHR getAddress (const DeviceInterface& vk,
479 const VkDevice device);
480 VkDeviceOrHostAddressConstKHR getAddressConst (const DeviceInterface& vk,
481 const VkDevice device);
482 VkDeviceSize getStorageSize ();
483 deUint64 getDeserializedSize ();
484
485 protected:
486 VkAccelerationStructureBuildTypeKHR m_buildType;
487 de::MovePtr<BufferWithMemory> m_buffer;
488 VkDeviceSize m_storageSize;
489
490 };
491
492 class BottomLevelAccelerationStructure
493 {
494 public:
495 static deUint32 getRequiredAllocationCount (void);
496
497 BottomLevelAccelerationStructure ();
498 BottomLevelAccelerationStructure (const BottomLevelAccelerationStructure& other) = delete;
499 virtual ~BottomLevelAccelerationStructure ();
500
501 virtual void setGeometryData (const std::vector<tcu::Vec3>& geometryData,
502 const bool triangles,
503 const VkGeometryFlagsKHR geometryFlags = 0u );
504 virtual void setDefaultGeometryData (const VkShaderStageFlagBits testStage,
505 const VkGeometryFlagsKHR geometryFlags = 0u );
506 virtual void setGeometryCount (const size_t geometryCount);
507 virtual void addGeometry (de::SharedPtr<RaytracedGeometryBase>& raytracedGeometry);
508 virtual void addGeometry (const std::vector<tcu::Vec3>& geometryData,
509 const bool triangles,
510 const VkGeometryFlagsKHR geometryFlags = 0u );
511
512 virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL;
513 virtual void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) = DE_NULL;
514 virtual void setCreateGeneric (bool createGeneric) = 0;
515 virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) = DE_NULL;
516 virtual void setBuildWithoutGeometries (bool buildWithoutGeometries) = 0;
517 virtual void setBuildWithoutPrimitives (bool buildWithoutPrimitives) = 0;
518 virtual void setDeferredOperation (const bool deferredOperation,
519 const deUint32 workerThreadCount = 0u ) = DE_NULL;
520 virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL;
521 virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer,
522 const VkDeviceSize indirectBufferOffset,
523 const deUint32 indirectBufferStride) = DE_NULL;
524 virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL;
525 VkDeviceSize getStructureSize () const;
526
527 // methods specific for each acceleration structure
528 virtual void create (const DeviceInterface& vk,
529 const VkDevice device,
530 Allocator& allocator,
531 VkDeviceSize structureSize,
532 VkDeviceAddress deviceAddress = 0u) = DE_NULL;
533 virtual void build (const DeviceInterface& vk,
534 const VkDevice device,
535 const VkCommandBuffer cmdBuffer) = DE_NULL;
536 virtual void copyFrom (const DeviceInterface& vk,
537 const VkDevice device,
538 const VkCommandBuffer cmdBuffer,
539 BottomLevelAccelerationStructure* accelerationStructure,
540 bool compactCopy) = DE_NULL;
541
542 virtual void serialize (const DeviceInterface& vk,
543 const VkDevice device,
544 const VkCommandBuffer cmdBuffer,
545 SerialStorage* storage) = DE_NULL;
546 virtual void deserialize (const DeviceInterface& vk,
547 const VkDevice device,
548 const VkCommandBuffer cmdBuffer,
549 SerialStorage* storage) = DE_NULL;
550
551 // helper methods for typical acceleration structure creation tasks
552 void createAndBuild (const DeviceInterface& vk,
553 const VkDevice device,
554 const VkCommandBuffer cmdBuffer,
555 Allocator& allocator,
556 VkDeviceAddress deviceAddress = 0u );
557 void createAndCopyFrom (const DeviceInterface& vk,
558 const VkDevice device,
559 const VkCommandBuffer cmdBuffer,
560 Allocator& allocator,
561 BottomLevelAccelerationStructure* accelerationStructure,
562 VkDeviceSize compactCopySize = 0u,
563 VkDeviceAddress deviceAddress = 0u);
564 void createAndDeserializeFrom (const DeviceInterface& vk,
565 const VkDevice device,
566 const VkCommandBuffer cmdBuffer,
567 Allocator& allocator,
568 SerialStorage* storage,
569 VkDeviceAddress deviceAddress = 0u);
570
571 virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL;
572 protected:
573 std::vector<de::SharedPtr<RaytracedGeometryBase>> m_geometriesData;
574 VkDeviceSize m_structureSize;
575 VkDeviceSize m_updateScratchSize;
576 VkDeviceSize m_buildScratchSize;
577 };
578
579 de::MovePtr<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ();
580
581 struct InstanceData
582 {
InstanceDatavk::InstanceData583 InstanceData (VkTransformMatrixKHR matrix_,
584 deUint32 instanceCustomIndex_,
585 deUint32 mask_,
586 deUint32 instanceShaderBindingTableRecordOffset_,
587 VkGeometryInstanceFlagsKHR flags_)
588 : matrix(matrix_), instanceCustomIndex(instanceCustomIndex_), mask(mask_), instanceShaderBindingTableRecordOffset(instanceShaderBindingTableRecordOffset_), flags(flags_)
589 {
590 }
591 VkTransformMatrixKHR matrix;
592 deUint32 instanceCustomIndex;
593 deUint32 mask;
594 deUint32 instanceShaderBindingTableRecordOffset;
595 VkGeometryInstanceFlagsKHR flags;
596 };
597
598 class TopLevelAccelerationStructure
599 {
600 public:
601 static deUint32 getRequiredAllocationCount (void);
602
603 TopLevelAccelerationStructure ();
604 TopLevelAccelerationStructure (const TopLevelAccelerationStructure& other) = delete;
605 virtual ~TopLevelAccelerationStructure ();
606
607 virtual void setInstanceCount (const size_t instanceCount);
608 virtual void addInstance (de::SharedPtr<BottomLevelAccelerationStructure> bottomLevelStructure,
609 const VkTransformMatrixKHR& matrix = identityMatrix3x4,
610 deUint32 instanceCustomIndex = 0,
611 deUint32 mask = 0xFF,
612 deUint32 instanceShaderBindingTableRecordOffset = 0,
613 VkGeometryInstanceFlagsKHR flags = VkGeometryInstanceFlagBitsKHR(0u) );
614
615 virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL;
616 virtual void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) = DE_NULL;
617 virtual void setCreateGeneric (bool createGeneric) = 0;
618 virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) = DE_NULL;
619 virtual void setBuildWithoutPrimitives (bool buildWithoutPrimitives) = 0;
620 virtual void setInactiveInstances (bool inactiveInstances) = 0;
621 virtual void setDeferredOperation (const bool deferredOperation,
622 const deUint32 workerThreadCount = 0u) = DE_NULL;
623 virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL;
624 virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer,
625 const VkDeviceSize indirectBufferOffset,
626 const deUint32 indirectBufferStride) = DE_NULL;
627 virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL;
628 VkDeviceSize getStructureSize () const;
629
630 // methods specific for each acceleration structure
631 virtual void create (const DeviceInterface& vk,
632 const VkDevice device,
633 Allocator& allocator,
634 VkDeviceSize structureSize = 0u,
635 VkDeviceAddress deviceAddress = 0u ) = DE_NULL;
636 virtual void build (const DeviceInterface& vk,
637 const VkDevice device,
638 const VkCommandBuffer cmdBuffer) = DE_NULL;
639 virtual void copyFrom (const DeviceInterface& vk,
640 const VkDevice device,
641 const VkCommandBuffer cmdBuffer,
642 TopLevelAccelerationStructure* accelerationStructure,
643 bool compactCopy) = DE_NULL;
644
645 virtual void serialize (const DeviceInterface& vk,
646 const VkDevice device,
647 const VkCommandBuffer cmdBuffer,
648 SerialStorage* storage) = DE_NULL;
649 virtual void deserialize (const DeviceInterface& vk,
650 const VkDevice device,
651 const VkCommandBuffer cmdBuffer,
652 SerialStorage* storage) = DE_NULL;
653
654 // helper methods for typical acceleration structure creation tasks
655 void createAndBuild (const DeviceInterface& vk,
656 const VkDevice device,
657 const VkCommandBuffer cmdBuffer,
658 Allocator& allocator,
659 VkDeviceAddress deviceAddress = 0u );
660 void createAndCopyFrom (const DeviceInterface& vk,
661 const VkDevice device,
662 const VkCommandBuffer cmdBuffer,
663 Allocator& allocator,
664 TopLevelAccelerationStructure* accelerationStructure,
665 VkDeviceSize compactCopySize = 0u,
666 VkDeviceAddress deviceAddress = 0u);
667 void createAndDeserializeFrom (const DeviceInterface& vk,
668 const VkDevice device,
669 const VkCommandBuffer cmdBuffer,
670 Allocator& allocator,
671 SerialStorage* storage,
672 VkDeviceAddress deviceAddress = 0u);
673
674 virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL;
675
676 protected:
677 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > m_bottomLevelInstances;
678 std::vector<InstanceData> m_instanceData;
679 VkDeviceSize m_structureSize;
680 VkDeviceSize m_updateScratchSize;
681 VkDeviceSize m_buildScratchSize;
682 };
683
684 de::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ();
685
686 bool queryAccelerationStructureSize (const DeviceInterface& vk,
687 const VkDevice device,
688 const VkCommandBuffer cmdBuffer,
689 const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
690 VkAccelerationStructureBuildTypeKHR buildType,
691 const VkQueryPool queryPool,
692 VkQueryType queryType,
693 deUint32 firstQuery,
694 std::vector<VkDeviceSize>& results);
695
696 class RayTracingPipeline
697 {
698 public:
699 RayTracingPipeline ();
700 ~RayTracingPipeline ();
701
702 void addShader (VkShaderStageFlagBits shaderStage,
703 Move<VkShaderModule> shaderModule,
704 deUint32 group,
705 const VkSpecializationInfo* specializationInfo = nullptr);
706 void addShader (VkShaderStageFlagBits shaderStage,
707 de::SharedPtr<Move<VkShaderModule>> shaderModule,
708 deUint32 group,
709 const VkSpecializationInfo* specializationInfoPtr = nullptr);
710 void addLibrary (de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary);
711 Move<VkPipeline> createPipeline (const DeviceInterface& vk,
712 const VkDevice device,
713 const VkPipelineLayout pipelineLayout,
714 const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries = std::vector<de::SharedPtr<Move<VkPipeline>>>());
715 std::vector<de::SharedPtr<Move<VkPipeline>>> createPipelineWithLibraries (const DeviceInterface& vk,
716 const VkDevice device,
717 const VkPipelineLayout pipelineLayout);
718 de::MovePtr<BufferWithMemory> createShaderBindingTable (const DeviceInterface& vk,
719 const VkDevice device,
720 const VkPipeline pipeline,
721 Allocator& allocator,
722 const deUint32& shaderGroupHandleSize,
723 const deUint32 shaderGroupBaseAlignment,
724 const deUint32& firstGroup,
725 const deUint32& groupCount,
726 const VkBufferCreateFlags& additionalBufferCreateFlags = VkBufferCreateFlags(0u),
727 const VkBufferUsageFlags& additionalBufferUsageFlags = VkBufferUsageFlags(0u),
728 const MemoryRequirement& additionalMemoryRequirement = MemoryRequirement::Any,
729 const VkDeviceAddress& opaqueCaptureAddress = 0u,
730 const deUint32 shaderBindingTableOffset = 0u,
731 const deUint32 shaderRecordSize = 0u,
732 const void** shaderGroupDataPtrPerGroup = nullptr);
733 void setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags);
734 void setMaxRecursionDepth (const deUint32& maxRecursionDepth);
735 void setMaxPayloadSize (const deUint32& maxPayloadSize);
736 void setMaxAttributeSize (const deUint32& maxAttributeSize);
737 void setDeferredOperation (const bool deferredOperation,
738 const deUint32 workerThreadCount = 0);
739 void addDynamicState (const VkDynamicState& dynamicState);
740
741
742 protected:
743 Move<VkPipeline> createPipelineKHR (const DeviceInterface& vk,
744 const VkDevice device,
745 const VkPipelineLayout pipelineLayout,
746 const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries);
747
748 std::vector<de::SharedPtr<Move<VkShaderModule> > > m_shadersModules;
749 std::vector<de::SharedPtr<de::MovePtr<RayTracingPipeline>>> m_pipelineLibraries;
750 std::vector<VkPipelineShaderStageCreateInfo> m_shaderCreateInfos;
751 std::vector<VkRayTracingShaderGroupCreateInfoKHR> m_shadersGroupCreateInfos;
752 VkPipelineCreateFlags m_pipelineCreateFlags;
753 deUint32 m_maxRecursionDepth;
754 deUint32 m_maxPayloadSize;
755 deUint32 m_maxAttributeSize;
756 bool m_deferredOperation;
757 deUint32 m_workerThreadCount;
758 std::vector<VkDynamicState> m_dynamicStates;
759 };
760
761 class RayTracingProperties
762 {
763 protected:
RayTracingProperties()764 RayTracingProperties () {};
765
766 public:
RayTracingProperties(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)767 RayTracingProperties (const InstanceInterface& vki,
768 const VkPhysicalDevice physicalDevice) { DE_UNREF(vki); DE_UNREF(physicalDevice); };
~RayTracingProperties()769 virtual ~RayTracingProperties () {};
770
771 virtual deUint32 getShaderGroupHandleSize (void) = DE_NULL;
772 virtual deUint32 getMaxRecursionDepth (void) = DE_NULL;
773 virtual deUint32 getMaxShaderGroupStride (void) = DE_NULL;
774 virtual deUint32 getShaderGroupBaseAlignment (void) = DE_NULL;
775 virtual deUint64 getMaxGeometryCount (void) = DE_NULL;
776 virtual deUint64 getMaxInstanceCount (void) = DE_NULL;
777 virtual deUint64 getMaxPrimitiveCount (void) = DE_NULL;
778 virtual deUint32 getMaxDescriptorSetAccelerationStructures (void) = DE_NULL;
779 virtual deUint32 getMaxRayDispatchInvocationCount (void) = DE_NULL;
780 virtual deUint32 getMaxRayHitAttributeSize (void) = DE_NULL;
781 };
782
783 de::MovePtr<RayTracingProperties> makeRayTracingProperties (const InstanceInterface& vki,
784 const VkPhysicalDevice physicalDevice);
785
786 void cmdTraceRays (const DeviceInterface& vk,
787 VkCommandBuffer commandBuffer,
788 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
789 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
790 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
791 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
792 deUint32 width,
793 deUint32 height,
794 deUint32 depth);
795
796 void cmdTraceRaysIndirect (const DeviceInterface& vk,
797 VkCommandBuffer commandBuffer,
798 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
799 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
800 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
801 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
802 VkDeviceAddress indirectDeviceAddress);
803 } // vk
804
805 #endif // _VKRAYTRACINGUTIL_HPP
806