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 #include "qpWatchDog.h"
36
37 #include <vector>
38 #include <limits>
39 #include <stdexcept>
40
41 namespace vk
42 {
43
44 #ifndef CTS_USES_VULKANSC
45
46 constexpr VkShaderStageFlags SHADER_STAGE_ALL_RAY_TRACING = VK_SHADER_STAGE_RAYGEN_BIT_KHR
47 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR
48 | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
49 | VK_SHADER_STAGE_MISS_BIT_KHR
50 | VK_SHADER_STAGE_INTERSECTION_BIT_KHR
51 | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
52
53 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 } } };
54
55 template<typename T>
makeVkSharedPtr(Move<T> move)56 inline de::SharedPtr<Move<T>> makeVkSharedPtr(Move<T> move)
57 {
58 return de::SharedPtr<Move<T>>(new Move<T>(move));
59 }
60
61 template<typename T>
makeVkSharedPtr(de::MovePtr<T> movePtr)62 inline de::SharedPtr<de::MovePtr<T> > makeVkSharedPtr(de::MovePtr<T> movePtr)
63 {
64 return de::SharedPtr<de::MovePtr<T> >(new de::MovePtr<T>(movePtr));
65 }
66
updateRayTracingGLSL(const std::string & str)67 inline std::string updateRayTracingGLSL (const std::string& str)
68 {
69 return str;
70 }
71
72 std::string getCommonRayGenerationShader (void);
73
74 // Get lowercase version of the format name with no VK_FORMAT_ prefix.
75 std::string getFormatSimpleName (vk::VkFormat format);
76
77 // Test whether given poin p belons to the triangle (p0, p1, p2)
78 bool pointInTriangle2D(const tcu::Vec3& p, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::Vec3& p2);
79
80 // Checks the given vertex buffer format is valid for acceleration structures.
81 // Note: VK_KHR_get_physical_device_properties2 and VK_KHR_acceleration_structure are supposed to be supported.
82 void checkAccelerationStructureVertexBufferFormat (const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice, vk::VkFormat format);
83
84 class RaytracedGeometryBase
85 {
86 public:
87 RaytracedGeometryBase () = delete;
88 RaytracedGeometryBase (const RaytracedGeometryBase& geometry) = delete;
89 RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType);
90 virtual ~RaytracedGeometryBase ();
91
getGeometryType(void) const92 inline VkGeometryTypeKHR getGeometryType (void) const { return m_geometryType; }
isTrianglesType(void) const93 inline bool isTrianglesType (void) const { return m_geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR; }
getVertexFormat(void) const94 inline VkFormat getVertexFormat (void) const { return m_vertexFormat; }
getIndexType(void) const95 inline VkIndexType getIndexType (void) const { return m_indexType; }
usesIndices(void) const96 inline bool usesIndices (void) const { return m_indexType != VK_INDEX_TYPE_NONE_KHR; }
getGeometryFlags(void) const97 inline VkGeometryFlagsKHR getGeometryFlags (void) const { return m_geometryFlags; }
setGeometryFlags(const VkGeometryFlagsKHR geometryFlags)98 inline void setGeometryFlags (const VkGeometryFlagsKHR geometryFlags) { m_geometryFlags = geometryFlags; }
getOpacityMicromap(void)99 inline VkAccelerationStructureTrianglesOpacityMicromapEXT& getOpacityMicromap(void) { return m_opacityGeometryMicromap; }
getHasOpacityMicromap(void) const100 inline bool getHasOpacityMicromap (void) const { return m_hasOpacityMicromap; }
setOpacityMicromap(const VkAccelerationStructureTrianglesOpacityMicromapEXT * opacityGeometryMicromap)101 inline void setOpacityMicromap (const VkAccelerationStructureTrianglesOpacityMicromapEXT* opacityGeometryMicromap) { m_hasOpacityMicromap = true; m_opacityGeometryMicromap = *opacityGeometryMicromap; }
102 virtual deUint32 getVertexCount (void) const = 0;
103 virtual const deUint8* getVertexPointer (void) const = 0;
104 virtual VkDeviceSize getVertexStride (void) const = 0;
105 virtual VkDeviceSize getAABBStride (void) const = 0;
106 virtual size_t getVertexByteSize (void) const = 0;
107 virtual deUint32 getIndexCount (void) const = 0;
108 virtual const deUint8* getIndexPointer (void) const = 0;
109 virtual VkDeviceSize getIndexStride (void) const = 0;
110 virtual size_t getIndexByteSize (void) const = 0;
111 virtual deUint32 getPrimitiveCount (void) const = 0;
112 virtual void addVertex (const tcu::Vec3& vertex) = 0;
113 virtual void addIndex (const deUint32& index) = 0;
114 private:
115 VkGeometryTypeKHR m_geometryType;
116 VkFormat m_vertexFormat;
117 VkIndexType m_indexType;
118 VkGeometryFlagsKHR m_geometryFlags;
119 bool m_hasOpacityMicromap;
120 VkAccelerationStructureTrianglesOpacityMicromapEXT m_opacityGeometryMicromap;
121 };
122
123 template <typename T>
convertSatRte(float f)124 inline T convertSatRte (float f)
125 {
126 // \note Doesn't work for 64-bit types
127 DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64));
128 DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
129
130 deInt64 minVal = std::numeric_limits<T>::min();
131 deInt64 maxVal = std::numeric_limits<T>::max();
132 float q = deFloatFrac(f);
133 deInt64 intVal = (deInt64)(f-q);
134
135 // Rounding.
136 if (q == 0.5f)
137 {
138 if (intVal % 2 != 0)
139 intVal++;
140 }
141 else if (q > 0.5f)
142 intVal++;
143 // else Don't add anything
144
145 // Saturate.
146 intVal = de::max(minVal, de::min(maxVal, intVal));
147
148 return (T)intVal;
149 }
150
151 // Converts float to signed integer with variable width.
152 // Source float is assumed to be in the [-1, 1] range.
153 template <typename T>
deFloat32ToSNorm(float src)154 inline T deFloat32ToSNorm (float src)
155 {
156 DE_STATIC_ASSERT(std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed);
157 const T range = std::numeric_limits<T>::max();
158 const T intVal = convertSatRte<T>(src * static_cast<float>(range));
159 return de::clamp<T>(intVal, -range, range);
160 }
161
162 typedef tcu::Vector<deFloat16, 2> Vec2_16;
163 typedef tcu::Vector<deFloat16, 3> Vec3_16;
164 typedef tcu::Vector<deFloat16, 4> Vec4_16;
165 typedef tcu::Vector<deInt16, 2> Vec2_16SNorm;
166 typedef tcu::Vector<deInt16, 3> Vec3_16SNorm;
167 typedef tcu::Vector<deInt16, 4> Vec4_16SNorm;
168 typedef tcu::Vector<deInt8, 2> Vec2_8SNorm;
169 typedef tcu::Vector<deInt8, 3> Vec3_8SNorm;
170 typedef tcu::Vector<deInt8, 4> Vec4_8SNorm;
171
172 template<typename V> VkFormat vertexFormatFromType ();
vertexFormatFromType()173 template<> inline VkFormat vertexFormatFromType<tcu::Vec2> () { return VK_FORMAT_R32G32_SFLOAT; }
vertexFormatFromType()174 template<> inline VkFormat vertexFormatFromType<tcu::Vec3> () { return VK_FORMAT_R32G32B32_SFLOAT; }
vertexFormatFromType()175 template<> inline VkFormat vertexFormatFromType<tcu::Vec4> () { return VK_FORMAT_R32G32B32A32_SFLOAT; }
vertexFormatFromType()176 template<> inline VkFormat vertexFormatFromType<Vec2_16> () { return VK_FORMAT_R16G16_SFLOAT; }
vertexFormatFromType()177 template<> inline VkFormat vertexFormatFromType<Vec3_16> () { return VK_FORMAT_R16G16B16_SFLOAT; }
vertexFormatFromType()178 template<> inline VkFormat vertexFormatFromType<Vec4_16> () { return VK_FORMAT_R16G16B16A16_SFLOAT; }
vertexFormatFromType()179 template<> inline VkFormat vertexFormatFromType<Vec2_16SNorm> () { return VK_FORMAT_R16G16_SNORM; }
vertexFormatFromType()180 template<> inline VkFormat vertexFormatFromType<Vec3_16SNorm> () { return VK_FORMAT_R16G16B16_SNORM; }
vertexFormatFromType()181 template<> inline VkFormat vertexFormatFromType<Vec4_16SNorm> () { return VK_FORMAT_R16G16B16A16_SNORM; }
vertexFormatFromType()182 template<> inline VkFormat vertexFormatFromType<tcu::DVec2> () { return VK_FORMAT_R64G64_SFLOAT; }
vertexFormatFromType()183 template<> inline VkFormat vertexFormatFromType<tcu::DVec3> () { return VK_FORMAT_R64G64B64_SFLOAT; }
vertexFormatFromType()184 template<> inline VkFormat vertexFormatFromType<tcu::DVec4> () { return VK_FORMAT_R64G64B64A64_SFLOAT; }
vertexFormatFromType()185 template<> inline VkFormat vertexFormatFromType<Vec2_8SNorm> () { return VK_FORMAT_R8G8_SNORM; }
vertexFormatFromType()186 template<> inline VkFormat vertexFormatFromType<Vec3_8SNorm> () { return VK_FORMAT_R8G8B8_SNORM; }
vertexFormatFromType()187 template<> inline VkFormat vertexFormatFromType<Vec4_8SNorm> () { return VK_FORMAT_R8G8B8A8_SNORM; }
188
189 struct EmptyIndex {};
190 template<typename I> VkIndexType indexTypeFromType ();
indexTypeFromType()191 template<> inline VkIndexType indexTypeFromType<deUint16> () { return VK_INDEX_TYPE_UINT16; }
indexTypeFromType()192 template<> inline VkIndexType indexTypeFromType<deUint32> () { return VK_INDEX_TYPE_UINT32; }
indexTypeFromType()193 template<> inline VkIndexType indexTypeFromType<EmptyIndex> () { return VK_INDEX_TYPE_NONE_KHR; }
194
195 template<typename V> V convertFloatTo (const tcu::Vec3& vertex);
convertFloatTo(const tcu::Vec3 & vertex)196 template<> inline tcu::Vec2 convertFloatTo<tcu::Vec2> (const tcu::Vec3& vertex) { return tcu::Vec2(vertex.x(), vertex.y()); }
convertFloatTo(const tcu::Vec3 & vertex)197 template<> inline tcu::Vec3 convertFloatTo<tcu::Vec3> (const tcu::Vec3& vertex) { return vertex; }
convertFloatTo(const tcu::Vec3 & vertex)198 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)199 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)200 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)201 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)202 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)203 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)204 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)205 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)206 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)207 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)208 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)209 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)210 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)); }
211
212 template<typename V> V convertIndexTo (deUint32 index);
convertIndexTo(deUint32 index)213 template<> inline EmptyIndex convertIndexTo<EmptyIndex> (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Cannot add empty index"); }
convertIndexTo(deUint32 index)214 template<> inline deUint16 convertIndexTo<deUint16> (deUint32 index) { return static_cast<deUint16>(index); }
convertIndexTo(deUint32 index)215 template<> inline deUint32 convertIndexTo<deUint32> (deUint32 index) { return index; }
216
217 template<typename V, typename I>
218 class RaytracedGeometry : public RaytracedGeometryBase
219 {
220 public:
221 RaytracedGeometry () = delete;
222 RaytracedGeometry (const RaytracedGeometry& geometry) = delete;
223 RaytracedGeometry (VkGeometryTypeKHR geometryType, deUint32 paddingBlocks = 0u);
224 RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices = std::vector<I>(), deUint32 paddingBlocks = 0u);
225
226 deUint32 getVertexCount (void) const override;
227 const deUint8* getVertexPointer (void) const override;
228 VkDeviceSize getVertexStride (void) const override;
229 VkDeviceSize getAABBStride (void) const override;
230 size_t getVertexByteSize (void) const override;
231 deUint32 getIndexCount (void) const override;
232 const deUint8* getIndexPointer (void) const override;
233 VkDeviceSize getIndexStride (void) const override;
234 size_t getIndexByteSize (void) const override;
235 deUint32 getPrimitiveCount (void) const override;
236
237 void addVertex (const tcu::Vec3& vertex) override;
238 void addIndex (const deUint32& index) override;
239
240 private:
241 void init (); // To be run in constructors.
242 void checkGeometryType () const; // Checks geometry type is valid.
243 void calcBlockSize (); // Calculates and saves vertex buffer block size.
244 size_t getBlockSize () const; // Return stored vertex buffer block size.
245 void addNativeVertex (const V& vertex); // Adds new vertex in native format.
246
247 // The implementation below stores vertices as byte blocks to take the requested padding into account. m_vertices is the array
248 // of bytes containing vertex data.
249 //
250 // 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
251 // equivalent to:
252 //
253 // struct Vertex
254 // {
255 // V vertex;
256 // deUint8 padding[m_paddingBlocks * sizeof(V)];
257 // };
258 //
259 // For AABBs, the padding block has a size that is a multiple of kAABBPadBaseSize (see below) and vertices are stored in pairs
260 // before the padding block. This is equivalent to:
261 //
262 // struct VertexPair
263 // {
264 // V vertices[2];
265 // deUint8 padding[m_paddingBlocks * kAABBPadBaseSize];
266 // };
267 //
268 // The size of each pseudo-structure above is saved to one of the correspoding union members below.
269 union BlockSize
270 {
271 size_t trianglesBlockSize;
272 size_t aabbsBlockSize;
273 };
274
275 const deUint32 m_paddingBlocks;
276 size_t m_vertexCount;
277 std::vector<deUint8> m_vertices; // Vertices are stored as byte blocks.
278 std::vector<I> m_indices; // Indices are stored natively.
279 BlockSize m_blockSize; // For m_vertices.
280
281 // Data sizes.
282 static constexpr size_t kVertexSize = sizeof(V);
283 static constexpr size_t kIndexSize = sizeof(I);
284 static constexpr size_t kAABBPadBaseSize = 8; // As required by the spec.
285 };
286
287 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,deUint32 paddingBlocks)288 RaytracedGeometry<V, I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, deUint32 paddingBlocks)
289 : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
290 , m_paddingBlocks(paddingBlocks)
291 , m_vertexCount(0)
292 {
293 init();
294 }
295
296 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,const std::vector<V> & vertices,const std::vector<I> & indices,deUint32 paddingBlocks)297 RaytracedGeometry<V,I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices, deUint32 paddingBlocks)
298 : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
299 , m_paddingBlocks(paddingBlocks)
300 , m_vertexCount(0)
301 , m_vertices()
302 , m_indices(indices)
303 {
304 init();
305 for (const auto& vertex : vertices)
306 addNativeVertex(vertex);
307 }
308
309 template<typename V, typename I>
getVertexCount(void) const310 deUint32 RaytracedGeometry<V,I>::getVertexCount (void) const
311 {
312 return (isTrianglesType() ? static_cast<deUint32>(m_vertexCount) : 0u);
313 }
314
315 template<typename V, typename I>
getVertexPointer(void) const316 const deUint8* RaytracedGeometry<V, I>::getVertexPointer (void) const
317 {
318 DE_ASSERT(!m_vertices.empty());
319 return reinterpret_cast<const deUint8*>(m_vertices.data());
320 }
321
322 template<typename V, typename I>
getVertexStride(void) const323 VkDeviceSize RaytracedGeometry<V,I>::getVertexStride (void) const
324 {
325 return ((!isTrianglesType()) ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
326 }
327
328 template<typename V, typename I>
getAABBStride(void) const329 VkDeviceSize RaytracedGeometry<V, I>::getAABBStride (void) const
330 {
331 return (isTrianglesType() ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
332 }
333
334 template<typename V, typename I>
getVertexByteSize(void) const335 size_t RaytracedGeometry<V, I>::getVertexByteSize (void) const
336 {
337 return m_vertices.size();
338 }
339
340 template<typename V, typename I>
getIndexCount(void) const341 deUint32 RaytracedGeometry<V, I>::getIndexCount (void) const
342 {
343 return static_cast<deUint32>(isTrianglesType() ? m_indices.size() : 0);
344 }
345
346 template<typename V, typename I>
getIndexPointer(void) const347 const deUint8* RaytracedGeometry<V, I>::getIndexPointer (void) const
348 {
349 const auto indexCount = getIndexCount();
350 DE_UNREF(indexCount); // For release builds.
351 DE_ASSERT(indexCount > 0u);
352
353 return reinterpret_cast<const deUint8*>(m_indices.data());
354 }
355
356 template<typename V, typename I>
getIndexStride(void) const357 VkDeviceSize RaytracedGeometry<V, I>::getIndexStride (void) const
358 {
359 return static_cast<VkDeviceSize>(kIndexSize);
360 }
361
362 template<typename V, typename I>
getIndexByteSize(void) const363 size_t RaytracedGeometry<V, I>::getIndexByteSize (void) const
364 {
365 const auto indexCount = getIndexCount();
366 DE_ASSERT(indexCount > 0u);
367
368 return (indexCount * kIndexSize);
369 }
370
371 template<typename V, typename I>
getPrimitiveCount(void) const372 deUint32 RaytracedGeometry<V,I>::getPrimitiveCount (void) const
373 {
374 return static_cast<deUint32>(isTrianglesType() ? (usesIndices() ? m_indices.size() / 3 : m_vertexCount / 3) : (m_vertexCount / 2));
375 }
376
377 template<typename V, typename I>
addVertex(const tcu::Vec3 & vertex)378 void RaytracedGeometry<V, I>::addVertex (const tcu::Vec3& vertex)
379 {
380 addNativeVertex(convertFloatTo<V>(vertex));
381 }
382
383 template<typename V, typename I>
addNativeVertex(const V & vertex)384 void RaytracedGeometry<V, I>::addNativeVertex (const V& vertex)
385 {
386 const auto oldSize = m_vertices.size();
387 const auto blockSize = getBlockSize();
388
389 if (isTrianglesType())
390 {
391 // Reserve new block, copy vertex at the beginning of the new block.
392 m_vertices.resize(oldSize + blockSize, deUint8{0});
393 deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
394 }
395 else // AABB
396 {
397 if (m_vertexCount % 2 == 0)
398 {
399 // New block needed.
400 m_vertices.resize(oldSize + blockSize, deUint8{0});
401 deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
402 }
403 else
404 {
405 // Insert in the second position of last existing block.
406 //
407 // Vertex Size
408 // +-------+
409 // +-------------+------------+----------------------------------------+
410 // | | | ... | vertex vertex padding |
411 // +-------------+------------+----------------+-----------------------+
412 // +-----------------------+
413 // Block Size
414 // +-------------------------------------------------------------------+
415 // Old Size
416 //
417 deMemcpy(&m_vertices[oldSize - blockSize + kVertexSize], &vertex, kVertexSize);
418 }
419 }
420
421 ++m_vertexCount;
422 }
423
424 template<typename V, typename I>
addIndex(const deUint32 & index)425 void RaytracedGeometry<V, I>::addIndex (const deUint32& index)
426 {
427 m_indices.push_back(convertIndexTo<I>(index));
428 }
429
430 template<typename V, typename I>
init()431 void RaytracedGeometry<V, I>::init ()
432 {
433 checkGeometryType();
434 calcBlockSize();
435 }
436
437 template<typename V, typename I>
checkGeometryType() const438 void RaytracedGeometry<V, I>::checkGeometryType () const
439 {
440 const auto geometryType = getGeometryType();
441 DE_UNREF(geometryType); // For release builds.
442 DE_ASSERT(geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
443 }
444
445 template<typename V, typename I>
calcBlockSize()446 void RaytracedGeometry<V, I>::calcBlockSize ()
447 {
448 if (isTrianglesType())
449 m_blockSize.trianglesBlockSize = kVertexSize * static_cast<size_t>(1u + m_paddingBlocks);
450 else
451 m_blockSize.aabbsBlockSize = 2 * kVertexSize + m_paddingBlocks * kAABBPadBaseSize;
452 }
453
454 template<typename V, typename I>
getBlockSize() const455 size_t RaytracedGeometry<V, I>::getBlockSize () const
456 {
457 return (isTrianglesType() ? m_blockSize.trianglesBlockSize : m_blockSize.aabbsBlockSize);
458 }
459
460 de::SharedPtr<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType, bool padVertices = false);
461
462 VkDeviceAddress getBufferDeviceAddress ( const DeviceInterface& vkd,
463 const VkDevice device,
464 const VkBuffer buffer,
465 VkDeviceSize offset );
466
467 // type used for creating a deep serialization/deserialization of top-level acceleration structures
468 class SerialInfo
469 {
470 std::vector<deUint64> m_addresses;
471 std::vector<VkDeviceSize> m_sizes;
472 public:
473
474 SerialInfo() = default;
475
476 // addresses: { (owner-top-level AS address) [, (first bottom_level AS address), (second bottom_level AS address), ...] }
477 // sizes: { (owner-top-level AS serial size) [, (first bottom_level AS serial size), (second bottom_level AS serial size), ...] }
SerialInfo(const std::vector<deUint64> & addresses,const std::vector<VkDeviceSize> & sizes)478 SerialInfo(const std::vector<deUint64>& addresses, const std::vector<VkDeviceSize>& sizes)
479 : m_addresses(addresses), m_sizes(sizes)
480 {
481 DE_ASSERT(!addresses.empty() && addresses.size() == sizes.size());
482 }
483
addresses() const484 const std::vector<deUint64>& addresses () const { return m_addresses; }
sizes() const485 const std::vector<VkDeviceSize>& sizes () const { return m_sizes; }
486 };
487
488 class SerialStorage
489 {
490 public:
491 enum
492 {
493 DE_SERIALIZED_FIELD(DRIVER_UUID, VK_UUID_SIZE), // VK_UUID_SIZE bytes of data matching VkPhysicalDeviceIDProperties::driverUUID
494 DE_SERIALIZED_FIELD(COMPAT_UUID, VK_UUID_SIZE), // VK_UUID_SIZE bytes of data identifying the compatibility for comparison using vkGetDeviceAccelerationStructureCompatibilityKHR
495 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
496 DE_SERIALIZED_FIELD(DESERIALIZED_SIZE, sizeof(deUint64)), // A 64-bit integer of the deserialized size to be passed in to VkAccelerationStructureCreateInfoKHR::size
497 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.
498 SERIAL_STORAGE_SIZE_MIN
499 };
500
501 // An old fashion C-style structure that simplifies an access to the AS header
502 struct alignas(16) AccelerationStructureHeader
503 {
504 union {
505 struct {
506 deUint8 driverUUID[VK_UUID_SIZE];
507 deUint8 compactUUID[VK_UUID_SIZE];
508 };
509 deUint8 uuids[VK_UUID_SIZE * 2];
510 };
511 deUint64 serializedSize;
512 deUint64 deserializedSize;
513 deUint64 handleCount;
514 VkDeviceAddress handleArray[1];
515 };
516
517 SerialStorage () = delete;
518 SerialStorage (const DeviceInterface& vk,
519 const VkDevice device,
520 Allocator& allocator,
521 const VkAccelerationStructureBuildTypeKHR buildType,
522 const VkDeviceSize storageSize);
523 // An additional constructor for creating a deep copy of top-level AS's.
524 SerialStorage (const DeviceInterface& vk,
525 const VkDevice device,
526 Allocator& allocator,
527 const VkAccelerationStructureBuildTypeKHR buildType,
528 const SerialInfo& SerialInfo);
529
530 // below methods will return host addres if AS was build on cpu and device addres when it was build on gpu
531 VkDeviceOrHostAddressKHR getAddress (const DeviceInterface& vk,
532 const VkDevice device,
533 const VkAccelerationStructureBuildTypeKHR buildType);
534 VkDeviceOrHostAddressConstKHR getAddressConst (const DeviceInterface& vk,
535 const VkDevice device,
536 const VkAccelerationStructureBuildTypeKHR buildType);
537
538 // this methods retun host address regardless of where AS was built
539 VkDeviceOrHostAddressKHR getHostAddress (VkDeviceSize offset = 0);
540 VkDeviceOrHostAddressConstKHR getHostAddressConst (VkDeviceSize offset = 0);
541
542 // works the similar way as getHostAddressConst() but returns more readable/intuitive object
543 AccelerationStructureHeader* getASHeader ();
544 bool hasDeepFormat () const;
545 de::SharedPtr<SerialStorage> getBottomStorage (deUint32 index) const;
546
547 VkDeviceSize getStorageSize () const;
548 const SerialInfo& getSerialInfo () const;
549 deUint64 getDeserializedSize ();
550
551 protected:
552 const VkAccelerationStructureBuildTypeKHR m_buildType;
553 const VkDeviceSize m_storageSize;
554 const SerialInfo m_serialInfo;
555 de::MovePtr<BufferWithMemory> m_buffer;
556 std::vector<de::SharedPtr<SerialStorage>> m_bottoms;
557 };
558
559 class BottomLevelAccelerationStructure
560 {
561 public:
562 static deUint32 getRequiredAllocationCount (void);
563
564 BottomLevelAccelerationStructure ();
565 BottomLevelAccelerationStructure (const BottomLevelAccelerationStructure& other) = delete;
566 virtual ~BottomLevelAccelerationStructure ();
567
568 virtual void setGeometryData (const std::vector<tcu::Vec3>& geometryData,
569 const bool triangles,
570 const VkGeometryFlagsKHR geometryFlags = 0u );
571 virtual void setDefaultGeometryData (const VkShaderStageFlagBits testStage,
572 const VkGeometryFlagsKHR geometryFlags = 0u );
573 virtual void setGeometryCount (const size_t geometryCount);
574 virtual void addGeometry (de::SharedPtr<RaytracedGeometryBase>& raytracedGeometry);
575 virtual void addGeometry (const std::vector<tcu::Vec3>& geometryData,
576 const bool triangles,
577 const VkGeometryFlagsKHR geometryFlags = 0u,
578 const VkAccelerationStructureTrianglesOpacityMicromapEXT *opacityGeometryMicromap = DE_NULL );
579
580 virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL;
581 virtual VkAccelerationStructureBuildTypeKHR getBuildType () const = 0;
582 virtual void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) = DE_NULL;
583 virtual void setCreateGeneric (bool createGeneric) = 0;
584 virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) = DE_NULL;
585 virtual void setBuildWithoutGeometries (bool buildWithoutGeometries) = 0;
586 virtual void setBuildWithoutPrimitives (bool buildWithoutPrimitives) = 0;
587 virtual void setDeferredOperation (const bool deferredOperation,
588 const deUint32 workerThreadCount = 0u ) = DE_NULL;
589 virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL;
590 virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer,
591 const VkDeviceSize indirectBufferOffset,
592 const deUint32 indirectBufferStride) = DE_NULL;
593 virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL;
594 VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes () const;
595
596 // methods specific for each acceleration structure
597 virtual void create (const DeviceInterface& vk,
598 const VkDevice device,
599 Allocator& allocator,
600 VkDeviceSize structureSize,
601 VkDeviceAddress deviceAddress = 0u,
602 const void* pNext = DE_NULL,
603 const MemoryRequirement& addMemoryRequirement = MemoryRequirement::Any) = DE_NULL;
604 virtual void build (const DeviceInterface& vk,
605 const VkDevice device,
606 const VkCommandBuffer cmdBuffer) = DE_NULL;
607 virtual void copyFrom (const DeviceInterface& vk,
608 const VkDevice device,
609 const VkCommandBuffer cmdBuffer,
610 BottomLevelAccelerationStructure* accelerationStructure,
611 bool compactCopy) = DE_NULL;
612
613 virtual void serialize (const DeviceInterface& vk,
614 const VkDevice device,
615 const VkCommandBuffer cmdBuffer,
616 SerialStorage* storage) = DE_NULL;
617 virtual void deserialize (const DeviceInterface& vk,
618 const VkDevice device,
619 const VkCommandBuffer cmdBuffer,
620 SerialStorage* storage) = DE_NULL;
621
622 // helper methods for typical acceleration structure creation tasks
623 void createAndBuild (const DeviceInterface& vk,
624 const VkDevice device,
625 const VkCommandBuffer cmdBuffer,
626 Allocator& allocator,
627 VkDeviceAddress deviceAddress = 0u );
628 void createAndCopyFrom (const DeviceInterface& vk,
629 const VkDevice device,
630 const VkCommandBuffer cmdBuffer,
631 Allocator& allocator,
632 BottomLevelAccelerationStructure* accelerationStructure,
633 VkDeviceSize compactCopySize = 0u,
634 VkDeviceAddress deviceAddress = 0u);
635 void createAndDeserializeFrom (const DeviceInterface& vk,
636 const VkDevice device,
637 const VkCommandBuffer cmdBuffer,
638 Allocator& allocator,
639 SerialStorage* storage,
640 VkDeviceAddress deviceAddress = 0u);
641
642 virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL;
643 protected:
644 std::vector<de::SharedPtr<RaytracedGeometryBase>> m_geometriesData;
645 VkDeviceSize m_structureSize;
646 VkDeviceSize m_updateScratchSize;
647 VkDeviceSize m_buildScratchSize;
648 };
649
650 de::MovePtr<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ();
651
652 /**
653 * @brief Implements a pool of BottomLevelAccelerationStructure
654 */
655 class BottomLevelAccelerationStructurePool
656 {
657 public:
658 typedef de::SharedPtr<BottomLevelAccelerationStructure> BlasPtr;
659 struct BlasInfo {
660 VkDeviceSize structureSize;
661 VkDeviceAddress deviceAddress;
662 };
663
664 BottomLevelAccelerationStructurePool();
665 virtual ~BottomLevelAccelerationStructurePool();
666
at(deUint32 index) const667 BlasPtr at (deUint32 index) const { return m_structs[index]; }
operator [](deUint32 index) const668 BlasPtr operator[] (deUint32 index) const { return m_structs[index]; }
structures() const669 auto structures () const -> const std::vector<BlasPtr>& { return m_structs; }
structCount() const670 deUint32 structCount () const { return static_cast<deUint32>(m_structs.size()); }
671
672 // defines how many structures will be packet in single buffer
batchStructCount() const673 deUint32 batchStructCount () const {return m_batchStructCount; }
674 void batchStructCount (const deUint32& value);
675
676 // defines how many geometries (vertices and/or indices) will be packet in single buffer
batchGeomCount() const677 deUint32 batchGeomCount () const {return m_batchGeomCount; }
batchGeomCount(const deUint32 & value)678 void batchGeomCount (const deUint32& value) { m_batchGeomCount = value; }
679
tryCachedMemory() const680 bool tryCachedMemory () const { return m_tryCachedMemory; }
tryCachedMemory(const bool cachedMemory)681 void tryCachedMemory (const bool cachedMemory) { m_tryCachedMemory = cachedMemory; }
682
683 BlasPtr add (VkDeviceSize structureSize = 0,
684 VkDeviceAddress deviceAddress = 0);
685 /**
686 * @brief Creates previously added bottoms at a time.
687 * @note All geometries must be known before call this method.
688 */
689 void batchCreate (const DeviceInterface& vkd,
690 const VkDevice device,
691 Allocator& allocator);
692 void batchCreateAdjust (const DeviceInterface& vkd,
693 const VkDevice device,
694 Allocator& allocator,
695 const VkDeviceSize maxBufferSize);
696 void batchBuild (const DeviceInterface& vk,
697 const VkDevice device,
698 VkCommandBuffer cmdBuffer);
699 void batchBuild (const DeviceInterface& vk,
700 const VkDevice device,
701 VkCommandPool cmdPool,
702 VkQueue queue,
703 qpWatchDog* watchDog);
704 size_t getAllocationCount () const;
705 size_t getAllocationCount (const DeviceInterface& vk,
706 const VkDevice device,
707 const VkDeviceSize maxBufferSize) const;
708 auto getAllocationSizes (const DeviceInterface& vk, // (strBuff, scratchBuff, vertBuff, indexBuff)
709 const VkDevice device) const -> tcu::Vector<VkDeviceSize, 4>;
710 protected:
711 deUint32 m_batchStructCount; // default is 4
712 deUint32 m_batchGeomCount; // default is 0, if zero then batchStructCount is used
713 std::vector<BlasInfo> m_infos;
714 std::vector<BlasPtr> m_structs;
715 bool m_createOnce;
716 bool m_tryCachedMemory;
717 VkDeviceSize m_structsBuffSize;
718 VkDeviceSize m_updatesScratchSize;
719 VkDeviceSize m_buildsScratchSize;
720 VkDeviceSize m_verticesSize;
721 VkDeviceSize m_indicesSize;
722
723 protected:
724 struct Impl;
725 Impl* m_impl;
726 };
727
728 struct InstanceData
729 {
InstanceDatavk::InstanceData730 InstanceData (VkTransformMatrixKHR matrix_,
731 deUint32 instanceCustomIndex_,
732 deUint32 mask_,
733 deUint32 instanceShaderBindingTableRecordOffset_,
734 VkGeometryInstanceFlagsKHR flags_)
735 : matrix(matrix_), instanceCustomIndex(instanceCustomIndex_), mask(mask_), instanceShaderBindingTableRecordOffset(instanceShaderBindingTableRecordOffset_), flags(flags_)
736 {
737 }
738 VkTransformMatrixKHR matrix;
739 deUint32 instanceCustomIndex;
740 deUint32 mask;
741 deUint32 instanceShaderBindingTableRecordOffset;
742 VkGeometryInstanceFlagsKHR flags;
743 };
744
745 class TopLevelAccelerationStructure
746 {
747 public:
748 struct CreationSizes
749 {
750 VkDeviceSize structure;
751 VkDeviceSize updateScratch;
752 VkDeviceSize buildScratch;
753 VkDeviceSize instancePointers;
754 VkDeviceSize instancesBuffer;
755 VkDeviceSize sum () const;
756 };
757
758 static deUint32 getRequiredAllocationCount (void);
759
760 TopLevelAccelerationStructure ();
761 TopLevelAccelerationStructure (const TopLevelAccelerationStructure& other) = delete;
762 virtual ~TopLevelAccelerationStructure ();
763
764 virtual void setInstanceCount (const size_t instanceCount);
765 virtual void addInstance (de::SharedPtr<BottomLevelAccelerationStructure> bottomLevelStructure,
766 const VkTransformMatrixKHR& matrix = identityMatrix3x4,
767 deUint32 instanceCustomIndex = 0,
768 deUint32 mask = 0xFF,
769 deUint32 instanceShaderBindingTableRecordOffset = 0,
770 VkGeometryInstanceFlagsKHR flags = VkGeometryInstanceFlagBitsKHR(0u) );
771
772 virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL;
773 virtual void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) = DE_NULL;
774 virtual void setCreateGeneric (bool createGeneric) = 0;
775 virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) = DE_NULL;
776 virtual void setBuildWithoutPrimitives (bool buildWithoutPrimitives) = 0;
777 virtual void setInactiveInstances (bool inactiveInstances) = 0;
778 virtual void setDeferredOperation (const bool deferredOperation,
779 const deUint32 workerThreadCount = 0u) = DE_NULL;
780 virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL;
781 virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer,
782 const VkDeviceSize indirectBufferOffset,
783 const deUint32 indirectBufferStride) = DE_NULL;
784 virtual void setUsePPGeometries (const bool usePPGeometries) = 0;
785 virtual void setTryCachedMemory (const bool tryCachedMemory) = 0;
786 virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL;
787 VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes () const;
788
789 // methods specific for each acceleration structure
790 virtual void getCreationSizes (const DeviceInterface& vk,
791 const VkDevice device,
792 const VkDeviceSize structureSize,
793 CreationSizes& sizes) = 0;
794 virtual void create (const DeviceInterface& vk,
795 const VkDevice device,
796 Allocator& allocator,
797 VkDeviceSize structureSize = 0u,
798 VkDeviceAddress deviceAddress = 0u,
799 const void* pNext = DE_NULL,
800 const MemoryRequirement& addMemoryRequirement = MemoryRequirement::Any) = DE_NULL;
801 virtual void build (const DeviceInterface& vk,
802 const VkDevice device,
803 const VkCommandBuffer cmdBuffer) = DE_NULL;
804 virtual void copyFrom (const DeviceInterface& vk,
805 const VkDevice device,
806 const VkCommandBuffer cmdBuffer,
807 TopLevelAccelerationStructure* accelerationStructure,
808 bool compactCopy) = DE_NULL;
809
810 virtual void serialize (const DeviceInterface& vk,
811 const VkDevice device,
812 const VkCommandBuffer cmdBuffer,
813 SerialStorage* storage) = DE_NULL;
814 virtual void deserialize (const DeviceInterface& vk,
815 const VkDevice device,
816 const VkCommandBuffer cmdBuffer,
817 SerialStorage* storage) = DE_NULL;
818
819 virtual std::vector<VkDeviceSize> getSerializingSizes (const DeviceInterface& vk,
820 const VkDevice device,
821 const VkQueue queue,
822 const deUint32 queueFamilyIndex) = DE_NULL;
823
824 virtual std::vector<deUint64> getSerializingAddresses (const DeviceInterface& vk,
825 const VkDevice device) const = DE_NULL;
826
827 // helper methods for typical acceleration structure creation tasks
828 void createAndBuild (const DeviceInterface& vk,
829 const VkDevice device,
830 const VkCommandBuffer cmdBuffer,
831 Allocator& allocator,
832 VkDeviceAddress deviceAddress = 0u );
833 void createAndCopyFrom (const DeviceInterface& vk,
834 const VkDevice device,
835 const VkCommandBuffer cmdBuffer,
836 Allocator& allocator,
837 TopLevelAccelerationStructure* accelerationStructure,
838 VkDeviceSize compactCopySize = 0u,
839 VkDeviceAddress deviceAddress = 0u);
840 void createAndDeserializeFrom (const DeviceInterface& vk,
841 const VkDevice device,
842 const VkCommandBuffer cmdBuffer,
843 Allocator& allocator,
844 SerialStorage* storage,
845 VkDeviceAddress deviceAddress = 0u);
846
847 virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL;
848
849 virtual void updateInstanceMatrix (const DeviceInterface& vk,
850 const VkDevice device,
851 size_t instanceIndex,
852 const VkTransformMatrixKHR& matrix) = 0;
853
854 protected:
855 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > m_bottomLevelInstances;
856 std::vector<InstanceData> m_instanceData;
857 VkDeviceSize m_structureSize;
858 VkDeviceSize m_updateScratchSize;
859 VkDeviceSize m_buildScratchSize;
860
861 virtual void createAndDeserializeBottoms (const DeviceInterface& vk,
862 const VkDevice device,
863 const VkCommandBuffer cmdBuffer,
864 Allocator& allocator,
865 SerialStorage* storage) = DE_NULL;
866 };
867
868 de::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ();
869
870 template<class ASType> de::MovePtr<ASType> makeAccelerationStructure ();
makeAccelerationStructure()871 template<> inline de::MovePtr<BottomLevelAccelerationStructure> makeAccelerationStructure () { return makeBottomLevelAccelerationStructure(); }
makeAccelerationStructure()872 template<> inline de::MovePtr<TopLevelAccelerationStructure> makeAccelerationStructure () { return makeTopLevelAccelerationStructure(); }
873
874 bool queryAccelerationStructureSize (const DeviceInterface& vk,
875 const VkDevice device,
876 const VkCommandBuffer cmdBuffer,
877 const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
878 VkAccelerationStructureBuildTypeKHR buildType,
879 const VkQueryPool queryPool,
880 VkQueryType queryType,
881 deUint32 firstQuery,
882 std::vector<VkDeviceSize>& results);
883
884 class RayTracingPipeline
885 {
886 public:
887 class CompileRequiredError : public std::runtime_error
888 {
889 public:
CompileRequiredError(const std::string & error)890 CompileRequiredError (const std::string& error)
891 : std::runtime_error(error)
892 {}
893 };
894
895 RayTracingPipeline ();
896 ~RayTracingPipeline ();
897
898 void addShader (VkShaderStageFlagBits shaderStage,
899 Move<VkShaderModule> shaderModule,
900 deUint32 group,
901 const VkSpecializationInfo* specializationInfo = nullptr,
902 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
903 const void* pipelineShaderStageCreateInfopNext = nullptr);
904 void addShader (VkShaderStageFlagBits shaderStage,
905 de::SharedPtr<Move<VkShaderModule>> shaderModule,
906 deUint32 group,
907 const VkSpecializationInfo* specializationInfoPtr = nullptr,
908 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
909 const void* pipelineShaderStageCreateInfopNext = nullptr);
910 void addShader (VkShaderStageFlagBits shaderStage,
911 VkShaderModule shaderModule,
912 deUint32 group,
913 const VkSpecializationInfo* specializationInfo = nullptr,
914 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
915 const void* pipelineShaderStageCreateInfopNext = nullptr);
916 void addLibrary (de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary);
917 Move<VkPipeline> createPipeline (const DeviceInterface& vk,
918 const VkDevice device,
919 const VkPipelineLayout pipelineLayout,
920 const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries = std::vector<de::SharedPtr<Move<VkPipeline>>>());
921 Move<VkPipeline> createPipeline (const DeviceInterface& vk,
922 const VkDevice device,
923 const VkPipelineLayout pipelineLayout,
924 const std::vector<VkPipeline>& pipelineLibraries,
925 const VkPipelineCache pipelineCache);
926 std::vector<de::SharedPtr<Move<VkPipeline>>> createPipelineWithLibraries (const DeviceInterface& vk,
927 const VkDevice device,
928 const VkPipelineLayout pipelineLayout);
929 de::MovePtr<BufferWithMemory> createShaderBindingTable (const DeviceInterface& vk,
930 const VkDevice device,
931 const VkPipeline pipeline,
932 Allocator& allocator,
933 const deUint32& shaderGroupHandleSize,
934 const deUint32 shaderGroupBaseAlignment,
935 const deUint32& firstGroup,
936 const deUint32& groupCount,
937 const VkBufferCreateFlags& additionalBufferCreateFlags = VkBufferCreateFlags(0u),
938 const VkBufferUsageFlags& additionalBufferUsageFlags = VkBufferUsageFlags(0u),
939 const MemoryRequirement& additionalMemoryRequirement = MemoryRequirement::Any,
940 const VkDeviceAddress& opaqueCaptureAddress = 0u,
941 const deUint32 shaderBindingTableOffset = 0u,
942 const deUint32 shaderRecordSize = 0u,
943 const void** shaderGroupDataPtrPerGroup = nullptr,
944 const bool autoAlignRecords = true);
945 void setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags);
946 void setMaxRecursionDepth (const deUint32& maxRecursionDepth);
947 void setMaxPayloadSize (const deUint32& maxPayloadSize);
948 void setMaxAttributeSize (const deUint32& maxAttributeSize);
949 void setDeferredOperation (const bool deferredOperation,
950 const deUint32 workerThreadCount = 0);
951 void addDynamicState (const VkDynamicState& dynamicState);
952
953
954 protected:
955 Move<VkPipeline> createPipelineKHR (const DeviceInterface& vk,
956 const VkDevice device,
957 const VkPipelineLayout pipelineLayout,
958 const std::vector<VkPipeline>& pipelineLibraries,
959 const VkPipelineCache pipelineCache = DE_NULL);
960
961 std::vector<de::SharedPtr<Move<VkShaderModule> > > m_shadersModules;
962 std::vector<de::SharedPtr<de::MovePtr<RayTracingPipeline>>> m_pipelineLibraries;
963 std::vector<VkPipelineShaderStageCreateInfo> m_shaderCreateInfos;
964 std::vector<VkRayTracingShaderGroupCreateInfoKHR> m_shadersGroupCreateInfos;
965 VkPipelineCreateFlags m_pipelineCreateFlags;
966 deUint32 m_maxRecursionDepth;
967 deUint32 m_maxPayloadSize;
968 deUint32 m_maxAttributeSize;
969 bool m_deferredOperation;
970 deUint32 m_workerThreadCount;
971 std::vector<VkDynamicState> m_dynamicStates;
972 };
973
974 class RayTracingProperties
975 {
976 protected:
RayTracingProperties()977 RayTracingProperties () {}
978
979 public:
RayTracingProperties(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)980 RayTracingProperties (const InstanceInterface& vki,
981 const VkPhysicalDevice physicalDevice) { DE_UNREF(vki); DE_UNREF(physicalDevice); }
~RayTracingProperties()982 virtual ~RayTracingProperties () {}
983
984 virtual uint32_t getShaderGroupHandleSize (void) = 0;
985 virtual uint32_t getShaderGroupHandleAlignment (void) = 0;
986 virtual uint32_t getMaxRecursionDepth (void) = 0;
987 virtual uint32_t getMaxShaderGroupStride (void) = 0;
988 virtual uint32_t getShaderGroupBaseAlignment (void) = 0;
989 virtual uint64_t getMaxGeometryCount (void) = 0;
990 virtual uint64_t getMaxInstanceCount (void) = 0;
991 virtual uint64_t getMaxPrimitiveCount (void) = 0;
992 virtual uint32_t getMaxDescriptorSetAccelerationStructures (void) = 0;
993 virtual uint32_t getMaxRayDispatchInvocationCount (void) = 0;
994 virtual uint32_t getMaxRayHitAttributeSize (void) = 0;
995 virtual uint32_t getMaxMemoryAllocationCount (void) = 0;
996 };
997
998 de::MovePtr<RayTracingProperties> makeRayTracingProperties (const InstanceInterface& vki,
999 const VkPhysicalDevice physicalDevice);
1000
1001 void cmdTraceRays (const DeviceInterface& vk,
1002 VkCommandBuffer commandBuffer,
1003 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
1004 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
1005 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
1006 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
1007 deUint32 width,
1008 deUint32 height,
1009 deUint32 depth);
1010
1011 void cmdTraceRaysIndirect (const DeviceInterface& vk,
1012 VkCommandBuffer commandBuffer,
1013 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
1014 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
1015 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
1016 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
1017 VkDeviceAddress indirectDeviceAddress);
1018
1019 void cmdTraceRaysIndirect2 (const DeviceInterface& vk,
1020 VkCommandBuffer commandBuffer,
1021 VkDeviceAddress indirectDeviceAddress);
1022
1023
makeDeviceOrHostAddressConstKHR(const void * hostAddress)1024 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR(const void* hostAddress)
1025 {
1026 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1027 VkDeviceOrHostAddressConstKHR result;
1028
1029 deMemset(&result, 0, sizeof(result));
1030
1031 result.hostAddress = hostAddress;
1032
1033 return result;
1034 }
1035
makeDeviceOrHostAddressKHR(void * hostAddress)1036 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR(void* hostAddress)
1037 {
1038 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1039 VkDeviceOrHostAddressKHR result;
1040
1041 deMemset(&result, 0, sizeof(result));
1042
1043 result.hostAddress = hostAddress;
1044
1045 return result;
1046 }
1047
makeDeviceOrHostAddressConstKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)1048 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR(const DeviceInterface& vk,
1049 const VkDevice device,
1050 VkBuffer buffer,
1051 VkDeviceSize offset)
1052 {
1053 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1054 VkDeviceOrHostAddressConstKHR result;
1055
1056 deMemset(&result, 0, sizeof(result));
1057
1058 VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
1059 {
1060 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
1061 DE_NULL, // const void* pNext;
1062 buffer, // VkBuffer buffer
1063 };
1064 result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
1065
1066 return result;
1067 }
1068
makeDeviceOrHostAddressKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)1069 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR(const DeviceInterface& vk,
1070 const VkDevice device,
1071 VkBuffer buffer,
1072 VkDeviceSize offset)
1073 {
1074 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1075 VkDeviceOrHostAddressKHR result;
1076
1077 deMemset(&result, 0, sizeof(result));
1078
1079 VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
1080 {
1081 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
1082 DE_NULL, // const void* pNext;
1083 buffer, // VkBuffer buffer
1084 };
1085 result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
1086
1087 return result;
1088 }
1089
1090 #else
1091
1092 deUint32 rayTracingDefineAnything();
1093
1094 #endif // CTS_USES_VULKANSC
1095
1096 } // vk
1097
1098 #endif // _VKRAYTRACINGUTIL_HPP
1099