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