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