1 /*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Utilities for creating commonly used Vulkan objects
22 *//*--------------------------------------------------------------------*/
23
24 #include "vkRayTracingUtil.hpp"
25
26 #include "vkRefUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkObjUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkCmdUtil.hpp"
31
32 #include "deStringUtil.hpp"
33
34 #include <vector>
35 #include <string>
36 #include <thread>
37 #include <limits>
38
39 namespace vk
40 {
41
42 struct DeferredThreadParams
43 {
44 const DeviceInterface& vk;
45 VkDevice device;
46 VkDeferredOperationKHR deferredOperation;
47 VkResult result;
48 };
49
getFormatSimpleName(vk::VkFormat format)50 std::string getFormatSimpleName (vk::VkFormat format)
51 {
52 constexpr size_t kPrefixLen = 10; // strlen("VK_FORMAT_")
53 return de::toLower(de::toString(format).substr(kPrefixLen));
54 }
55
56 // Returns true if VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR needs to be supported for the given format.
isMandatoryAccelerationStructureVertexBufferFormat(vk::VkFormat format)57 static bool isMandatoryAccelerationStructureVertexBufferFormat (vk::VkFormat format)
58 {
59 bool mandatory = false;
60
61 switch (format)
62 {
63 case VK_FORMAT_R32G32_SFLOAT:
64 case VK_FORMAT_R32G32B32_SFLOAT:
65 case VK_FORMAT_R16G16_SFLOAT:
66 case VK_FORMAT_R16G16B16A16_SFLOAT:
67 case VK_FORMAT_R16G16_SNORM:
68 case VK_FORMAT_R16G16B16A16_SNORM:
69 mandatory = true;
70 break;
71 default:
72 break;
73 }
74
75 return mandatory;
76 }
77
checkAccelerationStructureVertexBufferFormat(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkFormat format)78 void checkAccelerationStructureVertexBufferFormat (const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice, vk::VkFormat format)
79 {
80 const vk::VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
81
82 if ((formatProperties.bufferFeatures & vk::VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR) == 0u)
83 {
84 const std::string errorMsg = "Format not supported for acceleration structure vertex buffers";
85 if (isMandatoryAccelerationStructureVertexBufferFormat(format))
86 TCU_FAIL(errorMsg);
87 TCU_THROW(NotSupportedError, errorMsg);
88 }
89 }
90
getCommonRayGenerationShader(void)91 std::string getCommonRayGenerationShader (void)
92 {
93 return
94 "#version 460 core\n"
95 "#extension GL_EXT_ray_tracing : require\n"
96 "layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
97 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
98 "\n"
99 "void main()\n"
100 "{\n"
101 " uint rayFlags = 0;\n"
102 " uint cullMask = 0xFF;\n"
103 " float tmin = 0.0;\n"
104 " float tmax = 9.0;\n"
105 " vec3 origin = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
106 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
107 " traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
108 "}\n";
109 }
110
RaytracedGeometryBase(VkGeometryTypeKHR geometryType,VkFormat vertexFormat,VkIndexType indexType)111 RaytracedGeometryBase::RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType)
112 : m_geometryType (geometryType)
113 , m_vertexFormat (vertexFormat)
114 , m_indexType (indexType)
115 , m_geometryFlags ((VkGeometryFlagsKHR)0u)
116 {
117 if (m_geometryType == VK_GEOMETRY_TYPE_AABBS_KHR)
118 DE_ASSERT(m_vertexFormat == VK_FORMAT_R32G32B32_SFLOAT);
119 }
120
~RaytracedGeometryBase()121 RaytracedGeometryBase::~RaytracedGeometryBase ()
122 {
123 }
124
125 struct GeometryBuilderParams
126 {
127 VkGeometryTypeKHR geometryType;
128 bool usePadding;
129 };
130
131 template <typename V, typename I>
buildRaytracedGeometry(const GeometryBuilderParams & params)132 RaytracedGeometryBase* buildRaytracedGeometry (const GeometryBuilderParams& params)
133 {
134 return new RaytracedGeometry<V, I>(params.geometryType, (params.usePadding ? 1u : 0u));
135 }
136
makeRaytracedGeometry(VkGeometryTypeKHR geometryType,VkFormat vertexFormat,VkIndexType indexType,bool padVertices)137 de::SharedPtr<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType, bool padVertices)
138 {
139 const GeometryBuilderParams builderParams { geometryType, padVertices };
140
141 switch (vertexFormat)
142 {
143 case VK_FORMAT_R32G32_SFLOAT:
144 switch (indexType)
145 {
146 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, deUint16>(builderParams));
147 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, deUint32>(builderParams));
148 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, EmptyIndex>(builderParams));
149 default: TCU_THROW(InternalError, "Wrong index type");
150 }
151 case VK_FORMAT_R32G32B32_SFLOAT:
152 switch (indexType)
153 {
154 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, deUint16>(builderParams));
155 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, deUint32>(builderParams));
156 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, EmptyIndex>(builderParams));
157 default: TCU_THROW(InternalError, "Wrong index type");
158 }
159 case VK_FORMAT_R32G32B32A32_SFLOAT:
160 switch (indexType)
161 {
162 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, deUint16>(builderParams));
163 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, deUint32>(builderParams));
164 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, EmptyIndex>(builderParams));
165 default: TCU_THROW(InternalError, "Wrong index type");
166 }
167 case VK_FORMAT_R16G16_SFLOAT:
168 switch (indexType)
169 {
170 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, deUint16>(builderParams));
171 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, deUint32>(builderParams));
172 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, EmptyIndex>(builderParams));
173 default: TCU_THROW(InternalError, "Wrong index type");
174 }
175 case VK_FORMAT_R16G16B16_SFLOAT:
176 switch (indexType)
177 {
178 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, deUint16>(builderParams));
179 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, deUint32>(builderParams));
180 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, EmptyIndex>(builderParams));
181 default: TCU_THROW(InternalError, "Wrong index type");
182 }
183 case VK_FORMAT_R16G16B16A16_SFLOAT:
184 switch (indexType)
185 {
186 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, deUint16>(builderParams));
187 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, deUint32>(builderParams));
188 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, EmptyIndex>(builderParams));
189 default: TCU_THROW(InternalError, "Wrong index type");
190 }
191 case VK_FORMAT_R16G16_SNORM:
192 switch (indexType)
193 {
194 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, deUint16>(builderParams));
195 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, deUint32>(builderParams));
196 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, EmptyIndex>(builderParams));
197 default: TCU_THROW(InternalError, "Wrong index type");
198 }
199 case VK_FORMAT_R16G16B16_SNORM:
200 switch (indexType)
201 {
202 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, deUint16>(builderParams));
203 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, deUint32>(builderParams));
204 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, EmptyIndex>(builderParams));
205 default: TCU_THROW(InternalError, "Wrong index type");
206 }
207 case VK_FORMAT_R16G16B16A16_SNORM:
208 switch (indexType)
209 {
210 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, deUint16>(builderParams));
211 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, deUint32>(builderParams));
212 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, EmptyIndex>(builderParams));
213 default: TCU_THROW(InternalError, "Wrong index type");
214 }
215 case VK_FORMAT_R64G64_SFLOAT:
216 switch (indexType)
217 {
218 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, deUint16>(builderParams));
219 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, deUint32>(builderParams));
220 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, EmptyIndex>(builderParams));
221 default: TCU_THROW(InternalError, "Wrong index type");
222 }
223 case VK_FORMAT_R64G64B64_SFLOAT:
224 switch (indexType)
225 {
226 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, deUint16>(builderParams));
227 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, deUint32>(builderParams));
228 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, EmptyIndex>(builderParams));
229 default: TCU_THROW(InternalError, "Wrong index type");
230 }
231 case VK_FORMAT_R64G64B64A64_SFLOAT:
232 switch (indexType)
233 {
234 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, deUint16>(builderParams));
235 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, deUint32>(builderParams));
236 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, EmptyIndex>(builderParams));
237 default: TCU_THROW(InternalError, "Wrong index type");
238 }
239 case VK_FORMAT_R8G8_SNORM:
240 switch (indexType)
241 {
242 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, deUint16>(builderParams));
243 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, deUint32>(builderParams));
244 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, EmptyIndex>(builderParams));
245 default: TCU_THROW(InternalError, "Wrong index type");
246 }
247 case VK_FORMAT_R8G8B8_SNORM:
248 switch (indexType)
249 {
250 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, deUint16>(builderParams));
251 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, deUint32>(builderParams));
252 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, EmptyIndex>(builderParams));
253 default: TCU_THROW(InternalError, "Wrong index type");
254 }
255 case VK_FORMAT_R8G8B8A8_SNORM:
256 switch (indexType)
257 {
258 case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, deUint16>(builderParams));
259 case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, deUint32>(builderParams));
260 case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, EmptyIndex>(builderParams));
261 default: TCU_THROW(InternalError, "Wrong index type");
262 }
263 default:
264 TCU_THROW(InternalError, "Wrong vertex format");
265 }
266
267 }
268
getBufferDeviceAddress(const DeviceInterface & vk,const VkDevice device,const VkBuffer buffer,VkDeviceSize offset)269 VkDeviceAddress getBufferDeviceAddress ( const DeviceInterface& vk,
270 const VkDevice device,
271 const VkBuffer buffer,
272 VkDeviceSize offset )
273 {
274
275 if (buffer == DE_NULL)
276 return 0;
277
278 VkBufferDeviceAddressInfo deviceAddressInfo
279 {
280 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, // VkStructureType sType
281 DE_NULL, // const void* pNext
282 buffer // VkBuffer buffer;
283 };
284 return vk.getBufferDeviceAddress(device, &deviceAddressInfo) + offset;
285 }
286
287
makeDeviceOrHostAddressConstKHR(const void * hostAddress)288 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR (const void* hostAddress)
289 {
290 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
291 VkDeviceOrHostAddressConstKHR result;
292
293 deMemset(&result, 0, sizeof(result));
294
295 result.hostAddress = hostAddress;
296
297 return result;
298 }
299
makeDeviceOrHostAddressKHR(void * hostAddress)300 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR (void* hostAddress)
301 {
302 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
303 VkDeviceOrHostAddressKHR result;
304
305 deMemset(&result, 0, sizeof(result));
306
307 result.hostAddress = hostAddress;
308
309 return result;
310 }
311
makeDeviceOrHostAddressConstKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)312 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR (const DeviceInterface& vk,
313 const VkDevice device,
314 VkBuffer buffer,
315 VkDeviceSize offset)
316 {
317 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
318 VkDeviceOrHostAddressConstKHR result;
319
320 deMemset(&result, 0, sizeof(result));
321
322 VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
323 {
324 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
325 DE_NULL, // const void* pNext;
326 buffer, // VkBuffer buffer
327 };
328 result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
329
330 return result;
331 }
332
makeDeviceOrHostAddressKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)333 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR (const DeviceInterface& vk,
334 const VkDevice device,
335 VkBuffer buffer,
336 VkDeviceSize offset)
337 {
338 // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
339 VkDeviceOrHostAddressKHR result;
340
341 deMemset(&result, 0, sizeof(result));
342
343 VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
344 {
345 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
346 DE_NULL, // const void* pNext;
347 buffer, // VkBuffer buffer
348 };
349 result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
350
351 return result;
352 }
353
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,deUint32 queryCount)354 static inline Move<VkQueryPool> makeQueryPool (const DeviceInterface& vk,
355 const VkDevice device,
356 const VkQueryType queryType,
357 deUint32 queryCount)
358 {
359 const VkQueryPoolCreateInfo queryPoolCreateInfo =
360 {
361 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
362 DE_NULL, // pNext
363 (VkQueryPoolCreateFlags)0, // flags
364 queryType, // queryType
365 queryCount, // queryCount
366 0u, // pipelineStatistics
367 };
368 return createQueryPool(vk, device, &queryPoolCreateInfo);
369 }
370
makeVkAccelerationStructureGeometryDataKHR(const VkAccelerationStructureGeometryTrianglesDataKHR & triangles)371 static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryTrianglesDataKHR& triangles)
372 {
373 VkAccelerationStructureGeometryDataKHR result;
374
375 deMemset(&result, 0, sizeof(result));
376
377 result.triangles = triangles;
378
379 return result;
380 }
381
makeVkAccelerationStructureGeometryDataKHR(const VkAccelerationStructureGeometryAabbsDataKHR & aabbs)382 static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryAabbsDataKHR& aabbs)
383 {
384 VkAccelerationStructureGeometryDataKHR result;
385
386 deMemset(&result, 0, sizeof(result));
387
388 result.aabbs = aabbs;
389
390 return result;
391 }
392
makeVkAccelerationStructureInstancesDataKHR(const VkAccelerationStructureGeometryInstancesDataKHR & instances)393 static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureInstancesDataKHR (const VkAccelerationStructureGeometryInstancesDataKHR& instances)
394 {
395 VkAccelerationStructureGeometryDataKHR result;
396
397 deMemset(&result, 0, sizeof(result));
398
399 result.instances = instances;
400
401 return result;
402 }
403
makeVkAccelerationStructureInstanceKHR(const VkTransformMatrixKHR & transform,deUint32 instanceCustomIndex,deUint32 mask,deUint32 instanceShaderBindingTableRecordOffset,VkGeometryInstanceFlagsKHR flags,deUint64 accelerationStructureReference)404 static inline VkAccelerationStructureInstanceKHR makeVkAccelerationStructureInstanceKHR (const VkTransformMatrixKHR& transform,
405 deUint32 instanceCustomIndex,
406 deUint32 mask,
407 deUint32 instanceShaderBindingTableRecordOffset,
408 VkGeometryInstanceFlagsKHR flags,
409 deUint64 accelerationStructureReference)
410 {
411 VkAccelerationStructureInstanceKHR instance = { transform, 0, 0, 0, 0, accelerationStructureReference };
412 instance.instanceCustomIndex = instanceCustomIndex & 0xFFFFFF;
413 instance.mask = mask & 0xFF;
414 instance.instanceShaderBindingTableRecordOffset = instanceShaderBindingTableRecordOffset & 0xFFFFFF;
415 instance.flags = flags & 0xFF;
416 return instance;
417 }
418
getRayTracingShaderGroupHandlesKHR(const DeviceInterface & vk,const VkDevice device,const VkPipeline pipeline,const deUint32 firstGroup,const deUint32 groupCount,const deUintptr dataSize,void * pData)419 VkResult getRayTracingShaderGroupHandlesKHR (const DeviceInterface& vk,
420 const VkDevice device,
421 const VkPipeline pipeline,
422 const deUint32 firstGroup,
423 const deUint32 groupCount,
424 const deUintptr dataSize,
425 void* pData)
426 {
427 return vk.getRayTracingShaderGroupHandlesKHR(device, pipeline, firstGroup, groupCount, dataSize, pData);
428 }
429
getRayTracingShaderGroupHandles(const DeviceInterface & vk,const VkDevice device,const VkPipeline pipeline,const deUint32 firstGroup,const deUint32 groupCount,const deUintptr dataSize,void * pData)430 VkResult getRayTracingShaderGroupHandles (const DeviceInterface& vk,
431 const VkDevice device,
432 const VkPipeline pipeline,
433 const deUint32 firstGroup,
434 const deUint32 groupCount,
435 const deUintptr dataSize,
436 void* pData)
437 {
438 return getRayTracingShaderGroupHandlesKHR(vk, device, pipeline, firstGroup, groupCount, dataSize, pData);
439 }
440
finishDeferredOperation(const DeviceInterface & vk,VkDevice device,VkDeferredOperationKHR deferredOperation)441 VkResult finishDeferredOperation (const DeviceInterface& vk,
442 VkDevice device,
443 VkDeferredOperationKHR deferredOperation)
444 {
445 VkResult result = vk.deferredOperationJoinKHR(device, deferredOperation);
446
447 while (result == VK_THREAD_IDLE_KHR)
448 {
449 std::this_thread::yield();
450 result = vk.deferredOperationJoinKHR(device, deferredOperation);
451 }
452
453 switch( result )
454 {
455 case VK_SUCCESS:
456 {
457 // Deferred operation has finished. Query its result
458 result = vk.getDeferredOperationResultKHR(device, deferredOperation);
459
460 break;
461 }
462
463 case VK_THREAD_DONE_KHR:
464 {
465 // Deferred operation is being wrapped up by another thread
466 // wait for that thread to finish
467 do
468 {
469 std::this_thread::yield();
470 result = vk.getDeferredOperationResultKHR(device, deferredOperation);
471 } while (result == VK_NOT_READY);
472
473 break;
474 }
475
476 default:
477 {
478 DE_ASSERT(false);
479
480 break;
481 }
482 }
483
484 return result;
485 }
486
finishDeferredOperationThreaded(DeferredThreadParams * deferredThreadParams)487 void finishDeferredOperationThreaded (DeferredThreadParams* deferredThreadParams)
488 {
489 deferredThreadParams->result = finishDeferredOperation(deferredThreadParams->vk, deferredThreadParams->device, deferredThreadParams->deferredOperation);
490 }
491
finishDeferredOperation(const DeviceInterface & vk,VkDevice device,VkDeferredOperationKHR deferredOperation,const deUint32 workerThreadCount,const bool operationNotDeferred)492 void finishDeferredOperation (const DeviceInterface& vk,
493 VkDevice device,
494 VkDeferredOperationKHR deferredOperation,
495 const deUint32 workerThreadCount,
496 const bool operationNotDeferred)
497 {
498
499 if (operationNotDeferred)
500 {
501 // when the operation deferral returns VK_OPERATION_NOT_DEFERRED_KHR,
502 // the deferred operation should act as if no command was deferred
503 VK_CHECK(vk.getDeferredOperationResultKHR(device, deferredOperation));
504
505
506 // there is not need to join any threads to the deferred operation,
507 // so below can be skipped.
508 return;
509 }
510
511 if (workerThreadCount == 0)
512 {
513 VK_CHECK(finishDeferredOperation(vk, device, deferredOperation));
514 }
515 else
516 {
517 const deUint32 maxThreadCountSupported = deMinu32(256u, vk.getDeferredOperationMaxConcurrencyKHR(device, deferredOperation));
518 const deUint32 requestedThreadCount = workerThreadCount;
519 const deUint32 testThreadCount = requestedThreadCount == std::numeric_limits<deUint32>::max() ? maxThreadCountSupported : requestedThreadCount;
520
521 if (maxThreadCountSupported == 0)
522 TCU_FAIL("vkGetDeferredOperationMaxConcurrencyKHR must not return 0");
523
524 const DeferredThreadParams deferredThreadParams =
525 {
526 vk, // const DeviceInterface& vk;
527 device, // VkDevice device;
528 deferredOperation, // VkDeferredOperationKHR deferredOperation;
529 VK_RESULT_MAX_ENUM, // VResult result;
530 };
531 std::vector<DeferredThreadParams> threadParams (testThreadCount, deferredThreadParams);
532 std::vector<de::MovePtr<std::thread> > threads (testThreadCount);
533 bool executionResult = false;
534
535 DE_ASSERT(threads.size() > 0 && threads.size() == testThreadCount);
536
537 for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
538 threads[threadNdx] = de::MovePtr<std::thread>(new std::thread(finishDeferredOperationThreaded, &threadParams[threadNdx]));
539
540 for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
541 threads[threadNdx]->join();
542
543 for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
544 if (threadParams[threadNdx].result == VK_SUCCESS)
545 executionResult = true;
546
547 if (!executionResult)
548 TCU_FAIL("Neither reported VK_SUCCESS");
549 }
550 }
551
SerialStorage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkAccelerationStructureBuildTypeKHR buildType,const VkDeviceSize storageSize)552 SerialStorage::SerialStorage (const DeviceInterface& vk,
553 const VkDevice device,
554 Allocator& allocator,
555 const VkAccelerationStructureBuildTypeKHR buildType,
556 const VkDeviceSize storageSize)
557 : m_buildType (buildType)
558 , m_storageSize (storageSize)
559 {
560 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(storageSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
561 try
562 {
563 m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
564 }
565 catch (const tcu::NotSupportedError&)
566 {
567 // retry without Cached flag
568 m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
569 }
570 }
571
SerialStorage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkAccelerationStructureBuildTypeKHR buildType,const SerialInfo & serialInfo)572 SerialStorage::SerialStorage (const DeviceInterface& vk,
573 const VkDevice device,
574 Allocator& allocator,
575 const VkAccelerationStructureBuildTypeKHR buildType,
576 const SerialInfo& serialInfo)
577 : m_buildType (buildType)
578 , m_storageSize (serialInfo.sizes()[0]) // raise assertion if serialInfo is empty
579 , m_serialInfo (serialInfo)
580 {
581 DE_ASSERT(serialInfo.sizes().size() >= 2u);
582
583 // create buffer for top-level acceleration structure
584 {
585 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_storageSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
586 m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
587 }
588
589 // create buffers for bottom-level acceleration structures
590 {
591 std::vector<deUint64> addrs;
592
593 for (std::size_t i = 1; i < serialInfo.addresses().size(); ++i)
594 {
595 const deUint64& lookAddr = serialInfo.addresses()[i];
596 auto end = addrs.end();
597 auto match = std::find_if(addrs.begin(), end, [&](const deUint64& item){ return item == lookAddr; });
598 if (match == end)
599 {
600 addrs.emplace_back(lookAddr);
601 m_bottoms.emplace_back(de::SharedPtr<SerialStorage>(new SerialStorage(vk, device, allocator, buildType, serialInfo.sizes()[i])));
602 }
603 }
604 }
605 }
606
getAddress(const DeviceInterface & vk,const VkDevice device,const VkAccelerationStructureBuildTypeKHR buildType)607 VkDeviceOrHostAddressKHR SerialStorage::getAddress (const DeviceInterface& vk,
608 const VkDevice device,
609 const VkAccelerationStructureBuildTypeKHR buildType)
610 {
611 if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
612 return makeDeviceOrHostAddressKHR(vk, device, m_buffer->get(), 0);
613 else
614 return makeDeviceOrHostAddressKHR(m_buffer->getAllocation().getHostPtr());
615 }
616
getASHeader()617 SerialStorage::AccelerationStructureHeader* SerialStorage::getASHeader ()
618 {
619 return reinterpret_cast<AccelerationStructureHeader*>(getHostAddress().hostAddress);
620 }
621
hasDeepFormat() const622 bool SerialStorage::hasDeepFormat () const
623 {
624 return (m_serialInfo.sizes().size() >= 2u);
625 }
626
getBottomStorage(deUint32 index) const627 de::SharedPtr<SerialStorage> SerialStorage::getBottomStorage (deUint32 index) const
628 {
629 return m_bottoms[index];
630 }
631
getHostAddress(VkDeviceSize offset)632 VkDeviceOrHostAddressKHR SerialStorage::getHostAddress (VkDeviceSize offset)
633 {
634 DE_ASSERT(offset < m_storageSize);
635 return makeDeviceOrHostAddressKHR(static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr()) + offset);
636 }
637
getHostAddressConst(VkDeviceSize offset)638 VkDeviceOrHostAddressConstKHR SerialStorage::getHostAddressConst (VkDeviceSize offset)
639 {
640 return makeDeviceOrHostAddressConstKHR(static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr()) + offset);
641 }
642
getAddressConst(const DeviceInterface & vk,const VkDevice device,const VkAccelerationStructureBuildTypeKHR buildType)643 VkDeviceOrHostAddressConstKHR SerialStorage::getAddressConst (const DeviceInterface& vk,
644 const VkDevice device,
645 const VkAccelerationStructureBuildTypeKHR buildType)
646 {
647 if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
648 return makeDeviceOrHostAddressConstKHR(vk, device, m_buffer->get(), 0);
649 else
650 return getHostAddressConst();
651 }
652
getStorageSize() const653 inline VkDeviceSize SerialStorage::getStorageSize () const
654 {
655 return m_storageSize;
656 }
657
getSerialInfo() const658 inline const SerialInfo& SerialStorage::getSerialInfo () const
659 {
660 return m_serialInfo;
661 }
662
getDeserializedSize()663 deUint64 SerialStorage::getDeserializedSize ()
664 {
665 deUint64 result = 0;
666 const deUint8* startPtr = static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr());
667
668 DE_ASSERT(sizeof(result) == DESERIALIZED_SIZE_SIZE);
669
670 deMemcpy(&result, startPtr + DESERIALIZED_SIZE_OFFSET, sizeof(result));
671
672 return result;
673 }
674
~BottomLevelAccelerationStructure()675 BottomLevelAccelerationStructure::~BottomLevelAccelerationStructure ()
676 {
677 }
678
BottomLevelAccelerationStructure()679 BottomLevelAccelerationStructure::BottomLevelAccelerationStructure ()
680 : m_structureSize (0u)
681 , m_updateScratchSize (0u)
682 , m_buildScratchSize (0u)
683 {
684 }
685
setGeometryData(const std::vector<tcu::Vec3> & geometryData,const bool triangles,const VkGeometryFlagsKHR geometryFlags)686 void BottomLevelAccelerationStructure::setGeometryData (const std::vector<tcu::Vec3>& geometryData,
687 const bool triangles,
688 const VkGeometryFlagsKHR geometryFlags)
689 {
690 if (triangles)
691 DE_ASSERT((geometryData.size() % 3) == 0);
692 else
693 DE_ASSERT((geometryData.size() % 2) == 0);
694
695 setGeometryCount(1u);
696
697 addGeometry(geometryData, triangles, geometryFlags);
698 }
699
setDefaultGeometryData(const VkShaderStageFlagBits testStage,const VkGeometryFlagsKHR geometryFlags)700 void BottomLevelAccelerationStructure::setDefaultGeometryData (const VkShaderStageFlagBits testStage,
701 const VkGeometryFlagsKHR geometryFlags)
702 {
703 bool trianglesData = false;
704 float z = 0.0f;
705 std::vector<tcu::Vec3> geometryData;
706
707 switch (testStage)
708 {
709 case VK_SHADER_STAGE_RAYGEN_BIT_KHR: z = -1.0f; trianglesData = true; break;
710 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: z = -1.0f; trianglesData = true; break;
711 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: z = -1.0f; trianglesData = true; break;
712 case VK_SHADER_STAGE_MISS_BIT_KHR: z = -9.9f; trianglesData = true; break;
713 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: z = -1.0f; trianglesData = false; break;
714 case VK_SHADER_STAGE_CALLABLE_BIT_KHR: z = -1.0f; trianglesData = true; break;
715 default: TCU_THROW(InternalError, "Unacceptable stage");
716 }
717
718 if (trianglesData)
719 {
720 geometryData.reserve(6);
721
722 geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z));
723 geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z));
724 geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z));
725 geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z));
726 geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z));
727 geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z));
728 }
729 else
730 {
731 geometryData.reserve(2);
732
733 geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z));
734 geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z));
735 }
736
737 setGeometryCount(1u);
738
739 addGeometry(geometryData, trianglesData, geometryFlags);
740 }
741
setGeometryCount(const size_t geometryCount)742 void BottomLevelAccelerationStructure::setGeometryCount (const size_t geometryCount)
743 {
744 m_geometriesData.clear();
745
746 m_geometriesData.reserve(geometryCount);
747 }
748
addGeometry(de::SharedPtr<RaytracedGeometryBase> & raytracedGeometry)749 void BottomLevelAccelerationStructure::addGeometry (de::SharedPtr<RaytracedGeometryBase>& raytracedGeometry)
750 {
751 m_geometriesData.push_back(raytracedGeometry);
752 }
753
addGeometry(const std::vector<tcu::Vec3> & geometryData,const bool triangles,const VkGeometryFlagsKHR geometryFlags)754 void BottomLevelAccelerationStructure::addGeometry (const std::vector<tcu::Vec3>& geometryData,
755 const bool triangles,
756 const VkGeometryFlagsKHR geometryFlags)
757 {
758 DE_ASSERT(geometryData.size() > 0);
759 DE_ASSERT((triangles && geometryData.size() % 3 == 0) || (!triangles && geometryData.size() % 2 == 0));
760
761 if (!triangles)
762 for (size_t posNdx = 0; posNdx < geometryData.size() / 2; ++posNdx)
763 {
764 DE_ASSERT(geometryData[2 * posNdx].x() <= geometryData[2 * posNdx + 1].x());
765 DE_ASSERT(geometryData[2 * posNdx].y() <= geometryData[2 * posNdx + 1].y());
766 DE_ASSERT(geometryData[2 * posNdx].z() <= geometryData[2 * posNdx + 1].z());
767 }
768
769 de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(triangles ? VK_GEOMETRY_TYPE_TRIANGLES_KHR : VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
770 for (auto it = begin(geometryData), eit = end(geometryData); it != eit; ++it)
771 geometry->addVertex(*it);
772
773 geometry->setGeometryFlags(geometryFlags);
774 addGeometry(geometry);
775 }
776
getStructureSize() const777 VkDeviceSize BottomLevelAccelerationStructure::getStructureSize() const
778 {
779 return m_structureSize;
780 }
781
createVertexBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const std::vector<de::SharedPtr<RaytracedGeometryBase>> & geometriesData)782 BufferWithMemory* createVertexBuffer (const DeviceInterface& vk,
783 const VkDevice device,
784 Allocator& allocator,
785 const std::vector<de::SharedPtr<RaytracedGeometryBase>>& geometriesData)
786 {
787 DE_ASSERT(geometriesData.size() != 0);
788
789 VkDeviceSize bufferSizeBytes = 0;
790 for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
791 bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getVertexByteSize(),8);
792
793 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
794 return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
795 }
796
updateVertexBuffer(const DeviceInterface & vk,const VkDevice device,const std::vector<de::SharedPtr<RaytracedGeometryBase>> & geometriesData,BufferWithMemory * vertexBuffer)797 void updateVertexBuffer (const DeviceInterface& vk,
798 const VkDevice device,
799 const std::vector<de::SharedPtr<RaytracedGeometryBase>>& geometriesData,
800 BufferWithMemory* vertexBuffer)
801 {
802 const Allocation& geometryAlloc = vertexBuffer->getAllocation();
803 deUint8* bufferStart = static_cast<deUint8*>(geometryAlloc.getHostPtr());
804 VkDeviceSize bufferOffset = 0;
805
806 for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
807 {
808 const void* geometryPtr = geometriesData[geometryNdx]->getVertexPointer();
809 const size_t geometryPtrSize = geometriesData[geometryNdx]->getVertexByteSize();
810
811 deMemcpy(&bufferStart[bufferOffset], geometryPtr, geometryPtrSize);
812
813 bufferOffset += deAlignSize(geometryPtrSize,8);
814 }
815
816 flushMappedMemoryRange(vk, device, geometryAlloc.getMemory(), geometryAlloc.getOffset(), VK_WHOLE_SIZE);
817 }
818
createIndexBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const std::vector<de::SharedPtr<RaytracedGeometryBase>> & geometriesData)819 BufferWithMemory* createIndexBuffer (const DeviceInterface& vk,
820 const VkDevice device,
821 Allocator& allocator,
822 const std::vector<de::SharedPtr<RaytracedGeometryBase>>& geometriesData)
823 {
824 DE_ASSERT(!geometriesData.empty());
825
826 VkDeviceSize bufferSizeBytes = 0;
827 for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
828 if(geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
829 bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getIndexByteSize(),8);
830
831 if (bufferSizeBytes == 0)
832 return DE_NULL;
833
834 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
835 return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
836 }
837
updateIndexBuffer(const DeviceInterface & vk,const VkDevice device,const std::vector<de::SharedPtr<RaytracedGeometryBase>> & geometriesData,BufferWithMemory * indexBuffer)838 void updateIndexBuffer (const DeviceInterface& vk,
839 const VkDevice device,
840 const std::vector<de::SharedPtr<RaytracedGeometryBase>>& geometriesData,
841 BufferWithMemory* indexBuffer)
842 {
843 const Allocation& indexAlloc = indexBuffer->getAllocation();
844 deUint8* bufferStart = static_cast<deUint8*>(indexAlloc.getHostPtr());
845 VkDeviceSize bufferOffset = 0;
846
847 for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
848 {
849 if (geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
850 {
851 const void* indexPtr = geometriesData[geometryNdx]->getIndexPointer();
852 const size_t indexPtrSize = geometriesData[geometryNdx]->getIndexByteSize();
853
854 deMemcpy(&bufferStart[bufferOffset], indexPtr, indexPtrSize);
855
856 bufferOffset += deAlignSize(indexPtrSize, 8);
857 }
858 }
859
860 flushMappedMemoryRange(vk, device, indexAlloc.getMemory(), indexAlloc.getOffset(), VK_WHOLE_SIZE);
861 }
862
863 class BottomLevelAccelerationStructureKHR : public BottomLevelAccelerationStructure
864 {
865 public:
866 static deUint32 getRequiredAllocationCount (void);
867
868 BottomLevelAccelerationStructureKHR ();
869 BottomLevelAccelerationStructureKHR (const BottomLevelAccelerationStructureKHR& other) = delete;
870 virtual ~BottomLevelAccelerationStructureKHR ();
871
872 void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) override;
873 void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) override;
874 void setCreateGeneric (bool createGeneric) override;
875 void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) override;
876 void setBuildWithoutGeometries (bool buildWithoutGeometries) override;
877 void setBuildWithoutPrimitives (bool buildWithoutPrimitives) override;
878 void setDeferredOperation (const bool deferredOperation,
879 const deUint32 workerThreadCount) override;
880 void setUseArrayOfPointers (const bool useArrayOfPointers) override;
881 void setIndirectBuildParameters (const VkBuffer indirectBuffer,
882 const VkDeviceSize indirectBufferOffset,
883 const deUint32 indirectBufferStride) override;
884 VkBuildAccelerationStructureFlagsKHR getBuildFlags () const override;
885
886 void create (const DeviceInterface& vk,
887 const VkDevice device,
888 Allocator& allocator,
889 VkDeviceSize structureSize,
890 VkDeviceAddress deviceAddress = 0u ) override;
891 void build (const DeviceInterface& vk,
892 const VkDevice device,
893 const VkCommandBuffer cmdBuffer) override;
894 void copyFrom (const DeviceInterface& vk,
895 const VkDevice device,
896 const VkCommandBuffer cmdBuffer,
897 BottomLevelAccelerationStructure* accelerationStructure,
898 bool compactCopy) override;
899
900 void serialize (const DeviceInterface& vk,
901 const VkDevice device,
902 const VkCommandBuffer cmdBuffer,
903 SerialStorage* storage) override;
904 void deserialize (const DeviceInterface& vk,
905 const VkDevice device,
906 const VkCommandBuffer cmdBuffer,
907 SerialStorage* storage) override;
908
909 const VkAccelerationStructureKHR* getPtr (void) const override;
910
911 protected:
912 VkAccelerationStructureBuildTypeKHR m_buildType;
913 VkAccelerationStructureCreateFlagsKHR m_createFlags;
914 bool m_createGeneric;
915 VkBuildAccelerationStructureFlagsKHR m_buildFlags;
916 bool m_buildWithoutGeometries;
917 bool m_buildWithoutPrimitives;
918 bool m_deferredOperation;
919 deUint32 m_workerThreadCount;
920 bool m_useArrayOfPointers;
921 de::MovePtr<BufferWithMemory> m_accelerationStructureBuffer;
922 de::MovePtr<BufferWithMemory> m_vertexBuffer;
923 de::MovePtr<BufferWithMemory> m_indexBuffer;
924 de::MovePtr<BufferWithMemory> m_deviceScratchBuffer;
925 std::vector<deUint8> m_hostScratchBuffer;
926 Move<VkAccelerationStructureKHR> m_accelerationStructureKHR;
927 VkBuffer m_indirectBuffer;
928 VkDeviceSize m_indirectBufferOffset;
929 deUint32 m_indirectBufferStride;
930
931 void prepareGeometries (const DeviceInterface& vk,
932 const VkDevice device,
933 std::vector<VkAccelerationStructureGeometryKHR>& accelerationStructureGeometriesKHR,
934 std::vector<VkAccelerationStructureGeometryKHR*>& accelerationStructureGeometriesKHRPointers,
935 std::vector<VkAccelerationStructureBuildRangeInfoKHR>& accelerationStructureBuildRangeInfoKHR,
936 std::vector<deUint32>& maxPrimitiveCounts);
937 };
938
getRequiredAllocationCount(void)939 deUint32 BottomLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
940 {
941 /*
942 de::MovePtr<BufferWithMemory> m_geometryBuffer; // but only when m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR
943 de::MovePtr<Allocation> m_accelerationStructureAlloc;
944 de::MovePtr<BufferWithMemory> m_deviceScratchBuffer;
945 */
946 return 3u;
947 }
948
~BottomLevelAccelerationStructureKHR()949 BottomLevelAccelerationStructureKHR::~BottomLevelAccelerationStructureKHR ()
950 {
951 }
952
BottomLevelAccelerationStructureKHR()953 BottomLevelAccelerationStructureKHR::BottomLevelAccelerationStructureKHR ()
954 : BottomLevelAccelerationStructure ()
955 , m_buildType (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
956 , m_createFlags (0u)
957 , m_createGeneric (false)
958 , m_buildFlags (0u)
959 , m_buildWithoutGeometries (false)
960 , m_buildWithoutPrimitives (false)
961 , m_deferredOperation (false)
962 , m_workerThreadCount (0)
963 , m_useArrayOfPointers (false)
964 , m_accelerationStructureBuffer (DE_NULL)
965 , m_vertexBuffer (DE_NULL)
966 , m_indexBuffer (DE_NULL)
967 , m_deviceScratchBuffer (DE_NULL)
968 , m_accelerationStructureKHR ()
969 , m_indirectBuffer (DE_NULL)
970 , m_indirectBufferOffset (0)
971 , m_indirectBufferStride (0)
972 {
973 }
974
setBuildType(const VkAccelerationStructureBuildTypeKHR buildType)975 void BottomLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR buildType)
976 {
977 m_buildType = buildType;
978 }
979
setCreateFlags(const VkAccelerationStructureCreateFlagsKHR createFlags)980 void BottomLevelAccelerationStructureKHR::setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags)
981 {
982 m_createFlags = createFlags;
983 }
984
setCreateGeneric(bool createGeneric)985 void BottomLevelAccelerationStructureKHR::setCreateGeneric (bool createGeneric)
986 {
987 m_createGeneric = createGeneric;
988 }
989
setBuildFlags(const VkBuildAccelerationStructureFlagsKHR buildFlags)990 void BottomLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags)
991 {
992 m_buildFlags = buildFlags;
993 }
994
setBuildWithoutGeometries(bool buildWithoutGeometries)995 void BottomLevelAccelerationStructureKHR::setBuildWithoutGeometries (bool buildWithoutGeometries)
996 {
997 m_buildWithoutGeometries = buildWithoutGeometries;
998 }
999
setBuildWithoutPrimitives(bool buildWithoutPrimitives)1000 void BottomLevelAccelerationStructureKHR::setBuildWithoutPrimitives (bool buildWithoutPrimitives)
1001 {
1002 m_buildWithoutPrimitives = buildWithoutPrimitives;
1003 }
1004
setDeferredOperation(const bool deferredOperation,const deUint32 workerThreadCount)1005 void BottomLevelAccelerationStructureKHR::setDeferredOperation (const bool deferredOperation,
1006 const deUint32 workerThreadCount)
1007 {
1008 m_deferredOperation = deferredOperation;
1009 m_workerThreadCount = workerThreadCount;
1010 }
1011
setUseArrayOfPointers(const bool useArrayOfPointers)1012 void BottomLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool useArrayOfPointers)
1013 {
1014 m_useArrayOfPointers = useArrayOfPointers;
1015 }
1016
setIndirectBuildParameters(const VkBuffer indirectBuffer,const VkDeviceSize indirectBufferOffset,const deUint32 indirectBufferStride)1017 void BottomLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer indirectBuffer,
1018 const VkDeviceSize indirectBufferOffset,
1019 const deUint32 indirectBufferStride)
1020 {
1021 m_indirectBuffer = indirectBuffer;
1022 m_indirectBufferOffset = indirectBufferOffset;
1023 m_indirectBufferStride = indirectBufferStride;
1024 }
1025
getBuildFlags() const1026 VkBuildAccelerationStructureFlagsKHR BottomLevelAccelerationStructureKHR::getBuildFlags () const
1027 {
1028 return m_buildFlags;
1029 }
1030
create(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,VkDeviceSize structureSize,VkDeviceAddress deviceAddress)1031 void BottomLevelAccelerationStructureKHR::create (const DeviceInterface& vk,
1032 const VkDevice device,
1033 Allocator& allocator,
1034 VkDeviceSize structureSize,
1035 VkDeviceAddress deviceAddress)
1036 {
1037 // AS may be built from geometries using vkCmdBuildAccelerationStructuresKHR / vkBuildAccelerationStructuresKHR
1038 // or may be copied/compacted/deserialized from other AS ( in this case AS does not need geometries, but it needs to know its size before creation ).
1039 DE_ASSERT(!m_geometriesData.empty() != !(structureSize == 0)); // logical xor
1040
1041 if (structureSize == 0)
1042 {
1043 std::vector<VkAccelerationStructureGeometryKHR> accelerationStructureGeometriesKHR;
1044 std::vector<VkAccelerationStructureGeometryKHR*> accelerationStructureGeometriesKHRPointers;
1045 std::vector<VkAccelerationStructureBuildRangeInfoKHR> accelerationStructureBuildRangeInfoKHR;
1046 std::vector<deUint32> maxPrimitiveCounts;
1047 prepareGeometries(vk, device, accelerationStructureGeometriesKHR, accelerationStructureGeometriesKHRPointers, accelerationStructureBuildRangeInfoKHR, maxPrimitiveCounts);
1048
1049 const VkAccelerationStructureGeometryKHR* accelerationStructureGeometriesKHRPointer = accelerationStructureGeometriesKHR.data();
1050 const VkAccelerationStructureGeometryKHR* const* accelerationStructureGeometry = accelerationStructureGeometriesKHRPointers.data();
1051
1052 VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR =
1053 {
1054 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType;
1055 DE_NULL, // const void* pNext;
1056 VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, // VkAccelerationStructureTypeKHR type;
1057 m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags;
1058 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR, // VkBuildAccelerationStructureModeKHR mode;
1059 DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure;
1060 DE_NULL, // VkAccelerationStructureKHR dstAccelerationStructure;
1061 static_cast<deUint32>(accelerationStructureGeometriesKHR.size()), // deUint32 geometryCount;
1062 m_useArrayOfPointers ? DE_NULL : accelerationStructureGeometriesKHRPointer, // const VkAccelerationStructureGeometryKHR* pGeometries;
1063 m_useArrayOfPointers ? accelerationStructureGeometry : DE_NULL, // const VkAccelerationStructureGeometryKHR* const* ppGeometries;
1064 makeDeviceOrHostAddressKHR(DE_NULL) // VkDeviceOrHostAddressKHR scratchData;
1065 };
1066 VkAccelerationStructureBuildSizesInfoKHR sizeInfo =
1067 {
1068 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, // VkStructureType sType;
1069 DE_NULL, // const void* pNext;
1070 0, // VkDeviceSize accelerationStructureSize;
1071 0, // VkDeviceSize updateScratchSize;
1072 0 // VkDeviceSize buildScratchSize;
1073 };
1074
1075 vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
1076
1077 m_structureSize = sizeInfo.accelerationStructureSize;
1078 m_updateScratchSize = sizeInfo.updateScratchSize;
1079 m_buildScratchSize = sizeInfo.buildScratchSize;
1080 }
1081 else
1082 {
1083 m_structureSize = structureSize;
1084 m_updateScratchSize = 0u;
1085 m_buildScratchSize = 0u;
1086 }
1087
1088 {
1089 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_structureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1090 try
1091 {
1092 m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1093 }
1094 catch (const tcu::NotSupportedError&)
1095 {
1096 // retry without Cached flag
1097 m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1098 }
1099 }
1100
1101 {
1102 const VkAccelerationStructureTypeKHR structureType = (m_createGeneric
1103 ? VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
1104 : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);
1105 const VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfoKHR
1106 {
1107 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, // VkStructureType sType;
1108 DE_NULL, // const void* pNext;
1109 m_createFlags, // VkAccelerationStructureCreateFlagsKHR createFlags;
1110 m_accelerationStructureBuffer->get(), // VkBuffer buffer;
1111 0u, // VkDeviceSize offset;
1112 m_structureSize, // VkDeviceSize size;
1113 structureType, // VkAccelerationStructureTypeKHR type;
1114 deviceAddress // VkDeviceAddress deviceAddress;
1115 };
1116
1117 m_accelerationStructureKHR = createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL);
1118 }
1119
1120 if (m_buildScratchSize > 0u)
1121 {
1122 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1123 {
1124 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1125 m_deviceScratchBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1126 }
1127 else
1128 {
1129 m_hostScratchBuffer.resize(static_cast<size_t>(m_buildScratchSize));
1130 }
1131 }
1132
1133 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR && !m_geometriesData.empty())
1134 {
1135 m_vertexBuffer = de::MovePtr<BufferWithMemory>(createVertexBuffer(vk, device, allocator, m_geometriesData));
1136 m_indexBuffer = de::MovePtr<BufferWithMemory>(createIndexBuffer(vk, device, allocator, m_geometriesData));
1137 }
1138 }
1139
build(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer)1140 void BottomLevelAccelerationStructureKHR::build (const DeviceInterface& vk,
1141 const VkDevice device,
1142 const VkCommandBuffer cmdBuffer)
1143 {
1144 DE_ASSERT(!m_geometriesData.empty());
1145 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1146 DE_ASSERT(m_buildScratchSize != 0);
1147
1148 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1149 {
1150 updateVertexBuffer(vk, device, m_geometriesData, m_vertexBuffer.get());
1151 if(m_indexBuffer.get() != DE_NULL)
1152 updateIndexBuffer(vk, device, m_geometriesData, m_indexBuffer.get());
1153 }
1154
1155 {
1156 std::vector<VkAccelerationStructureGeometryKHR> accelerationStructureGeometriesKHR;
1157 std::vector<VkAccelerationStructureGeometryKHR*> accelerationStructureGeometriesKHRPointers;
1158 std::vector<VkAccelerationStructureBuildRangeInfoKHR> accelerationStructureBuildRangeInfoKHR;
1159 std::vector<deUint32> maxPrimitiveCounts;
1160
1161 prepareGeometries(vk, device, accelerationStructureGeometriesKHR, accelerationStructureGeometriesKHRPointers, accelerationStructureBuildRangeInfoKHR, maxPrimitiveCounts);
1162
1163 const VkAccelerationStructureGeometryKHR* accelerationStructureGeometriesKHRPointer = accelerationStructureGeometriesKHR.data();
1164 const VkAccelerationStructureGeometryKHR* const* accelerationStructureGeometry = accelerationStructureGeometriesKHRPointers.data();
1165 VkDeviceOrHostAddressKHR scratchData = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1166 ? makeDeviceOrHostAddressKHR(vk, device, m_deviceScratchBuffer->get(), 0)
1167 : makeDeviceOrHostAddressKHR(m_hostScratchBuffer.data());
1168 const deUint32 geometryCount = (m_buildWithoutGeometries
1169 ? 0u
1170 : static_cast<deUint32>(accelerationStructureGeometriesKHR.size()));
1171
1172 VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR =
1173 {
1174 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType;
1175 DE_NULL, // const void* pNext;
1176 VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, // VkAccelerationStructureTypeKHR type;
1177 m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags;
1178 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR, // VkBuildAccelerationStructureModeKHR mode;
1179 DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure;
1180 m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR dstAccelerationStructure;
1181 geometryCount, // deUint32 geometryCount;
1182 m_useArrayOfPointers ? DE_NULL : accelerationStructureGeometriesKHRPointer, // const VkAccelerationStructureGeometryKHR* pGeometries;
1183 m_useArrayOfPointers ? accelerationStructureGeometry : DE_NULL, // const VkAccelerationStructureGeometryKHR* const* ppGeometries;
1184 scratchData // VkDeviceOrHostAddressKHR scratchData;
1185 };
1186
1187 VkAccelerationStructureBuildRangeInfoKHR* accelerationStructureBuildRangeInfoKHRPtr = accelerationStructureBuildRangeInfoKHR.data();
1188
1189 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1190 {
1191 if (m_indirectBuffer == DE_NULL)
1192 vk.cmdBuildAccelerationStructuresKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
1193 else
1194 {
1195 VkDeviceAddress indirectDeviceAddress = getBufferDeviceAddress(vk, device, m_indirectBuffer, m_indirectBufferOffset);
1196 deUint32* pMaxPrimitiveCounts = maxPrimitiveCounts.data();
1197 vk.cmdBuildAccelerationStructuresIndirectKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, &indirectDeviceAddress, &m_indirectBufferStride, &pMaxPrimitiveCounts);
1198 }
1199 }
1200 else if (!m_deferredOperation)
1201 {
1202 VK_CHECK(vk.buildAccelerationStructuresKHR(device, DE_NULL, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr));
1203 }
1204 else
1205 {
1206 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
1207 const auto deferredOperation = deferredOperationPtr.get();
1208
1209 VkResult result = vk.buildAccelerationStructuresKHR(device, deferredOperation, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
1210
1211 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1212
1213 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1214 }
1215 }
1216
1217 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1218 {
1219 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1220 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
1221
1222 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1223 }
1224 }
1225
copyFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,BottomLevelAccelerationStructure * accelerationStructure,bool compactCopy)1226 void BottomLevelAccelerationStructureKHR::copyFrom (const DeviceInterface& vk,
1227 const VkDevice device,
1228 const VkCommandBuffer cmdBuffer,
1229 BottomLevelAccelerationStructure* accelerationStructure,
1230 bool compactCopy)
1231 {
1232 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1233 DE_ASSERT(accelerationStructure != DE_NULL);
1234
1235 VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo =
1236 {
1237 VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
1238 DE_NULL, // const void* pNext;
1239 *(accelerationStructure->getPtr()), // VkAccelerationStructureKHR src;
1240 *(getPtr()), // VkAccelerationStructureKHR dst;
1241 compactCopy ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR // VkCopyAccelerationStructureModeKHR mode;
1242 };
1243
1244 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1245 {
1246 vk.cmdCopyAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo);
1247 }
1248 else if (!m_deferredOperation)
1249 {
1250 VK_CHECK(vk.copyAccelerationStructureKHR(device, DE_NULL, ©AccelerationStructureInfo));
1251 }
1252 else
1253 {
1254 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
1255 const auto deferredOperation = deferredOperationPtr.get();
1256
1257 VkResult result = vk.copyAccelerationStructureKHR(device, deferredOperation, ©AccelerationStructureInfo);
1258
1259 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1260
1261 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1262 }
1263
1264 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1265 {
1266 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1267 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
1268
1269 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1270 }
1271 }
1272
serialize(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,SerialStorage * storage)1273 void BottomLevelAccelerationStructureKHR::serialize (const DeviceInterface& vk,
1274 const VkDevice device,
1275 const VkCommandBuffer cmdBuffer,
1276 SerialStorage* storage)
1277 {
1278 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1279 DE_ASSERT(storage != DE_NULL);
1280
1281 const VkCopyAccelerationStructureToMemoryInfoKHR copyAccelerationStructureInfo =
1282 {
1283 VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR, // VkStructureType sType;
1284 DE_NULL, // const void* pNext;
1285 *(getPtr()), // VkAccelerationStructureKHR src;
1286 storage->getAddress(vk, device, m_buildType), // VkDeviceOrHostAddressKHR dst;
1287 VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode;
1288 };
1289
1290 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1291 {
1292 vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, ©AccelerationStructureInfo);
1293 }
1294 else if (!m_deferredOperation)
1295 {
1296 VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, DE_NULL, ©AccelerationStructureInfo));
1297 }
1298 else
1299 {
1300 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
1301 const auto deferredOperation = deferredOperationPtr.get();
1302
1303 const VkResult result = vk.copyAccelerationStructureToMemoryKHR(device, deferredOperation, ©AccelerationStructureInfo);
1304
1305 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1306
1307 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1308 }
1309 }
1310
deserialize(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,SerialStorage * storage)1311 void BottomLevelAccelerationStructureKHR::deserialize (const DeviceInterface& vk,
1312 const VkDevice device,
1313 const VkCommandBuffer cmdBuffer,
1314 SerialStorage* storage)
1315 {
1316 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1317 DE_ASSERT(storage != DE_NULL);
1318
1319 const VkCopyMemoryToAccelerationStructureInfoKHR copyAccelerationStructureInfo =
1320 {
1321 VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
1322 DE_NULL, // const void* pNext;
1323 storage->getAddressConst(vk, device, m_buildType), // VkDeviceOrHostAddressConstKHR src;
1324 *(getPtr()), // VkAccelerationStructureKHR dst;
1325 VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode;
1326 };
1327
1328 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1329 {
1330 vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo);
1331 }
1332 else if (!m_deferredOperation)
1333 {
1334 VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, DE_NULL, ©AccelerationStructureInfo));
1335 }
1336 else
1337 {
1338 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
1339 const auto deferredOperation = deferredOperationPtr.get();
1340
1341 const VkResult result = vk.copyMemoryToAccelerationStructureKHR(device, deferredOperation, ©AccelerationStructureInfo);
1342
1343 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1344
1345 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1346 }
1347
1348 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1349 {
1350 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1351 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
1352
1353 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1354 }
1355 }
1356
getPtr(void) const1357 const VkAccelerationStructureKHR* BottomLevelAccelerationStructureKHR::getPtr (void) const
1358 {
1359 return &m_accelerationStructureKHR.get();
1360 }
1361
prepareGeometries(const DeviceInterface & vk,const VkDevice device,std::vector<VkAccelerationStructureGeometryKHR> & accelerationStructureGeometriesKHR,std::vector<VkAccelerationStructureGeometryKHR * > & accelerationStructureGeometriesKHRPointers,std::vector<VkAccelerationStructureBuildRangeInfoKHR> & accelerationStructureBuildRangeInfoKHR,std::vector<deUint32> & maxPrimitiveCounts)1362 void BottomLevelAccelerationStructureKHR::prepareGeometries (const DeviceInterface& vk,
1363 const VkDevice device,
1364 std::vector<VkAccelerationStructureGeometryKHR>& accelerationStructureGeometriesKHR,
1365 std::vector<VkAccelerationStructureGeometryKHR*>& accelerationStructureGeometriesKHRPointers,
1366 std::vector<VkAccelerationStructureBuildRangeInfoKHR>& accelerationStructureBuildRangeInfoKHR,
1367 std::vector<deUint32>& maxPrimitiveCounts)
1368 {
1369 accelerationStructureGeometriesKHR.resize(m_geometriesData.size());
1370 accelerationStructureGeometriesKHRPointers.resize(m_geometriesData.size());
1371 accelerationStructureBuildRangeInfoKHR.resize(m_geometriesData.size());
1372 maxPrimitiveCounts.resize(m_geometriesData.size());
1373
1374 VkDeviceSize vertexBufferOffset = 0, indexBufferOffset = 0;
1375
1376 for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx)
1377 {
1378 de::SharedPtr<RaytracedGeometryBase>& geometryData = m_geometriesData[geometryNdx];
1379 VkDeviceOrHostAddressConstKHR vertexData, indexData;
1380 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1381 {
1382 if (m_vertexBuffer.get() != DE_NULL)
1383 {
1384 vertexData = makeDeviceOrHostAddressConstKHR(vk, device, m_vertexBuffer->get(), vertexBufferOffset);
1385 vertexBufferOffset += deAlignSize(geometryData->getVertexByteSize(), 8);
1386 }
1387 else
1388 vertexData = makeDeviceOrHostAddressConstKHR(DE_NULL);
1389
1390 if (m_indexBuffer.get() != DE_NULL && geometryData->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
1391 {
1392 indexData = makeDeviceOrHostAddressConstKHR(vk, device, m_indexBuffer->get(), indexBufferOffset);
1393 indexBufferOffset += deAlignSize(geometryData->getIndexByteSize(), 8);
1394 }
1395 else
1396 indexData = makeDeviceOrHostAddressConstKHR(DE_NULL);
1397 }
1398 else
1399 {
1400 vertexData = makeDeviceOrHostAddressConstKHR(geometryData->getVertexPointer());
1401 if (geometryData->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
1402 indexData = makeDeviceOrHostAddressConstKHR(geometryData->getIndexPointer());
1403 else
1404 indexData = makeDeviceOrHostAddressConstKHR(DE_NULL);
1405 }
1406
1407 const VkAccelerationStructureGeometryTrianglesDataKHR accelerationStructureGeometryTrianglesDataKHR =
1408 {
1409 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, // VkStructureType sType;
1410 DE_NULL, // const void* pNext;
1411 geometryData->getVertexFormat(), // VkFormat vertexFormat;
1412 vertexData, // VkDeviceOrHostAddressConstKHR vertexData;
1413 geometryData->getVertexStride(), // VkDeviceSize vertexStride;
1414 static_cast<deUint32>(geometryData->getVertexCount()), // uint32_t maxVertex;
1415 geometryData->getIndexType(), // VkIndexType indexType;
1416 indexData, // VkDeviceOrHostAddressConstKHR indexData;
1417 makeDeviceOrHostAddressConstKHR(DE_NULL), // VkDeviceOrHostAddressConstKHR transformData;
1418 };
1419
1420 const VkAccelerationStructureGeometryAabbsDataKHR accelerationStructureGeometryAabbsDataKHR =
1421 {
1422 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR, // VkStructureType sType;
1423 DE_NULL, // const void* pNext;
1424 vertexData, // VkDeviceOrHostAddressConstKHR data;
1425 geometryData->getAABBStride() // VkDeviceSize stride;
1426 };
1427 const VkAccelerationStructureGeometryDataKHR geometry = (geometryData->isTrianglesType())
1428 ? makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryTrianglesDataKHR)
1429 : makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryAabbsDataKHR);
1430 const VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR =
1431 {
1432 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // VkStructureType sType;
1433 DE_NULL, // const void* pNext;
1434 geometryData->getGeometryType(), // VkGeometryTypeKHR geometryType;
1435 geometry, // VkAccelerationStructureGeometryDataKHR geometry;
1436 geometryData->getGeometryFlags() // VkGeometryFlagsKHR flags;
1437 };
1438
1439 const deUint32 primitiveCount = (m_buildWithoutPrimitives ? 0u : geometryData->getPrimitiveCount());
1440
1441 const VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfosKHR =
1442 {
1443 primitiveCount, // deUint32 primitiveCount;
1444 0, // deUint32 primitiveOffset;
1445 0, // deUint32 firstVertex;
1446 0 // deUint32 firstTransform;
1447 };
1448
1449 accelerationStructureGeometriesKHR[geometryNdx] = accelerationStructureGeometryKHR;
1450 accelerationStructureGeometriesKHRPointers[geometryNdx] = &accelerationStructureGeometriesKHR[geometryNdx];
1451 accelerationStructureBuildRangeInfoKHR[geometryNdx] = accelerationStructureBuildRangeInfosKHR;
1452 maxPrimitiveCounts[geometryNdx] = geometryData->getPrimitiveCount();
1453 }
1454 }
1455
getRequiredAllocationCount(void)1456 deUint32 BottomLevelAccelerationStructure::getRequiredAllocationCount (void)
1457 {
1458 return BottomLevelAccelerationStructureKHR::getRequiredAllocationCount();
1459 }
1460
createAndBuild(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,VkDeviceAddress deviceAddress)1461 void BottomLevelAccelerationStructure::createAndBuild (const DeviceInterface& vk,
1462 const VkDevice device,
1463 const VkCommandBuffer cmdBuffer,
1464 Allocator& allocator,
1465 VkDeviceAddress deviceAddress)
1466 {
1467 create(vk, device, allocator, 0u, deviceAddress);
1468 build(vk, device, cmdBuffer);
1469 }
1470
createAndCopyFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,BottomLevelAccelerationStructure * accelerationStructure,VkDeviceSize compactCopySize,VkDeviceAddress deviceAddress)1471 void BottomLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface& vk,
1472 const VkDevice device,
1473 const VkCommandBuffer cmdBuffer,
1474 Allocator& allocator,
1475 BottomLevelAccelerationStructure* accelerationStructure,
1476 VkDeviceSize compactCopySize,
1477 VkDeviceAddress deviceAddress)
1478 {
1479 DE_ASSERT(accelerationStructure != NULL);
1480 VkDeviceSize copiedSize = compactCopySize > 0u ? compactCopySize : accelerationStructure->getStructureSize();
1481 DE_ASSERT(copiedSize != 0u);
1482
1483 create(vk, device, allocator, copiedSize, deviceAddress);
1484 copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize > 0u);
1485 }
1486
createAndDeserializeFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,SerialStorage * storage,VkDeviceAddress deviceAddress)1487 void BottomLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface& vk,
1488 const VkDevice device,
1489 const VkCommandBuffer cmdBuffer,
1490 Allocator& allocator,
1491 SerialStorage* storage,
1492 VkDeviceAddress deviceAddress )
1493 {
1494 DE_ASSERT(storage != NULL);
1495 DE_ASSERT(storage->getStorageSize() >= SerialStorage::SERIAL_STORAGE_SIZE_MIN);
1496 create(vk, device, allocator, storage->getDeserializedSize(), deviceAddress);
1497 deserialize(vk, device, cmdBuffer, storage);
1498 }
1499
makeBottomLevelAccelerationStructure()1500 de::MovePtr<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ()
1501 {
1502 return de::MovePtr<BottomLevelAccelerationStructure>(new BottomLevelAccelerationStructureKHR);
1503 }
1504
~TopLevelAccelerationStructure()1505 TopLevelAccelerationStructure::~TopLevelAccelerationStructure ()
1506 {
1507 }
1508
TopLevelAccelerationStructure()1509 TopLevelAccelerationStructure::TopLevelAccelerationStructure ()
1510 : m_structureSize (0u)
1511 , m_updateScratchSize (0u)
1512 , m_buildScratchSize (0u)
1513 {
1514 }
1515
setInstanceCount(const size_t instanceCount)1516 void TopLevelAccelerationStructure::setInstanceCount (const size_t instanceCount)
1517 {
1518 m_bottomLevelInstances.reserve(instanceCount);
1519 m_instanceData.reserve(instanceCount);
1520 }
1521
addInstance(de::SharedPtr<BottomLevelAccelerationStructure> bottomLevelStructure,const VkTransformMatrixKHR & matrix,deUint32 instanceCustomIndex,deUint32 mask,deUint32 instanceShaderBindingTableRecordOffset,VkGeometryInstanceFlagsKHR flags)1522 void TopLevelAccelerationStructure::addInstance (de::SharedPtr<BottomLevelAccelerationStructure> bottomLevelStructure,
1523 const VkTransformMatrixKHR& matrix,
1524 deUint32 instanceCustomIndex,
1525 deUint32 mask,
1526 deUint32 instanceShaderBindingTableRecordOffset,
1527 VkGeometryInstanceFlagsKHR flags)
1528 {
1529 m_bottomLevelInstances.push_back(bottomLevelStructure);
1530 m_instanceData.push_back(InstanceData(matrix, instanceCustomIndex, mask, instanceShaderBindingTableRecordOffset, flags));
1531 }
1532
getStructureSize() const1533 VkDeviceSize TopLevelAccelerationStructure::getStructureSize () const
1534 {
1535 return m_structureSize;
1536 }
1537
createAndBuild(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,VkDeviceAddress deviceAddress)1538 void TopLevelAccelerationStructure::createAndBuild (const DeviceInterface& vk,
1539 const VkDevice device,
1540 const VkCommandBuffer cmdBuffer,
1541 Allocator& allocator,
1542 VkDeviceAddress deviceAddress)
1543 {
1544 create(vk, device, allocator, 0u, deviceAddress);
1545 build(vk, device, cmdBuffer);
1546 }
1547
createAndCopyFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,TopLevelAccelerationStructure * accelerationStructure,VkDeviceSize compactCopySize,VkDeviceAddress deviceAddress)1548 void TopLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface& vk,
1549 const VkDevice device,
1550 const VkCommandBuffer cmdBuffer,
1551 Allocator& allocator,
1552 TopLevelAccelerationStructure* accelerationStructure,
1553 VkDeviceSize compactCopySize,
1554 VkDeviceAddress deviceAddress)
1555 {
1556 DE_ASSERT(accelerationStructure != NULL);
1557 VkDeviceSize copiedSize = compactCopySize > 0u ? compactCopySize : accelerationStructure->getStructureSize();
1558 DE_ASSERT(copiedSize != 0u);
1559
1560 create(vk, device, allocator, copiedSize, deviceAddress);
1561 copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize > 0u);
1562 }
1563
createAndDeserializeFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,SerialStorage * storage,VkDeviceAddress deviceAddress)1564 void TopLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface& vk,
1565 const VkDevice device,
1566 const VkCommandBuffer cmdBuffer,
1567 Allocator& allocator,
1568 SerialStorage* storage,
1569 VkDeviceAddress deviceAddress)
1570 {
1571 DE_ASSERT(storage != NULL);
1572 DE_ASSERT(storage->getStorageSize() >= SerialStorage::SERIAL_STORAGE_SIZE_MIN);
1573 create(vk, device, allocator, storage->getDeserializedSize(), deviceAddress);
1574 if (storage->hasDeepFormat()) createAndDeserializeBottoms(vk, device, cmdBuffer, allocator, storage);
1575 deserialize(vk, device, cmdBuffer, storage);
1576 }
1577
createInstanceBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelInstances,std::vector<InstanceData> instanceData)1578 BufferWithMemory* createInstanceBuffer (const DeviceInterface& vk,
1579 const VkDevice device,
1580 Allocator& allocator,
1581 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelInstances,
1582 std::vector<InstanceData> instanceData)
1583 {
1584 DE_ASSERT(bottomLevelInstances.size() != 0);
1585 DE_ASSERT(bottomLevelInstances.size() == instanceData.size());
1586 DE_UNREF(instanceData);
1587
1588 const VkDeviceSize bufferSizeBytes = bottomLevelInstances.size() * sizeof(VkAccelerationStructureInstanceKHR);
1589 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1590 try
1591 {
1592 return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
1593 }
1594 catch (const tcu::NotSupportedError&)
1595 {
1596 // retry without Cached flag
1597 return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
1598 }
1599 }
1600
updateSingleInstance(const DeviceInterface & vk,const VkDevice device,const BottomLevelAccelerationStructure & bottomLevelAccelerationStructure,const InstanceData & instanceData,deUint8 * bufferLocation,VkAccelerationStructureBuildTypeKHR buildType,bool inactiveInstances)1601 void updateSingleInstance (const DeviceInterface& vk,
1602 const VkDevice device,
1603 const BottomLevelAccelerationStructure& bottomLevelAccelerationStructure,
1604 const InstanceData& instanceData,
1605 deUint8* bufferLocation,
1606 VkAccelerationStructureBuildTypeKHR buildType,
1607 bool inactiveInstances)
1608 {
1609 const VkAccelerationStructureKHR accelerationStructureKHR = *bottomLevelAccelerationStructure.getPtr();
1610
1611 // This part needs to be fixed once a new version of the VkAccelerationStructureInstanceKHR will be added to vkStructTypes.inl
1612 VkDeviceAddress accelerationStructureAddress;
1613 if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1614 {
1615 VkAccelerationStructureDeviceAddressInfoKHR asDeviceAddressInfo =
1616 {
1617 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
1618 DE_NULL, // const void* pNext;
1619 accelerationStructureKHR // VkAccelerationStructureKHR accelerationStructure;
1620 };
1621 accelerationStructureAddress = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
1622 }
1623
1624 deUint64 structureReference;
1625 if (inactiveInstances)
1626 {
1627 // Instances will be marked inactive by making their references VK_NULL_HANDLE or having address zero.
1628 structureReference = 0ull;
1629 }
1630 else
1631 {
1632 structureReference = (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1633 ? deUint64(accelerationStructureAddress)
1634 : deUint64(accelerationStructureKHR.getInternal());
1635 }
1636
1637 VkAccelerationStructureInstanceKHR accelerationStructureInstanceKHR = makeVkAccelerationStructureInstanceKHR
1638 (
1639 instanceData.matrix, // VkTransformMatrixKHR transform;
1640 instanceData.instanceCustomIndex, // deUint32 instanceCustomIndex:24;
1641 instanceData.mask, // deUint32 mask:8;
1642 instanceData.instanceShaderBindingTableRecordOffset, // deUint32 instanceShaderBindingTableRecordOffset:24;
1643 instanceData.flags, // VkGeometryInstanceFlagsKHR flags:8;
1644 structureReference // deUint64 accelerationStructureReference;
1645 );
1646
1647 deMemcpy(bufferLocation, &accelerationStructureInstanceKHR, sizeof(VkAccelerationStructureInstanceKHR));
1648 }
1649
updateInstanceBuffer(const DeviceInterface & vk,const VkDevice device,const std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelInstances,const std::vector<InstanceData> & instanceData,const BufferWithMemory * instanceBuffer,VkAccelerationStructureBuildTypeKHR buildType,bool inactiveInstances)1650 void updateInstanceBuffer (const DeviceInterface& vk,
1651 const VkDevice device,
1652 const std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>& bottomLevelInstances,
1653 const std::vector<InstanceData>& instanceData,
1654 const BufferWithMemory* instanceBuffer,
1655 VkAccelerationStructureBuildTypeKHR buildType,
1656 bool inactiveInstances)
1657 {
1658 DE_ASSERT(bottomLevelInstances.size() != 0);
1659 DE_ASSERT(bottomLevelInstances.size() == instanceData.size());
1660
1661 auto& instancesAlloc = instanceBuffer->getAllocation();
1662 auto bufferStart = reinterpret_cast<deUint8*>(instancesAlloc.getHostPtr());
1663 VkDeviceSize bufferOffset = 0ull;
1664
1665 for (size_t instanceNdx = 0; instanceNdx < bottomLevelInstances.size(); ++instanceNdx)
1666 {
1667 const auto& blas = *bottomLevelInstances[instanceNdx];
1668 updateSingleInstance(vk, device, blas, instanceData[instanceNdx], bufferStart + bufferOffset, buildType, inactiveInstances);
1669 bufferOffset += sizeof(VkAccelerationStructureInstanceKHR);
1670 }
1671
1672 flushMappedMemoryRange(vk, device, instancesAlloc.getMemory(), instancesAlloc.getOffset(), VK_WHOLE_SIZE);
1673 }
1674
1675 class TopLevelAccelerationStructureKHR : public TopLevelAccelerationStructure
1676 {
1677 public:
1678 static deUint32 getRequiredAllocationCount (void);
1679
1680 TopLevelAccelerationStructureKHR ();
1681 TopLevelAccelerationStructureKHR (const TopLevelAccelerationStructureKHR& other) = delete;
1682 virtual ~TopLevelAccelerationStructureKHR ();
1683
1684 void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) override;
1685 void setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags) override;
1686 void setCreateGeneric (bool createGeneric) override;
1687 void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags) override;
1688 void setBuildWithoutPrimitives (bool buildWithoutPrimitives) override;
1689 void setInactiveInstances (bool inactiveInstances) override;
1690 void setDeferredOperation (const bool deferredOperation,
1691 const deUint32 workerThreadCount) override;
1692 void setUseArrayOfPointers (const bool useArrayOfPointers) override;
1693 void setIndirectBuildParameters (const VkBuffer indirectBuffer,
1694 const VkDeviceSize indirectBufferOffset,
1695 const deUint32 indirectBufferStride) override;
1696 void setUsePPGeometries (const bool usePPGeometries) override;
1697 VkBuildAccelerationStructureFlagsKHR getBuildFlags () const override;
1698
1699 void create (const DeviceInterface& vk,
1700 const VkDevice device,
1701 Allocator& allocator,
1702 VkDeviceSize structureSize,
1703 VkDeviceAddress deviceAddress = 0u ) override;
1704 void build (const DeviceInterface& vk,
1705 const VkDevice device,
1706 const VkCommandBuffer cmdBuffer) override;
1707 void copyFrom (const DeviceInterface& vk,
1708 const VkDevice device,
1709 const VkCommandBuffer cmdBuffer,
1710 TopLevelAccelerationStructure* accelerationStructure,
1711 bool compactCopy) override;
1712 void serialize (const DeviceInterface& vk,
1713 const VkDevice device,
1714 const VkCommandBuffer cmdBuffer,
1715 SerialStorage* storage) override;
1716 void deserialize (const DeviceInterface& vk,
1717 const VkDevice device,
1718 const VkCommandBuffer cmdBuffer,
1719 SerialStorage* storage) override;
1720
1721 std::vector<VkDeviceSize> getSerializingSizes (const DeviceInterface& vk,
1722 const VkDevice device,
1723 const VkQueue queue,
1724 const deUint32 queueFamilyIndex) override;
1725
1726 std::vector<deUint64> getSerializingAddresses (const DeviceInterface& vk,
1727 const VkDevice device) const override;
1728
1729
1730 const VkAccelerationStructureKHR* getPtr (void) const override;
1731
1732 void updateInstanceMatrix (const DeviceInterface& vk,
1733 const VkDevice device,
1734 size_t instanceIndex,
1735 const VkTransformMatrixKHR& matrix) override;
1736
1737 protected:
1738 VkAccelerationStructureBuildTypeKHR m_buildType;
1739 VkAccelerationStructureCreateFlagsKHR m_createFlags;
1740 bool m_createGeneric;
1741 VkBuildAccelerationStructureFlagsKHR m_buildFlags;
1742 bool m_buildWithoutPrimitives;
1743 bool m_inactiveInstances;
1744 bool m_deferredOperation;
1745 deUint32 m_workerThreadCount;
1746 bool m_useArrayOfPointers;
1747 de::MovePtr<BufferWithMemory> m_accelerationStructureBuffer;
1748 de::MovePtr<BufferWithMemory> m_instanceBuffer;
1749 de::MovePtr<BufferWithMemory> m_instanceAddressBuffer;
1750 de::MovePtr<BufferWithMemory> m_deviceScratchBuffer;
1751 std::vector<deUint8> m_hostScratchBuffer;
1752 Move<VkAccelerationStructureKHR> m_accelerationStructureKHR;
1753 VkBuffer m_indirectBuffer;
1754 VkDeviceSize m_indirectBufferOffset;
1755 deUint32 m_indirectBufferStride;
1756 bool m_usePPGeometries;
1757
1758
1759 void prepareInstances (const DeviceInterface& vk,
1760 const VkDevice device,
1761 VkAccelerationStructureGeometryKHR& accelerationStructureGeometryKHR,
1762 std::vector<deUint32>& maxPrimitiveCounts);
1763
1764 void serializeBottoms (const DeviceInterface& vk,
1765 const VkDevice device,
1766 const VkCommandBuffer cmdBuffer,
1767 SerialStorage* storage,
1768 VkDeferredOperationKHR deferredOperation);
1769
1770 void createAndDeserializeBottoms (const DeviceInterface& vk,
1771 const VkDevice device,
1772 const VkCommandBuffer cmdBuffer,
1773 Allocator& allocator,
1774 SerialStorage* storage) override;
1775 };
1776
getRequiredAllocationCount(void)1777 deUint32 TopLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
1778 {
1779 /*
1780 de::MovePtr<BufferWithMemory> m_instanceBuffer;
1781 de::MovePtr<Allocation> m_accelerationStructureAlloc;
1782 de::MovePtr<BufferWithMemory> m_deviceScratchBuffer;
1783 */
1784 return 3u;
1785 }
1786
TopLevelAccelerationStructureKHR()1787 TopLevelAccelerationStructureKHR::TopLevelAccelerationStructureKHR ()
1788 : TopLevelAccelerationStructure ()
1789 , m_buildType (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1790 , m_createFlags (0u)
1791 , m_createGeneric (false)
1792 , m_buildFlags (0u)
1793 , m_buildWithoutPrimitives (false)
1794 , m_inactiveInstances (false)
1795 , m_deferredOperation (false)
1796 , m_workerThreadCount (0)
1797 , m_useArrayOfPointers (false)
1798 , m_accelerationStructureBuffer (DE_NULL)
1799 , m_instanceBuffer (DE_NULL)
1800 , m_instanceAddressBuffer (DE_NULL)
1801 , m_deviceScratchBuffer (DE_NULL)
1802 , m_accelerationStructureKHR ()
1803 , m_indirectBuffer (DE_NULL)
1804 , m_indirectBufferOffset (0)
1805 , m_indirectBufferStride (0)
1806 , m_usePPGeometries (false)
1807 {
1808 }
1809
~TopLevelAccelerationStructureKHR()1810 TopLevelAccelerationStructureKHR::~TopLevelAccelerationStructureKHR ()
1811 {
1812 }
1813
setBuildType(const VkAccelerationStructureBuildTypeKHR buildType)1814 void TopLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR buildType)
1815 {
1816 m_buildType = buildType;
1817 }
1818
setCreateFlags(const VkAccelerationStructureCreateFlagsKHR createFlags)1819 void TopLevelAccelerationStructureKHR::setCreateFlags (const VkAccelerationStructureCreateFlagsKHR createFlags)
1820 {
1821 m_createFlags = createFlags;
1822 }
1823
setCreateGeneric(bool createGeneric)1824 void TopLevelAccelerationStructureKHR::setCreateGeneric (bool createGeneric)
1825 {
1826 m_createGeneric = createGeneric;
1827 }
1828
setInactiveInstances(bool inactiveInstances)1829 void TopLevelAccelerationStructureKHR::setInactiveInstances (bool inactiveInstances)
1830 {
1831 m_inactiveInstances = inactiveInstances;
1832 }
1833
setBuildFlags(const VkBuildAccelerationStructureFlagsKHR buildFlags)1834 void TopLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR buildFlags)
1835 {
1836 m_buildFlags = buildFlags;
1837 }
1838
setBuildWithoutPrimitives(bool buildWithoutPrimitives)1839 void TopLevelAccelerationStructureKHR::setBuildWithoutPrimitives (bool buildWithoutPrimitives)
1840 {
1841 m_buildWithoutPrimitives = buildWithoutPrimitives;
1842 }
1843
setDeferredOperation(const bool deferredOperation,const deUint32 workerThreadCount)1844 void TopLevelAccelerationStructureKHR::setDeferredOperation (const bool deferredOperation,
1845 const deUint32 workerThreadCount)
1846 {
1847 m_deferredOperation = deferredOperation;
1848 m_workerThreadCount = workerThreadCount;
1849 }
1850
setUseArrayOfPointers(const bool useArrayOfPointers)1851 void TopLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool useArrayOfPointers)
1852 {
1853 m_useArrayOfPointers = useArrayOfPointers;
1854 }
1855
setUsePPGeometries(const bool usePPGeometries)1856 void TopLevelAccelerationStructureKHR::setUsePPGeometries (const bool usePPGeometries)
1857 {
1858 m_usePPGeometries = usePPGeometries;
1859 }
1860
setIndirectBuildParameters(const VkBuffer indirectBuffer,const VkDeviceSize indirectBufferOffset,const deUint32 indirectBufferStride)1861 void TopLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer indirectBuffer,
1862 const VkDeviceSize indirectBufferOffset,
1863 const deUint32 indirectBufferStride)
1864 {
1865 m_indirectBuffer = indirectBuffer;
1866 m_indirectBufferOffset = indirectBufferOffset;
1867 m_indirectBufferStride = indirectBufferStride;
1868 }
1869
getBuildFlags() const1870 VkBuildAccelerationStructureFlagsKHR TopLevelAccelerationStructureKHR::getBuildFlags () const
1871 {
1872 return m_buildFlags;
1873 }
1874
create(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,VkDeviceSize structureSize,VkDeviceAddress deviceAddress)1875 void TopLevelAccelerationStructureKHR::create (const DeviceInterface& vk,
1876 const VkDevice device,
1877 Allocator& allocator,
1878 VkDeviceSize structureSize,
1879 VkDeviceAddress deviceAddress)
1880 {
1881 // AS may be built from geometries using vkCmdBuildAccelerationStructureKHR / vkBuildAccelerationStructureKHR
1882 // or may be copied/compacted/deserialized from other AS ( in this case AS does not need geometries, but it needs to know its size before creation ).
1883 DE_ASSERT(!m_bottomLevelInstances.empty() != !(structureSize == 0)); // logical xor
1884
1885 if (structureSize == 0)
1886 {
1887 VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR;
1888 const auto accelerationStructureGeometryKHRPtr = &accelerationStructureGeometryKHR;
1889 std::vector<deUint32> maxPrimitiveCounts;
1890 prepareInstances(vk, device, accelerationStructureGeometryKHR, maxPrimitiveCounts);
1891
1892 VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR =
1893 {
1894 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType;
1895 DE_NULL, // const void* pNext;
1896 VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, // VkAccelerationStructureTypeKHR type;
1897 m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags;
1898 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR, // VkBuildAccelerationStructureModeKHR mode;
1899 DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure;
1900 DE_NULL, // VkAccelerationStructureKHR dstAccelerationStructure;
1901 1u, // deUint32 geometryCount;
1902 (m_usePPGeometries ? nullptr : &accelerationStructureGeometryKHR), // const VkAccelerationStructureGeometryKHR* pGeometries;
1903 (m_usePPGeometries ? &accelerationStructureGeometryKHRPtr : nullptr), // const VkAccelerationStructureGeometryKHR* const* ppGeometries;
1904 makeDeviceOrHostAddressKHR(DE_NULL) // VkDeviceOrHostAddressKHR scratchData;
1905 };
1906
1907 VkAccelerationStructureBuildSizesInfoKHR sizeInfo =
1908 {
1909 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, // VkStructureType sType;
1910 DE_NULL, // const void* pNext;
1911 0, // VkDeviceSize accelerationStructureSize;
1912 0, // VkDeviceSize updateScratchSize;
1913 0 // VkDeviceSize buildScratchSize;
1914 };
1915
1916 vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
1917
1918 m_structureSize = sizeInfo.accelerationStructureSize;
1919 m_updateScratchSize = sizeInfo.updateScratchSize;
1920 m_buildScratchSize = sizeInfo.buildScratchSize;
1921 }
1922 else
1923 {
1924 m_structureSize = structureSize;
1925 m_updateScratchSize = 0u;
1926 m_buildScratchSize = 0u;
1927 }
1928
1929 {
1930 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_structureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1931 try
1932 {
1933 m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1934 }
1935 catch (const tcu::NotSupportedError&)
1936 {
1937 // retry without Cached flag
1938 m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1939 }
1940 }
1941
1942 {
1943 const VkAccelerationStructureTypeKHR structureType = (m_createGeneric
1944 ? VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
1945 : VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR);
1946 const VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfoKHR =
1947 {
1948 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, // VkStructureType sType;
1949 DE_NULL, // const void* pNext;
1950 m_createFlags, // VkAccelerationStructureCreateFlagsKHR createFlags;
1951 m_accelerationStructureBuffer->get(), // VkBuffer buffer;
1952 0u, // VkDeviceSize offset;
1953 m_structureSize, // VkDeviceSize size;
1954 structureType, // VkAccelerationStructureTypeKHR type;
1955 deviceAddress // VkDeviceAddress deviceAddress;
1956 };
1957
1958 m_accelerationStructureKHR = createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL);
1959 }
1960
1961 if (m_buildScratchSize > 0u)
1962 {
1963 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1964 {
1965 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1966 m_deviceScratchBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1967 }
1968 else
1969 {
1970 m_hostScratchBuffer.resize(static_cast<size_t>(m_buildScratchSize));
1971 }
1972 }
1973
1974 if (m_useArrayOfPointers)
1975 {
1976 const size_t pointerSize = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) ? sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress) : sizeof(VkDeviceOrHostAddressConstKHR::hostAddress);
1977 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(m_bottomLevelInstances.size() * pointerSize), VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1978 m_instanceAddressBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1979 }
1980
1981 if(!m_bottomLevelInstances.empty())
1982 m_instanceBuffer = de::MovePtr<BufferWithMemory>(createInstanceBuffer(vk, device, allocator, m_bottomLevelInstances, m_instanceData));
1983 }
1984
updateInstanceMatrix(const DeviceInterface & vk,const VkDevice device,size_t instanceIndex,const VkTransformMatrixKHR & matrix)1985 void TopLevelAccelerationStructureKHR::updateInstanceMatrix (const DeviceInterface& vk, const VkDevice device, size_t instanceIndex, const VkTransformMatrixKHR& matrix)
1986 {
1987 DE_ASSERT(m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR);
1988 DE_ASSERT(instanceIndex < m_bottomLevelInstances.size());
1989 DE_ASSERT(instanceIndex < m_instanceData.size());
1990
1991 const auto& blas = *m_bottomLevelInstances[instanceIndex];
1992 auto& instanceData = m_instanceData[instanceIndex];
1993 auto& instancesAlloc = m_instanceBuffer->getAllocation();
1994 auto bufferStart = reinterpret_cast<deUint8*>(instancesAlloc.getHostPtr());
1995 VkDeviceSize bufferOffset = sizeof(VkAccelerationStructureInstanceKHR) * instanceIndex;
1996
1997 instanceData.matrix = matrix;
1998 updateSingleInstance(vk, device, blas, instanceData, bufferStart + bufferOffset, m_buildType, m_inactiveInstances);
1999 flushMappedMemoryRange(vk, device, instancesAlloc.getMemory(), instancesAlloc.getOffset(), VK_WHOLE_SIZE);
2000 }
2001
build(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer)2002 void TopLevelAccelerationStructureKHR::build (const DeviceInterface& vk,
2003 const VkDevice device,
2004 const VkCommandBuffer cmdBuffer)
2005 {
2006 DE_ASSERT(!m_bottomLevelInstances.empty());
2007 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
2008 DE_ASSERT(m_buildScratchSize != 0);
2009
2010 updateInstanceBuffer(vk, device, m_bottomLevelInstances, m_instanceData, m_instanceBuffer.get(), m_buildType, m_inactiveInstances);
2011
2012 VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR;
2013 const auto accelerationStructureGeometryKHRPtr = &accelerationStructureGeometryKHR;
2014 std::vector<deUint32> maxPrimitiveCounts;
2015 prepareInstances(vk, device, accelerationStructureGeometryKHR, maxPrimitiveCounts);
2016
2017 VkDeviceOrHostAddressKHR scratchData = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2018 ? makeDeviceOrHostAddressKHR(vk, device, m_deviceScratchBuffer->get(), 0)
2019 : makeDeviceOrHostAddressKHR(m_hostScratchBuffer.data());
2020
2021 VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR =
2022 {
2023 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType;
2024 DE_NULL, // const void* pNext;
2025 VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, // VkAccelerationStructureTypeKHR type;
2026 m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags;
2027 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR, // VkBuildAccelerationStructureModeKHR mode;
2028 DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure;
2029 m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR dstAccelerationStructure;
2030 1u, // deUint32 geometryCount;
2031 (m_usePPGeometries ? nullptr : &accelerationStructureGeometryKHR), // const VkAccelerationStructureGeometryKHR* pGeometries;
2032 (m_usePPGeometries ? &accelerationStructureGeometryKHRPtr : nullptr), // const VkAccelerationStructureGeometryKHR* const* ppGeometries;
2033 scratchData // VkDeviceOrHostAddressKHR scratchData;
2034 };
2035
2036 const deUint32 primitiveCount = (m_buildWithoutPrimitives ? 0u : static_cast<deUint32>(m_bottomLevelInstances.size()));
2037
2038 VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfoKHR =
2039 {
2040 primitiveCount, // deUint32 primitiveCount;
2041 0, // deUint32 primitiveOffset;
2042 0, // deUint32 firstVertex;
2043 0 // deUint32 transformOffset;
2044 };
2045 VkAccelerationStructureBuildRangeInfoKHR* accelerationStructureBuildRangeInfoKHRPtr = &accelerationStructureBuildRangeInfoKHR;
2046
2047 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2048 {
2049 if (m_indirectBuffer == DE_NULL)
2050 vk.cmdBuildAccelerationStructuresKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
2051 else
2052 {
2053 VkDeviceAddress indirectDeviceAddress = getBufferDeviceAddress(vk, device, m_indirectBuffer, m_indirectBufferOffset);
2054 deUint32* pMaxPrimitiveCounts = maxPrimitiveCounts.data();
2055 vk.cmdBuildAccelerationStructuresIndirectKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, &indirectDeviceAddress, &m_indirectBufferStride, &pMaxPrimitiveCounts);
2056 }
2057 }
2058 else if (!m_deferredOperation)
2059 {
2060 VK_CHECK(vk.buildAccelerationStructuresKHR(device, DE_NULL, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr));
2061 }
2062 else
2063 {
2064 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
2065 const auto deferredOperation = deferredOperationPtr.get();
2066
2067 VkResult result = vk.buildAccelerationStructuresKHR(device, deferredOperation, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
2068
2069 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
2070
2071 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
2072
2073 accelerationStructureBuildGeometryInfoKHR.pNext = DE_NULL;
2074 }
2075
2076 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2077 {
2078 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
2079 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
2080
2081 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
2082 }
2083 }
2084
copyFrom(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,TopLevelAccelerationStructure * accelerationStructure,bool compactCopy)2085 void TopLevelAccelerationStructureKHR::copyFrom (const DeviceInterface& vk,
2086 const VkDevice device,
2087 const VkCommandBuffer cmdBuffer,
2088 TopLevelAccelerationStructure* accelerationStructure,
2089 bool compactCopy)
2090 {
2091 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
2092 DE_ASSERT(accelerationStructure != DE_NULL);
2093
2094 VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo =
2095 {
2096 VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
2097 DE_NULL, // const void* pNext;
2098 *(accelerationStructure->getPtr()), // VkAccelerationStructureKHR src;
2099 *(getPtr()), // VkAccelerationStructureKHR dst;
2100 compactCopy ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR // VkCopyAccelerationStructureModeKHR mode;
2101 };
2102
2103 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2104 {
2105 vk.cmdCopyAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo);
2106 }
2107 else if (!m_deferredOperation)
2108 {
2109 VK_CHECK(vk.copyAccelerationStructureKHR(device, DE_NULL, ©AccelerationStructureInfo));
2110 }
2111 else
2112 {
2113 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
2114 const auto deferredOperation = deferredOperationPtr.get();
2115
2116 VkResult result = vk.copyAccelerationStructureKHR(device, deferredOperation, ©AccelerationStructureInfo);
2117
2118 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
2119
2120 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
2121 }
2122
2123 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2124 {
2125 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
2126 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
2127
2128 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
2129 }
2130
2131 }
2132
serialize(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,SerialStorage * storage)2133 void TopLevelAccelerationStructureKHR::serialize (const DeviceInterface& vk,
2134 const VkDevice device,
2135 const VkCommandBuffer cmdBuffer,
2136 SerialStorage* storage)
2137 {
2138 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
2139 DE_ASSERT(storage != DE_NULL);
2140
2141 const VkCopyAccelerationStructureToMemoryInfoKHR copyAccelerationStructureInfo =
2142 {
2143 VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR, // VkStructureType sType;
2144 DE_NULL, // const void* pNext;
2145 *(getPtr()), // VkAccelerationStructureKHR src;
2146 storage->getAddress(vk, device, m_buildType), // VkDeviceOrHostAddressKHR dst;
2147 VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode;
2148 };
2149
2150 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2151 {
2152 vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, ©AccelerationStructureInfo);
2153 if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, DE_NULL);
2154 }
2155 else if (!m_deferredOperation)
2156 {
2157 VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, DE_NULL, ©AccelerationStructureInfo));
2158 if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, DE_NULL);
2159 }
2160 else
2161 {
2162 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
2163 const auto deferredOperation = deferredOperationPtr.get();
2164
2165 const VkResult result = vk.copyAccelerationStructureToMemoryKHR(device, deferredOperation, ©AccelerationStructureInfo);
2166
2167 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
2168 if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, deferredOperation);
2169
2170 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
2171 }
2172 }
2173
deserialize(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,SerialStorage * storage)2174 void TopLevelAccelerationStructureKHR::deserialize (const DeviceInterface& vk,
2175 const VkDevice device,
2176 const VkCommandBuffer cmdBuffer,
2177 SerialStorage* storage)
2178 {
2179 DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
2180 DE_ASSERT(storage != DE_NULL);
2181
2182 const VkCopyMemoryToAccelerationStructureInfoKHR copyAccelerationStructureInfo =
2183 {
2184 VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
2185 DE_NULL, // const void* pNext;
2186 storage->getAddressConst(vk, device, m_buildType), // VkDeviceOrHostAddressConstKHR src;
2187 *(getPtr()), // VkAccelerationStructureKHR dst;
2188 VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode;
2189 };
2190
2191 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2192 {
2193 vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo);
2194 }
2195 else if (!m_deferredOperation)
2196 {
2197 VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, DE_NULL, ©AccelerationStructureInfo));
2198 }
2199 else
2200 {
2201 const auto deferredOperationPtr = createDeferredOperationKHR(vk, device);
2202 const auto deferredOperation = deferredOperationPtr.get();
2203
2204 const VkResult result = vk.copyMemoryToAccelerationStructureKHR(device, deferredOperation, ©AccelerationStructureInfo);
2205
2206 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
2207
2208 finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
2209 }
2210
2211 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2212 {
2213 const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
2214 const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
2215
2216 cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
2217 }
2218 }
2219
serializeBottoms(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,SerialStorage * storage,VkDeferredOperationKHR deferredOperation)2220 void TopLevelAccelerationStructureKHR::serializeBottoms (const DeviceInterface& vk,
2221 const VkDevice device,
2222 const VkCommandBuffer cmdBuffer,
2223 SerialStorage* storage,
2224 VkDeferredOperationKHR deferredOperation)
2225 {
2226 DE_UNREF(deferredOperation);
2227 DE_ASSERT(storage->hasDeepFormat());
2228
2229 const std::vector<deUint64>& addresses = storage->getSerialInfo().addresses();
2230 const std::size_t cbottoms = m_bottomLevelInstances.size();
2231
2232 deUint32 storageIndex = 0;
2233 std::vector<deUint64> matches;
2234
2235 for (std::size_t i = 0; i < cbottoms; ++i)
2236 {
2237 const deUint64& lookAddr = addresses[i+1];
2238 auto end = matches.end();
2239 auto match = std::find_if(matches.begin(), end, [&](const deUint64& item){ return item == lookAddr; });
2240 if (match == end)
2241 {
2242 matches.emplace_back(lookAddr);
2243 m_bottomLevelInstances[i].get()->serialize(vk, device, cmdBuffer, storage->getBottomStorage(storageIndex).get());
2244 storageIndex += 1;
2245 }
2246 }
2247 }
2248
createAndDeserializeBottoms(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,Allocator & allocator,SerialStorage * storage)2249 void TopLevelAccelerationStructureKHR::createAndDeserializeBottoms (const DeviceInterface& vk,
2250 const VkDevice device,
2251 const VkCommandBuffer cmdBuffer,
2252 Allocator& allocator,
2253 SerialStorage* storage)
2254 {
2255 DE_ASSERT(storage->hasDeepFormat());
2256 DE_ASSERT(m_bottomLevelInstances.size() == 0);
2257
2258 const std::vector<deUint64>& addresses = storage->getSerialInfo().addresses();
2259 const std::size_t cbottoms = addresses.size() - 1;
2260 deUint32 storageIndex = 0;
2261 std::vector<std::pair<deUint64, std::size_t>> matches;
2262
2263 for (std::size_t i = 0; i < cbottoms; ++i)
2264 {
2265 const deUint64& lookAddr = addresses[i+1];
2266 auto end = matches.end();
2267 auto match = std::find_if(matches.begin(), end, [&](const std::pair<deUint64, deUint32>& item){ return item.first == lookAddr; });
2268 if (match != end)
2269 {
2270 m_bottomLevelInstances .emplace_back(m_bottomLevelInstances[match->second]);
2271 }
2272 else
2273 {
2274 de::MovePtr<BottomLevelAccelerationStructure> blas = makeBottomLevelAccelerationStructure();
2275 blas->createAndDeserializeFrom(vk, device, cmdBuffer, allocator, storage->getBottomStorage(storageIndex).get());
2276 m_bottomLevelInstances.emplace_back(de::SharedPtr<BottomLevelAccelerationStructure>(blas.release()));
2277 matches.emplace_back(lookAddr, i);
2278 storageIndex += 1;
2279 }
2280 }
2281
2282 std::vector<deUint64> newAddresses = getSerializingAddresses(vk, device);
2283 DE_ASSERT(addresses.size() == newAddresses.size());
2284
2285 SerialStorage::AccelerationStructureHeader* header = storage->getASHeader();
2286 DE_ASSERT(cbottoms ==header->handleCount);
2287
2288 // finally update bottom-level AS addresses before top-level AS deserialization
2289 for (std::size_t i = 0; i < cbottoms; ++i)
2290 {
2291 header->handleArray[i] = newAddresses[i+1];
2292 }
2293 }
2294
getSerializingSizes(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const deUint32 queueFamilyIndex)2295 std::vector<VkDeviceSize> TopLevelAccelerationStructureKHR::getSerializingSizes (const DeviceInterface& vk,
2296 const VkDevice device,
2297 const VkQueue queue,
2298 const deUint32 queueFamilyIndex)
2299 {
2300 const deUint32 queryCount(deUint32(m_bottomLevelInstances.size()) + 1);
2301 std::vector<VkAccelerationStructureKHR> handles(queryCount);
2302 std::vector<VkDeviceSize> sizes(queryCount);
2303
2304 handles[0] = m_accelerationStructureKHR.get();
2305
2306 for (deUint32 h = 1; h < queryCount; ++h)
2307 handles[h] = *m_bottomLevelInstances[h-1].get()->getPtr();
2308
2309 if (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR == m_buildType)
2310 queryAccelerationStructureSize(vk, device, DE_NULL, handles, m_buildType, DE_NULL, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, sizes);
2311 else
2312 {
2313 const Move<VkCommandPool> cmdPool = createCommandPool(vk, device, 0, queueFamilyIndex);
2314 const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2315 const Move<VkQueryPool> queryPool = makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
2316
2317 beginCommandBuffer(vk, *cmdBuffer);
2318 queryAccelerationStructureSize(vk, device, *cmdBuffer, handles, m_buildType, *queryPool, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, sizes);
2319 endCommandBuffer(vk, *cmdBuffer);
2320 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2321
2322 VK_CHECK(vk.getQueryPoolResults(device, *queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize), sizes.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2323 }
2324
2325 return sizes;
2326 }
2327
getSerializingAddresses(const DeviceInterface & vk,const VkDevice device) const2328 std::vector<deUint64> TopLevelAccelerationStructureKHR::getSerializingAddresses (const DeviceInterface& vk, const VkDevice device) const
2329 {
2330 std::vector<deUint64> result(m_bottomLevelInstances.size() + 1);
2331
2332 VkAccelerationStructureDeviceAddressInfoKHR asDeviceAddressInfo =
2333 {
2334 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType;
2335 DE_NULL, // const void* pNext;
2336 DE_NULL // VkAccelerationStructureKHR accelerationStructure;
2337 };
2338
2339 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2340 {
2341 asDeviceAddressInfo.accelerationStructure = m_accelerationStructureKHR.get();
2342 result[0] = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
2343 }
2344 else
2345 {
2346 result[0] = deUint64(getPtr()->getInternal());
2347 }
2348
2349 for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
2350 {
2351 const BottomLevelAccelerationStructure& bottomLevelAccelerationStructure = *m_bottomLevelInstances[instanceNdx];
2352 const VkAccelerationStructureKHR accelerationStructureKHR = *bottomLevelAccelerationStructure.getPtr();
2353
2354 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2355 {
2356 asDeviceAddressInfo.accelerationStructure = accelerationStructureKHR;
2357 result[instanceNdx+1] = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
2358 }
2359 else
2360 {
2361 result[instanceNdx+1] = deUint64(accelerationStructureKHR.getInternal());
2362 }
2363 }
2364
2365 return result;
2366 }
2367
getPtr(void) const2368 const VkAccelerationStructureKHR* TopLevelAccelerationStructureKHR::getPtr (void) const
2369 {
2370 return &m_accelerationStructureKHR.get();
2371 }
2372
prepareInstances(const DeviceInterface & vk,const VkDevice device,VkAccelerationStructureGeometryKHR & accelerationStructureGeometryKHR,std::vector<deUint32> & maxPrimitiveCounts)2373 void TopLevelAccelerationStructureKHR::prepareInstances (const DeviceInterface& vk,
2374 const VkDevice device,
2375 VkAccelerationStructureGeometryKHR& accelerationStructureGeometryKHR,
2376 std::vector<deUint32>& maxPrimitiveCounts)
2377 {
2378 maxPrimitiveCounts.resize(1);
2379 maxPrimitiveCounts[0] = static_cast<deUint32>(m_bottomLevelInstances.size());
2380
2381 VkDeviceOrHostAddressConstKHR instancesData;
2382 if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2383 {
2384 if(m_instanceBuffer.get() != DE_NULL)
2385 {
2386 if (m_useArrayOfPointers)
2387 {
2388 deUint8* bufferStart = static_cast<deUint8*>(m_instanceAddressBuffer->getAllocation().getHostPtr());
2389 VkDeviceSize bufferOffset = 0;
2390 VkDeviceOrHostAddressConstKHR firstInstance = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0);
2391 for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
2392 {
2393 VkDeviceOrHostAddressConstKHR currentInstance;
2394 currentInstance.deviceAddress = firstInstance.deviceAddress + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR);
2395
2396 deMemcpy(&bufferStart[bufferOffset], ¤tInstance, sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress));
2397 bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress);
2398 }
2399 flushMappedMemoryRange(vk, device, m_instanceAddressBuffer->getAllocation().getMemory(), m_instanceAddressBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
2400
2401 instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceAddressBuffer->get(), 0);
2402 }
2403 else
2404 instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0);
2405 }
2406 else
2407 instancesData = makeDeviceOrHostAddressConstKHR(DE_NULL);
2408 }
2409 else
2410 {
2411 if (m_instanceBuffer.get() != DE_NULL)
2412 {
2413 if (m_useArrayOfPointers)
2414 {
2415 deUint8* bufferStart = static_cast<deUint8*>(m_instanceAddressBuffer->getAllocation().getHostPtr());
2416 VkDeviceSize bufferOffset = 0;
2417 for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
2418 {
2419 VkDeviceOrHostAddressConstKHR currentInstance;
2420 currentInstance.hostAddress = (deUint8*)m_instanceBuffer->getAllocation().getHostPtr() + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR);
2421
2422 deMemcpy(&bufferStart[bufferOffset], ¤tInstance, sizeof(VkDeviceOrHostAddressConstKHR::hostAddress));
2423 bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR::hostAddress);
2424 }
2425 instancesData = makeDeviceOrHostAddressConstKHR(m_instanceAddressBuffer->getAllocation().getHostPtr());
2426 }
2427 else
2428 instancesData = makeDeviceOrHostAddressConstKHR(m_instanceBuffer->getAllocation().getHostPtr());
2429 }
2430 else
2431 instancesData = makeDeviceOrHostAddressConstKHR(DE_NULL);
2432 }
2433
2434 VkAccelerationStructureGeometryInstancesDataKHR accelerationStructureGeometryInstancesDataKHR =
2435 {
2436 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, // VkStructureType sType;
2437 DE_NULL, // const void* pNext;
2438 (VkBool32)( m_useArrayOfPointers ? DE_TRUE : DE_FALSE ), // VkBool32 arrayOfPointers;
2439 instancesData // VkDeviceOrHostAddressConstKHR data;
2440 };
2441
2442 accelerationStructureGeometryKHR =
2443 {
2444 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // VkStructureType sType;
2445 DE_NULL, // const void* pNext;
2446 VK_GEOMETRY_TYPE_INSTANCES_KHR, // VkGeometryTypeKHR geometryType;
2447 makeVkAccelerationStructureInstancesDataKHR(accelerationStructureGeometryInstancesDataKHR), // VkAccelerationStructureGeometryDataKHR geometry;
2448 (VkGeometryFlagsKHR)0u // VkGeometryFlagsKHR flags;
2449 };
2450 }
2451
getRequiredAllocationCount(void)2452 deUint32 TopLevelAccelerationStructure::getRequiredAllocationCount (void)
2453 {
2454 return TopLevelAccelerationStructureKHR::getRequiredAllocationCount();
2455 }
2456
makeTopLevelAccelerationStructure()2457 de::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ()
2458 {
2459 return de::MovePtr<TopLevelAccelerationStructure>(new TopLevelAccelerationStructureKHR);
2460 }
2461
queryAccelerationStructureSizeKHR(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,const std::vector<VkAccelerationStructureKHR> & accelerationStructureHandles,VkAccelerationStructureBuildTypeKHR buildType,const VkQueryPool queryPool,VkQueryType queryType,deUint32 firstQuery,std::vector<VkDeviceSize> & results)2462 bool queryAccelerationStructureSizeKHR (const DeviceInterface& vk,
2463 const VkDevice device,
2464 const VkCommandBuffer cmdBuffer,
2465 const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
2466 VkAccelerationStructureBuildTypeKHR buildType,
2467 const VkQueryPool queryPool,
2468 VkQueryType queryType,
2469 deUint32 firstQuery,
2470 std::vector<VkDeviceSize>& results)
2471 {
2472 DE_ASSERT(queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR || queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR);
2473
2474 if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2475 {
2476 // queryPool must be large enough to contain at least (firstQuery + accelerationStructureHandles.size()) queries
2477 vk.cmdResetQueryPool(cmdBuffer, queryPool, firstQuery, deUint32(accelerationStructureHandles.size()));
2478 vk.cmdWriteAccelerationStructuresPropertiesKHR(cmdBuffer, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType, queryPool, firstQuery);
2479 // results cannot be retrieved to CPU at the moment - you need to do it using getQueryPoolResults after cmdBuffer is executed. Meanwhile function returns a vector of 0s.
2480 results.resize(accelerationStructureHandles.size(), 0u);
2481 return false;
2482 }
2483 // buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR
2484 results.resize(accelerationStructureHandles.size(), 0u);
2485 vk.writeAccelerationStructuresPropertiesKHR(device, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType,
2486 sizeof(VkDeviceSize) * accelerationStructureHandles.size(), results.data(), sizeof(VkDeviceSize));
2487 // results will contain proper values
2488 return true;
2489 }
2490
queryAccelerationStructureSize(const DeviceInterface & vk,const VkDevice device,const VkCommandBuffer cmdBuffer,const std::vector<VkAccelerationStructureKHR> & accelerationStructureHandles,VkAccelerationStructureBuildTypeKHR buildType,const VkQueryPool queryPool,VkQueryType queryType,deUint32 firstQuery,std::vector<VkDeviceSize> & results)2491 bool queryAccelerationStructureSize (const DeviceInterface& vk,
2492 const VkDevice device,
2493 const VkCommandBuffer cmdBuffer,
2494 const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
2495 VkAccelerationStructureBuildTypeKHR buildType,
2496 const VkQueryPool queryPool,
2497 VkQueryType queryType,
2498 deUint32 firstQuery,
2499 std::vector<VkDeviceSize>& results)
2500 {
2501 return queryAccelerationStructureSizeKHR(vk, device, cmdBuffer, accelerationStructureHandles, buildType, queryPool, queryType, firstQuery, results);
2502 }
2503
RayTracingPipeline()2504 RayTracingPipeline::RayTracingPipeline ()
2505 : m_shadersModules ()
2506 , m_pipelineLibraries ()
2507 , m_shaderCreateInfos ()
2508 , m_shadersGroupCreateInfos ()
2509 , m_pipelineCreateFlags (0U)
2510 , m_maxRecursionDepth (1U)
2511 , m_maxPayloadSize (0U)
2512 , m_maxAttributeSize (0U)
2513 , m_deferredOperation (false)
2514 , m_workerThreadCount (0)
2515 {
2516 }
2517
~RayTracingPipeline()2518 RayTracingPipeline::~RayTracingPipeline ()
2519 {
2520 }
2521
2522 #define CHECKED_ASSIGN_SHADER(SHADER, STAGE) \
2523 if (SHADER == VK_SHADER_UNUSED_KHR) \
2524 SHADER = STAGE; \
2525 else \
2526 TCU_THROW(InternalError, "Attempt to reassign shader")
2527
addShader(VkShaderStageFlagBits shaderStage,Move<VkShaderModule> shaderModule,deUint32 group,const VkSpecializationInfo * specializationInfo,const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,const void * pipelineShaderStageCreateInfopNext)2528 void RayTracingPipeline::addShader (VkShaderStageFlagBits shaderStage,
2529 Move<VkShaderModule> shaderModule,
2530 deUint32 group,
2531 const VkSpecializationInfo* specializationInfo,
2532 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,
2533 const void* pipelineShaderStageCreateInfopNext)
2534 {
2535 addShader(shaderStage, makeVkSharedPtr(shaderModule), group, specializationInfo, pipelineShaderStageCreateFlags, pipelineShaderStageCreateInfopNext);
2536 }
2537
addShader(VkShaderStageFlagBits shaderStage,de::SharedPtr<Move<VkShaderModule>> shaderModule,deUint32 group,const VkSpecializationInfo * specializationInfoPtr,const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,const void * pipelineShaderStageCreateInfopNext)2538 void RayTracingPipeline::addShader (VkShaderStageFlagBits shaderStage,
2539 de::SharedPtr<Move<VkShaderModule>> shaderModule,
2540 deUint32 group,
2541 const VkSpecializationInfo* specializationInfoPtr,
2542 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,
2543 const void* pipelineShaderStageCreateInfopNext)
2544 {
2545 addShader(shaderStage, **shaderModule, group, specializationInfoPtr, pipelineShaderStageCreateFlags, pipelineShaderStageCreateInfopNext);
2546 m_shadersModules.push_back(shaderModule);
2547 }
2548
addShader(VkShaderStageFlagBits shaderStage,VkShaderModule shaderModule,deUint32 group,const VkSpecializationInfo * specializationInfoPtr,const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,const void * pipelineShaderStageCreateInfopNext)2549 void RayTracingPipeline::addShader (VkShaderStageFlagBits shaderStage,
2550 VkShaderModule shaderModule,
2551 deUint32 group,
2552 const VkSpecializationInfo* specializationInfoPtr,
2553 const VkPipelineShaderStageCreateFlags pipelineShaderStageCreateFlags,
2554 const void* pipelineShaderStageCreateInfopNext)
2555 {
2556 if (group >= m_shadersGroupCreateInfos.size())
2557 {
2558 for (size_t groupNdx = m_shadersGroupCreateInfos.size(); groupNdx <= group; ++groupNdx)
2559 {
2560 VkRayTracingShaderGroupCreateInfoKHR shaderGroupCreateInfo =
2561 {
2562 VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, // VkStructureType sType;
2563 DE_NULL, // const void* pNext;
2564 VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR, // VkRayTracingShaderGroupTypeKHR type;
2565 VK_SHADER_UNUSED_KHR, // deUint32 generalShader;
2566 VK_SHADER_UNUSED_KHR, // deUint32 closestHitShader;
2567 VK_SHADER_UNUSED_KHR, // deUint32 anyHitShader;
2568 VK_SHADER_UNUSED_KHR, // deUint32 intersectionShader;
2569 DE_NULL, // const void* pShaderGroupCaptureReplayHandle;
2570 };
2571
2572 m_shadersGroupCreateInfos.push_back(shaderGroupCreateInfo);
2573 }
2574 }
2575
2576 const deUint32 shaderStageNdx = (deUint32)m_shaderCreateInfos.size();
2577 VkRayTracingShaderGroupCreateInfoKHR& shaderGroupCreateInfo = m_shadersGroupCreateInfos[group];
2578
2579 switch (shaderStage)
2580 {
2581 case VK_SHADER_STAGE_RAYGEN_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break;
2582 case VK_SHADER_STAGE_MISS_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break;
2583 case VK_SHADER_STAGE_CALLABLE_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break;
2584 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.anyHitShader, shaderStageNdx); break;
2585 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.closestHitShader, shaderStageNdx); break;
2586 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.intersectionShader, shaderStageNdx); break;
2587 default: TCU_THROW(InternalError, "Unacceptable stage");
2588 }
2589
2590 switch (shaderStage)
2591 {
2592 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2593 case VK_SHADER_STAGE_MISS_BIT_KHR:
2594 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2595 {
2596 DE_ASSERT(shaderGroupCreateInfo.type == VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR);
2597 shaderGroupCreateInfo.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
2598
2599 break;
2600 }
2601
2602 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2603 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2604 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2605 {
2606 DE_ASSERT(shaderGroupCreateInfo.type != VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR);
2607 shaderGroupCreateInfo.type = (shaderGroupCreateInfo.intersectionShader == VK_SHADER_UNUSED_KHR)
2608 ? VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR
2609 : VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR;
2610
2611 break;
2612 }
2613
2614 default: TCU_THROW(InternalError, "Unacceptable stage");
2615 }
2616
2617 {
2618 const VkPipelineShaderStageCreateInfo shaderCreateInfo =
2619 {
2620 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2621 pipelineShaderStageCreateInfopNext, // const void* pNext;
2622 pipelineShaderStageCreateFlags, // VkPipelineShaderStageCreateFlags flags;
2623 shaderStage, // VkShaderStageFlagBits stage;
2624 shaderModule, // VkShaderModule module;
2625 "main", // const char* pName;
2626 specializationInfoPtr, // const VkSpecializationInfo* pSpecializationInfo;
2627 };
2628
2629 m_shaderCreateInfos.push_back(shaderCreateInfo);
2630 }
2631 }
2632
addLibrary(de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary)2633 void RayTracingPipeline::addLibrary (de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary)
2634 {
2635 m_pipelineLibraries.push_back(pipelineLibrary);
2636 }
2637
createPipelineKHR(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const std::vector<de::SharedPtr<Move<VkPipeline>>> & pipelineLibraries)2638 Move<VkPipeline> RayTracingPipeline::createPipelineKHR (const DeviceInterface& vk,
2639 const VkDevice device,
2640 const VkPipelineLayout pipelineLayout,
2641 const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries)
2642 {
2643 for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx)
2644 DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR);
2645
2646 DE_ASSERT(m_shaderCreateInfos.size() > 0);
2647 DE_ASSERT(m_shadersGroupCreateInfos.size() > 0);
2648
2649 std::vector<VkPipeline> vkPipelineLibraries;
2650 for (auto it = begin(pipelineLibraries), eit = end(pipelineLibraries); it != eit; ++it)
2651 vkPipelineLibraries.push_back( it->get()->get() );
2652 VkPipelineLibraryCreateInfoKHR librariesCreateInfo =
2653 {
2654 VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType;
2655 DE_NULL, // const void* pNext;
2656 deUint32(vkPipelineLibraries.size()), // deUint32 libraryCount;
2657 dataOrNullPtr(vkPipelineLibraries) // VkPipeline* pLibraries;
2658 };
2659 const VkRayTracingPipelineInterfaceCreateInfoKHR pipelineInterfaceCreateInfo =
2660 {
2661 VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR, // VkStructureType sType;
2662 DE_NULL, // const void* pNext;
2663 m_maxPayloadSize, // deUint32 maxPayloadSize;
2664 m_maxAttributeSize // deUint32 maxAttributeSize;
2665 };
2666 const bool addPipelineInterfaceCreateInfo = m_maxPayloadSize != 0 || m_maxAttributeSize != 0;
2667 const VkRayTracingPipelineInterfaceCreateInfoKHR* pipelineInterfaceCreateInfoPtr = addPipelineInterfaceCreateInfo ? &pipelineInterfaceCreateInfo : DE_NULL;
2668 const VkPipelineLibraryCreateInfoKHR* librariesCreateInfoPtr = (vkPipelineLibraries.empty() ? nullptr : &librariesCreateInfo);
2669
2670 Move<VkDeferredOperationKHR> deferredOperation;
2671 if (m_deferredOperation)
2672 deferredOperation = createDeferredOperationKHR(vk, device);
2673
2674 VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
2675 {
2676 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
2677 DE_NULL, // const void* pNext;
2678 0, // VkPipelineDynamicStateCreateFlags flags;
2679 static_cast<deUint32>(m_dynamicStates.size() ), // deUint32 dynamicStateCount;
2680 m_dynamicStates.data(), // const VkDynamicState* pDynamicStates;
2681 };
2682
2683 const VkRayTracingPipelineCreateInfoKHR pipelineCreateInfo =
2684 {
2685 VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType;
2686 DE_NULL, // const void* pNext;
2687 m_pipelineCreateFlags, // VkPipelineCreateFlags flags;
2688 (deUint32)m_shaderCreateInfos.size(), // deUint32 stageCount;
2689 m_shaderCreateInfos.data(), // const VkPipelineShaderStageCreateInfo* pStages;
2690 (deUint32)m_shadersGroupCreateInfos.size(), // deUint32 groupCount;
2691 m_shadersGroupCreateInfos.data(), // const VkRayTracingShaderGroupCreateInfoKHR* pGroups;
2692 m_maxRecursionDepth, // deUint32 maxRecursionDepth;
2693 librariesCreateInfoPtr, // VkPipelineLibraryCreateInfoKHR* pLibraryInfo;
2694 pipelineInterfaceCreateInfoPtr, // VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface;
2695 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2696 pipelineLayout, // VkPipelineLayout layout;
2697 (VkPipeline)DE_NULL, // VkPipeline basePipelineHandle;
2698 0, // deInt32 basePipelineIndex;
2699 };
2700 VkPipeline object = DE_NULL;
2701 VkResult result = vk.createRayTracingPipelinesKHR(device, deferredOperation.get(), DE_NULL, 1u, &pipelineCreateInfo, DE_NULL, &object);
2702 Move<VkPipeline> pipeline (check<VkPipeline>(object), Deleter<VkPipeline>(vk, device, DE_NULL));
2703
2704 if (m_deferredOperation)
2705 {
2706 DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
2707
2708 finishDeferredOperation(vk, device, deferredOperation.get(), m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
2709 }
2710
2711 return pipeline;
2712 }
2713
2714
createPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const std::vector<de::SharedPtr<Move<VkPipeline>>> & pipelineLibraries)2715 Move<VkPipeline> RayTracingPipeline::createPipeline (const DeviceInterface& vk,
2716 const VkDevice device,
2717 const VkPipelineLayout pipelineLayout,
2718 const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries)
2719 {
2720 return createPipelineKHR(vk, device, pipelineLayout, pipelineLibraries);
2721 }
2722
createPipelineWithLibraries(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout)2723 std::vector<de::SharedPtr<Move<VkPipeline>>> RayTracingPipeline::createPipelineWithLibraries (const DeviceInterface& vk,
2724 const VkDevice device,
2725 const VkPipelineLayout pipelineLayout)
2726 {
2727 for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx)
2728 DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR);
2729
2730 DE_ASSERT(m_shaderCreateInfos.size() > 0);
2731 DE_ASSERT(m_shadersGroupCreateInfos.size() > 0);
2732
2733 std::vector<de::SharedPtr<Move<VkPipeline>>> result, allLibraries, firstLibraries;
2734 for(auto it=begin(m_pipelineLibraries), eit=end(m_pipelineLibraries); it!=eit; ++it)
2735 {
2736 auto childLibraries = (*it)->get()->createPipelineWithLibraries(vk, device, pipelineLayout);
2737 DE_ASSERT(childLibraries.size() > 0);
2738 firstLibraries.push_back(childLibraries[0]);
2739 std::copy(begin(childLibraries), end(childLibraries), std::back_inserter(allLibraries));
2740 }
2741 result.push_back(makeVkSharedPtr(createPipeline(vk, device, pipelineLayout, firstLibraries)));
2742 std::copy(begin(allLibraries), end(allLibraries), std::back_inserter(result));
2743 return result;
2744 }
2745
createShaderBindingTable(const DeviceInterface & vk,const VkDevice device,const VkPipeline pipeline,Allocator & allocator,const deUint32 & shaderGroupHandleSize,const deUint32 shaderGroupBaseAlignment,const deUint32 & firstGroup,const deUint32 & groupCount,const VkBufferCreateFlags & additionalBufferCreateFlags,const VkBufferUsageFlags & additionalBufferUsageFlags,const MemoryRequirement & additionalMemoryRequirement,const VkDeviceAddress & opaqueCaptureAddress,const deUint32 shaderBindingTableOffset,const deUint32 shaderRecordSize,const void ** shaderGroupDataPtrPerGroup)2746 de::MovePtr<BufferWithMemory> RayTracingPipeline::createShaderBindingTable (const DeviceInterface& vk,
2747 const VkDevice device,
2748 const VkPipeline pipeline,
2749 Allocator& allocator,
2750 const deUint32& shaderGroupHandleSize,
2751 const deUint32 shaderGroupBaseAlignment,
2752 const deUint32& firstGroup,
2753 const deUint32& groupCount,
2754 const VkBufferCreateFlags& additionalBufferCreateFlags,
2755 const VkBufferUsageFlags& additionalBufferUsageFlags,
2756 const MemoryRequirement& additionalMemoryRequirement,
2757 const VkDeviceAddress& opaqueCaptureAddress,
2758 const deUint32 shaderBindingTableOffset,
2759 const deUint32 shaderRecordSize,
2760 const void** shaderGroupDataPtrPerGroup)
2761 {
2762 DE_ASSERT(shaderGroupBaseAlignment != 0u);
2763 DE_ASSERT((shaderBindingTableOffset % shaderGroupBaseAlignment) == 0);
2764 DE_UNREF(shaderGroupBaseAlignment);
2765
2766 const deUint32 sbtSize = shaderBindingTableOffset + groupCount * deAlign32(shaderGroupHandleSize + shaderRecordSize, shaderGroupHandleSize);
2767 const VkBufferUsageFlags sbtFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | additionalBufferUsageFlags;
2768 VkBufferCreateInfo sbtCreateInfo = makeBufferCreateInfo(sbtSize, sbtFlags);
2769 sbtCreateInfo.flags |= additionalBufferCreateFlags;
2770 VkBufferOpaqueCaptureAddressCreateInfo sbtCaptureAddressInfo =
2771 {
2772 VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, // VkStructureType sType;
2773 DE_NULL, // const void* pNext;
2774 deUint64(opaqueCaptureAddress) // deUint64 opaqueCaptureAddress;
2775 };
2776
2777 if (opaqueCaptureAddress != 0u)
2778 {
2779 sbtCreateInfo.pNext = &sbtCaptureAddressInfo;
2780 sbtCreateInfo.flags |= VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
2781 }
2782 const MemoryRequirement sbtMemRequirements = MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress | additionalMemoryRequirement;
2783 de::MovePtr<BufferWithMemory> sbtBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, sbtCreateInfo, sbtMemRequirements));
2784 vk::Allocation& sbtAlloc = sbtBuffer->getAllocation();
2785
2786 // collect shader group handles
2787 std::vector<deUint8> shaderHandles (groupCount * shaderGroupHandleSize);
2788 VK_CHECK(getRayTracingShaderGroupHandles(vk, device, pipeline, firstGroup, groupCount, groupCount * shaderGroupHandleSize, shaderHandles.data()));
2789
2790 // reserve place for ShaderRecordKHR after each shader handle ( ShaderRecordKHR size might be 0 ). Also take alignment into consideration
2791 deUint8* shaderBegin = (deUint8*)sbtAlloc.getHostPtr() + shaderBindingTableOffset;
2792 for (deUint32 idx = 0; idx < groupCount; ++idx)
2793 {
2794 deUint8* shaderSrcPos = shaderHandles.data() + idx * shaderGroupHandleSize;
2795 deUint8* shaderDstPos = shaderBegin + idx * deAlign32(shaderGroupHandleSize + shaderRecordSize, shaderGroupHandleSize);
2796 deMemcpy(shaderDstPos, shaderSrcPos, shaderGroupHandleSize);
2797
2798 if (shaderGroupDataPtrPerGroup != nullptr &&
2799 shaderGroupDataPtrPerGroup[idx] != nullptr)
2800 {
2801 DE_ASSERT(sbtSize >= static_cast<deUint32>(shaderDstPos - shaderBegin) + shaderGroupHandleSize);
2802
2803 deMemcpy( shaderDstPos + shaderGroupHandleSize,
2804 shaderGroupDataPtrPerGroup[idx],
2805 shaderRecordSize);
2806 }
2807 }
2808
2809 flushMappedMemoryRange(vk, device, sbtAlloc.getMemory(), sbtAlloc.getOffset(), VK_WHOLE_SIZE);
2810
2811 return sbtBuffer;
2812 }
2813
setCreateFlags(const VkPipelineCreateFlags & pipelineCreateFlags)2814 void RayTracingPipeline::setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags)
2815 {
2816 m_pipelineCreateFlags = pipelineCreateFlags;
2817 }
2818
setMaxRecursionDepth(const deUint32 & maxRecursionDepth)2819 void RayTracingPipeline::setMaxRecursionDepth (const deUint32& maxRecursionDepth)
2820 {
2821 m_maxRecursionDepth = maxRecursionDepth;
2822 }
2823
setMaxPayloadSize(const deUint32 & maxPayloadSize)2824 void RayTracingPipeline::setMaxPayloadSize (const deUint32& maxPayloadSize)
2825 {
2826 m_maxPayloadSize = maxPayloadSize;
2827 }
2828
setMaxAttributeSize(const deUint32 & maxAttributeSize)2829 void RayTracingPipeline::setMaxAttributeSize (const deUint32& maxAttributeSize)
2830 {
2831 m_maxAttributeSize = maxAttributeSize;
2832 }
2833
setDeferredOperation(const bool deferredOperation,const deUint32 workerThreadCount)2834 void RayTracingPipeline::setDeferredOperation (const bool deferredOperation,
2835 const deUint32 workerThreadCount)
2836 {
2837 m_deferredOperation = deferredOperation;
2838 m_workerThreadCount = workerThreadCount;
2839 }
2840
addDynamicState(const VkDynamicState & dynamicState)2841 void RayTracingPipeline::addDynamicState(const VkDynamicState& dynamicState)
2842 {
2843 m_dynamicStates.push_back(dynamicState);
2844 }
2845
2846 class RayTracingPropertiesKHR : public RayTracingProperties
2847 {
2848 public:
2849 RayTracingPropertiesKHR () = delete;
2850 RayTracingPropertiesKHR (const InstanceInterface& vki,
2851 const VkPhysicalDevice physicalDevice);
2852 virtual ~RayTracingPropertiesKHR ();
2853
getShaderGroupHandleSize(void)2854 virtual deUint32 getShaderGroupHandleSize (void) { return m_rayTracingPipelineProperties.shaderGroupHandleSize; }
getMaxRecursionDepth(void)2855 virtual deUint32 getMaxRecursionDepth (void) { return m_rayTracingPipelineProperties.maxRayRecursionDepth; }
getMaxShaderGroupStride(void)2856 virtual deUint32 getMaxShaderGroupStride (void) { return m_rayTracingPipelineProperties.maxShaderGroupStride; }
getShaderGroupBaseAlignment(void)2857 virtual deUint32 getShaderGroupBaseAlignment (void) { return m_rayTracingPipelineProperties.shaderGroupBaseAlignment; }
getMaxGeometryCount(void)2858 virtual deUint64 getMaxGeometryCount (void) { return m_accelerationStructureProperties.maxGeometryCount; }
getMaxInstanceCount(void)2859 virtual deUint64 getMaxInstanceCount (void) { return m_accelerationStructureProperties.maxInstanceCount; }
getMaxPrimitiveCount(void)2860 virtual deUint64 getMaxPrimitiveCount (void) { return m_accelerationStructureProperties.maxPrimitiveCount; }
getMaxDescriptorSetAccelerationStructures(void)2861 virtual deUint32 getMaxDescriptorSetAccelerationStructures (void) { return m_accelerationStructureProperties.maxDescriptorSetAccelerationStructures; }
getMaxRayDispatchInvocationCount(void)2862 deUint32 getMaxRayDispatchInvocationCount (void) { return m_rayTracingPipelineProperties.maxRayDispatchInvocationCount; }
getMaxRayHitAttributeSize(void)2863 deUint32 getMaxRayHitAttributeSize (void) { return m_rayTracingPipelineProperties.maxRayHitAttributeSize; }
2864
2865 protected:
2866 VkPhysicalDeviceAccelerationStructurePropertiesKHR m_accelerationStructureProperties;
2867 VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_rayTracingPipelineProperties;
2868 };
2869
~RayTracingPropertiesKHR()2870 RayTracingPropertiesKHR::~RayTracingPropertiesKHR ()
2871 {
2872 }
2873
RayTracingPropertiesKHR(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)2874 RayTracingPropertiesKHR::RayTracingPropertiesKHR (const InstanceInterface& vki,
2875 const VkPhysicalDevice physicalDevice)
2876 : RayTracingProperties (vki, physicalDevice)
2877 {
2878 m_accelerationStructureProperties = getPhysicalDeviceExtensionProperties(vki, physicalDevice);
2879 m_rayTracingPipelineProperties = getPhysicalDeviceExtensionProperties(vki, physicalDevice);
2880 }
2881
makeRayTracingProperties(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)2882 de::MovePtr<RayTracingProperties> makeRayTracingProperties (const InstanceInterface& vki,
2883 const VkPhysicalDevice physicalDevice)
2884 {
2885 return de::MovePtr<RayTracingProperties>(new RayTracingPropertiesKHR(vki, physicalDevice));
2886 }
2887
cmdTraceRaysKHR(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const VkStridedDeviceAddressRegionKHR * raygenShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * missShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * hitShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * callableShaderBindingTableRegion,deUint32 width,deUint32 height,deUint32 depth)2888 static inline void cmdTraceRaysKHR (const DeviceInterface& vk,
2889 VkCommandBuffer commandBuffer,
2890 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
2891 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
2892 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
2893 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
2894 deUint32 width,
2895 deUint32 height,
2896 deUint32 depth)
2897 {
2898 return vk.cmdTraceRaysKHR(commandBuffer,
2899 raygenShaderBindingTableRegion,
2900 missShaderBindingTableRegion,
2901 hitShaderBindingTableRegion,
2902 callableShaderBindingTableRegion,
2903 width,
2904 height,
2905 depth);
2906 }
2907
2908
cmdTraceRays(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const VkStridedDeviceAddressRegionKHR * raygenShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * missShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * hitShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * callableShaderBindingTableRegion,deUint32 width,deUint32 height,deUint32 depth)2909 void cmdTraceRays (const DeviceInterface& vk,
2910 VkCommandBuffer commandBuffer,
2911 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
2912 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
2913 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
2914 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
2915 deUint32 width,
2916 deUint32 height,
2917 deUint32 depth)
2918 {
2919 DE_ASSERT(raygenShaderBindingTableRegion != DE_NULL);
2920 DE_ASSERT(missShaderBindingTableRegion != DE_NULL);
2921 DE_ASSERT(hitShaderBindingTableRegion != DE_NULL);
2922 DE_ASSERT(callableShaderBindingTableRegion != DE_NULL);
2923
2924 return cmdTraceRaysKHR(vk,
2925 commandBuffer,
2926 raygenShaderBindingTableRegion,
2927 missShaderBindingTableRegion,
2928 hitShaderBindingTableRegion,
2929 callableShaderBindingTableRegion,
2930 width,
2931 height,
2932 depth);
2933 }
2934
cmdTraceRaysIndirectKHR(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const VkStridedDeviceAddressRegionKHR * raygenShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * missShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * hitShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * callableShaderBindingTableRegion,VkDeviceAddress indirectDeviceAddress)2935 static inline void cmdTraceRaysIndirectKHR (const DeviceInterface& vk,
2936 VkCommandBuffer commandBuffer,
2937 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
2938 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
2939 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
2940 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
2941 VkDeviceAddress indirectDeviceAddress )
2942 {
2943 DE_ASSERT(raygenShaderBindingTableRegion != DE_NULL);
2944 DE_ASSERT(missShaderBindingTableRegion != DE_NULL);
2945 DE_ASSERT(hitShaderBindingTableRegion != DE_NULL);
2946 DE_ASSERT(callableShaderBindingTableRegion != DE_NULL);
2947 DE_ASSERT(indirectDeviceAddress != 0);
2948
2949 return vk.cmdTraceRaysIndirectKHR(commandBuffer,
2950 raygenShaderBindingTableRegion,
2951 missShaderBindingTableRegion,
2952 hitShaderBindingTableRegion,
2953 callableShaderBindingTableRegion,
2954 indirectDeviceAddress);
2955 }
2956
cmdTraceRaysIndirect(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const VkStridedDeviceAddressRegionKHR * raygenShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * missShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * hitShaderBindingTableRegion,const VkStridedDeviceAddressRegionKHR * callableShaderBindingTableRegion,VkDeviceAddress indirectDeviceAddress)2957 void cmdTraceRaysIndirect (const DeviceInterface& vk,
2958 VkCommandBuffer commandBuffer,
2959 const VkStridedDeviceAddressRegionKHR* raygenShaderBindingTableRegion,
2960 const VkStridedDeviceAddressRegionKHR* missShaderBindingTableRegion,
2961 const VkStridedDeviceAddressRegionKHR* hitShaderBindingTableRegion,
2962 const VkStridedDeviceAddressRegionKHR* callableShaderBindingTableRegion,
2963 VkDeviceAddress indirectDeviceAddress)
2964 {
2965 return cmdTraceRaysIndirectKHR(vk,
2966 commandBuffer,
2967 raygenShaderBindingTableRegion,
2968 missShaderBindingTableRegion,
2969 hitShaderBindingTableRegion,
2970 callableShaderBindingTableRegion,
2971 indirectDeviceAddress);
2972 }
2973
2974 } // vk
2975