1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
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 Ray Tracing Acceleration Structures tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayTracingAccelerationStructuresTests.hpp"
25
26 #include "vkDefs.hpp"
27 #include "deClock.h"
28 #include "deRandom.h"
29
30 #include "vktTestCase.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37 #include "vkImageWithMemory.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkRayTracingUtil.hpp"
41 #include "tcuVectorUtil.hpp"
42 #include "tcuTexture.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFloat.hpp"
46 #include "deModularCounter.hpp"
47
48 #include <cmath>
49 #include <cstddef>
50 #include <set>
51 #include <limits>
52 #include <iostream>
53
54 namespace vkt
55 {
56 namespace RayTracing
57 {
58 namespace
59 {
60 using namespace vk;
61 using namespace vkt;
62 using namespace tcu;
63
64 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
65 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
66 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
67
68 enum class BottomTestType
69 {
70 TRIANGLES = 0,
71 AABBS = 1,
72 };
73
74 enum class TopTestType
75 {
76 IDENTICAL_INSTANCES,
77 DIFFERENT_INSTANCES,
78 UPDATED_INSTANCES,
79 MIX_INSTANCES,
80 };
81
82 enum OperationTarget
83 {
84 OT_NONE,
85 OT_TOP_ACCELERATION,
86 OT_BOTTOM_ACCELERATION
87 };
88
89 enum OperationType
90 {
91 OP_NONE,
92 OP_COPY,
93 OP_COMPACT,
94 OP_SERIALIZE,
95 OP_UPDATE,
96 OP_UPDATE_IN_PLACE
97 };
98
99 enum class InstanceCullFlags
100 {
101 NONE,
102 CULL_DISABLE,
103 COUNTERCLOCKWISE,
104 ALL,
105 };
106
107 enum class EmptyAccelerationStructureCase
108 {
109 NOT_EMPTY = 0,
110 INACTIVE_TRIANGLES = 1,
111 INACTIVE_INSTANCES = 2,
112 NO_GEOMETRIES_BOTTOM = 3, // geometryCount zero when building.
113 NO_PRIMITIVES_BOTTOM = 4, // primitiveCount zero when building.
114 NO_PRIMITIVES_TOP = 5, // primitiveCount zero when building.
115 };
116
117 enum class InstanceCustomIndexCase
118 {
119 NONE = 0,
120 CLOSEST_HIT = 1,
121 ANY_HIT = 2,
122 INTERSECTION = 3,
123 };
124
125 enum class UpdateCase
126 {
127 NONE,
128 VERTICES,
129 INDICES,
130 TRANSFORM
131 };
132
133 static const uint32_t RTAS_DEFAULT_SIZE = 8u;
134
135 // Chosen to have the most significant bit set to 1 when represented using 24 bits.
136 // This will make sure the instance custom index will not be sign-extended by mistake.
137 constexpr uint32_t INSTANCE_CUSTOM_INDEX_BASE = 0x807f00u;
138
139 struct TestParams;
140
141 class TestConfiguration
142 {
143 public:
~TestConfiguration()144 virtual ~TestConfiguration()
145 {
146 }
147
148 virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
149 Context &context, TestParams &testParams) = 0;
150 virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
151 Context &context, TestParams &testParams,
152 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) = 0;
153 virtual void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
154 TestParams &testParams) = 0;
155 virtual void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
156 TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
157 uint32_t shaderGroupBaseAlignment,
158 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
159 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
160 de::MovePtr<BufferWithMemory> &missShaderBindingTable) = 0;
161 virtual bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) = 0;
162 virtual VkFormat getResultImageFormat() = 0;
163 virtual size_t getResultImageFormatSize() = 0;
164 virtual VkClearValue getClearValue() = 0;
165 };
166
167 struct TestParams
168 {
169 vk::VkAccelerationStructureBuildTypeKHR buildType; // are we making AS on CPU or GPU
170 VkFormat vertexFormat;
171 bool padVertices;
172 VkIndexType indexType;
173 BottomTestType bottomTestType; // what kind of geometry is stored in bottom AS
174 InstanceCullFlags cullFlags; // Flags for instances, if needed.
175 bool bottomUsesAOP; // does bottom AS use arrays, or arrays of pointers
176 bool bottomGeneric; // Bottom created as generic AS type.
177 bool bottomUnboundedCreation; // Bottom created with unbounded buffer memory.
178 TopTestType topTestType; // If instances are identical then bottom geometries must have different vertices/aabbs
179 bool topUsesAOP; // does top AS use arrays, or arrays of pointers
180 bool topGeneric; // Top created as generic AS type.
181 bool topUnboundedCreation; // Top created with unbounded buffer memory.
182 VkBuildAccelerationStructureFlagsKHR buildFlags;
183 OperationTarget operationTarget;
184 OperationType operationType;
185 uint32_t width;
186 uint32_t height;
187 de::SharedPtr<TestConfiguration> testConfiguration;
188 uint32_t workerThreadsCount;
189 EmptyAccelerationStructureCase emptyASCase;
190 InstanceCustomIndexCase instanceCustomIndexCase;
191 bool useCullMask;
192 uint32_t cullMask;
193 UpdateCase updateCase;
194 };
195
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)196 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
197 {
198 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
199
200 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
201 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
202 }
203
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)204 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
205 {
206 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
207
208 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
209 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
210 }
211
makeImageCreateInfo(uint32_t width,uint32_t height,VkFormat format)212 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, VkFormat format)
213 {
214 const VkImageCreateInfo imageCreateInfo = {
215 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
216 nullptr, // const void* pNext;
217 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
218 VK_IMAGE_TYPE_2D, // VkImageType imageType;
219 format, // VkFormat format;
220 makeExtent3D(width, height, 1u), // VkExtent3D extent;
221 1u, // uint32_t mipLevels;
222 1u, // uint32_t arrayLayers;
223 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
224 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
225 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
226 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
227 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
228 0u, // uint32_t queueFamilyIndexCount;
229 nullptr, // const uint32_t* pQueueFamilyIndices;
230 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
231 };
232
233 return imageCreateInfo;
234 }
235
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,uint32_t queryCount)236 Move<VkQueryPool> makeQueryPool(const DeviceInterface &vk, const VkDevice device, const VkQueryType queryType,
237 uint32_t queryCount)
238 {
239 const VkQueryPoolCreateInfo queryPoolCreateInfo = {
240 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
241 nullptr, // pNext
242 (VkQueryPoolCreateFlags)0, // flags
243 queryType, // queryType
244 queryCount, // queryCount
245 0u, // pipelineStatistics
246 };
247 return createQueryPool(vk, device, &queryPoolCreateInfo);
248 }
249
getCullFlags(InstanceCullFlags flags)250 VkGeometryInstanceFlagsKHR getCullFlags(InstanceCullFlags flags)
251 {
252 VkGeometryInstanceFlagsKHR cullFlags = 0u;
253
254 if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
255 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
256
257 if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
258 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
259
260 return cullFlags;
261 }
262
263 class CheckerboardConfiguration : public TestConfiguration
264 {
265 public:
266 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
267 Context &context, TestParams &testParams) override;
268 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
269 Context &context, TestParams &testParams,
270 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
271 void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
272 TestParams &testParams) override;
273 void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
274 TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
275 uint32_t shaderGroupBaseAlignment,
276 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
277 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
278 de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
279 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
280 VkFormat getResultImageFormat() override;
281 size_t getResultImageFormatSize() override;
282 VkClearValue getClearValue() override;
283 };
284
285 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> CheckerboardConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)286 initBottomAccelerationStructures(Context &context, TestParams &testParams)
287 {
288 DE_UNREF(context);
289
290 // Cull flags can only be used with triangles.
291 DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE ||
292 testParams.bottomTestType == BottomTestType::TRIANGLES);
293
294 // Checkerboard configuration does not support empty geometry tests.
295 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
296
297 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
298
299 const auto instanceFlags = getCullFlags(testParams.cullFlags);
300
301 tcu::Vec3 v0(0.0, 1.0, 0.0);
302 tcu::Vec3 v1(0.0, 0.0, 0.0);
303 tcu::Vec3 v2(1.0, 1.0, 0.0);
304 tcu::Vec3 v3(1.0, 0.0, 0.0);
305
306 if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
307 {
308 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
309 makeBottomLevelAccelerationStructure();
310 bottomLevelAccelerationStructure->setGeometryCount(1u);
311 de::SharedPtr<RaytracedGeometryBase> geometry;
312 if (testParams.bottomTestType == BottomTestType::TRIANGLES)
313 {
314 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
315 testParams.indexType, testParams.padVertices);
316 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
317 {
318 if (instanceFlags == 0u)
319 {
320 geometry->addVertex(v0);
321 geometry->addVertex(v1);
322 geometry->addVertex(v2);
323 geometry->addVertex(v2);
324 geometry->addVertex(v1);
325 geometry->addVertex(v3);
326 }
327 else // Counterclockwise so the flags will be needed for the geometry to be visible.
328 {
329 geometry->addVertex(v2);
330 geometry->addVertex(v1);
331 geometry->addVertex(v0);
332 geometry->addVertex(v3);
333 geometry->addVertex(v1);
334 geometry->addVertex(v2);
335 }
336 }
337 else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
338 {
339 geometry->addVertex(v0);
340 geometry->addVertex(v1);
341 geometry->addVertex(v2);
342 geometry->addVertex(v3);
343
344 if (instanceFlags == 0u)
345 {
346 geometry->addIndex(0);
347 geometry->addIndex(1);
348 geometry->addIndex(2);
349 geometry->addIndex(2);
350 geometry->addIndex(1);
351 geometry->addIndex(3);
352 }
353 else // Counterclockwise so the flags will be needed for the geometry to be visible.
354 {
355 geometry->addIndex(2);
356 geometry->addIndex(1);
357 geometry->addIndex(0);
358 geometry->addIndex(3);
359 geometry->addIndex(1);
360 geometry->addIndex(2);
361 }
362 }
363 }
364 else // m_data.bottomTestType == BTT_AABBS
365 {
366 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType,
367 testParams.padVertices);
368
369 if (!testParams.padVertices)
370 {
371 // Single AABB.
372 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
373 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
374 }
375 else
376 {
377 // Multiple AABBs covering the same space.
378 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
379 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, 0.1f));
380
381 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
382 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
383
384 geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
385 geometry->addVertex(tcu::Vec3(0.5f, 1.0f, 0.1f));
386
387 geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
388 geometry->addVertex(tcu::Vec3(1.0f, 0.5f, 0.1f));
389 }
390 }
391
392 bottomLevelAccelerationStructure->addGeometry(geometry);
393
394 if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
395 geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
396
397 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
398 }
399 else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
400 {
401 // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
402 for (uint32_t y = 0; y < testParams.height; ++y)
403 for (uint32_t x = 0; x < testParams.width; ++x)
404 {
405 // let's build a chessboard of geometries
406 if (((x + y) % 2) == 0)
407 continue;
408 tcu::Vec3 xyz((float)x, (float)y, 0.0f);
409
410 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
411 makeBottomLevelAccelerationStructure();
412 bottomLevelAccelerationStructure->setGeometryCount(1u);
413
414 de::SharedPtr<RaytracedGeometryBase> geometry;
415 if (testParams.bottomTestType == BottomTestType::TRIANGLES)
416 {
417 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
418 testParams.indexType, testParams.padVertices);
419 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
420 {
421 if (instanceFlags == 0u)
422 {
423 geometry->addVertex(xyz + v0);
424 geometry->addVertex(xyz + v1);
425 geometry->addVertex(xyz + v2);
426 geometry->addVertex(xyz + v2);
427 geometry->addVertex(xyz + v1);
428 geometry->addVertex(xyz + v3);
429 }
430 else // Counterclockwise so the flags will be needed for the geometry to be visible.
431 {
432 geometry->addVertex(xyz + v2);
433 geometry->addVertex(xyz + v1);
434 geometry->addVertex(xyz + v0);
435 geometry->addVertex(xyz + v3);
436 geometry->addVertex(xyz + v1);
437 geometry->addVertex(xyz + v2);
438 }
439 }
440 else
441 {
442 geometry->addVertex(xyz + v0);
443 geometry->addVertex(xyz + v1);
444 geometry->addVertex(xyz + v2);
445 geometry->addVertex(xyz + v3);
446
447 if (instanceFlags == 0u)
448 {
449 geometry->addIndex(0);
450 geometry->addIndex(1);
451 geometry->addIndex(2);
452 geometry->addIndex(2);
453 geometry->addIndex(1);
454 geometry->addIndex(3);
455 }
456 else // Counterclockwise so the flags will be needed for the geometry to be visible.
457 {
458 geometry->addIndex(2);
459 geometry->addIndex(1);
460 geometry->addIndex(0);
461 geometry->addIndex(3);
462 geometry->addIndex(1);
463 geometry->addIndex(2);
464 }
465 }
466 }
467 else // testParams.bottomTestType == BTT_AABBS
468 {
469 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat,
470 testParams.indexType, testParams.padVertices);
471
472 if (!testParams.padVertices)
473 {
474 // Single AABB.
475 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
476 geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
477 }
478 else
479 {
480 // Multiple AABBs covering the same space.
481 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
482 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, 0.1f));
483
484 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, -0.1f));
485 geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
486
487 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.5f, -0.1f));
488 geometry->addVertex(xyz + tcu::Vec3(0.5f, 1.0f, 0.1f));
489
490 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.0f, -0.1f));
491 geometry->addVertex(xyz + tcu::Vec3(1.0f, 0.5f, 0.1f));
492 }
493 }
494
495 bottomLevelAccelerationStructure->addGeometry(geometry);
496
497 if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
498 geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
499
500 result.push_back(
501 de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
502 }
503 }
504
505 return result;
506 }
507
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)508 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure(
509 Context &context, TestParams &testParams,
510 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
511 {
512 // Checkerboard configuration does not support empty geometry tests.
513 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
514
515 DE_UNREF(context);
516
517 const auto instanceCount = testParams.width * testParams.height / 2u;
518 const auto instanceFlags = getCullFlags(testParams.cullFlags);
519
520 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
521 result->setInstanceCount(instanceCount);
522
523 if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
524 {
525
526 for (uint32_t y = 0; y < testParams.height; ++y)
527 for (uint32_t x = 0; x < testParams.width; ++x)
528 {
529 if (((x + y) % 2) == 0)
530 continue;
531 const VkTransformMatrixKHR transformMatrixKHR = {{
532 // float matrix[3][4];
533 {1.0f, 0.0f, 0.0f, (float)x},
534 {0.0f, 1.0f, 0.0f, (float)y},
535 {0.0f, 0.0f, 1.0f, 0.0f},
536 }};
537 const uint32_t instanceCustomIndex =
538 ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
539 (INSTANCE_CUSTOM_INDEX_BASE + x + y) :
540 0u);
541 result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, instanceCustomIndex,
542 0xFFu, 0u, instanceFlags);
543 }
544 }
545 else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
546 {
547 uint32_t currentInstanceIndex = 0;
548
549 for (uint32_t y = 0; y < testParams.height; ++y)
550 for (uint32_t x = 0; x < testParams.width; ++x)
551 {
552 if (((x + y) % 2) == 0)
553 continue;
554 const uint32_t instanceCustomIndex =
555 ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
556 (INSTANCE_CUSTOM_INDEX_BASE + x + y) :
557 0u);
558
559 if (testParams.useCullMask)
560 {
561 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4,
562 instanceCustomIndex, testParams.cullMask, 0u, instanceFlags);
563 }
564 else
565 {
566 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4,
567 instanceCustomIndex, 0xFFu, 0u, instanceFlags);
568 }
569 }
570 }
571
572 return result;
573 }
574
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)575 void CheckerboardConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
576 Context &context, TestParams &testParams)
577 {
578 DE_UNREF(testParams);
579 const DeviceInterface &vkd = context.getDeviceInterface();
580 const VkDevice device = context.getDevice();
581
582 const bool useAnyHit = (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT);
583 const auto hitShaderStage = (useAnyHit ? VK_SHADER_STAGE_ANY_HIT_BIT_KHR : VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
584 const auto hitShaderName = (useAnyHit ? "ahit" : "chit");
585
586 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
587 createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
588 rayTracingPipeline->addShader(
589 hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 1);
590 rayTracingPipeline->addShader(
591 hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 2);
592 if (testParams.bottomTestType == BottomTestType::AABBS)
593 rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
594 createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0),
595 2);
596 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
597 createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 3);
598 }
599
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)600 void CheckerboardConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
601 Context &context, TestParams &testParams, VkPipeline pipeline,
602 uint32_t shaderGroupHandleSize,
603 uint32_t shaderGroupBaseAlignment,
604 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
605 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
606 de::MovePtr<BufferWithMemory> &missShaderBindingTable)
607 {
608 const DeviceInterface &vkd = context.getDeviceInterface();
609 const VkDevice device = context.getDevice();
610 Allocator &allocator = context.getDefaultAllocator();
611
612 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
613 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
614 if (testParams.bottomTestType == BottomTestType::AABBS)
615 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
616 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
617 else // testParams.bottomTestType == BTT_TRIANGLES
618 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
619 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
620 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
621 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1);
622 }
623
bitfieldReverse(uint32_t num)624 uint32_t bitfieldReverse(uint32_t num)
625 {
626 uint32_t reverse_num = 0;
627 uint32_t i;
628 for (i = 0; i < 32; i++)
629 {
630 if ((num & (1 << i)))
631 reverse_num |= 1 << ((32 - 1) - i);
632 }
633 return reverse_num;
634 }
635
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)636 bool CheckerboardConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
637 {
638 // Checkerboard configuration does not support empty geometry tests.
639 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
640
641 DE_UNREF(context);
642 const auto *bufferPtr = (int32_t *)resultBuffer->getAllocation().getHostPtr();
643 uint32_t pos = 0;
644 uint32_t failures = 0;
645
646 // verify results - each test case should generate checkerboard pattern
647 for (uint32_t y = 0; y < testParams.height; ++y)
648 for (uint32_t x = 0; x < testParams.width; ++x)
649 {
650 // The hit value should match the shader code.
651 if (testParams.useCullMask)
652 {
653 const int32_t hitValue = testParams.cullMask & 0x000000FFu; // only 8 last bits are used by the cullMask
654 const int32_t expectedResult =
655 ((x + y) % 2) ? hitValue : bitfieldReverse(testParams.cullMask & 0x000000FFu);
656
657 if (bufferPtr[pos] != expectedResult)
658 failures++;
659 }
660 else
661 {
662 const int32_t hitValue = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
663 static_cast<int32_t>(INSTANCE_CUSTOM_INDEX_BASE + x + y) :
664 2);
665 const int32_t expectedResult = ((x + y) % 2) ? hitValue : 1;
666
667 if (bufferPtr[pos] != expectedResult)
668 failures++;
669 }
670
671 ++pos;
672 }
673 return failures == 0;
674 }
675
getResultImageFormat()676 VkFormat CheckerboardConfiguration::getResultImageFormat()
677 {
678 return VK_FORMAT_R32_SINT;
679 }
680
getResultImageFormatSize()681 size_t CheckerboardConfiguration::getResultImageFormatSize()
682 {
683 return sizeof(uint32_t);
684 }
685
getClearValue()686 VkClearValue CheckerboardConfiguration::getClearValue()
687 {
688 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
689 }
690
691 class SingleTriangleConfiguration : public TestConfiguration
692 {
693 public:
694 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
695 Context &context, TestParams &testParams) override;
696 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
697 Context &context, TestParams &testParams,
698 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
699 void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
700 TestParams &testParams) override;
701 void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
702 TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
703 uint32_t shaderGroupBaseAlignment,
704 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
705 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
706 de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
707 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
708 VkFormat getResultImageFormat() override;
709 size_t getResultImageFormatSize() override;
710 VkClearValue getClearValue() override;
711
712 // well, actually we have 2 triangles, but we ignore the first one ( see raygen shader for this configuration )
713 const std::vector<tcu::Vec3> vertices = {
714 tcu::Vec3(0.0f, 0.0f, -0.1f), tcu::Vec3(-0.1f, 0.0f, 0.0f), tcu::Vec3(0.0f, -0.1f, 0.0f),
715 tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
716 };
717
718 const std::vector<uint32_t> indices = {3, 4, 5};
719 // Different vertex configurations of a triangle whose parameter x is set to NaN during inactive_triangles tests
720 const bool nanConfig[7][3] = {
721 {true, true, true}, {true, false, false}, {false, true, false}, {false, false, true},
722 {true, true, false}, {false, true, true}, {true, false, true},
723 };
724 };
725
726 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> SingleTriangleConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)727 initBottomAccelerationStructures(Context &context, TestParams &testParams)
728 {
729 DE_UNREF(context);
730
731 // No other cases supported for the single triangle configuration.
732 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
733
734 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
735
736 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
737 makeBottomLevelAccelerationStructure();
738
739 unsigned int geometryCount = testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES ? 4U : 1U;
740
741 if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
742 {
743 bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
744
745 de::SharedPtr<RaytracedGeometryBase> geometry;
746 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
747
748 for (unsigned int i = 0; i < geometryCount; i++)
749 {
750 auto customVertices(vertices);
751
752 const auto nanValue = tcu::Float32::nan().asFloat();
753
754 if (nanConfig[i][0])
755 customVertices[3].x() = nanValue;
756 if (nanConfig[i][1])
757 customVertices[4].x() = nanValue;
758 if (nanConfig[i][2])
759 customVertices[5].x() = nanValue;
760
761 for (auto it = begin(customVertices), eit = end(customVertices); it != eit; ++it)
762 geometry->addVertex(*it);
763
764 if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
765 {
766 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
767 geometry->addIndex(*it);
768 }
769 bottomLevelAccelerationStructure->addGeometry(geometry);
770 }
771 }
772 else
773 {
774 bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
775
776 de::SharedPtr<RaytracedGeometryBase> geometry;
777 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
778
779 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
780 geometry->addVertex(*it);
781
782 if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
783 {
784 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
785 geometry->addIndex(*it);
786 }
787 bottomLevelAccelerationStructure->addGeometry(geometry);
788 }
789
790 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
791
792 return result;
793 }
794
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)795 de::MovePtr<TopLevelAccelerationStructure> SingleTriangleConfiguration::initTopAccelerationStructure(
796 Context &context, TestParams &testParams,
797 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
798 {
799 DE_UNREF(context);
800 DE_UNREF(testParams);
801
802 // Unsupported in this configuration.
803 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
804
805 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
806 result->setInstanceCount(1u);
807
808 result->addInstance(bottomLevelAccelerationStructures[0]);
809
810 return result;
811 }
812
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)813 void SingleTriangleConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
814 Context &context, TestParams &testParams)
815 {
816 DE_UNREF(testParams);
817 const DeviceInterface &vkd = context.getDeviceInterface();
818 const VkDevice device = context.getDevice();
819
820 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
821 createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"), 0),
822 0);
823 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
824 createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"), 0),
825 1);
826 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
827 createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"), 0),
828 2);
829 }
830
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)831 void SingleTriangleConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
832 Context &context, TestParams &testParams, VkPipeline pipeline,
833 uint32_t shaderGroupHandleSize,
834 uint32_t shaderGroupBaseAlignment,
835 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
836 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
837 de::MovePtr<BufferWithMemory> &missShaderBindingTable)
838 {
839 DE_UNREF(testParams);
840 const DeviceInterface &vkd = context.getDeviceInterface();
841 const VkDevice device = context.getDevice();
842 Allocator &allocator = context.getDefaultAllocator();
843
844 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
845 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
846 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
847 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
848 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
849 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
850 }
851
pointInTriangle2D(const tcu::Vec3 & p,const tcu::Vec3 & p0,const tcu::Vec3 & p1,const tcu::Vec3 & p2)852 bool pointInTriangle2D(const tcu::Vec3 &p, const tcu::Vec3 &p0, const tcu::Vec3 &p1, const tcu::Vec3 &p2)
853 {
854 float s = p0.y() * p2.x() - p0.x() * p2.y() + (p2.y() - p0.y()) * p.x() + (p0.x() - p2.x()) * p.y();
855 float t = p0.x() * p1.y() - p0.y() * p1.x() + (p0.y() - p1.y()) * p.x() + (p1.x() - p0.x()) * p.y();
856
857 if ((s < 0) != (t < 0))
858 return false;
859
860 float a = -p1.y() * p2.x() + p0.y() * (p2.x() - p1.x()) + p0.x() * (p1.y() - p2.y()) + p1.x() * p2.y();
861
862 return a < 0 ? (s <= 0 && s + t >= a) : (s >= 0 && s + t <= a);
863 }
864
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)865 bool SingleTriangleConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
866 {
867 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
868 tcu::TextureFormat vertexFormat = vk::mapVkFormat(testParams.vertexFormat);
869 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 1,
870 resultBuffer->getAllocation().getHostPtr());
871
872 std::vector<float> reference(testParams.width * testParams.height);
873 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
874
875 // verify results
876 tcu::Vec3 v0 = vertices[3];
877 tcu::Vec3 v1 = vertices[4];
878 tcu::Vec3 v2 = vertices[5];
879 const int numChannels = tcu::getNumUsedChannels(vertexFormat.order);
880 if (numChannels < 3)
881 {
882 v0.z() = 0.0f;
883 v1.z() = 0.0f;
884 v2.z() = 0.0f;
885 }
886 tcu::Vec3 abc = tcu::cross((v2 - v0), (v1 - v0));
887
888 for (uint32_t j = 0; j < testParams.height; ++j)
889 {
890 float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
891 for (uint32_t i = 0; i < testParams.width; ++i)
892 {
893 float x = 0.1f + 0.2f * float(i) / float(testParams.width - 1);
894 float z = (abc.x() * x + abc.y() * y) / abc.z();
895 bool inTriangle = pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
896 float refValue =
897 ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f + z : 0.0f);
898 referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
899 }
900 }
901 return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
902 resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
903 }
904
getResultImageFormat()905 VkFormat SingleTriangleConfiguration::getResultImageFormat()
906 {
907 return VK_FORMAT_R32_SFLOAT;
908 }
909
getResultImageFormatSize()910 size_t SingleTriangleConfiguration::getResultImageFormatSize()
911 {
912 return sizeof(float);
913 }
914
getClearValue()915 VkClearValue SingleTriangleConfiguration::getClearValue()
916 {
917 return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
918 }
919
920 class UpdateableASConfiguration : public TestConfiguration
921 {
922 public:
923 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
924 Context &context, TestParams &testParams) override;
925 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
926 Context &context, TestParams &testParams,
927 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
928 void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
929 TestParams &testParams) override;
930 void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
931 TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
932 uint32_t shaderGroupBaseAlignment,
933 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
934 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
935 de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
936 bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
937 VkFormat getResultImageFormat() override;
938 size_t getResultImageFormatSize() override;
939 VkClearValue getClearValue() override;
940
941 // two triangles: one in the front we will replace with one in the back after updating
942 // update vertex: build with vertices[0], update vertices with vertices[1]
943 // update index: build with vertices[0], updade indices with indices[1]
944 const std::vector<tcu::Vec3> vertices = {
945 tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(0.5f, 0.0f, 0.0f), tcu::Vec3(0.0f, 0.5f, 0.0f),
946 tcu::Vec3(0.0f, 0.0f, -0.5f), tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
947 };
948
949 const std::vector<uint32_t> indices = {0, 1, 2};
950 };
951
952 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> UpdateableASConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)953 initBottomAccelerationStructures(Context &context, TestParams &testParams)
954 {
955 DE_UNREF(context);
956
957 // No other cases supported for the single triangle configuration.
958 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
959
960 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
961
962 {
963 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
964 makeBottomLevelAccelerationStructure();
965
966 unsigned int geometryCount = 1U;
967
968 bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
969
970 de::SharedPtr<RaytracedGeometryBase> geometry;
971 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
972
973 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
974 geometry->addVertex(*it);
975
976 if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
977 {
978 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
979 geometry->addIndex(*it);
980 }
981 bottomLevelAccelerationStructure->addGeometry(geometry);
982
983 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
984 }
985 return result;
986 }
987
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)988 de::MovePtr<TopLevelAccelerationStructure> UpdateableASConfiguration::initTopAccelerationStructure(
989 Context &context, TestParams &testParams,
990 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
991 {
992 DE_UNREF(context);
993 DE_UNREF(testParams);
994
995 // Unsupported in this configuration.
996 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
997
998 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
999 result->setInstanceCount(1u);
1000
1001 result->addInstance(bottomLevelAccelerationStructures[0]);
1002
1003 return result;
1004 }
1005
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)1006 void UpdateableASConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
1007 Context &context, TestParams &testParams)
1008 {
1009 DE_UNREF(testParams);
1010 const DeviceInterface &vkd = context.getDeviceInterface();
1011 const VkDevice device = context.getDevice();
1012
1013 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1014 createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"), 0),
1015 0);
1016 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1017 createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"), 0),
1018 1);
1019 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
1020 createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"), 0),
1021 2);
1022 }
1023
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)1024 void UpdateableASConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
1025 Context &context, TestParams &testParams, VkPipeline pipeline,
1026 uint32_t shaderGroupHandleSize,
1027 uint32_t shaderGroupBaseAlignment,
1028 de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
1029 de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
1030 de::MovePtr<BufferWithMemory> &missShaderBindingTable)
1031 {
1032 DE_UNREF(testParams);
1033 const DeviceInterface &vkd = context.getDeviceInterface();
1034 const VkDevice device = context.getDevice();
1035 Allocator &allocator = context.getDefaultAllocator();
1036
1037 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1038 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1039 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1040 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1041 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1042 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1043 }
1044
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)1045 bool UpdateableASConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
1046 {
1047 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
1048 tcu::TextureFormat vertexFormat = vk::mapVkFormat(testParams.vertexFormat);
1049 tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 1,
1050 resultBuffer->getAllocation().getHostPtr());
1051
1052 std::vector<float> reference(testParams.width * testParams.height);
1053 tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
1054
1055 // verify results
1056 tcu::Vec3 v0 = vertices[3];
1057 tcu::Vec3 v1 = vertices[4];
1058 tcu::Vec3 v2 = vertices[5];
1059 const int numChannels = tcu::getNumUsedChannels(vertexFormat.order);
1060 if (numChannels < 3)
1061 {
1062 v0.z() = 0.0f;
1063 v1.z() = 0.0f;
1064 v2.z() = 0.0f;
1065 }
1066
1067 for (uint32_t j = 0; j < testParams.height; ++j)
1068 {
1069 float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
1070 for (uint32_t i = 0; i < testParams.width; ++i)
1071 {
1072 float x = 0.1f + 0.2f * float(i) / float(testParams.width - 1);
1073 float z = v0.z();
1074 bool inTriangle = pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
1075 float refValue =
1076 ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f - z : 0.0f);
1077 referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
1078 }
1079 }
1080 return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
1081 resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1082 }
1083
getResultImageFormat()1084 VkFormat UpdateableASConfiguration::getResultImageFormat()
1085 {
1086 return VK_FORMAT_R32_SFLOAT;
1087 }
1088
getResultImageFormatSize()1089 size_t UpdateableASConfiguration::getResultImageFormatSize()
1090 {
1091 return sizeof(float);
1092 }
1093
getClearValue()1094 VkClearValue UpdateableASConfiguration::getClearValue()
1095 {
1096 return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
1097 }
1098
commonASTestsCheckSupport(Context & context)1099 void commonASTestsCheckSupport(Context &context)
1100 {
1101 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
1102 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1103 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1104
1105 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
1106 context.getRayTracingPipelineFeatures();
1107 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
1108 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
1109
1110 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1111 context.getAccelerationStructureFeatures();
1112 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
1113 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
1114 "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
1115 }
1116
1117 class RayTracingASBasicTestCase : public TestCase
1118 {
1119 public:
1120 RayTracingASBasicTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
1121 ~RayTracingASBasicTestCase(void);
1122
1123 void checkSupport(Context &context) const override;
1124 void initPrograms(SourceCollections &programCollection) const override;
1125 TestInstance *createInstance(Context &context) const override;
1126
1127 protected:
1128 TestParams m_data;
1129 };
1130
1131 // Same as RayTracingASBasicTestCase but it will only initialize programs for SingleTriangleConfiguration and use hand-tuned SPIR-V
1132 // assembly.
1133 class RayTracingASFuncArgTestCase : public RayTracingASBasicTestCase
1134 {
1135 public:
1136 RayTracingASFuncArgTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
~RayTracingASFuncArgTestCase(void)1137 ~RayTracingASFuncArgTestCase(void)
1138 {
1139 }
1140
1141 void initPrograms(SourceCollections &programCollection) const override;
1142 };
1143
1144 class RayTracingASBasicTestInstance : public TestInstance
1145 {
1146 public:
1147 RayTracingASBasicTestInstance(Context &context, const TestParams &data);
1148 ~RayTracingASBasicTestInstance(void) = default;
1149 tcu::TestStatus iterate(void) override;
1150
1151 protected:
1152 bool iterateNoWorkers(void);
1153 bool iterateWithWorkers(void);
1154 de::MovePtr<BufferWithMemory> runTest(const uint32_t workerThreadsCount);
1155
1156 private:
1157 TestParams m_data;
1158 };
1159
RayTracingASBasicTestCase(tcu::TestContext & context,const char * name,const TestParams & data)1160 RayTracingASBasicTestCase::RayTracingASBasicTestCase(tcu::TestContext &context, const char *name,
1161 const TestParams &data)
1162 : vkt::TestCase(context, name)
1163 , m_data(data)
1164 {
1165 }
1166
~RayTracingASBasicTestCase(void)1167 RayTracingASBasicTestCase::~RayTracingASBasicTestCase(void)
1168 {
1169 }
1170
checkSupport(Context & context) const1171 void RayTracingASBasicTestCase::checkSupport(Context &context) const
1172 {
1173 commonASTestsCheckSupport(context);
1174
1175 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1176 context.getAccelerationStructureFeatures();
1177 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
1178 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
1179 TCU_THROW(NotSupportedError,
1180 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
1181
1182 if (m_data.useCullMask)
1183 context.requireDeviceFunctionality("VK_KHR_ray_tracing_maintenance1");
1184
1185 // Check supported vertex format.
1186 checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
1187 m_data.vertexFormat);
1188 }
1189
initPrograms(SourceCollections & programCollection) const1190 void RayTracingASBasicTestCase::initPrograms(SourceCollections &programCollection) const
1191 {
1192 bool storeInRGen = false;
1193 bool storeInAHit = false;
1194 bool storeInCHit = false;
1195 bool storeInISec = false;
1196
1197 switch (m_data.instanceCustomIndexCase)
1198 {
1199 case InstanceCustomIndexCase::NONE:
1200 storeInRGen = true;
1201 break;
1202 case InstanceCustomIndexCase::CLOSEST_HIT:
1203 storeInCHit = true;
1204 break;
1205 case InstanceCustomIndexCase::ANY_HIT:
1206 storeInAHit = true;
1207 break;
1208 case InstanceCustomIndexCase::INTERSECTION:
1209 storeInISec = true;
1210 break;
1211 default:
1212 DE_ASSERT(false);
1213 break;
1214 }
1215
1216 const std::string imageDeclaration = "layout(r32i, set = 0, binding = 0) uniform iimage2D result;\n";
1217 const std::string storeCustomIndex =
1218 " imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_InstanceCustomIndexEXT, 0, 0, 1));\n";
1219 const std::string storeCullMask =
1220 " imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_CullMaskEXT, 0, 0, 1));\n";
1221 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1222
1223 {
1224 std::stringstream css;
1225 css << "#version 460 core\n"
1226 << "#extension GL_EXT_ray_tracing : require\n"
1227 << "layout(location = 0) rayPayloadEXT ivec4 hitValue;\n";
1228
1229 if (storeInRGen)
1230 css << imageDeclaration;
1231
1232 css << "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1233 << "\n"
1234 << "void main()\n"
1235 << "{\n"
1236 << " float tmin = 0.0;\n"
1237 << " float tmax = 1.0;\n"
1238 << " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
1239 << " vec3 direction = vec3(0.0,0.0,-1.0);\n"
1240 << " hitValue = ivec4(0,0,0,0);\n"
1241 << " traceRayEXT(topLevelAS, "
1242 << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0, " : "gl_RayFlagsCullBackFacingTrianglesEXT, ")
1243 << m_data.cullMask << ", 0, 0, 0, origin, tmin, direction, tmax, 0);\n";
1244
1245 if (storeInRGen)
1246 css << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1247
1248 css << "}\n";
1249
1250 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1251 }
1252
1253 {
1254 std::stringstream css;
1255 css << "#version 460 core\n"
1256 << "#extension GL_EXT_ray_tracing : require\n"
1257 << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1258 << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1259
1260 if (storeInCHit)
1261 css << imageDeclaration;
1262
1263 css << "void main()\n"
1264 << "{\n"
1265 << " hitValue = ivec4(2,0,0,1);\n";
1266
1267 if (storeInCHit)
1268 {
1269 if (m_data.useCullMask)
1270 {
1271 css << storeCullMask;
1272 }
1273 else
1274 {
1275 css << storeCustomIndex;
1276 }
1277 }
1278
1279 css << "}\n";
1280
1281 programCollection.glslSources.add("chit")
1282 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1283 }
1284
1285 if (storeInAHit)
1286 {
1287 std::stringstream css;
1288 css << "#version 460 core\n"
1289 << "#extension GL_EXT_ray_tracing : require\n"
1290 << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n") << imageDeclaration
1291 << "void main()\n"
1292 << "{\n"
1293 << ((m_data.useCullMask) ? storeCullMask : storeCustomIndex) << "}\n";
1294
1295 programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1296 }
1297
1298 {
1299 std::stringstream css;
1300 css << "#version 460 core\n"
1301 << "#extension GL_EXT_ray_tracing : require\n"
1302 << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1303 << "hitAttributeEXT ivec4 hitAttribute;\n";
1304
1305 if (storeInISec)
1306 css << imageDeclaration;
1307
1308 css << "void main()\n"
1309 << "{\n"
1310 << " hitAttribute = ivec4(0,0,0,0);\n"
1311 << " reportIntersectionEXT(0.5f, 0);\n";
1312 if (storeInISec)
1313 {
1314 if (m_data.useCullMask)
1315 {
1316 css << storeCullMask;
1317 }
1318 else
1319 {
1320 css << storeCustomIndex;
1321 }
1322 }
1323
1324 css << "}\n";
1325
1326 programCollection.glslSources.add("isect")
1327 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1328 }
1329
1330 {
1331 std::stringstream css;
1332 css << "#version 460 core\n"
1333 << "#extension GL_EXT_ray_tracing : require\n"
1334 << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1335 << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1336
1337 if (!storeInRGen)
1338 css << imageDeclaration;
1339
1340 css << "void main()\n"
1341 << "{\n"
1342 << " hitValue = ivec4(1,0,0,1);\n";
1343 if (!storeInRGen)
1344 {
1345 if (m_data.useCullMask)
1346 {
1347 css << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(bitfieldReverse(uint(gl_CullMaskEXT)), 0, "
1348 "0, 1)); \n";
1349 }
1350 else
1351 {
1352 css << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1353 }
1354 }
1355
1356 css << "}\n";
1357
1358 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1359 }
1360
1361 {
1362 std::stringstream css;
1363 css << "#version 460 core\n"
1364 "#extension GL_EXT_ray_tracing : require\n"
1365 "layout(location = 0) rayPayloadEXT vec4 hitValue;\n"
1366 "layout(r32f, set = 0, binding = 0) uniform image2D result;\n"
1367 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1368 "\n"
1369 "vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)\n"
1370 "{\n"
1371 " return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + "
1372 "(float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;\n"
1373 "}\n"
1374 "\n"
1375 "void main()\n"
1376 "{\n"
1377 " float tmin = 0.0;\n"
1378 " float tmax = 2.0;\n"
1379 " vec3 origin = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );\n"
1380 " vec3 direction = vec3(0.0,0.0,-1.0);\n"
1381 " hitValue = vec4(0.0,0.0,0.0,0.0);\n"
1382 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1383 " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
1384 "}\n";
1385 programCollection.glslSources.add("rgen_depth")
1386 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1387 }
1388
1389 {
1390 std::stringstream css;
1391 css << "#version 460 core\n"
1392 "#extension GL_EXT_ray_tracing : require\n"
1393 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1394 "void main()\n"
1395 "{\n"
1396 " hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1397 "}\n";
1398
1399 programCollection.glslSources.add("chit_depth")
1400 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1401 }
1402
1403 {
1404 std::stringstream css;
1405 css << "#version 460 core\n"
1406 "#extension GL_EXT_ray_tracing : require\n"
1407 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1408 "void main()\n"
1409 "{\n"
1410 " hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1411 "}\n";
1412
1413 programCollection.glslSources.add("miss_depth")
1414 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1415 }
1416 }
1417
createInstance(Context & context) const1418 TestInstance *RayTracingASBasicTestCase::createInstance(Context &context) const
1419 {
1420 return new RayTracingASBasicTestInstance(context, m_data);
1421 }
1422
RayTracingASFuncArgTestCase(tcu::TestContext & context,const char * name,const TestParams & data)1423 RayTracingASFuncArgTestCase::RayTracingASFuncArgTestCase(tcu::TestContext &context, const char *name,
1424 const TestParams &data)
1425 : RayTracingASBasicTestCase(context, name, data)
1426 {
1427 }
1428
initPrograms(SourceCollections & programCollection) const1429 void RayTracingASFuncArgTestCase::initPrograms(SourceCollections &programCollection) const
1430 {
1431 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1432 const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1433
1434 {
1435 // The SPIR-V assembly below is based on the following GLSL code. Some
1436 // modifications have been made to make traceRaysBottomWrapper take a bare
1437 // acceleration structure as its argument instead of a pointer to it, so we can
1438 // test passing a pointer and a bare value in the same test.
1439 //
1440 // #version 460 core
1441 // #extension GL_EXT_ray_tracing : require
1442 // layout(location = 0) rayPayloadEXT vec4 hitValue;
1443 // layout(r32f, set = 0, binding = 0) uniform image2D result;
1444 // layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;
1445 //
1446 // void traceRaysBottomWrapper(
1447 // accelerationStructureEXT topLevel,
1448 // uint rayFlags,
1449 // uint cullMask,
1450 // uint sbtRecordOffset,
1451 // uint sbtRecordStride,
1452 // uint missIndex,
1453 // vec3 origin,
1454 // float Tmin,
1455 // vec3 direction,
1456 // float Tmax)
1457 // {
1458 // traceRayEXT(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax, 0);
1459 // }
1460 //
1461 // void traceRaysTopWrapper(
1462 // accelerationStructureEXT topLevel,
1463 // uint rayFlags,
1464 // uint cullMask,
1465 // uint sbtRecordOffset,
1466 // uint sbtRecordStride,
1467 // uint missIndex,
1468 // vec3 origin,
1469 // float Tmin,
1470 // vec3 direction,
1471 // float Tmax)
1472 // {
1473 // traceRaysBottomWrapper(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax);
1474 // }
1475 //
1476 // vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)
1477 // {
1478 // return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;
1479 // }
1480 //
1481 // void main()
1482 // {
1483 // float tmin = 0.0;
1484 // float tmax = 2.0;
1485 // vec3 origin = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );
1486 // vec3 direction = vec3(0.0,0.0,-1.0);
1487 // hitValue = vec4(0.0,0.0,0.0,0.0);
1488 // traceRaysTopWrapper(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax);
1489 // imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);
1490 // }
1491
1492 std::ostringstream rgen;
1493 rgen
1494 << "; SPIR-V\n"
1495 << "; Version: 1.4\n"
1496 << "; Generator: Khronos Glslang Reference Front End; 10\n"
1497 << "; Bound: 156\n"
1498 << "; Schema: 0\n"
1499 << "OpCapability RayTracingKHR\n"
1500 << "OpExtension \"SPV_KHR_ray_tracing\"\n"
1501 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1502 << "OpMemoryModel Logical GLSL450\n"
1503 << "OpEntryPoint RayGenerationKHR %4 \"main\" %59 %82 %88 %130 %148\n"
1504 << "OpDecorate %59 Location 0\n"
1505 << "OpDecorate %82 BuiltIn LaunchIdKHR\n"
1506 << "OpDecorate %88 BuiltIn LaunchSizeKHR\n"
1507 << "OpDecorate %130 DescriptorSet 0\n"
1508 << "OpDecorate %130 Binding 1\n"
1509 << "OpDecorate %148 DescriptorSet 0\n"
1510 << "OpDecorate %148 Binding 0\n"
1511 << "%2 = OpTypeVoid\n"
1512 << "%3 = OpTypeFunction %2\n"
1513
1514 // This is the bare type.
1515 << "%6 = OpTypeAccelerationStructureKHR\n"
1516
1517 // This is the pointer type.
1518 << "%7 = OpTypePointer UniformConstant %6\n"
1519
1520 << "%8 = OpTypeInt 32 0\n"
1521 << "%9 = OpTypePointer Function %8\n"
1522 << "%10 = OpTypeFloat 32\n"
1523 << "%11 = OpTypeVector %10 3\n"
1524 << "%12 = OpTypePointer Function %11\n"
1525 << "%13 = OpTypePointer Function %10\n"
1526
1527 // This is the type for traceRaysTopWrapper and also the original traceRaysBottomWrapper.
1528 << "%14 = OpTypeFunction %2 %7 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1529
1530 // This is the modified type to take a bare AS as the first argument, for the modified version of traceRaysBottomWrapper.
1531 << "%14b = OpTypeFunction %2 %6 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1532
1533 << "%39 = OpTypeFunction %11 %12 %12 %12\n"
1534 << "%55 = OpTypeInt 32 1\n"
1535 << "%56 = OpConstant %55 0\n"
1536 << "%57 = OpTypeVector %10 4\n"
1537 << "%58 = OpTypePointer RayPayloadKHR %57\n"
1538 << "%59 = OpVariable %58 RayPayloadKHR\n"
1539 << "%80 = OpTypeVector %8 3\n"
1540 << "%81 = OpTypePointer Input %80\n"
1541 << "%82 = OpVariable %81 Input\n"
1542 << "%83 = OpConstant %8 0\n"
1543 << "%84 = OpTypePointer Input %8\n"
1544 << "%88 = OpVariable %81 Input\n"
1545 << "%91 = OpConstant %8 1\n"
1546 << "%112 = OpConstant %10 0\n"
1547 << "%114 = OpConstant %10 2\n"
1548 << "%116 = OpConstant %10 0.100000001\n"
1549 << "%117 = OpConstant %10 1\n"
1550 << "%118 = OpConstantComposite %11 %116 %116 %117\n"
1551 << "%119 = OpConstant %10 0.200000003\n"
1552 << "%120 = OpConstantComposite %11 %119 %112 %112\n"
1553 << "%121 = OpConstantComposite %11 %112 %119 %112\n"
1554 << "%127 = OpConstant %10 -1\n"
1555 << "%128 = OpConstantComposite %11 %112 %112 %127\n"
1556 << "%129 = OpConstantComposite %57 %112 %112 %112 %112\n"
1557 << "%130 = OpVariable %7 UniformConstant\n"
1558 << "%131 = OpConstant %8 255\n"
1559 << "%146 = OpTypeImage %10 2D 0 0 0 2 R32f\n"
1560 << "%147 = OpTypePointer UniformConstant %146\n"
1561 << "%148 = OpVariable %147 UniformConstant\n"
1562 << "%150 = OpTypeVector %8 2\n"
1563 << "%153 = OpTypeVector %55 2\n"
1564
1565 // This is main().
1566 << "%4 = OpFunction %2 None %3\n"
1567 << "%5 = OpLabel\n"
1568 << "%111 = OpVariable %13 Function\n"
1569 << "%113 = OpVariable %13 Function\n"
1570 << "%115 = OpVariable %12 Function\n"
1571 << "%122 = OpVariable %12 Function\n"
1572 << "%123 = OpVariable %12 Function\n"
1573 << "%124 = OpVariable %12 Function\n"
1574 << "%126 = OpVariable %12 Function\n"
1575 << "%132 = OpVariable %9 Function\n"
1576 << "%133 = OpVariable %9 Function\n"
1577 << "%134 = OpVariable %9 Function\n"
1578 << "%135 = OpVariable %9 Function\n"
1579 << "%136 = OpVariable %9 Function\n"
1580 << "%137 = OpVariable %12 Function\n"
1581 << "%139 = OpVariable %13 Function\n"
1582 << "%141 = OpVariable %12 Function\n"
1583 << "%143 = OpVariable %13 Function\n"
1584 << "OpStore %111 %112\n"
1585 << "OpStore %113 %114\n"
1586 << "OpStore %122 %118\n"
1587 << "OpStore %123 %120\n"
1588 << "OpStore %124 %121\n"
1589 << "%125 = OpFunctionCall %11 %43 %122 %123 %124\n"
1590 << "OpStore %115 %125\n"
1591 << "OpStore %126 %128\n"
1592 << "OpStore %59 %129\n"
1593 << "OpStore %132 %83\n"
1594 << "OpStore %133 %131\n"
1595 << "OpStore %134 %83\n"
1596 << "OpStore %135 %83\n"
1597 << "OpStore %136 %83\n"
1598 << "%138 = OpLoad %11 %115\n"
1599 << "OpStore %137 %138\n"
1600 << "%140 = OpLoad %10 %111\n"
1601 << "OpStore %139 %140\n"
1602 << "%142 = OpLoad %11 %126\n"
1603 << "OpStore %141 %142\n"
1604 << "%144 = OpLoad %10 %113\n"
1605 << "OpStore %143 %144\n"
1606 << "%145 = OpFunctionCall %2 %37 %130 %132 %133 %134 %135 %136 %137 %139 %141 %143\n"
1607 << "%149 = OpLoad %146 %148\n"
1608 << "%151 = OpLoad %80 %82\n"
1609 << "%152 = OpVectorShuffle %150 %151 %151 0 1\n"
1610 << "%154 = OpBitcast %153 %152\n"
1611 << "%155 = OpLoad %57 %59\n"
1612 << "OpImageWrite %149 %154 %155\n"
1613 << "OpReturn\n"
1614 << "OpFunctionEnd\n"
1615
1616 // This is traceRaysBottomWrapper, doing the OpTraceRayKHR call.
1617 // We have modified the type so it takes a bare AS as the first argument.
1618 // %25 = OpFunction %2 None %14
1619 << "%25 = OpFunction %2 None %14b\n"
1620
1621 // Also the type of the first argument here.
1622 // %15 = OpFunctionParameter %7
1623 << "%15 = OpFunctionParameter %6\n"
1624
1625 << "%16 = OpFunctionParameter %9\n"
1626 << "%17 = OpFunctionParameter %9\n"
1627 << "%18 = OpFunctionParameter %9\n"
1628 << "%19 = OpFunctionParameter %9\n"
1629 << "%20 = OpFunctionParameter %9\n"
1630 << "%21 = OpFunctionParameter %12\n"
1631 << "%22 = OpFunctionParameter %13\n"
1632 << "%23 = OpFunctionParameter %12\n"
1633 << "%24 = OpFunctionParameter %13\n"
1634 << "%26 = OpLabel\n"
1635
1636 // We no longer need to dereference the pointer here.
1637 // %45 = OpLoad %6 %15
1638
1639 << "%46 = OpLoad %8 %16\n"
1640 << "%47 = OpLoad %8 %17\n"
1641 << "%48 = OpLoad %8 %18\n"
1642 << "%49 = OpLoad %8 %19\n"
1643 << "%50 = OpLoad %8 %20\n"
1644 << "%51 = OpLoad %11 %21\n"
1645 << "%52 = OpLoad %10 %22\n"
1646 << "%53 = OpLoad %11 %23\n"
1647 << "%54 = OpLoad %10 %24\n"
1648
1649 // And we can use the first argument here directly.
1650 // OpTraceRayKHR %45 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59
1651 << "OpTraceRayKHR %15 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59\n"
1652
1653 << "OpReturn\n"
1654 << "OpFunctionEnd\n"
1655
1656 // This is traceRaysTopWrapper, which calls traceRaysBottomWrapper.
1657 << "%37 = OpFunction %2 None %14\n"
1658
1659 // First argument, pointer to AS.
1660 << "%27 = OpFunctionParameter %7\n"
1661
1662 << "%28 = OpFunctionParameter %9\n"
1663 << "%29 = OpFunctionParameter %9\n"
1664 << "%30 = OpFunctionParameter %9\n"
1665 << "%31 = OpFunctionParameter %9\n"
1666 << "%32 = OpFunctionParameter %9\n"
1667 << "%33 = OpFunctionParameter %12\n"
1668 << "%34 = OpFunctionParameter %13\n"
1669 << "%35 = OpFunctionParameter %12\n"
1670 << "%36 = OpFunctionParameter %13\n"
1671 << "%38 = OpLabel\n"
1672 << "%60 = OpVariable %9 Function\n"
1673 << "%62 = OpVariable %9 Function\n"
1674 << "%64 = OpVariable %9 Function\n"
1675 << "%66 = OpVariable %9 Function\n"
1676 << "%68 = OpVariable %9 Function\n"
1677 << "%70 = OpVariable %12 Function\n"
1678 << "%72 = OpVariable %13 Function\n"
1679 << "%74 = OpVariable %12 Function\n"
1680 << "%76 = OpVariable %13 Function\n"
1681
1682 // Dereference the pointer to pass the AS as the first argument.
1683 << "%27b = OpLoad %6 %27\n"
1684
1685 << "%61 = OpLoad %8 %28\n"
1686 << "OpStore %60 %61\n"
1687 << "%63 = OpLoad %8 %29\n"
1688 << "OpStore %62 %63\n"
1689 << "%65 = OpLoad %8 %30\n"
1690 << "OpStore %64 %65\n"
1691 << "%67 = OpLoad %8 %31\n"
1692 << "OpStore %66 %67\n"
1693 << "%69 = OpLoad %8 %32\n"
1694 << "OpStore %68 %69\n"
1695 << "%71 = OpLoad %11 %33\n"
1696 << "OpStore %70 %71\n"
1697 << "%73 = OpLoad %10 %34\n"
1698 << "OpStore %72 %73\n"
1699 << "%75 = OpLoad %11 %35\n"
1700 << "OpStore %74 %75\n"
1701 << "%77 = OpLoad %10 %36\n"
1702 << "OpStore %76 %77\n"
1703
1704 // %2 is void, %25 is traceRaysBottomWrapper and %27 was the first argument.
1705 // We need to pass the loaded AS instead.
1706 // %78 = OpFunctionCall %2 %25 %27 %60 %62 %64 %66 %68 %70 %72 %74 %76
1707 << "%78 = OpFunctionCall %2 %25 %27b %60 %62 %64 %66 %68 %70 %72 %74 %76\n"
1708
1709 << "OpReturn\n"
1710 << "OpFunctionEnd\n"
1711
1712 // This is calculateOrigin().
1713 << "%43 = OpFunction %11 None %39\n"
1714 << "%40 = OpFunctionParameter %12\n"
1715 << "%41 = OpFunctionParameter %12\n"
1716 << "%42 = OpFunctionParameter %12\n"
1717 << "%44 = OpLabel\n"
1718 << "%79 = OpLoad %11 %40\n"
1719 << "%85 = OpAccessChain %84 %82 %83\n"
1720 << "%86 = OpLoad %8 %85\n"
1721 << "%87 = OpConvertUToF %10 %86\n"
1722 << "%89 = OpAccessChain %84 %88 %83\n"
1723 << "%90 = OpLoad %8 %89\n"
1724 << "%92 = OpISub %8 %90 %91\n"
1725 << "%93 = OpConvertUToF %10 %92\n"
1726 << "%94 = OpFDiv %10 %87 %93\n"
1727 << "%95 = OpLoad %11 %41\n"
1728 << "%96 = OpVectorTimesScalar %11 %95 %94\n"
1729 << "%97 = OpFAdd %11 %79 %96\n"
1730 << "%98 = OpAccessChain %84 %82 %91\n"
1731 << "%99 = OpLoad %8 %98\n"
1732 << "%100 = OpConvertUToF %10 %99\n"
1733 << "%101 = OpAccessChain %84 %88 %91\n"
1734 << "%102 = OpLoad %8 %101\n"
1735 << "%103 = OpISub %8 %102 %91\n"
1736 << "%104 = OpConvertUToF %10 %103\n"
1737 << "%105 = OpFDiv %10 %100 %104\n"
1738 << "%106 = OpLoad %11 %42\n"
1739 << "%107 = OpVectorTimesScalar %11 %106 %105\n"
1740 << "%108 = OpFAdd %11 %97 %107\n"
1741 << "OpReturnValue %108\n"
1742 << "OpFunctionEnd\n";
1743
1744 programCollection.spirvAsmSources.add("rgen_depth") << spvBuildOptions << rgen.str();
1745 }
1746
1747 // chit_depth and miss_depth below have been left untouched.
1748
1749 {
1750 std::stringstream css;
1751 css << "#version 460 core\n"
1752 "#extension GL_EXT_ray_tracing : require\n"
1753 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1754 "void main()\n"
1755 "{\n"
1756 " hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1757 "}\n";
1758
1759 programCollection.glslSources.add("chit_depth")
1760 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1761 }
1762
1763 {
1764 std::stringstream css;
1765 css << "#version 460 core\n"
1766 "#extension GL_EXT_ray_tracing : require\n"
1767 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1768 "void main()\n"
1769 "{\n"
1770 " hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1771 "}\n";
1772
1773 programCollection.glslSources.add("miss_depth")
1774 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1775 }
1776 }
1777
RayTracingASBasicTestInstance(Context & context,const TestParams & data)1778 RayTracingASBasicTestInstance::RayTracingASBasicTestInstance(Context &context, const TestParams &data)
1779 : vkt::TestInstance(context)
1780 , m_data(data)
1781 {
1782 }
1783
runTest(const uint32_t workerThreadsCount)1784 de::MovePtr<BufferWithMemory> RayTracingASBasicTestInstance::runTest(const uint32_t workerThreadsCount)
1785 {
1786 const InstanceInterface &vki = m_context.getInstanceInterface();
1787 const DeviceInterface &vkd = m_context.getDeviceInterface();
1788 const VkDevice device = m_context.getDevice();
1789 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1790 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1791 const VkQueue queue = m_context.getUniversalQueue();
1792 Allocator &allocator = m_context.getDefaultAllocator();
1793 const uint32_t pixelCount = m_data.width * m_data.height;
1794 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1795 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1796 const bool htCopy = (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
1797 const bool htSerialize = (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
1798
1799 const Move<VkDescriptorSetLayout> descriptorSetLayout =
1800 DescriptorSetLayoutBuilder()
1801 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1802 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1803 .build(vkd, device);
1804 const Move<VkDescriptorPool> descriptorPool =
1805 DescriptorPoolBuilder()
1806 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1807 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1808 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1809 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1810 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1811
1812 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1813 m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
1814 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1815
1816 de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
1817 de::MovePtr<BufferWithMemory> hitShaderBindingTable;
1818 de::MovePtr<BufferWithMemory> missShaderBindingTable;
1819 m_data.testConfiguration->initShaderBindingTables(
1820 rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment,
1821 raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
1822
1823 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
1824 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
1825 shaderGroupHandleSize, shaderGroupHandleSize);
1826 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
1827 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
1828 shaderGroupHandleSize, shaderGroupHandleSize);
1829 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
1830 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
1831 shaderGroupHandleSize, shaderGroupHandleSize);
1832 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
1833
1834 const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat();
1835 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
1836 const VkImageSubresourceRange imageSubresourceRange =
1837 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1838 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1839 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1840 const Move<VkImageView> imageView =
1841 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
1842
1843 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
1844 pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1845 const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
1846 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1847 const VkBufferImageCopy resultBufferImageRegion =
1848 makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
1849 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
1850 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1851
1852 const VkDescriptorImageInfo descriptorImageInfo =
1853 makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1854
1855 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1856 const Move<VkCommandBuffer> cmdBuffer =
1857 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1858
1859 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
1860 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1861 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
1862 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
1863 std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
1864 std::vector<de::SharedPtr<SerialStorage>> topSerialized;
1865 std::vector<VkDeviceSize> accelerationCompactedSizes;
1866 std::vector<VkDeviceSize> accelerationSerialSizes;
1867 Move<VkQueryPool> m_queryPoolCompact;
1868 Move<VkQueryPool> m_queryPoolSerial;
1869
1870 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1871 {
1872 const VkImageMemoryBarrier preImageBarrier =
1873 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1874 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1875 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1876 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1877 const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
1878 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1879 &imageSubresourceRange);
1880 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1881 VK_ACCESS_TRANSFER_WRITE_BIT,
1882 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1883 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1884 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1885 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1886
1887 // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1888 bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1889 bool bottomSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1890 const bool buildWithoutGeom = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
1891 const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
1892 const bool topNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
1893 const bool inactiveInstances = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
1894 bottomLevelAccelerationStructures =
1895 m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1896 VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
1897 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1898 VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
1899 VkBuildAccelerationStructureFlagsKHR bottomCompactFlags =
1900 (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1901 VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
1902 std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
1903 std::vector<VkDeviceSize> bottomBlasCompactSize;
1904 std::vector<VkDeviceSize> bottomBlasSerialSize;
1905
1906 for (auto &blas : bottomLevelAccelerationStructures)
1907 {
1908 blas->setBuildType(m_data.buildType);
1909 blas->setBuildFlags(bottomBuildFlags);
1910 blas->setUseArrayOfPointers(m_data.bottomUsesAOP);
1911 blas->setCreateGeneric(m_data.bottomGeneric);
1912 blas->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
1913 blas->setBuildWithoutGeometries(buildWithoutGeom);
1914 blas->setBuildWithoutPrimitives(bottomNoPrimitives);
1915 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
1916 accelerationStructureHandles.push_back(*(blas->getPtr()));
1917 }
1918
1919 if (m_data.operationType == OP_COMPACT)
1920 {
1921 uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1922 uint32_t(bottomLevelAccelerationStructures.size()) :
1923 1u;
1924 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1925 m_queryPoolCompact =
1926 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1927 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1928 queryAccelerationStructureSize(
1929 vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
1930 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1931 }
1932 if (m_data.operationType == OP_SERIALIZE)
1933 {
1934 uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1935 uint32_t(bottomLevelAccelerationStructures.size()) :
1936 1u;
1937 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1938 m_queryPoolSerial =
1939 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1940 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1941 queryAccelerationStructureSize(
1942 vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
1943 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1944 }
1945
1946 // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1947 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1948 {
1949 endCommandBuffer(vkd, *cmdBuffer);
1950
1951 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1952
1953 if (bottomCompact)
1954 VK_CHECK(vkd.getQueryPoolResults(
1955 device, *m_queryPoolCompact, 0u, uint32_t(bottomBlasCompactSize.size()),
1956 sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(),
1957 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1958 if (bottomSerial)
1959 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(bottomBlasSerialSize.size()),
1960 sizeof(VkDeviceSize) * bottomBlasSerialSize.size(),
1961 bottomBlasSerialSize.data(), sizeof(VkDeviceSize),
1962 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1963
1964 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1965 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1966 }
1967
1968 auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
1969 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1970 {
1971 switch (m_data.operationType)
1972 {
1973 case OP_COPY:
1974 {
1975 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1976 {
1977 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1978 asCopy->setDeferredOperation(htCopy, workerThreadsCount);
1979 asCopy->setBuildType(m_data.buildType);
1980 asCopy->setBuildFlags(m_data.buildFlags);
1981 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1982 asCopy->setCreateGeneric(m_data.bottomGeneric);
1983 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
1984 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1985 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1986 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
1987 bottomLevelAccelerationStructures[i].get(), 0u, 0u);
1988 bottomLevelAccelerationStructureCopies.push_back(
1989 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1990 }
1991 break;
1992 }
1993 case OP_COMPACT:
1994 {
1995 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1996 {
1997 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1998 asCopy->setBuildType(m_data.buildType);
1999 asCopy->setBuildFlags(m_data.buildFlags);
2000 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2001 asCopy->setCreateGeneric(m_data.bottomGeneric);
2002 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2003 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2004 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2005 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2006 bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
2007 bottomLevelAccelerationStructureCopies.push_back(
2008 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2009 }
2010 break;
2011 }
2012 case OP_SERIALIZE:
2013 {
2014 //bottomLevelAccelerationStructureCopies = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
2015 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2016 {
2017 de::SharedPtr<SerialStorage> storage(
2018 new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
2019
2020 bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
2021 bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
2022 bottomSerialized.push_back(storage);
2023
2024 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2025 {
2026 endCommandBuffer(vkd, *cmdBuffer);
2027
2028 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2029
2030 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2031 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2032 }
2033
2034 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2035 asCopy->setBuildType(m_data.buildType);
2036 asCopy->setBuildFlags(m_data.buildFlags);
2037 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2038 asCopy->setCreateGeneric(m_data.bottomGeneric);
2039 asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2040 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2041 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2042 asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2043 asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
2044 bottomLevelAccelerationStructureCopies.push_back(
2045 de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2046 }
2047 break;
2048 }
2049 default:
2050 DE_ASSERT(false);
2051 }
2052 bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
2053 }
2054
2055 // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
2056 bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
2057 bool topSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
2058 VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
2059 VkBuildAccelerationStructureFlagsKHR topBuildFlags = m_data.buildFlags | topCompactFlags;
2060 std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
2061 std::vector<VkDeviceSize> topBlasCompactSize;
2062 std::vector<VkDeviceSize> topBlasSerialSize;
2063
2064 topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(
2065 m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2066 topLevelAccelerationStructure->setBuildType(m_data.buildType);
2067 topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
2068 topLevelAccelerationStructure->setBuildWithoutPrimitives(topNoPrimitives);
2069 topLevelAccelerationStructure->setUseArrayOfPointers(m_data.topUsesAOP);
2070 topLevelAccelerationStructure->setCreateGeneric(m_data.topGeneric);
2071 topLevelAccelerationStructure->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2072 topLevelAccelerationStructure->setInactiveInstances(inactiveInstances);
2073 topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
2074 topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
2075
2076 if (topCompact)
2077 queryAccelerationStructureSize(
2078 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
2079 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
2080 if (topSerial)
2081 queryAccelerationStructureSize(
2082 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
2083 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
2084
2085 // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
2086 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
2087 {
2088 endCommandBuffer(vkd, *cmdBuffer);
2089
2090 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2091
2092 if (topCompact)
2093 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, uint32_t(topBlasCompactSize.size()),
2094 sizeof(VkDeviceSize) * topBlasCompactSize.size(),
2095 topBlasCompactSize.data(), sizeof(VkDeviceSize),
2096 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2097 if (topSerial)
2098 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(topBlasSerialSize.size()),
2099 sizeof(VkDeviceSize) * topBlasSerialSize.size(),
2100 topBlasSerialSize.data(), sizeof(VkDeviceSize),
2101 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2102
2103 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2104 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2105 }
2106
2107 const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
2108 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
2109 {
2110 switch (m_data.operationType)
2111 {
2112 case OP_COPY:
2113 {
2114 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2115 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2116 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2117 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2118 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2119 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2120 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2121 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2122 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2123 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2124 topLevelAccelerationStructure.get(), 0u, 0u);
2125 break;
2126 }
2127 case OP_COMPACT:
2128 {
2129 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2130 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2131 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2132 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2133 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2134 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2135 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2136 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2137 topLevelAccelerationStructureCopy->createAndCopyFrom(
2138 vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
2139 break;
2140 }
2141 case OP_SERIALIZE:
2142 {
2143 de::SharedPtr<SerialStorage> storage = de::SharedPtr<SerialStorage>(
2144 new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
2145
2146 topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
2147 topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
2148 topSerialized.push_back(storage);
2149
2150 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2151 {
2152 endCommandBuffer(vkd, *cmdBuffer);
2153
2154 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2155
2156 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2157 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2158 }
2159
2160 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2161 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2162 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2163 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2164 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2165 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2166 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2167 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2168 topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2169 topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator,
2170 storage.get(), 0u);
2171 break;
2172 }
2173 case OP_UPDATE:
2174 {
2175 topLevelAccelerationStructureCopy = m_data.testConfiguration->initTopAccelerationStructure(
2176 m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2177 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2178 topLevelAccelerationStructureCopy->create(vkd, device, allocator, 0u, 0u);
2179 // Update AS based on topLevelAccelerationStructure
2180 topLevelAccelerationStructureCopy->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2181 break;
2182 }
2183 case OP_UPDATE_IN_PLACE:
2184 {
2185 // Update in place
2186 topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2187 // Make a coppy
2188 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2189 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2190 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2191 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2192 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2193 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2194 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2195 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2196 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2197 topLevelAccelerationStructure.get(), 0u, 0u);
2198 break;
2199 }
2200 default:
2201 DE_ASSERT(false);
2202 }
2203 topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
2204 }
2205
2206 const VkMemoryBarrier preTraceMemoryBarrier =
2207 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
2208 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2209 VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
2210
2211 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
2212 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
2213 nullptr, // const void* pNext;
2214 1u, // uint32_t accelerationStructureCount;
2215 topLevelRayTracedPtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
2216 };
2217
2218 DescriptorSetUpdateBuilder()
2219 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
2220 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
2221 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
2222 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
2223 .update(vkd, device);
2224
2225 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
2226 &descriptorSet.get(), 0, nullptr);
2227
2228 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2229
2230 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
2231 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
2232
2233 const VkMemoryBarrier postTraceMemoryBarrier =
2234 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2235 const VkMemoryBarrier postCopyMemoryBarrier =
2236 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2237 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
2238 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2239
2240 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
2241 &resultBufferImageRegion);
2242
2243 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2244 &postCopyMemoryBarrier);
2245 }
2246 endCommandBuffer(vkd, *cmdBuffer);
2247
2248 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2249
2250 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
2251 resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t));
2252
2253 return resultBuffer;
2254 }
2255
iterateNoWorkers(void)2256 bool RayTracingASBasicTestInstance::iterateNoWorkers(void)
2257 {
2258 // run test using arrays of pointers
2259 const de::MovePtr<BufferWithMemory> buffer = runTest(0);
2260
2261 return m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data);
2262 }
2263
iterateWithWorkers(void)2264 bool RayTracingASBasicTestInstance::iterateWithWorkers(void)
2265 {
2266 de::MovePtr<BufferWithMemory> singleThreadBufferCPU = runTest(0);
2267 const bool singleThreadValidation =
2268 m_data.testConfiguration->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
2269
2270 de::MovePtr<BufferWithMemory> multiThreadBufferCPU = runTest(m_data.workerThreadsCount);
2271 const bool multiThreadValidation =
2272 m_data.testConfiguration->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
2273
2274 const uint32_t result = singleThreadValidation && multiThreadValidation;
2275
2276 return result;
2277 }
2278
iterate(void)2279 tcu::TestStatus RayTracingASBasicTestInstance::iterate(void)
2280 {
2281 bool result;
2282
2283 if (m_data.workerThreadsCount != 0)
2284 result = iterateWithWorkers();
2285 else
2286 result = iterateNoWorkers();
2287
2288 if (result)
2289 return tcu::TestStatus::pass("Pass");
2290 else
2291 return tcu::TestStatus::fail("Fail");
2292 }
2293
2294 // Tests dynamic indexing of acceleration structures
2295 class RayTracingASDynamicIndexingTestCase : public TestCase
2296 {
2297 public:
2298 RayTracingASDynamicIndexingTestCase(tcu::TestContext &context, const char *name);
2299 ~RayTracingASDynamicIndexingTestCase(void) = default;
2300
2301 void checkSupport(Context &context) const override;
2302 void initPrograms(SourceCollections &programCollection) const override;
2303 TestInstance *createInstance(Context &context) const override;
2304 };
2305
2306 class RayTracingASDynamicIndexingTestInstance : public TestInstance
2307 {
2308 public:
2309 RayTracingASDynamicIndexingTestInstance(Context &context);
2310 ~RayTracingASDynamicIndexingTestInstance(void) = default;
2311 tcu::TestStatus iterate(void) override;
2312 };
2313
RayTracingASDynamicIndexingTestCase(tcu::TestContext & context,const char * name)2314 RayTracingASDynamicIndexingTestCase::RayTracingASDynamicIndexingTestCase(tcu::TestContext &context, const char *name)
2315 : TestCase(context, name)
2316 {
2317 }
2318
checkSupport(Context & context) const2319 void RayTracingASDynamicIndexingTestCase::checkSupport(Context &context) const
2320 {
2321 commonASTestsCheckSupport(context);
2322 context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
2323 }
2324
initPrograms(SourceCollections & programCollection) const2325 void RayTracingASDynamicIndexingTestCase::initPrograms(SourceCollections &programCollection) const
2326 {
2327 const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2328 const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2329
2330 // raygen shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
2331 // original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
2332 //
2333 // #version 460 core
2334 // #extension GL_EXT_ray_tracing : require
2335 // #extension GL_EXT_nonuniform_qualifier : enable
2336 // #define ARRAY_SIZE 500
2337 // layout(location = 0) rayPayloadEXT uvec2 payload; // offset and flag indicating if we are using descriptors or pointers
2338
2339 // layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
2340 // layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
2341 // uvec2 ptr[];
2342 // } tlasPointers;
2343 // layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
2344 // uint idx[];
2345 // } tlasIndices;
2346 // layout(set = 0, binding = 3, std430) writeonly buffer Result {
2347 // uint value[];
2348 // } result;
2349
2350 // void main()
2351 // {
2352 // float tmin = 0.0;\n"
2353 // float tmax = 2.0;\n"
2354 // vec3 origin = vec3(0.25f, 0.5f, 1.0);\n"
2355 // vec3 direction = vec3(0.0,0.0,-1.0);\n"
2356 // uint activeTlasIndex = gl_LaunchIDEXT.x;\n"
2357 // uint activeTlasCount = gl_LaunchSizeEXT.x;\n"
2358 // uint tlasIndex = tlasIndices.idx[nonuniformEXT(activeTlasIndex)];\n"
2359
2360 // atomicAdd(result.value[nonuniformEXT(activeTlasIndex)], 2);\n"
2361 // payload = uvec2(activeTlasIndex + activeTlasCount.x, 0);\n"
2362 // traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
2363
2364 // atomicAdd(result.value[nonuniformEXT(activeTlasIndex + activeTlasCount * 2)], 5);\n"
2365 // payload = uvec2(activeTlasIndex + activeTlasCount * 3, 1);\n"
2366 // traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0); // used to generate initial spirv
2367 // //traceRayEXT(*tlasPointers.ptr[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0); // not available in glsl but should be done in spirv
2368 // };
2369
2370 const std::string rgenSource =
2371 "OpCapability RayTracingKHR\n"
2372 "OpCapability ShaderNonUniform\n"
2373 "OpExtension \"SPV_EXT_descriptor_indexing\"\n"
2374 "OpExtension \"SPV_KHR_ray_tracing\"\n"
2375 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2376 "OpMemoryModel Logical GLSL450\n"
2377 "OpEntryPoint RayGenerationKHR %4 \"main\" %27 %33 %var_tlas_indices %var_result %60 %var_as_arr_ptr "
2378 "%var_as_pointers_ssbo\n"
2379 "OpDecorate %27 BuiltIn LaunchIdNV\n"
2380 "OpDecorate %33 BuiltIn LaunchSizeNV\n"
2381 "OpDecorate %37 ArrayStride 4\n"
2382 "OpMemberDecorate %38 0 NonWritable\n"
2383 "OpMemberDecorate %38 0 Offset 0\n"
2384 "OpDecorate %38 Block\n"
2385 "OpDecorate %var_tlas_indices DescriptorSet 0\n"
2386 "OpDecorate %var_tlas_indices Binding 2\n"
2387 "OpDecorate %44 NonUniform\n"
2388 "OpDecorate %46 NonUniform\n"
2389 "OpDecorate %47 NonUniform\n"
2390 "OpDecorate %48 ArrayStride 4\n"
2391 "OpMemberDecorate %49 0 NonReadable\n"
2392 "OpMemberDecorate %49 0 Offset 0\n"
2393 "OpDecorate %49 Block\n"
2394 "OpDecorate %var_result DescriptorSet 0\n"
2395 "OpDecorate %var_result Binding 3\n"
2396 "OpDecorate %53 NonUniform\n"
2397 "OpDecorate %60 Location 0\n"
2398 "OpDecorate %var_as_arr_ptr DescriptorSet 0\n"
2399 "OpDecorate %var_as_arr_ptr Binding 0\n"
2400 "OpDecorate %71 NonUniform\n"
2401 "OpDecorate %73 NonUniform\n"
2402 "OpDecorate %74 NonUniform\n"
2403 "OpDecorate %85 NonUniform\n"
2404 "OpDecorate %as_index NonUniform\n"
2405 "OpDecorate %as_device_addres NonUniform\n"
2406 "OpDecorate %104 ArrayStride 8\n"
2407 "OpMemberDecorate %105 0 NonWritable\n"
2408 "OpMemberDecorate %105 0 Offset 0\n"
2409 "OpDecorate %105 Block\n"
2410 "OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
2411 "OpDecorate %var_as_pointers_ssbo Binding 1\n"
2412 // types, constants and variables
2413 "%2 = OpTypeVoid\n"
2414 "%3 = OpTypeFunction %2\n"
2415 "%6 = OpTypeFloat 32\n"
2416 "%7 = OpTypePointer Function %6\n"
2417 "%9 = OpConstant %6 0\n"
2418 "%11 = OpConstant %6 2\n"
2419 "%12 = OpTypeVector %6 3\n"
2420 "%13 = OpTypePointer Function %12\n"
2421 "%15 = OpConstant %6 0.25\n"
2422 "%16 = OpConstant %6 0.5\n"
2423 "%17 = OpConstant %6 1\n"
2424 "%18 = OpConstantComposite %12 %15 %16 %17\n"
2425 "%20 = OpConstant %6 -1\n"
2426 "%21 = OpConstantComposite %12 %9 %9 %20\n"
2427 "%type_uint32 = OpTypeInt 32 0\n"
2428 "%23 = OpTypePointer Function %type_uint32\n"
2429 "%25 = OpTypeVector %type_uint32 3\n"
2430 "%26 = OpTypePointer Input %25\n"
2431 "%27 = OpVariable %26 Input\n"
2432 "%28 = OpConstant %type_uint32 0\n"
2433 "%29 = OpTypePointer Input %type_uint32\n"
2434 "%33 = OpVariable %26 Input\n"
2435 "%37 = OpTypeRuntimeArray %type_uint32\n"
2436 "%38 = OpTypeStruct %37\n"
2437 "%39 = OpTypePointer StorageBuffer %38\n"
2438 "%var_tlas_indices = OpVariable %39 StorageBuffer\n"
2439 "%type_int32 = OpTypeInt 32 1\n"
2440 "%c_int32_0 = OpConstant %type_int32 0\n"
2441 "%45 = OpTypePointer StorageBuffer %type_uint32\n"
2442 "%48 = OpTypeRuntimeArray %type_uint32\n"
2443 "%49 = OpTypeStruct %48\n"
2444 "%50 = OpTypePointer StorageBuffer %49\n"
2445 "%var_result = OpVariable %50 StorageBuffer\n"
2446 "%55 = OpConstant %type_uint32 2\n"
2447 "%56 = OpConstant %type_uint32 1\n"
2448 "%58 = OpTypeVector %type_uint32 2\n"
2449 "%59 = OpTypePointer RayPayloadNV %58\n"
2450 "%60 = OpVariable %59 RayPayloadNV\n"
2451 "%type_as = OpTypeAccelerationStructureKHR\n"
2452 "%66 = OpConstant %type_uint32 500\n"
2453 "%67 = OpTypeArray %type_as %66\n"
2454 "%68 = OpTypePointer UniformConstant %67\n"
2455 "%var_as_arr_ptr = OpVariable %68 UniformConstant\n"
2456 "%72 = OpTypePointer UniformConstant %type_as\n"
2457 "%75 = OpConstant %type_uint32 16\n"
2458 "%76 = OpConstant %type_uint32 255\n"
2459 "%87 = OpConstant %type_uint32 5\n"
2460 "%91 = OpConstant %type_uint32 3\n"
2461
2462 // <changed_section>
2463 "%104 = OpTypeRuntimeArray %58\n"
2464 "%105 = OpTypeStruct %104\n"
2465 "%106 = OpTypePointer StorageBuffer %105\n"
2466 "%var_as_pointers_ssbo = OpVariable %106 StorageBuffer\n"
2467 "%type_uint64_ssbo_ptr = OpTypePointer StorageBuffer %58\n"
2468 // </changed_section>
2469
2470 // void main()
2471 "%4 = OpFunction %2 None %3\n"
2472 "%5 = OpLabel\n"
2473 "%8 = OpVariable %7 Function\n"
2474 "%10 = OpVariable %7 Function\n"
2475 "%14 = OpVariable %13 Function\n"
2476 "%19 = OpVariable %13 Function\n"
2477 "%24 = OpVariable %23 Function\n"
2478 "%32 = OpVariable %23 Function\n"
2479 "%36 = OpVariable %23 Function\n"
2480 "OpStore %8 %9\n"
2481 "OpStore %10 %11\n"
2482 "OpStore %14 %18\n"
2483 "OpStore %19 %21\n"
2484 "%30 = OpAccessChain %29 %27 %28\n"
2485 "%31 = OpLoad %type_uint32 %30\n"
2486 "OpStore %24 %31\n"
2487 "%34 = OpAccessChain %29 %33 %28\n"
2488 "%35 = OpLoad %type_uint32 %34\n"
2489 "OpStore %32 %35\n"
2490 "%43 = OpLoad %type_uint32 %24\n"
2491 "%44 = OpCopyObject %type_uint32 %43\n"
2492 "%46 = OpAccessChain %45 %var_tlas_indices %c_int32_0 %44\n"
2493 "%47 = OpLoad %type_uint32 %46\n"
2494 "OpStore %36 %47\n"
2495 // atomicAdd
2496 "%52 = OpLoad %type_uint32 %24\n"
2497 "%53 = OpCopyObject %type_uint32 %52\n"
2498 "%54 = OpAccessChain %45 %var_result %c_int32_0 %53\n"
2499 "%57 = OpAtomicIAdd %type_uint32 %54 %56 %28 %55\n"
2500 // setup payload
2501 "%61 = OpLoad %type_uint32 %24\n"
2502 "%62 = OpLoad %type_uint32 %32\n"
2503 "%63 = OpIAdd %type_uint32 %61 %62\n"
2504 "%64 = OpCompositeConstruct %58 %63 %28\n"
2505 "OpStore %60 %64\n"
2506 // trace rays using tlas from array
2507 "%70 = OpLoad %type_uint32 %36\n"
2508 "%71 = OpCopyObject %type_uint32 %70\n"
2509 "%73 = OpAccessChain %72 %var_as_arr_ptr %71\n"
2510 "%74 = OpLoad %type_as %73\n"
2511 "%77 = OpLoad %12 %14\n"
2512 "%78 = OpLoad %6 %8\n"
2513 "%79 = OpLoad %12 %19\n"
2514 "%80 = OpLoad %6 %10\n"
2515 "OpTraceRayKHR %74 %75 %76 %28 %28 %28 %77 %78 %79 %80 %60\n"
2516 // atomicAdd
2517 "%81 = OpLoad %type_uint32 %24\n"
2518 "%82 = OpLoad %type_uint32 %32\n"
2519 "%83 = OpIMul %type_uint32 %82 %55\n"
2520 "%84 = OpIAdd %type_uint32 %81 %83\n"
2521 "%85 = OpCopyObject %type_uint32 %84\n"
2522 "%86 = OpAccessChain %45 %var_result %c_int32_0 %85\n"
2523 "%88 = OpAtomicIAdd %type_uint32 %86 %56 %28 %87\n"
2524 // setup payload
2525 "%89 = OpLoad %type_uint32 %24\n"
2526 "%90 = OpLoad %type_uint32 %32\n"
2527 "%92 = OpIMul %type_uint32 %90 %91\n"
2528 "%93 = OpIAdd %type_uint32 %89 %92\n"
2529 "%94 = OpCompositeConstruct %58 %93 %56\n"
2530 "OpStore %60 %94\n"
2531 // trace rays using pointers to tlas
2532 "%95 = OpLoad %type_uint32 %36\n"
2533 "%as_index = OpCopyObject %type_uint32 %95\n"
2534
2535 // <changed_section> OLD
2536 "%as_device_addres_ptr = OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 "
2537 "%as_index\n"
2538 "%as_device_addres = OpLoad %58 %as_device_addres_ptr\n"
2539 "%as_to_use = OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
2540 // </changed_section>
2541
2542 "%99 = OpLoad %12 %14\n"
2543 "%100 = OpLoad %6 %8\n"
2544 "%101 = OpLoad %12 %19\n"
2545 "%102 = OpLoad %6 %10\n"
2546 "OpTraceRayKHR %as_to_use %75 %76 %28 %28 %28 %99 %100 %101 %102 %60\n"
2547 "OpReturn\n"
2548 "OpFunctionEnd\n";
2549 programCollection.spirvAsmSources.add("rgen") << rgenSource << spvBuildOptions;
2550
2551 std::string chitSource = "#version 460 core\n"
2552 "#extension GL_EXT_ray_tracing : require\n"
2553 "#extension GL_EXT_nonuniform_qualifier : enable\n"
2554 "layout(location = 0) rayPayloadInEXT uvec2 payload;\n"
2555 "\n"
2556 "layout(set = 0, binding = 3) writeonly buffer Result {\n"
2557 " uint value[];\n"
2558 "} result;\n"
2559 "void main()\n"
2560 "{\n"
2561 // payload.y is 0 or 1 so we will add 3 or 7 (just two prime numbers)
2562 " atomicAdd(result.value[nonuniformEXT(payload.x)], 3 + payload.y * 4);\n"
2563 "}\n";
2564 programCollection.glslSources.add("chit") << glu::ClosestHitSource(chitSource) << glslBuildOptions;
2565 }
2566
createInstance(Context & context) const2567 TestInstance *RayTracingASDynamicIndexingTestCase::createInstance(Context &context) const
2568 {
2569 return new RayTracingASDynamicIndexingTestInstance(context);
2570 }
2571
RayTracingASDynamicIndexingTestInstance(Context & context)2572 RayTracingASDynamicIndexingTestInstance::RayTracingASDynamicIndexingTestInstance(Context &context)
2573 : vkt::TestInstance(context)
2574 {
2575 }
2576
iterate(void)2577 tcu::TestStatus RayTracingASDynamicIndexingTestInstance::iterate(void)
2578 {
2579 const InstanceInterface &vki = m_context.getInstanceInterface();
2580 const DeviceInterface &vkd = m_context.getDeviceInterface();
2581 const VkDevice device = m_context.getDevice();
2582 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
2583 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2584 const VkQueue queue = m_context.getUniversalQueue();
2585 Allocator &allocator = m_context.getDefaultAllocator();
2586 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
2587 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
2588 const uint32_t tlasCount = 500; // changing this will require also changing shaders
2589 const uint32_t activeTlasCount = 32; // number of tlas out of <tlasCount> that will be active
2590
2591 const Move<VkDescriptorSetLayout> descriptorSetLayout =
2592 DescriptorSetLayoutBuilder()
2593 .addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, ALL_RAY_TRACING_STAGES)
2594 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2595 ALL_RAY_TRACING_STAGES) // pointers to all acceleration structures
2596 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2597 ALL_RAY_TRACING_STAGES) // ssbo with indices of all acceleration structures
2598 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES) // ssbo with result values
2599 .build(vkd, device);
2600
2601 const Move<VkDescriptorPool> descriptorPool =
2602 DescriptorPoolBuilder()
2603 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
2604 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2605 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2606 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2607 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2608 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
2609
2610 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
2611 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
2612 createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
2613 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
2614 createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
2615
2616 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
2617 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
2618 de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
2619 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
2620 de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
2621 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
2622
2623 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
2624 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
2625 shaderGroupHandleSize, shaderGroupHandleSize);
2626 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2627 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
2628 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
2629 shaderGroupHandleSize, shaderGroupHandleSize);
2630 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2631
2632 const VkDeviceSize pointerBufferSize = tlasCount * sizeof(VkDeviceAddress);
2633 const VkBufferCreateInfo pointerBufferCreateInfo =
2634 makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2635 de::MovePtr<BufferWithMemory> pointerBuffer = de::MovePtr<BufferWithMemory>(
2636 new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo,
2637 MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
2638
2639 const VkDeviceSize indicesBufferSize = activeTlasCount * sizeof(uint32_t);
2640 const VkBufferCreateInfo indicesBufferCreateInfo =
2641 makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2642 de::MovePtr<BufferWithMemory> indicesBuffer = de::MovePtr<BufferWithMemory>(
2643 new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
2644
2645 const VkDeviceSize resultBufferSize = activeTlasCount * sizeof(uint32_t) * 4;
2646 const VkBufferCreateInfo resultBufferCreateInfo =
2647 makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2648 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
2649 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2650
2651 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
2652 const Move<VkCommandBuffer> cmdBuffer =
2653 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2654
2655 de::SharedPtr<BottomLevelAccelerationStructure> blas =
2656 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
2657 std::vector<de::MovePtr<TopLevelAccelerationStructure>> tlasVect(tlasCount);
2658 std::vector<VkDeviceAddress> tlasPtrVect(tlasCount);
2659 std::vector<VkAccelerationStructureKHR> tlasVkVect;
2660
2661 // randomly scatter active AS across the range
2662 deRandom rnd;
2663 deRandom_init(&rnd, 123);
2664 std::set<uint32_t> asIndicesSet;
2665 while (asIndicesSet.size() < activeTlasCount)
2666 asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
2667
2668 // fill indices buffer
2669 uint32_t helperIndex = 0;
2670 auto &indicesBufferAlloc = indicesBuffer->getAllocation();
2671 uint32_t *indicesBufferPtr = reinterpret_cast<uint32_t *>(indicesBufferAlloc.getHostPtr());
2672 std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
2673 [&helperIndex, indicesBufferPtr](const uint32_t &index) { indicesBufferPtr[helperIndex++] = index; });
2674 vk::flushAlloc(vkd, device, indicesBufferAlloc);
2675
2676 // clear result buffer
2677 auto &resultBufferAlloc = resultBuffer->getAllocation();
2678 void *resultBufferPtr = resultBufferAlloc.getHostPtr();
2679 deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
2680 vk::flushAlloc(vkd, device, resultBufferAlloc);
2681
2682 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2683 {
2684 // build bottom level acceleration structure
2685 blas->setGeometryData(
2686 {
2687 {0.0, 0.0, 0.0},
2688 {1.0, 0.0, 0.0},
2689 {0.0, 1.0, 0.0},
2690 },
2691 true, VK_GEOMETRY_OPAQUE_BIT_KHR);
2692
2693 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2694
2695 // build top level acceleration structures
2696 for (uint32_t tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
2697 {
2698 auto &tlas = tlasVect[tlasIndex];
2699 tlas = makeTopLevelAccelerationStructure();
2700 tlas->setInstanceCount(1);
2701 tlas->addInstance(blas);
2702 if (!asIndicesSet.count(tlasIndex))
2703 {
2704 // tlas that are not in asIndicesSet should be empty but it is hard to do
2705 // that with current cts utils so we are marking them as inactive instead
2706 tlas->setInactiveInstances(true);
2707 }
2708 tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2709
2710 // get acceleration structure device address
2711 const VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {
2712 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType
2713 nullptr, // const void* pNext
2714 *tlas->getPtr() // VkAccelerationStructureKHR accelerationStructure
2715 };
2716 VkDeviceAddress vkda = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
2717 tlasPtrVect[tlasIndex] = vkda;
2718 }
2719
2720 // fill pointer buffer
2721 vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
2722
2723 // wait for data transfers
2724 const VkMemoryBarrier bufferUploadBarrier =
2725 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
2726 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2727 VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &bufferUploadBarrier, 1u);
2728
2729 // wait for as build
2730 const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
2731 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
2732 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
2733 VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &asBuildBarrier, 1u);
2734
2735 tlasVkVect.reserve(tlasCount);
2736 for (auto &tlas : tlasVect)
2737 tlasVkVect.push_back(*tlas->getPtr());
2738
2739 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
2740 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
2741 nullptr, // const void* pNext;
2742 tlasCount, // uint32_t accelerationStructureCount;
2743 tlasVkVect.data(), // const VkAccelerationStructureKHR* pAccelerationStructures;
2744 };
2745
2746 const vk::VkDescriptorBufferInfo pointerBufferInfo =
2747 makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
2748 const vk::VkDescriptorBufferInfo indicesBufferInfo =
2749 makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
2750 const vk::VkDescriptorBufferInfo resultInfo = makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE);
2751
2752 DescriptorSetUpdateBuilder()
2753 .writeArray(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
2754 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount,
2755 &accelerationStructureWriteDescriptorSet)
2756 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
2757 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
2758 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
2759 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
2760 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u),
2761 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
2762 .update(vkd, device);
2763
2764 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
2765 &descriptorSet.get(), 0, nullptr);
2766
2767 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2768
2769 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
2770 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, activeTlasCount, 1, 1);
2771
2772 const VkMemoryBarrier postTraceMemoryBarrier =
2773 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2774 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
2775 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2776 }
2777 endCommandBuffer(vkd, *cmdBuffer);
2778
2779 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2780
2781 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
2782 resultBuffer->getAllocation().getOffset(), resultBufferSize);
2783
2784 // verify result buffer
2785 uint32_t failures = 0;
2786 const uint32_t *resultPtr = reinterpret_cast<uint32_t *>(resultBuffer->getAllocation().getHostPtr());
2787 for (uint32_t index = 0; index < activeTlasCount; ++index)
2788 {
2789 failures += (resultPtr[0 * activeTlasCount + index] != 2) + (resultPtr[1 * activeTlasCount + index] != 3) +
2790 (resultPtr[2 * activeTlasCount + index] != 5) + (resultPtr[3 * activeTlasCount + index] != 7);
2791 }
2792
2793 if (failures)
2794 return tcu::TestStatus::fail(de::toString(failures) + " failures, " +
2795 de::toString(4 * activeTlasCount - failures) + " are ok");
2796 return tcu::TestStatus::pass("Pass");
2797 }
2798
2799 // Tests the vkGetDeviceAccelerationStructureKHR routine
2800 class RayTracingDeviceASCompabilityKHRTestInstance : public TestInstance
2801 {
2802 public:
RayTracingDeviceASCompabilityKHRTestInstance(Context & context,const de::SharedPtr<TestParams> params)2803 RayTracingDeviceASCompabilityKHRTestInstance(Context &context, const de::SharedPtr<TestParams> params)
2804 : TestInstance(context)
2805 , m_params(params)
2806 {
2807 }
2808
2809 tcu::TestStatus iterate(void) override;
2810
2811 protected:
2812 template <class ASType>
2813 bool performTest(VkCommandPool cmdPool, VkCommandBuffer cmdBuffer,
2814 const std::vector<de::SharedPtr<ASType>> sourceStructures,
2815 const std::vector<VkDeviceSize> ©Sizes, const std::vector<VkDeviceSize> &compactSizes);
2816
2817 VkAccelerationStructureCompatibilityKHR getDeviceASCompatibilityKHR(const uint8_t *versionInfoData);
2818 std::string getUUIDsString(const uint8_t *header) const;
2819
2820 private:
2821 const de::SharedPtr<TestParams> m_params;
2822 };
2823
2824 // Tests for updating botto-level AS(s) address(es) in top-level AS's header
2825 class RayTracingHeaderBottomAddressTestInstance : public TestInstance
2826 {
2827 public:
RayTracingHeaderBottomAddressTestInstance(Context & context,const de::SharedPtr<TestParams> params)2828 RayTracingHeaderBottomAddressTestInstance(Context &context, const de::SharedPtr<TestParams> params)
2829 : TestInstance(context)
2830 , m_params(params)
2831 {
2832 }
2833 tcu::TestStatus iterate(void) override;
2834
2835 protected:
2836 de::SharedPtr<TopLevelAccelerationStructure> prepareTopAccelerationStructure(const DeviceInterface &vk,
2837 VkDevice device, Allocator &allocator,
2838 VkCommandBuffer cmdBuffer);
2839
2840 bool areAddressesTheSame(const std::vector<uint64_t> &addresses,
2841 const SerialStorage::AccelerationStructureHeader *header);
2842
2843 bool areAddressesDifferent(const std::vector<uint64_t> &addresses1, const std::vector<uint64_t> &addresses2);
2844
2845 private:
2846 const de::SharedPtr<TestParams> m_params;
2847 };
2848
2849 class RayTracingDeviceASCompabilityKHRTestCase : public TestCase
2850 {
2851 public:
RayTracingDeviceASCompabilityKHRTestCase(tcu::TestContext & ctx,const char * name,const de::SharedPtr<TestParams> params)2852 RayTracingDeviceASCompabilityKHRTestCase(tcu::TestContext &ctx, const char *name,
2853 const de::SharedPtr<TestParams> params)
2854 : TestCase(ctx, name)
2855 , m_params(params)
2856 {
2857 }
2858
2859 void checkSupport(Context &context) const override;
createInstance(Context & context) const2860 TestInstance *createInstance(Context &context) const override
2861 {
2862 return new RayTracingDeviceASCompabilityKHRTestInstance(context, m_params);
2863 }
2864
2865 private:
2866 de::SharedPtr<TestParams> m_params;
2867 };
2868
2869 class RayTracingHeaderBottomAddressTestCase : public TestCase
2870 {
2871 public:
RayTracingHeaderBottomAddressTestCase(tcu::TestContext & ctx,const char * name,const de::SharedPtr<TestParams> params)2872 RayTracingHeaderBottomAddressTestCase(tcu::TestContext &ctx, const char *name,
2873 const de::SharedPtr<TestParams> params)
2874 : TestCase(ctx, name)
2875 , m_params(params)
2876 {
2877 }
2878
2879 void checkSupport(Context &context) const override;
createInstance(Context & context) const2880 TestInstance *createInstance(Context &context) const override
2881 {
2882 return new RayTracingHeaderBottomAddressTestInstance(context, m_params);
2883 }
2884
2885 private:
2886 de::SharedPtr<TestParams> m_params;
2887 };
2888
checkSupport(Context & context) const2889 void RayTracingDeviceASCompabilityKHRTestCase ::checkSupport(Context &context) const
2890 {
2891 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2892 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2893
2894 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
2895 context.getAccelerationStructureFeatures();
2896 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
2897 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
2898 TCU_THROW(NotSupportedError,
2899 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
2900
2901 // Check supported vertex format.
2902 checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
2903 m_params->vertexFormat);
2904 }
2905
checkSupport(Context & context) const2906 void RayTracingHeaderBottomAddressTestCase ::checkSupport(Context &context) const
2907 {
2908 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2909
2910 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
2911 context.getAccelerationStructureFeatures();
2912 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
2913 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
2914 TCU_THROW(NotSupportedError,
2915 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
2916
2917 // Check supported vertex format.
2918 checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
2919 m_params->vertexFormat);
2920 }
2921
getDeviceASCompatibilityKHR(const uint8_t * versionInfoData)2922 VkAccelerationStructureCompatibilityKHR RayTracingDeviceASCompabilityKHRTestInstance::getDeviceASCompatibilityKHR(
2923 const uint8_t *versionInfoData)
2924 {
2925 const VkDevice device = m_context.getDevice();
2926 const DeviceInterface &vkd = m_context.getDeviceInterface();
2927
2928 VkAccelerationStructureCompatibilityKHR compability = VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR;
2929
2930 const VkAccelerationStructureVersionInfoKHR versionInfo = {
2931 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR, // sType
2932 nullptr, // pNext
2933 versionInfoData // pVersionData
2934 };
2935
2936 vkd.getDeviceAccelerationStructureCompatibilityKHR(device, &versionInfo, &compability);
2937
2938 return compability;
2939 }
2940
getUUIDsString(const uint8_t * header) const2941 std::string RayTracingDeviceASCompabilityKHRTestInstance::getUUIDsString(const uint8_t *header) const
2942 {
2943 std::stringstream ss;
2944
2945 int offset = 0;
2946 const int widths[] = {4, 2, 2, 2, 6};
2947
2948 for (int h = 0; h < 2; ++h)
2949 {
2950 if (h)
2951 ss << ' ';
2952
2953 for (int w = 0; w < DE_LENGTH_OF_ARRAY(widths); ++w)
2954 {
2955 if (w)
2956 ss << '-';
2957
2958 for (int i = 0; i < widths[w]; ++i)
2959 ss << std::hex << std::uppercase << static_cast<int>(header[i + offset]);
2960
2961 offset += widths[w];
2962 }
2963 }
2964
2965 return ss.str();
2966 }
2967
iterate(void)2968 tcu::TestStatus RayTracingDeviceASCompabilityKHRTestInstance::iterate(void)
2969 {
2970 const DeviceInterface &vkd = m_context.getDeviceInterface();
2971 const VkDevice device = m_context.getDevice();
2972 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2973 const VkQueue queue = m_context.getUniversalQueue();
2974 Allocator &allocator = m_context.getDefaultAllocator();
2975
2976 const Move<VkCommandPool> cmdPool =
2977 createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2978 const Move<VkCommandBuffer> cmdBuffer =
2979 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2980
2981 bool result = false;
2982
2983 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomStructures;
2984 std::vector<VkAccelerationStructureKHR> bottomHandles;
2985 std::vector<de::SharedPtr<TopLevelAccelerationStructure>> topStructures;
2986 std::vector<VkAccelerationStructureKHR> topHandles;
2987 Move<VkQueryPool> queryPoolCompact;
2988 Move<VkQueryPool> queryPoolSerial;
2989 std::vector<VkDeviceSize> compactSizes;
2990 std::vector<VkDeviceSize> serialSizes;
2991
2992 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2993
2994 bottomStructures = m_params->testConfiguration->initBottomAccelerationStructures(m_context, *m_params);
2995 for (auto &blas : bottomStructures)
2996 {
2997 blas->setBuildType(m_params->buildType);
2998 blas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
2999 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3000 bottomHandles.push_back(*(blas->getPtr()));
3001 }
3002
3003 if (m_params->operationTarget == OT_TOP_ACCELERATION)
3004 {
3005 de::MovePtr<TopLevelAccelerationStructure> tlas =
3006 m_params->testConfiguration->initTopAccelerationStructure(m_context, *m_params, bottomStructures);
3007 tlas->setBuildType(m_params->buildType);
3008 tlas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3009 tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3010 topHandles.push_back(*(tlas->getPtr()));
3011 topStructures.push_back(de::SharedPtr<TopLevelAccelerationStructure>(tlas.release()));
3012 }
3013
3014 const uint32_t queryCount = uint32_t(
3015 (m_params->operationTarget == OT_BOTTOM_ACCELERATION) ? bottomStructures.size() : topStructures.size());
3016 const std::vector<VkAccelerationStructureKHR> &handles =
3017 (m_params->operationTarget == OT_BOTTOM_ACCELERATION) ? bottomHandles : topHandles;
3018
3019 // query compact size
3020 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3021 queryPoolCompact =
3022 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
3023 queryAccelerationStructureSize(vkd, device, *cmdBuffer, handles, m_params->buildType, *queryPoolCompact,
3024 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, compactSizes);
3025
3026 // query serialization size
3027 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3028 queryPoolSerial =
3029 makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
3030 queryAccelerationStructureSize(vkd, device, *cmdBuffer, handles, m_params->buildType, queryPoolSerial.get(),
3031 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, serialSizes);
3032
3033 endCommandBuffer(vkd, *cmdBuffer);
3034 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
3035
3036 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3037 {
3038 VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolCompact, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3039 compactSizes.data(), sizeof(VkDeviceSize),
3040 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3041 VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolSerial, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3042 serialSizes.data(), sizeof(VkDeviceSize),
3043 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3044
3045 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
3046 }
3047
3048 if (m_params->operationTarget == OT_BOTTOM_ACCELERATION)
3049 result = performTest<BottomLevelAccelerationStructure>(*cmdPool, *cmdBuffer, bottomStructures, compactSizes,
3050 serialSizes);
3051 else
3052 result =
3053 performTest<TopLevelAccelerationStructure>(*cmdPool, *cmdBuffer, topStructures, compactSizes, serialSizes);
3054
3055 return result ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
3056 }
3057
3058 template <class ASType>
performTest(VkCommandPool cmdPool,VkCommandBuffer cmdBuffer,const std::vector<de::SharedPtr<ASType>> sourceStructures,const std::vector<VkDeviceSize> & compactSizes,const std::vector<VkDeviceSize> & serialSizes)3059 bool RayTracingDeviceASCompabilityKHRTestInstance::performTest(
3060 VkCommandPool cmdPool, VkCommandBuffer cmdBuffer, const std::vector<de::SharedPtr<ASType>> sourceStructures,
3061 const std::vector<VkDeviceSize> &compactSizes, const std::vector<VkDeviceSize> &serialSizes)
3062 {
3063 const VkQueue queue = m_context.getUniversalQueue();
3064 const VkDevice device = m_context.getDevice();
3065 const DeviceInterface &vkd = m_context.getDeviceInterface();
3066 Allocator &allocator = m_context.getDefaultAllocator();
3067
3068 const uint32_t sourceStructuresCount = uint32_t(sourceStructures.size());
3069
3070 Move<VkQueryPool> queryPoolCompactSerial;
3071 std::vector<VkDeviceSize> compactSerialSizes;
3072
3073 std::vector<VkAccelerationStructureKHR> compactHandles;
3074 std::vector<de::SharedPtr<ASType>> compactStructures;
3075
3076 std::vector<de::SharedPtr<SerialStorage>> sourceSerialized;
3077 std::vector<de::SharedPtr<SerialStorage>> compactSerialized;
3078
3079 // make compact copy of acceleration structure
3080 {
3081 beginCommandBuffer(vkd, cmdBuffer, 0u);
3082
3083 for (size_t i = 0; i < sourceStructuresCount; ++i)
3084 {
3085 de::MovePtr<ASType> asCopy = makeAccelerationStructure<ASType>();
3086 asCopy->setBuildType(m_params->buildType);
3087 asCopy->createAndCopyFrom(vkd, device, cmdBuffer, allocator, sourceStructures[i].get(), compactSizes[i],
3088 0u);
3089 compactHandles.push_back(*(asCopy->getPtr()));
3090 compactStructures.push_back(de::SharedPtr<ASType>(asCopy.release()));
3091 }
3092
3093 // query serialization size of compact acceleration structures
3094 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3095 queryPoolCompactSerial = makeQueryPool(
3096 vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, sourceStructuresCount);
3097 queryAccelerationStructureSize(
3098 vkd, device, cmdBuffer, compactHandles, m_params->buildType, *queryPoolCompactSerial,
3099 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, compactSerialSizes);
3100
3101 endCommandBuffer(vkd, cmdBuffer);
3102 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3103
3104 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3105 {
3106 VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolCompactSerial, 0u, sourceStructuresCount,
3107 (sourceStructuresCount * sizeof(VkDeviceSize)), compactSerialSizes.data(),
3108 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3109 vkd.resetCommandPool(device, cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
3110 }
3111 }
3112
3113 // serialize both structures to memory
3114 {
3115 beginCommandBuffer(vkd, cmdBuffer, 0u);
3116
3117 for (size_t i = 0; i < sourceStructuresCount; ++i)
3118 {
3119 sourceSerialized.push_back(de::SharedPtr<SerialStorage>(
3120 new SerialStorage(vkd, device, allocator, m_params->buildType, serialSizes[i])));
3121 sourceStructures[i]->serialize(vkd, device, cmdBuffer, sourceSerialized.back().get());
3122
3123 compactSerialized.push_back(de::SharedPtr<SerialStorage>(
3124 new SerialStorage(vkd, device, allocator, m_params->buildType, compactSerialSizes[i])));
3125 compactStructures[i]->serialize(vkd, device, cmdBuffer, compactSerialized.back().get());
3126 }
3127
3128 endCommandBuffer(vkd, cmdBuffer);
3129 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3130 }
3131
3132 // verify compatibility
3133 bool result = true;
3134 for (size_t i = 0; result && (i < sourceStructuresCount); ++i)
3135 {
3136 const uint8_t *s_header = static_cast<const uint8_t *>(sourceSerialized[i]->getHostAddressConst().hostAddress);
3137 const uint8_t *c_header = static_cast<const uint8_t *>(compactSerialized[i]->getHostAddressConst().hostAddress);
3138
3139 const auto s_compability = getDeviceASCompatibilityKHR(s_header);
3140 const auto c_compability = getDeviceASCompatibilityKHR(c_header);
3141
3142 result &= ((s_compability == c_compability) &&
3143 (s_compability == VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR));
3144
3145 if (!result)
3146 {
3147 tcu::TestLog &log = m_context.getTestContext().getLog();
3148
3149 log << tcu::TestLog::Message << getUUIDsString(s_header) << " serialized AS compability failed"
3150 << tcu::TestLog::EndMessage;
3151 log << tcu::TestLog::Message << getUUIDsString(c_header) << " compact AS compability failed"
3152 << tcu::TestLog::EndMessage;
3153 }
3154 }
3155
3156 return result;
3157 }
3158
prepareTopAccelerationStructure(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer)3159 de::SharedPtr<TopLevelAccelerationStructure> RayTracingHeaderBottomAddressTestInstance::prepareTopAccelerationStructure(
3160 const DeviceInterface &vk, VkDevice device, Allocator &allocator, VkCommandBuffer cmdBuffer)
3161 {
3162 const std::vector<tcu::Vec3> geometryData = {
3163 {0.0, 0.0, 0.0},
3164 {1.0, 0.0, 0.0},
3165 {0.0, 1.0, 0.0},
3166 };
3167
3168 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottoms;
3169
3170 if (TopTestType::IDENTICAL_INSTANCES == m_params->topTestType)
3171 {
3172 auto blas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3173 blas->setBuildType(m_params->buildType);
3174 blas->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3175 blas->createAndBuild(vk, device, cmdBuffer, allocator);
3176 for (uint32_t i = 0; i < m_params->width; ++i)
3177 {
3178 bottoms.emplace_back(blas);
3179 }
3180 }
3181 else if (TopTestType::DIFFERENT_INSTANCES == m_params->topTestType)
3182 {
3183 for (uint32_t i = 0; i < m_params->width; ++i)
3184 {
3185 auto blas =
3186 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3187 blas->setBuildType(m_params->buildType);
3188 blas->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3189 blas->createAndBuild(vk, device, cmdBuffer, allocator);
3190 bottoms.emplace_back(blas);
3191 }
3192 }
3193 else // TTT_MIX_INSTANCES == m_params->topTestType
3194 {
3195 for (uint32_t i = 0; i < m_params->width; ++i)
3196 {
3197 {
3198 auto blas1 =
3199 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3200 blas1->setBuildType(m_params->buildType);
3201 blas1->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3202 blas1->createAndBuild(vk, device, cmdBuffer, allocator);
3203 bottoms.emplace_back(blas1);
3204 }
3205
3206 {
3207 auto blas2 =
3208 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3209 blas2->setBuildType(m_params->buildType);
3210 blas2->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3211 blas2->createAndBuild(vk, device, cmdBuffer, allocator);
3212 bottoms.emplace_back(blas2);
3213 }
3214 }
3215 }
3216
3217 const std::size_t instanceCount = bottoms.size();
3218
3219 de::MovePtr<TopLevelAccelerationStructure> tlas = makeTopLevelAccelerationStructure();
3220 tlas->setBuildType(m_params->buildType);
3221 tlas->setInstanceCount(instanceCount);
3222
3223 for (std::size_t i = 0; i < instanceCount; ++i)
3224 {
3225 const VkTransformMatrixKHR transformMatrixKHR = {{
3226 // float matrix[3][4];
3227 {1.0f, 0.0f, 0.0f, (float)i},
3228 {0.0f, 1.0f, 0.0f, (float)i},
3229 {0.0f, 0.0f, 1.0f, 0.0f},
3230 }};
3231 tlas->addInstance(bottoms[i], transformMatrixKHR, 0, m_params->cullMask, 0u,
3232 getCullFlags((m_params->cullFlags)));
3233 }
3234
3235 tlas->createAndBuild(vk, device, cmdBuffer, allocator);
3236
3237 return de::SharedPtr<TopLevelAccelerationStructure>(tlas.release());
3238 }
3239
iterate(void)3240 tcu::TestStatus RayTracingHeaderBottomAddressTestInstance::iterate(void)
3241 {
3242 const DeviceInterface &vkd = m_context.getDeviceInterface();
3243 const VkDevice device = m_context.getDevice();
3244 const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3245 const VkQueue queue = m_context.getUniversalQueue();
3246 Allocator &allocator = m_context.getDefaultAllocator();
3247
3248 const Move<VkCommandPool> cmdPool =
3249 createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3250 const Move<VkCommandBuffer> cmdBuffer =
3251 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3252
3253 beginCommandBuffer(vkd, *cmdBuffer, 0);
3254 de::SharedPtr<TopLevelAccelerationStructure> src =
3255 prepareTopAccelerationStructure(vkd, device, allocator, *cmdBuffer);
3256 endCommandBuffer(vkd, *cmdBuffer);
3257 submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3258
3259 de::MovePtr<TopLevelAccelerationStructure> dst = makeTopLevelAccelerationStructure();
3260
3261 const std::vector<uint64_t> inAddrs = src->getSerializingAddresses(vkd, device);
3262 const std::vector<VkDeviceSize> inSizes = src->getSerializingSizes(vkd, device, queue, familyIndex);
3263
3264 const SerialInfo serialInfo(inAddrs, inSizes);
3265 SerialStorage deepStorage(vkd, device, allocator, m_params->buildType, serialInfo);
3266
3267 // make deep serialization - top-level AS width bottom-level structures that it owns
3268 vkd.resetCommandBuffer(*cmdBuffer, 0);
3269 beginCommandBuffer(vkd, *cmdBuffer, 0);
3270 src->serialize(vkd, device, *cmdBuffer, &deepStorage);
3271 endCommandBuffer(vkd, *cmdBuffer);
3272 submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3273
3274 // deserialize all from the previous step to a new top-level AS
3275 // bottom-level structure addresses should be updated when deep data is deserialized
3276 vkd.resetCommandBuffer(*cmdBuffer, 0);
3277 beginCommandBuffer(vkd, *cmdBuffer, 0);
3278 dst->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, &deepStorage);
3279 endCommandBuffer(vkd, *cmdBuffer);
3280 submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3281
3282 SerialStorage shallowStorage(vkd, device, allocator, m_params->buildType, inSizes[0]);
3283
3284 // make shallow serialization - only top-level AS without bottom-level structures
3285 vkd.resetCommandBuffer(*cmdBuffer, 0);
3286 beginCommandBuffer(vkd, *cmdBuffer, 0);
3287 dst->serialize(vkd, device, *cmdBuffer, &shallowStorage);
3288 endCommandBuffer(vkd, *cmdBuffer);
3289 submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3290
3291 // get data to verification
3292 const std::vector<uint64_t> outAddrs = dst->getSerializingAddresses(vkd, device);
3293 const SerialStorage::AccelerationStructureHeader *header = shallowStorage.getASHeader();
3294
3295 return (areAddressesDifferent(inAddrs, outAddrs) && areAddressesTheSame(outAddrs, header)) ?
3296 tcu::TestStatus::pass("") :
3297 tcu::TestStatus::fail("");
3298 }
3299
areAddressesTheSame(const std::vector<uint64_t> & addresses,const SerialStorage::AccelerationStructureHeader * header)3300 bool RayTracingHeaderBottomAddressTestInstance::areAddressesTheSame(
3301 const std::vector<uint64_t> &addresses, const SerialStorage::AccelerationStructureHeader *header)
3302 {
3303 const uint32_t cbottoms = uint32_t(addresses.size() - 1);
3304
3305 // header should contain the same number of handles as serialized/deserialized top-level AS
3306 if (cbottoms != header->handleCount)
3307 return false;
3308
3309 std::set<uint64_t> refAddrs;
3310 std::set<uint64_t> checkAddrs;
3311
3312 // distinct, squach and sort address list
3313 for (uint32_t i = 0; i < cbottoms; ++i)
3314 {
3315 refAddrs.insert(addresses[i + 1]);
3316 checkAddrs.insert(header->handleArray[i]);
3317 }
3318
3319 return std::equal(refAddrs.begin(), refAddrs.end(), checkAddrs.begin());
3320 }
3321
areAddressesDifferent(const std::vector<uint64_t> & addresses1,const std::vector<uint64_t> & addresses2)3322 bool RayTracingHeaderBottomAddressTestInstance::areAddressesDifferent(const std::vector<uint64_t> &addresses1,
3323 const std::vector<uint64_t> &addresses2)
3324 {
3325 // the number of addresses must be equal
3326 if (addresses1.size() != addresses2.size())
3327 return false;
3328
3329 // adresses of top-level AS must differ
3330 if (addresses1[0] == addresses2[0])
3331 return false;
3332
3333 std::set<uint64_t> addrs1;
3334 std::set<uint64_t> addrs2;
3335 uint32_t matches = 0;
3336 const uint32_t cbottoms = uint32_t(addresses1.size() - 1);
3337
3338 for (uint32_t i = 0; i < cbottoms; ++i)
3339 {
3340 addrs1.insert(addresses1[i + 1]);
3341 addrs2.insert(addresses2[i + 1]);
3342 }
3343
3344 // the first addresses set must not contain any address from the second addresses set
3345 for (auto &addr1 : addrs1)
3346 {
3347 if (addrs2.end() != addrs2.find(addr1))
3348 ++matches;
3349 }
3350
3351 return (matches == 0);
3352 }
3353
3354 template <class X, class... Y>
makeShared(Y &&...ctorArgs)3355 inline de::SharedPtr<X> makeShared(Y &&...ctorArgs)
3356 {
3357 return de::SharedPtr<X>(new X(std::forward<Y>(ctorArgs)...));
3358 }
3359 template <class X, class... Y>
makeMovePtr(Y &&...ctorArgs)3360 inline de::MovePtr<X> makeMovePtr(Y &&...ctorArgs)
3361 {
3362 return de::MovePtr<X>(new X(std::forward<Y>(ctorArgs)...));
3363 }
3364 template <class X>
makeSharedFrom(const X & x)3365 inline de::SharedPtr<X> makeSharedFrom(const X &x)
3366 {
3367 return makeShared<X>(x);
3368 }
3369
3370 struct QueryPoolResultsParams
3371 {
3372 enum class Type
3373 {
3374 StructureSize,
3375 PointerCount
3376 } queryType;
3377 VkAccelerationStructureBuildTypeKHR buildType;
3378 uint32_t blasCount;
3379 bool inVkBuffer;
3380 bool compacted;
3381 };
3382
3383 typedef de::SharedPtr<const QueryPoolResultsParams> QueryPoolResultsParamsPtr;
3384
3385 struct ASInterface;
3386 typedef de::SharedPtr<ASInterface> ASInterfacePtr;
3387
3388 class QueryPoolResultsInstance : public TestInstance
3389 {
3390 public:
3391 using TlasPtr = de::SharedPtr<TopLevelAccelerationStructure>;
3392 using BlasPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
3393
QueryPoolResultsInstance(Context & context,QueryPoolResultsParamsPtr params)3394 QueryPoolResultsInstance(Context &context, QueryPoolResultsParamsPtr params)
3395 : TestInstance(context)
3396 , m_params(params)
3397 {
3398 }
3399 auto prepareBottomAccStructures(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3400 VkCommandBuffer cmdBuffer) -> std::vector<BlasPtr>;
3401 TlasPtr prepareTopAccStructure(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3402 VkCommandBuffer cmdBuffer, const std::vector<BlasPtr> &bottoms);
3403
3404 protected:
3405 const QueryPoolResultsParamsPtr m_params;
3406 };
3407
3408 struct ASInterface
3409 {
~ASInterfacevkt::RayTracing::__anon7ff8e1c10111::ASInterface3410 virtual ~ASInterface()
3411 {
3412 }
3413 virtual VkAccelerationStructureKHR getPtr() const = 0;
3414 virtual VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes() const = 0;
3415 virtual ASInterfacePtr clone(Context &ctx, VkAccelerationStructureBuildTypeKHR buildType, const VkCommandBuffer cmd,
3416 VkDeviceSize size) = 0;
3417 };
3418
3419 template <class>
3420 struct ASAllocator;
3421 template <>
3422 struct ASAllocator<QueryPoolResultsInstance::TlasPtr>
3423 {
3424 typedef QueryPoolResultsInstance::TlasPtr TlasPtr;
allocvkt::RayTracing::__anon7ff8e1c10111::ASAllocator3425 static TlasPtr alloc()
3426 {
3427 return TlasPtr(makeTopLevelAccelerationStructure().release());
3428 }
3429 };
3430 template <>
3431 struct ASAllocator<QueryPoolResultsInstance::BlasPtr>
3432 {
3433 typedef QueryPoolResultsInstance::BlasPtr BlasPtr;
allocvkt::RayTracing::__anon7ff8e1c10111::ASAllocator3434 static BlasPtr alloc()
3435 {
3436 return BlasPtr(makeBottomLevelAccelerationStructure().release());
3437 }
3438 };
3439
3440 template <class SharedPtrType>
3441 struct ASInterfaceImpl : ASInterface
3442 {
3443 SharedPtrType m_source;
ASInterfaceImplvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3444 ASInterfaceImpl(SharedPtrType src) : m_source(src)
3445 {
3446 }
getPtrvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3447 virtual VkAccelerationStructureKHR getPtr() const override
3448 {
3449 return *m_source->getPtr();
3450 }
getStructureBuildSizesvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3451 virtual VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes() const override
3452 {
3453 return m_source->getStructureBuildSizes();
3454 }
clonevkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3455 virtual ASInterfacePtr clone(Context &ctx, VkAccelerationStructureBuildTypeKHR buildType, const VkCommandBuffer cmd,
3456 VkDeviceSize size) override
3457 {
3458 const DeviceInterface &vk = ctx.getDeviceInterface();
3459 const VkDevice device = ctx.getDevice();
3460 Allocator &allocator = ctx.getDefaultAllocator();
3461
3462 auto ptr = ASAllocator<SharedPtrType>::alloc();
3463 ptr->setBuildType(buildType);
3464 ptr->setBuildFlags(m_source->getBuildFlags());
3465 ptr->create(vk, device, allocator, size);
3466 ptr->copyFrom(vk, device, cmd, m_source.get(), false);
3467 return de::SharedPtr<ASInterface>(new ASInterfaceImpl(ptr));
3468 }
3469 };
3470
3471 template <class SharedPtrType>
makeASInterfacePtr(SharedPtrType asPtr)3472 ASInterfacePtr makeASInterfacePtr(SharedPtrType asPtr)
3473 {
3474 return ASInterfacePtr(new ASInterfaceImpl<SharedPtrType>(asPtr));
3475 }
3476
3477 class QueryPoolResultsSizeInstance : public QueryPoolResultsInstance
3478 {
3479 public:
QueryPoolResultsSizeInstance(Context & context,QueryPoolResultsParamsPtr params)3480 QueryPoolResultsSizeInstance(Context &context, QueryPoolResultsParamsPtr params)
3481 : QueryPoolResultsInstance(context, params)
3482 {
3483 }
3484 TestStatus iterate(void) override;
3485 auto makeCopyOfStructures(const std::vector<ASInterfacePtr> &structs, const std::vector<VkDeviceSize> sizes)
3486 -> std::vector<ASInterfacePtr>;
3487 auto getStructureSizes(const std::vector<VkAccelerationStructureKHR> &handles) -> std::vector<VkDeviceSize>;
3488 };
3489
3490 class QueryPoolResultsPointersInstance : public QueryPoolResultsInstance
3491 {
3492 public:
QueryPoolResultsPointersInstance(Context & context,QueryPoolResultsParamsPtr params)3493 QueryPoolResultsPointersInstance(Context &context, QueryPoolResultsParamsPtr params)
3494 : QueryPoolResultsInstance(context, params)
3495 {
3496 }
3497
3498 TestStatus iterate(void) override;
3499 };
3500
3501 class QueryPoolResultsCase : public TestCase
3502 {
3503 public:
QueryPoolResultsCase(TestContext & ctx,const char * name,QueryPoolResultsParamsPtr params)3504 QueryPoolResultsCase(TestContext &ctx, const char *name, QueryPoolResultsParamsPtr params)
3505 : TestCase(ctx, name)
3506 , m_params(params)
3507 {
3508 }
3509 void checkSupport(Context &context) const override;
3510 TestInstance *createInstance(Context &context) const override;
3511
3512 template <class T, class P = T (*)[1], class R = decltype(std::begin(*std::declval<P>()))>
makeStdBeginEnd(void * p,uint32_t n)3513 static auto makeStdBeginEnd(void *p, uint32_t n) -> std::pair<R, R>
3514 {
3515 auto tmp = std::begin(*P(p));
3516 auto begin = tmp;
3517 std::advance(tmp, n);
3518 return {begin, tmp};
3519 }
3520
3521 private:
3522 const QueryPoolResultsParamsPtr m_params;
3523 };
3524
createInstance(Context & context) const3525 TestInstance *QueryPoolResultsCase::createInstance(Context &context) const
3526 {
3527 switch (m_params->queryType)
3528 {
3529 case QueryPoolResultsParams::Type::StructureSize:
3530 return new QueryPoolResultsSizeInstance(context, m_params);
3531 case QueryPoolResultsParams::Type::PointerCount:
3532 return new QueryPoolResultsPointersInstance(context, m_params);
3533 }
3534 TCU_THROW(InternalError, "Unknown test type");
3535 return nullptr;
3536 }
3537
checkSupport(Context & context) const3538 void QueryPoolResultsCase::checkSupport(Context &context) const
3539 {
3540 context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
3541 context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
3542
3543 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
3544 context.getAccelerationStructureFeatures();
3545 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
3546 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
3547 TCU_THROW(NotSupportedError,
3548 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
3549
3550 const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
3551 context.getRayTracingMaintenance1Features();
3552 if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
3553 TCU_THROW(NotSupportedError,
3554 "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
3555 }
3556
prepareBottomAccStructures(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer)3557 auto QueryPoolResultsInstance::prepareBottomAccStructures(const DeviceInterface &vk, VkDevice device,
3558 Allocator &allocator, VkCommandBuffer cmdBuffer)
3559 -> std::vector<BlasPtr>
3560 {
3561 std::vector<Vec3> triangle = {
3562 {0.0, 0.0, 0.0},
3563 {0.5, 0.0, 0.0},
3564 {0.0, 0.5, 0.0},
3565 };
3566
3567 const uint32_t triangleCount = ((1 + m_params->blasCount) * m_params->blasCount) / 2;
3568 const float angle = (4.0f * std::acos(0.0f)) / float(triangleCount);
3569 auto rotateCcwZ = [&](const Vec3 &p, const Vec3 ¢er) -> tcu::Vec3
3570 {
3571 const float s = std::sin(angle);
3572 const float c = std::cos(angle);
3573 const auto t = p - center;
3574 return tcu::Vec3(c * t.x() - s * t.y(), s * t.x() + c * t.y(), t.z()) + center;
3575 };
3576 auto nextGeometry = [&]() -> void
3577 {
3578 for (auto &vertex : triangle)
3579 vertex = rotateCcwZ(vertex, Vec3(0.0f, 0.0f, 0.0f));
3580 };
3581
3582 std::vector<BlasPtr> bottoms(m_params->blasCount);
3583
3584 for (uint32_t b = 0; b < m_params->blasCount; ++b)
3585 {
3586 BlasPtr blas(makeBottomLevelAccelerationStructure().release());
3587
3588 blas->setBuildType(m_params->buildType);
3589 if (m_params->compacted)
3590 {
3591 blas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3592 }
3593 blas->addGeometry(triangle, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3594 for (uint32_t geom = b; geom < m_params->blasCount; ++geom)
3595 {
3596 nextGeometry();
3597 blas->addGeometry(triangle, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3598 }
3599
3600 blas->createAndBuild(vk, device, cmdBuffer, allocator);
3601
3602 bottoms[b] = blas;
3603 }
3604
3605 return bottoms;
3606 }
3607
prepareTopAccStructure(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer,const std::vector<BlasPtr> & bottoms)3608 auto QueryPoolResultsInstance::prepareTopAccStructure(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3609 VkCommandBuffer cmdBuffer, const std::vector<BlasPtr> &bottoms)
3610 -> TlasPtr
3611 {
3612 const std::size_t instanceCount = bottoms.size();
3613
3614 de::MovePtr<TopLevelAccelerationStructure> tlas = makeTopLevelAccelerationStructure();
3615 tlas->setBuildType(m_params->buildType);
3616 if (m_params->compacted)
3617 {
3618 tlas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3619 }
3620 tlas->setInstanceCount(instanceCount);
3621
3622 for (std::size_t i = 0; i < instanceCount; ++i)
3623 {
3624 tlas->addInstance(bottoms[i], identityMatrix3x4, 0, 0xFFu, 0u, VkGeometryInstanceFlagsKHR(0));
3625 }
3626
3627 tlas->createAndBuild(vk, device, cmdBuffer, allocator);
3628
3629 return TlasPtr(tlas.release());
3630 }
3631
getStructureSizes(const std::vector<VkAccelerationStructureKHR> & handles)3632 auto QueryPoolResultsSizeInstance::getStructureSizes(const std::vector<VkAccelerationStructureKHR> &handles)
3633 -> std::vector<VkDeviceSize>
3634 {
3635 const DeviceInterface &vk = m_context.getDeviceInterface();
3636 const VkDevice device = m_context.getDevice();
3637 const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3638 const VkQueue queue = m_context.getUniversalQueue();
3639 Allocator &allocator = m_context.getDefaultAllocator();
3640
3641 const Move<VkCommandPool> cmdPool = createCommandPool(vk, device, 0, familyIndex);
3642 const Move<VkCommandBuffer> cmdBuffer =
3643 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3644
3645 const uint32_t queryCount = static_cast<uint32_t>(handles.size());
3646
3647 Move<VkQueryPool> queryPoolSize =
3648 makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, queryCount);
3649 Move<VkQueryPool> queryPoolSerial =
3650 makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
3651 Move<VkQueryPool> queryPoolCompact =
3652 m_params->compacted ?
3653 makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount) :
3654 Move<VkQueryPool>();
3655
3656 de::MovePtr<BufferWithMemory> buffer;
3657 std::vector<VkDeviceSize> sizeSizes(queryCount, 0);
3658 std::vector<VkDeviceSize> serialSizes(queryCount, 0);
3659 std::vector<VkDeviceSize> compactSizes(queryCount, 0);
3660
3661 if (m_params->inVkBuffer)
3662 {
3663 const auto vci = makeBufferCreateInfo((m_params->compacted ? 3 : 2) * queryCount * sizeof(VkDeviceSize),
3664 VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3665 buffer = makeMovePtr<BufferWithMemory>(vk, device, allocator, vci,
3666 MemoryRequirement::Coherent | MemoryRequirement::HostVisible);
3667 }
3668
3669 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3670 {
3671 beginCommandBuffer(vk, *cmdBuffer, 0);
3672
3673 vk.cmdResetQueryPool(*cmdBuffer, *queryPoolSize, 0, queryCount);
3674 vk.cmdResetQueryPool(*cmdBuffer, *queryPoolSerial, 0, queryCount);
3675 if (m_params->compacted)
3676 {
3677 vk.cmdResetQueryPool(*cmdBuffer, *queryPoolCompact, 0, queryCount);
3678 }
3679
3680 vk.cmdWriteAccelerationStructuresPropertiesKHR(
3681 *cmdBuffer, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, *queryPoolSize, 0);
3682 vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(),
3683 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR,
3684 *queryPoolSerial, 0);
3685
3686 if (m_params->compacted)
3687 {
3688 vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(),
3689 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
3690 *queryPoolCompact, 0);
3691 }
3692
3693 if (m_params->inVkBuffer)
3694 {
3695 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolSize, 0, queryCount, **buffer,
3696 (0 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3697 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3698 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolSerial, 0, queryCount, **buffer,
3699 (1 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3700 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3701 if (m_params->compacted)
3702 {
3703 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolCompact, 0, queryCount, **buffer,
3704 (2 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3705 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3706 }
3707 }
3708 endCommandBuffer(vk, *cmdBuffer);
3709 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3710
3711 if (m_params->inVkBuffer)
3712 {
3713 Allocation &alloc = buffer->getAllocation();
3714 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
3715
3716 uint8_t *ptrSize = reinterpret_cast<uint8_t *>(alloc.getHostPtr());
3717 uint8_t *ptrSerial = ptrSize + queryCount * sizeof(VkDeviceSize);
3718
3719 auto rangeSize = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrSize, queryCount);
3720 auto rangeSerial = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrSerial, queryCount);
3721
3722 std::copy_n(rangeSize.first, queryCount, sizeSizes.begin());
3723 std::copy_n(rangeSerial.first, queryCount, serialSizes.begin());
3724
3725 if (m_params->compacted)
3726 {
3727 auto ptrCompact = ptrSize + 2 * queryCount * sizeof(VkDeviceSize);
3728 auto rangeCompact = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrCompact, queryCount);
3729 std::copy_n(rangeCompact.first, queryCount, compactSizes.begin());
3730 }
3731 }
3732 else
3733 {
3734 VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSize, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3735 sizeSizes.data(), sizeof(VkDeviceSize),
3736 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3737 VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSerial, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3738 serialSizes.data(), sizeof(VkDeviceSize),
3739 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3740 if (m_params->compacted)
3741 {
3742 VK_CHECK(vk.getQueryPoolResults(
3743 device, *queryPoolCompact, 0u, queryCount, queryCount * sizeof(VkDeviceSize), compactSizes.data(),
3744 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3745 }
3746 }
3747 }
3748 else
3749 {
3750 vk.writeAccelerationStructuresPropertiesKHR(
3751 device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR,
3752 queryCount * sizeof(VkDeviceSize), sizeSizes.data(), sizeof(VkDeviceSize));
3753 vk.writeAccelerationStructuresPropertiesKHR(
3754 device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR,
3755 queryCount * sizeof(VkDeviceSize), serialSizes.data(), sizeof(VkDeviceSize));
3756 if (m_params->compacted)
3757 {
3758 vk.writeAccelerationStructuresPropertiesKHR(
3759 device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
3760 queryCount * sizeof(VkDeviceSize), compactSizes.data(), sizeof(VkDeviceSize));
3761 }
3762 }
3763
3764 sizeSizes.insert(sizeSizes.end(), serialSizes.begin(), serialSizes.end());
3765 sizeSizes.insert(sizeSizes.end(), compactSizes.begin(), compactSizes.end());
3766
3767 return sizeSizes;
3768 }
3769
makeCopyOfStructures(const std::vector<ASInterfacePtr> & structs,const std::vector<VkDeviceSize> sizes)3770 auto QueryPoolResultsSizeInstance::makeCopyOfStructures(const std::vector<ASInterfacePtr> &structs,
3771 const std::vector<VkDeviceSize> sizes)
3772 -> std::vector<ASInterfacePtr>
3773 {
3774 const DeviceInterface &vk = m_context.getDeviceInterface();
3775 const VkDevice device = m_context.getDevice();
3776 const VkQueue queue = m_context.getUniversalQueue();
3777
3778 Move<VkCommandPool> cmdPool;
3779 Move<VkCommandBuffer> cmdBuffer;
3780
3781 std::vector<ASInterfacePtr> copies;
3782
3783 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3784 {
3785 const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3786 cmdPool = createCommandPool(vk, device, 0, familyIndex);
3787 cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3788 beginCommandBuffer(vk, *cmdBuffer, 0u);
3789 }
3790
3791 for (auto begin = structs.begin(), i = begin; i != structs.end(); ++i)
3792 {
3793 copies.push_back((*i)->clone(m_context, m_params->buildType, *cmdBuffer, sizes.at(std::distance(begin, i))));
3794 }
3795
3796 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3797 {
3798 endCommandBuffer(vk, *cmdBuffer);
3799 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3800 }
3801
3802 return copies;
3803 }
3804
iterate(void)3805 TestStatus QueryPoolResultsSizeInstance::iterate(void)
3806 {
3807 const DeviceInterface &vk = m_context.getDeviceInterface();
3808 const VkDevice device = m_context.getDevice();
3809 const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3810 const VkQueue queue = m_context.getUniversalQueue();
3811 Allocator &allocator = m_context.getDefaultAllocator();
3812
3813 const Move<VkCommandPool> cmdPool =
3814 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3815 const Move<VkCommandBuffer> cmdBuffer =
3816 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3817
3818 beginCommandBuffer(vk, *cmdBuffer, 0);
3819 const std::vector<BlasPtr> bottoms = prepareBottomAccStructures(vk, device, allocator, *cmdBuffer);
3820 TlasPtr tlas = prepareTopAccStructure(vk, device, allocator, *cmdBuffer, bottoms);
3821 endCommandBuffer(vk, *cmdBuffer);
3822 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3823
3824 const uint32_t queryCount = m_params->blasCount + 1;
3825 std::vector<VkAccelerationStructureKHR> handles(queryCount);
3826 handles[0] = *tlas->getPtr();
3827 std::transform(bottoms.begin(), bottoms.end(), std::next(handles.begin()),
3828 [](const BlasPtr &blas) { return *blas->getPtr(); });
3829
3830 // only the first queryCount elements are results from ACCELERATION_STRUCTURE_SIZE queries.
3831 const std::vector<VkDeviceSize> sourceSizes = getStructureSizes(handles);
3832
3833 std::vector<ASInterfacePtr> sourceStructures;
3834 sourceStructures.push_back(makeASInterfacePtr(tlas));
3835 for (BlasPtr blas : bottoms)
3836 sourceStructures.push_back(makeASInterfacePtr(blas));
3837
3838 std::vector<ASInterfacePtr> copies = makeCopyOfStructures(sourceStructures, sourceSizes);
3839 std::transform(copies.begin(), copies.end(), handles.begin(),
3840 [](const ASInterfacePtr &intf) { return intf->getPtr(); });
3841
3842 const std::vector<VkDeviceSize> copySizes = getStructureSizes(handles);
3843
3844 // verification
3845 bool pass = true;
3846 for (uint32_t i = 0; pass && i < queryCount; ++i)
3847 {
3848 pass = sourceSizes.at(i) == copySizes.at(i);
3849 }
3850
3851 return pass ? TestStatus::pass("") : TestStatus::fail("");
3852 }
3853
iterate(void)3854 TestStatus QueryPoolResultsPointersInstance::iterate(void)
3855 {
3856 const DeviceInterface &vk = m_context.getDeviceInterface();
3857 const VkDevice device = m_context.getDevice();
3858 const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3859 const VkQueue queue = m_context.getUniversalQueue();
3860 Allocator &allocator = m_context.getDefaultAllocator();
3861
3862 const Move<VkCommandPool> cmdPool =
3863 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3864 const Move<VkCommandBuffer> cmdBuffer =
3865 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3866
3867 beginCommandBuffer(vk, *cmdBuffer, 0);
3868 const std::vector<BlasPtr> bottoms = prepareBottomAccStructures(vk, device, allocator, *cmdBuffer);
3869 TlasPtr tlas = prepareTopAccStructure(vk, device, allocator, *cmdBuffer, bottoms);
3870 endCommandBuffer(vk, *cmdBuffer);
3871 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3872
3873 const uint32_t queryCount = m_params->blasCount + 1;
3874 std::vector<VkAccelerationStructureKHR> handles(queryCount);
3875 handles[0] = *tlas.get()->getPtr();
3876 std::transform(bottoms.begin(), bottoms.end(), std::next(handles.begin()),
3877 [](const BlasPtr &blas) { return *blas.get()->getPtr(); });
3878
3879 const VkQueryType queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR;
3880 Move<VkQueryPool> queryPoolCounts = makeQueryPool(vk, device, queryType, queryCount);
3881
3882 de::MovePtr<BufferWithMemory> buffer;
3883 std::vector<VkDeviceSize> pointerCounts(queryCount, 123u);
3884
3885 if (m_params->inVkBuffer)
3886 {
3887 const auto vci = makeBufferCreateInfo(queryCount * sizeof(VkDeviceSize), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3888 buffer = makeMovePtr<BufferWithMemory>(vk, device, allocator, vci,
3889 MemoryRequirement::Coherent | MemoryRequirement::HostVisible);
3890 }
3891
3892 if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3893 {
3894 beginCommandBuffer(vk, *cmdBuffer, 0);
3895 vk.cmdResetQueryPool(*cmdBuffer, *queryPoolCounts, 0, queryCount);
3896 vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(), queryType,
3897 *queryPoolCounts, 0);
3898 if (m_params->inVkBuffer)
3899 {
3900 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolCounts, 0, queryCount, **buffer, 0 /*offset*/,
3901 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3902 }
3903 endCommandBuffer(vk, *cmdBuffer);
3904 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3905
3906 if (m_params->inVkBuffer)
3907 {
3908 Allocation &alloc = buffer->getAllocation();
3909 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
3910 auto rangeCounts = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(alloc.getHostPtr(), queryCount);
3911 std::copy_n(rangeCounts.first, queryCount, pointerCounts.begin());
3912 }
3913 else
3914 {
3915 VK_CHECK(vk.getQueryPoolResults(device, *queryPoolCounts, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3916 pointerCounts.data(), sizeof(VkDeviceSize),
3917 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3918 }
3919 }
3920 else
3921 {
3922 vk.writeAccelerationStructuresPropertiesKHR(device, queryCount, handles.data(), queryType,
3923 queryCount * sizeof(VkDeviceSize), pointerCounts.data(),
3924 sizeof(VkDeviceSize));
3925 }
3926
3927 // verification
3928 const std::vector<VkDeviceSize> inSizes = tlas->getSerializingSizes(vk, device, queue, familyIndex);
3929 SerialStorage storage(vk, device, allocator, m_params->buildType, inSizes[0]);
3930
3931 beginCommandBuffer(vk, *cmdBuffer, 0);
3932 tlas->serialize(vk, device, *cmdBuffer, &storage);
3933 endCommandBuffer(vk, *cmdBuffer);
3934 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3935
3936 const SerialStorage::AccelerationStructureHeader *header = storage.getASHeader();
3937
3938 bool pass = (header->handleCount == pointerCounts[0]); // must be the same as bottoms.size()
3939 for (uint32_t i = 1; pass && i < queryCount; ++i)
3940 {
3941 pass = (0 == pointerCounts[i]); // bottoms have no chidren
3942 }
3943
3944 return pass ? TestStatus::pass("") : TestStatus::fail("");
3945 }
3946
3947 struct CopyWithinPipelineParams
3948 {
3949 enum class Type
3950 {
3951 StageASCopyBit,
3952 StageAllTransferBit,
3953 AccessSBTReadBit
3954 } type;
3955 uint32_t width;
3956 uint32_t height;
3957 VkAccelerationStructureBuildTypeKHR build;
3958 };
3959 typedef de::SharedPtr<const CopyWithinPipelineParams> CopyWithinPipelineParamsPtr;
3960
3961 class CopyWithinPipelineInstance : public TestInstance
3962 {
3963 public:
3964 using TlasPtr = de::SharedPtr<TopLevelAccelerationStructure>;
3965 using BlasPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
3966
CopyWithinPipelineInstance(Context & context,CopyWithinPipelineParamsPtr params)3967 CopyWithinPipelineInstance(Context &context, CopyWithinPipelineParamsPtr params)
3968 : TestInstance(context)
3969 , vk(context.getDeviceInterface())
3970 , device(context.getDevice())
3971 , allocator(context.getDefaultAllocator())
3972 , rgenShader(createShaderModule(vk, device, context.getBinaryCollection().get("rgen")))
3973 , chitShader(createShaderModule(vk, device, context.getBinaryCollection().get("chit")))
3974 , missShader(createShaderModule(vk, device, context.getBinaryCollection().get("miss")))
3975 , m_params(params)
3976 , m_format(VK_FORMAT_R32G32B32A32_SFLOAT)
3977 {
3978 }
3979
3980 protected:
3981 const DeviceInterface &vk;
3982 const VkDevice device;
3983 Allocator &allocator;
3984 Move<VkShaderModule> rgenShader;
3985 Move<VkShaderModule> chitShader;
3986 Move<VkShaderModule> missShader;
3987 CopyWithinPipelineParamsPtr m_params;
3988 VkFormat m_format;
3989 };
3990
3991 class CopyBlasInstance : public CopyWithinPipelineInstance
3992 {
3993 public:
CopyBlasInstance(Context & context,CopyWithinPipelineParamsPtr params)3994 CopyBlasInstance(Context &context, CopyWithinPipelineParamsPtr params) : CopyWithinPipelineInstance(context, params)
3995 {
3996 }
3997 TestStatus iterate(void) override;
3998 auto getRefImage(BlasPtr blas) const -> de::MovePtr<BufferWithMemory>;
3999 };
4000
4001 class CopySBTInstance : public CopyWithinPipelineInstance
4002 {
4003 public:
CopySBTInstance(Context & context,CopyWithinPipelineParamsPtr params)4004 CopySBTInstance(Context &context, CopyWithinPipelineParamsPtr params) : CopyWithinPipelineInstance(context, params)
4005 {
4006 }
4007 TestStatus iterate(void) override;
4008 auto getBufferSizeForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4009 const uint32_t &shaderGroupBaseAlignment) const -> VkDeviceSize;
4010 auto getBufferForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4011 const uint32_t &shaderGroupBaseAlignment) const -> de::MovePtr<BufferWithMemory>;
4012 };
4013
4014 class PipelineStageASCase : public TestCase
4015 {
4016 public:
PipelineStageASCase(TestContext & ctx,const char * name,CopyWithinPipelineParamsPtr params)4017 PipelineStageASCase(TestContext &ctx, const char *name, CopyWithinPipelineParamsPtr params)
4018 : TestCase(ctx, name)
4019 , m_params(params)
4020 {
4021 }
4022 void initPrograms(SourceCollections &programs) const override;
4023 void checkSupport(Context &context) const override;
4024 TestInstance *createInstance(Context &context) const override;
4025
4026 private:
4027 CopyWithinPipelineParamsPtr m_params;
4028 };
4029
4030 namespace u
4031 {
4032 namespace details
4033 {
4034 template <class X, class Y>
4035 struct BarrierMaker
4036 {
4037 const X &m_x;
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4038 BarrierMaker(const X &x) : m_x(x)
4039 {
4040 }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4041 uint32_t count() const
4042 {
4043 return 1;
4044 }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4045 const X *pointer() const
4046 {
4047 return &m_x;
4048 }
4049 };
4050 template <class Y>
4051 struct BarrierMaker<std::false_type, Y>
4052 {
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4053 BarrierMaker(const std::false_type &)
4054 {
4055 }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4056 uint32_t count() const
4057 {
4058 return 0;
4059 }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4060 Y *pointer() const
4061 {
4062 return nullptr;
4063 }
4064 };
4065 template <class Z, uint32_t N>
4066 struct BarrierMaker<const Z[N], Z>
4067 {
4068 const Z (&m_a)[N];
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4069 BarrierMaker(const Z (&a)[N]) : m_a(a)
4070 {
4071 }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4072 uint32_t count() const
4073 {
4074 return N;
4075 }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4076 const Z *pointer() const
4077 {
4078 return m_a;
4079 }
4080 };
4081 template <class Mem, class Buf, class Img, class Exp>
4082 struct Sel
4083 {
4084 typedef typename std::remove_cv<Mem>::type t_Mem;
4085 typedef typename std::remove_cv<Buf>::type t_Buf;
4086 typedef typename std::remove_cv<Img>::type t_Img;
4087 typedef std::integral_constant<uint32_t, 0> index0;
4088 typedef std::integral_constant<uint32_t, 1> index1;
4089 typedef std::integral_constant<uint32_t, 2> index2;
4090 typedef std::integral_constant<uint32_t, 3> index3;
4091 using isMem = std::is_same<t_Mem, Exp>;
4092 using isBuf = std::is_same<t_Buf, Exp>;
4093 using isImg = std::is_same<t_Img, Exp>;
4094 template <bool B, class T, class F>
4095 using choose = typename std::conditional<B, T, F>::type;
4096 typedef choose<isMem::value, BarrierMaker<Mem, Exp>,
4097 choose<isBuf::value, BarrierMaker<Buf, Exp>,
4098 choose<isImg::value, BarrierMaker<Img, Exp>, BarrierMaker<std::false_type, Exp>>>>
4099 type;
4100 typedef choose<isMem::value, index0, choose<isBuf::value, index1, choose<isImg::value, index2, index3>>> index;
4101 };
4102 } // namespace details
4103 constexpr std::false_type NoneBarriers{};
4104 /**
4105 * @brief Helper function that makes and populates VkDependencyInfoKHR structure.
4106 * @param barriers1 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (mandatory param)
4107 * @param barriers2 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (optional param)
4108 * @param barriers2 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (optional param)
4109 * @note The order of the parameters does not matter.
4110 */
4111 template <class Barriers1, class Barriers2 = std::false_type, class Barriers3 = std::false_type>
makeDependency(const Barriers1 & barriers1,const Barriers2 & barriers2=NoneBarriers,const Barriers3 & barriers3=NoneBarriers)4112 VkDependencyInfoKHR makeDependency(const Barriers1 &barriers1, const Barriers2 &barriers2 = NoneBarriers,
4113 const Barriers3 &barriers3 = NoneBarriers)
4114 {
4115 auto args = std::forward_as_tuple(barriers1, barriers2, barriers3, std::false_type());
4116 const uint32_t memIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkMemoryBarrier2KHR>::index::value;
4117 const uint32_t bufIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkBufferMemoryBarrier2KHR>::index::value;
4118 const uint32_t imgIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkImageMemoryBarrier2KHR>::index::value;
4119 typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkMemoryBarrier2KHR>::type memType;
4120 typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkBufferMemoryBarrier2KHR>::type bufType;
4121 typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkImageMemoryBarrier2KHR>::type imgType;
4122 return {
4123 VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR, // VkStructureType sType;
4124 nullptr, // const void* pNext;
4125 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
4126 memType(std::get<memIndex>(args)).count(), // uint32_t memoryBarrierCount;
4127 memType(std::get<memIndex>(args)).pointer(), // const VkMemoryBarrier2KHR* pMemoryBarriers;
4128 bufType(std::get<bufIndex>(args)).count(), // uint32_t bufferMemoryBarrierCount;
4129 bufType(std::get<bufIndex>(args)).pointer(), // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers;
4130 imgType(std::get<imgIndex>(args)).count(), // uint32_t imageMemoryBarrierCount;
4131 imgType(std::get<imgIndex>(args)).pointer() // const VkImageMemoryBarrier2KHR* pImageMemoryBarriers;
4132 };
4133 }
4134 } // namespace u
4135
createInstance(Context & context) const4136 TestInstance *PipelineStageASCase::createInstance(Context &context) const
4137 {
4138 de::MovePtr<TestInstance> instance;
4139 switch (m_params->type)
4140 {
4141 case CopyWithinPipelineParams::Type::StageASCopyBit:
4142 case CopyWithinPipelineParams::Type::StageAllTransferBit:
4143 instance = makeMovePtr<CopyBlasInstance>(context, m_params);
4144 break;
4145 case CopyWithinPipelineParams::Type::AccessSBTReadBit:
4146 instance = makeMovePtr<CopySBTInstance>(context, m_params);
4147 break;
4148 }
4149 return instance.release();
4150 }
4151
initPrograms(SourceCollections & programs) const4152 void PipelineStageASCase::initPrograms(SourceCollections &programs) const
4153 {
4154 const vk::ShaderBuildOptions buildOptions(programs.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
4155 const char endl = '\n';
4156
4157 {
4158 std::stringstream str;
4159 str << "#version 460 core" << endl
4160 << "#extension GL_EXT_ray_tracing : require" << endl
4161 << "layout(location = 0) rayPayloadEXT vec4 payload;" << endl
4162 << "layout(rgba32f, set = 0, binding = 0) uniform image2D result;" << endl
4163 << "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;" << endl
4164 << "void main()" << endl
4165 << "{" << endl
4166 << " float rx = (float(gl_LaunchIDEXT.x) + 0.5) / float(gl_LaunchSizeEXT.x);" << endl
4167 << " float ry = (float(gl_LaunchIDEXT.y) + 0.5) / float(gl_LaunchSizeEXT.y);" << endl
4168 << " payload = vec4(0.5, 0.5, 0.5, 1.0);" << endl
4169 << " vec3 orig = vec3(rx, ry, 1.0);" << endl
4170 << " vec3 dir = vec3(0.0, 0.0, -1.0);" << endl
4171 << " traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, 0xFFu, 0, 0, 0, orig, 0.0, dir, 2.0, 0);" << endl
4172 << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), payload);" << endl
4173 << "}";
4174 str.flush();
4175 programs.glslSources.add("rgen") << glu::RaygenSource(str.str()) << buildOptions;
4176 }
4177
4178 {
4179 std::stringstream str;
4180 str << "#version 460 core" << endl
4181 << "#extension GL_EXT_ray_tracing : require" << endl
4182 << "layout(location = 0) rayPayloadInEXT vec4 payload;" << endl
4183 << "void main()" << endl
4184 << "{" << endl
4185 << " payload = vec4(0.0, 1.0, 0.0, 1.0);" << endl
4186 << "}";
4187 str.flush();
4188 programs.glslSources.add("chit") << glu::ClosestHitSource(str.str()) << buildOptions;
4189 }
4190
4191 {
4192 std::stringstream str;
4193 str << "#version 460 core" << endl
4194 << "#extension GL_EXT_ray_tracing : require" << endl
4195 << "layout(location = 0) rayPayloadInEXT vec4 payload;" << endl
4196 << "void main()" << endl
4197 << "{" << endl
4198 << " payload = vec4(1.0, 0.0, 0.0, 1.0);" << endl
4199 << "}";
4200 str.flush();
4201 programs.glslSources.add("miss") << glu::MissSource(str.str()) << buildOptions;
4202 }
4203 }
4204
checkSupport(Context & context) const4205 void PipelineStageASCase::checkSupport(Context &context) const
4206 {
4207 context.requireInstanceFunctionality(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
4208 context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
4209 context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
4210 context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
4211 context.requireDeviceFunctionality(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
4212
4213 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
4214 context.getAccelerationStructureFeatures();
4215 if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
4216 accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
4217 TCU_THROW(NotSupportedError,
4218 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands");
4219
4220 const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
4221 context.getRayTracingMaintenance1Features();
4222 if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
4223 TCU_THROW(NotSupportedError,
4224 "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
4225
4226 const VkPhysicalDeviceSynchronization2FeaturesKHR &synchronization2Features = context.getSynchronization2Features();
4227 if (synchronization2Features.synchronization2 == VK_FALSE)
4228 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceSynchronization2FeaturesKHR::synchronization2");
4229
4230 if (m_params->type != CopyWithinPipelineParams::Type::AccessSBTReadBit)
4231 {
4232 context.requireDeviceFunctionality(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
4233 const VkPhysicalDevicePushDescriptorPropertiesKHR &pushDescriptorProperties =
4234 context.getPushDescriptorProperties();
4235 if (pushDescriptorProperties.maxPushDescriptors < 32)
4236 TCU_THROW(NotSupportedError, "Requires VK_KHR_push_descriptor extension");
4237 }
4238 }
4239
getRefImage(BlasPtr blas) const4240 auto CopyBlasInstance::getRefImage(BlasPtr blas) const -> de::MovePtr<BufferWithMemory>
4241 {
4242 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4243 const VkQueue queue = m_context.getUniversalQueue();
4244
4245 const de::MovePtr<RayTracingProperties> rtProps =
4246 makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4247 const uint32_t shaderGroupHandleSize = rtProps->getShaderGroupHandleSize();
4248 const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4249
4250 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4251 const VkImageSubresourceRange imageSubresourceRange =
4252 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4253 const de::MovePtr<ImageWithMemory> image =
4254 makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4255 const Move<VkImageView> view =
4256 makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4257
4258 const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4259 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4260 de::MovePtr<BufferWithMemory> buffer =
4261 makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4262
4263 const VkImageSubresourceLayers imageSubresourceLayers =
4264 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4265 const VkBufferImageCopy bufferCopyImageRegion =
4266 makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4267
4268 de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4269 rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4270 rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4271 rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4272
4273 const Move<VkDescriptorPool> descriptorPool =
4274 DescriptorPoolBuilder()
4275 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2)
4276 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 2)
4277 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4278 const Move<VkDescriptorSetLayout> descriptorSetLayout =
4279 DescriptorSetLayoutBuilder()
4280 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4281 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4282 .build(vk, device);
4283 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
4284
4285 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4286 Move<VkPipeline> pipeline = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4287
4288 de::MovePtr<BufferWithMemory> rgenSbt = rtPipeline->createShaderBindingTable(
4289 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
4290 VkStridedDeviceAddressRegionKHR rgenRegion = makeStridedDeviceAddressRegionKHR(
4291 getBufferDeviceAddress(vk, device, **rgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4292 de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4293 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4294 VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4295 getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4296 de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4297 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4298 VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4299 getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4300 const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4301
4302 const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4303
4304 const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4305 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4306 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4307 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4308 const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4309 makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4310 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4311 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4312 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4313 const VkDependencyInfoKHR preClearImageDependency = u::makeDependency(preClearImageImageBarrier);
4314 const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4315
4316 const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4317 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4318 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4319 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4320 const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4321 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4322 VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4323 **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4324 const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4325 const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4326
4327 const Move<VkCommandPool> cmdPool =
4328 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4329 const Move<VkCommandBuffer> cmdBuffer =
4330 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4331
4332 auto tlas = makeTopLevelAccelerationStructure();
4333 tlas->setBuildType(m_params->build);
4334 tlas->setInstanceCount(1);
4335 tlas->addInstance(blas, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4336 beginCommandBuffer(vk, *cmdBuffer);
4337 tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4338 endCommandBuffer(vk, *cmdBuffer);
4339 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4340
4341 const VkDescriptorImageInfo descriptorImageInfo =
4342 makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4343 const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4344 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
4345 nullptr, // const void* pNext;
4346 1, // uint32_t accelerationStructureCount;
4347 tlas->getPtr() // const VkAccelerationStructureKHR* pAccelerationStructures;
4348 };
4349
4350 DescriptorSetUpdateBuilder()
4351 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
4352 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4353 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
4354 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4355 .update(vk, device);
4356
4357 beginCommandBuffer(vk, *cmdBuffer);
4358 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4359 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4360 &descriptorSet.get(), 0, nullptr);
4361 vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4362 vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4363 &imageSubresourceRange);
4364 vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4365 cmdTraceRays(vk, *cmdBuffer,
4366 &rgenRegion, // rgen
4367 &missRegion, // miss
4368 &chitRegion, // hit
4369 &callRegion, // call
4370 m_params->width, m_params->height, 1);
4371 vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4372 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffer, 1u,
4373 &bufferCopyImageRegion);
4374 vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4375 endCommandBuffer(vk, *cmdBuffer);
4376 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4377
4378 invalidateMappedMemoryRange(vk, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
4379 bufferSize);
4380
4381 return buffer;
4382 }
4383
iterate(void)4384 TestStatus CopyBlasInstance::iterate(void)
4385 {
4386 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4387 const VkQueue queue = m_context.getUniversalQueue();
4388
4389 const de::MovePtr<RayTracingProperties> rtProps =
4390 makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4391 const uint32_t shaderGroupHandleSize = rtProps->getShaderGroupHandleSize();
4392 const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4393
4394 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4395 const VkImageSubresourceRange imageSubresourceRange =
4396 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4397 const de::MovePtr<ImageWithMemory> image =
4398 makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4399 const Move<VkImageView> view =
4400 makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4401
4402 const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4403 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4404 de::MovePtr<BufferWithMemory> resultImageBuffer =
4405 makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4406
4407 const VkImageSubresourceLayers imageSubresourceLayers =
4408 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4409 const VkBufferImageCopy bufferCopyImageRegion =
4410 makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4411
4412 de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4413 rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4414 rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4415 rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4416
4417 const Move<VkDescriptorSetLayout> descriptorSetLayout =
4418 DescriptorSetLayoutBuilder()
4419 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4420 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4421 .build(vk, device, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
4422
4423 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4424 Move<VkPipeline> pipeline = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4425
4426 de::MovePtr<BufferWithMemory> rgenSbt = rtPipeline->createShaderBindingTable(
4427 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
4428 VkStridedDeviceAddressRegionKHR rgenRegion = makeStridedDeviceAddressRegionKHR(
4429 getBufferDeviceAddress(vk, device, **rgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4430 de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4431 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4432 VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4433 getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4434 de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4435 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4436 VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4437 getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4438 const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4439
4440 const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4441
4442 const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4443 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4444 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4445 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4446 const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4447 makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4448 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4449 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4450 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4451 const VkDependencyInfoKHR preClearImageDependency = u::makeDependency(preClearImageImageBarrier);
4452 const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4453
4454 const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4455 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4456 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4457 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4458 const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4459 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4460 VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4461 **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4462 const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4463 const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4464 const VkPipelineStageFlags2KHR srcStageMask = m_params->type == CopyWithinPipelineParams::Type::StageASCopyBit ?
4465 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR :
4466 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR;
4467 const VkMemoryBarrier2KHR copyBlasMemoryBarrier = makeMemoryBarrier2(
4468 srcStageMask, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
4469 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR);
4470 const VkDependencyInfoKHR copyBlasDependency = u::makeDependency(copyBlasMemoryBarrier);
4471
4472 const Move<VkCommandPool> cmdPool =
4473 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4474 const Move<VkCommandBuffer> cmdBuffer =
4475 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4476
4477 std::vector<VkDeviceSize> blasSize(1);
4478 BlasPtr blas1(makeBottomLevelAccelerationStructure().release());
4479
4480 // After this block the blas1 stays on device or host respectively to its build type.
4481 // Once it is created it is asked for the serialization size that will be used for a
4482 // creation of an empty blas2. Probably this size will be bigger than it is needed but
4483 // one thing that is important is it must not be less.
4484 {
4485 const VkQueryType query = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR;
4486 Move<VkQueryPool> queryPoolSize = makeQueryPool(vk, device, query, 1);
4487 beginCommandBuffer(vk, *cmdBuffer);
4488 blas1->setBuildType(m_params->build);
4489 blas1->setGeometryData({{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
4490 blas1->createAndBuild(vk, device, *cmdBuffer, allocator);
4491 queryAccelerationStructureSize(vk, device, *cmdBuffer, {*blas1->getPtr()}, m_params->build, *queryPoolSize,
4492 query, 0u, blasSize);
4493 endCommandBuffer(vk, *cmdBuffer);
4494 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4495 if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
4496 {
4497 VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSize, 0u, 1, sizeof(VkDeviceSize), blasSize.data(),
4498 sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
4499 }
4500 }
4501
4502 de::MovePtr<BufferWithMemory> referenceImageBuffer = getRefImage(blas1);
4503
4504 // Create blas2 as empty struct
4505 BlasPtr blas2(makeBottomLevelAccelerationStructure().release());
4506 blas2->create(vk, device, allocator, blasSize[0]);
4507
4508 auto tlas = makeTopLevelAccelerationStructure();
4509 tlas->setBuildType(m_params->build);
4510 tlas->setInstanceCount(1);
4511 tlas->addInstance(blas2, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4512
4513 const VkCopyAccelerationStructureInfoKHR copyBlasInfo{
4514 VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
4515 nullptr, // const void* pNext;
4516 *blas1->getPtr(), // VkAccelerationStructureKHR src;
4517 *blas2->getPtr(), // VkAccelerationStructureKHR dst;
4518 VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR // VkCopyAccelerationStructureModeKHR mode;
4519 };
4520
4521 beginCommandBuffer(vk, *cmdBuffer);
4522 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4523
4524 if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
4525 {
4526 vk.cmdCopyAccelerationStructureKHR(*cmdBuffer, ©BlasInfo);
4527 vk.cmdPipelineBarrier2(*cmdBuffer, ©BlasDependency);
4528 }
4529 else
4530 VK_CHECK(vk.copyAccelerationStructureKHR(device, VK_NULL_HANDLE, ©BlasInfo));
4531
4532 tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4533
4534 const VkDescriptorImageInfo descriptorImageInfo =
4535 makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4536 const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4537 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
4538 nullptr, // const void* pNext;
4539 1, // uint32_t accelerationStructureCount;
4540 tlas->getPtr() // const VkAccelerationStructureKHR* pAccelerationStructures;
4541 };
4542
4543 DescriptorSetUpdateBuilder()
4544 .writeSingle(VkDescriptorSet(), DescriptorSetUpdateBuilder::Location::binding(0u),
4545 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4546 .writeSingle(VkDescriptorSet(), DescriptorSetUpdateBuilder::Location::binding(1u),
4547 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4548 .updateWithPush(vk, *cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 0, 2);
4549
4550 vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4551 vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4552 &imageSubresourceRange);
4553 vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4554
4555 cmdTraceRays(vk, *cmdBuffer,
4556 &rgenRegion, // rgen
4557 &missRegion, // miss
4558 &chitRegion, // hit
4559 &callRegion, // call
4560 m_params->width, m_params->height, 1);
4561
4562 vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4563 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultImageBuffer, 1u,
4564 &bufferCopyImageRegion);
4565 vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4566
4567 endCommandBuffer(vk, *cmdBuffer);
4568 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4569
4570 invalidateMappedMemoryRange(vk, device, resultImageBuffer->getAllocation().getMemory(),
4571 resultImageBuffer->getAllocation().getOffset(), bufferSize);
4572
4573 const void *referenceImageData = referenceImageBuffer->getAllocation().getHostPtr();
4574 const void *resultImageData = resultImageBuffer->getAllocation().getHostPtr();
4575
4576 return (deMemCmp(referenceImageData, resultImageData, bufferSize) == 0) ?
4577 TestStatus::pass("") :
4578 TestStatus::fail("Reference and result images differ");
4579 }
4580
getBufferSizeForSBT(const uint32_t & groupCount,const uint32_t & shaderGroupHandleSize,const uint32_t & shaderGroupBaseAlignment) const4581 VkDeviceSize CopySBTInstance::getBufferSizeForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4582 const uint32_t &shaderGroupBaseAlignment) const
4583 {
4584 DE_UNREF(shaderGroupBaseAlignment);
4585 return (groupCount * deAlign32(shaderGroupHandleSize, shaderGroupHandleSize));
4586 }
4587
getBufferForSBT(const uint32_t & groupCount,const uint32_t & shaderGroupHandleSize,const uint32_t & shaderGroupBaseAlignment) const4588 de::MovePtr<BufferWithMemory> CopySBTInstance::getBufferForSBT(const uint32_t &groupCount,
4589 const uint32_t &shaderGroupHandleSize,
4590 const uint32_t &shaderGroupBaseAlignment) const
4591 {
4592 const VkDeviceSize sbtSize = getBufferSizeForSBT(groupCount, shaderGroupHandleSize, shaderGroupBaseAlignment);
4593 const VkBufferUsageFlags sbtFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT |
4594 VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
4595 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
4596 const VkBufferCreateInfo sbtCreateInfo = makeBufferCreateInfo(sbtSize, sbtFlags);
4597 const MemoryRequirement sbtMemRequirements =
4598 MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress;
4599
4600 return makeMovePtr<BufferWithMemory>(vk, device, allocator, sbtCreateInfo, sbtMemRequirements);
4601 }
4602
iterate(void)4603 TestStatus CopySBTInstance::iterate(void)
4604 {
4605 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4606 const VkQueue queue = m_context.getUniversalQueue();
4607
4608 const de::MovePtr<RayTracingProperties> rtProps =
4609 makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4610 const uint32_t shaderGroupHandleSize = rtProps->getShaderGroupHandleSize();
4611 const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4612
4613 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4614 const VkImageSubresourceRange imageSubresourceRange =
4615 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4616 const de::MovePtr<ImageWithMemory> image =
4617 makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4618 const Move<VkImageView> view =
4619 makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4620
4621 const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4622 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4623 de::MovePtr<BufferWithMemory> referenceImageBuffer =
4624 makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4625 de::MovePtr<BufferWithMemory> resultImageBuffer =
4626 makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4627
4628 const VkImageSubresourceLayers imageSubresourceLayers =
4629 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4630 const VkBufferImageCopy bufferCopyImageRegion =
4631 makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4632
4633 de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4634 rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4635 rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4636 rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4637
4638 const Move<VkDescriptorPool> descriptorPool =
4639 DescriptorPoolBuilder()
4640 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
4641 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4642 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4643 const Move<VkDescriptorSetLayout> descriptorSetLayout =
4644 DescriptorSetLayoutBuilder()
4645 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4646 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4647 .build(vk, device);
4648 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
4649
4650 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4651 Move<VkPipeline> pipeline = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4652
4653 de::MovePtr<BufferWithMemory> sourceRgenSbt = rtPipeline->createShaderBindingTable(
4654 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, VkBufferCreateFlags(0),
4655 VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
4656 VkStridedDeviceAddressRegionKHR sourceRgenRegion = makeStridedDeviceAddressRegionKHR(
4657 getBufferDeviceAddress(vk, device, **sourceRgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4658 de::MovePtr<BufferWithMemory> copyRgenSbt = getBufferForSBT(1, shaderGroupHandleSize, shaderGroupBaseAlignment);
4659 VkStridedDeviceAddressRegionKHR copyRgenRegion = makeStridedDeviceAddressRegionKHR(
4660 getBufferDeviceAddress(vk, device, **copyRgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4661 de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4662 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4663 VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4664 getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4665 de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4666 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4667 VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4668 getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4669 const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4670
4671 const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4672
4673 const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4674 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4675 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4676 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4677 const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4678 makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4679 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4680 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4681 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4682 const VkDependencyInfoKHR preClearImageDependency = u::makeDependency(preClearImageImageBarrier);
4683 const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4684
4685 const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4686 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4687 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4688 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4689 const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4690 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4691 VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4692 **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4693 const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4694 const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4695
4696 const Move<VkCommandPool> cmdPool =
4697 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4698 const Move<VkCommandBuffer> cmdBuffer =
4699 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4700
4701 auto tlas = makeTopLevelAccelerationStructure();
4702 BlasPtr blas(makeBottomLevelAccelerationStructure().release());
4703 blas->setBuildType(m_params->build);
4704 blas->setGeometryData({{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
4705 tlas->setBuildType(m_params->build);
4706 tlas->setInstanceCount(1);
4707 tlas->addInstance(blas, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4708 beginCommandBuffer(vk, *cmdBuffer);
4709 blas->createAndBuild(vk, device, *cmdBuffer, allocator);
4710 tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4711 endCommandBuffer(vk, *cmdBuffer);
4712 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4713
4714 const VkDescriptorImageInfo descriptorImageInfo =
4715 makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4716 const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4717 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
4718 nullptr, // const void* pNext;
4719 1, // uint32_t accelerationStructureCount;
4720 tlas->getPtr() // const VkAccelerationStructureKHR* pAccelerationStructures;
4721 };
4722
4723 DescriptorSetUpdateBuilder()
4724 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
4725 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4726 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
4727 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4728 .update(vk, device);
4729
4730 beginCommandBuffer(vk, *cmdBuffer);
4731 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4732 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4733 &descriptorSet.get(), 0, nullptr);
4734 vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4735 vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4736 &imageSubresourceRange);
4737 vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4738 cmdTraceRays(vk, *cmdBuffer,
4739 &sourceRgenRegion, // rgen
4740 &missRegion, // miss
4741 &chitRegion, // hit
4742 &callRegion, // call
4743 m_params->width, m_params->height, 1);
4744 vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4745 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **referenceImageBuffer, 1u,
4746 &bufferCopyImageRegion);
4747 vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4748 endCommandBuffer(vk, *cmdBuffer);
4749 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4750
4751 const VkBufferCopy bufferCopy{0, // VkDeviceSize srcOffset;
4752 0, // VkDeviceSize srcOffset;
4753 getBufferSizeForSBT(1, shaderGroupHandleSize, shaderGroupBaseAlignment)};
4754 const VkMemoryBarrier2KHR postCopySBTMemoryBarrier = makeMemoryBarrier2(
4755 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, VkAccessFlags2KHR(0), VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR,
4756 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR);
4757 const VkDependencyInfoKHR postClearImgCopySBTDependency =
4758 u::makeDependency(postCopySBTMemoryBarrier, postClearImageImageBarrier);
4759
4760 beginCommandBuffer(vk, *cmdBuffer);
4761 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4762 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4763 &descriptorSet.get(), 0, nullptr);
4764 vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4765 &imageSubresourceRange);
4766 vk.cmdCopyBuffer(*cmdBuffer, **sourceRgenSbt, **copyRgenSbt, 1, &bufferCopy);
4767 vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImgCopySBTDependency);
4768 cmdTraceRays(vk, *cmdBuffer,
4769 ©RgenRegion, // rgen
4770 &missRegion, // miss
4771 &chitRegion, // hit
4772 &callRegion, // call
4773 m_params->width, m_params->height, 1);
4774 vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4775 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultImageBuffer, 1u,
4776 &bufferCopyImageRegion);
4777 vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4778 endCommandBuffer(vk, *cmdBuffer);
4779 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4780
4781 invalidateMappedMemoryRange(vk, device, referenceImageBuffer->getAllocation().getMemory(),
4782 referenceImageBuffer->getAllocation().getOffset(), bufferSize);
4783 invalidateMappedMemoryRange(vk, device, resultImageBuffer->getAllocation().getMemory(),
4784 resultImageBuffer->getAllocation().getOffset(), bufferSize);
4785
4786 const void *referenceImageDataPtr = referenceImageBuffer->getAllocation().getHostPtr();
4787 const void *resultImageDataPtr = resultImageBuffer->getAllocation().getHostPtr();
4788
4789 return (deMemCmp(referenceImageDataPtr, resultImageDataPtr, bufferSize) == 0) ? TestStatus::pass("") :
4790 TestStatus::fail("");
4791 }
4792
4793 class ASUpdateCase : public RayTracingASBasicTestCase
4794 {
4795 public:
4796 ASUpdateCase(tcu::TestContext &context, const char *name, const TestParams &data);
4797 ~ASUpdateCase(void);
4798
4799 TestInstance *createInstance(Context &context) const override;
4800 };
4801
4802 class ASUpdateInstance : public RayTracingASBasicTestInstance
4803 {
4804 public:
4805 ASUpdateInstance(Context &context, const TestParams &data);
4806 ~ASUpdateInstance(void) = default;
4807 tcu::TestStatus iterate(void) override;
4808
4809 private:
4810 TestParams m_data;
4811 };
4812
ASUpdateCase(tcu::TestContext & context,const char * name,const TestParams & data)4813 ASUpdateCase::ASUpdateCase(tcu::TestContext &context, const char *name, const TestParams &data)
4814 : RayTracingASBasicTestCase(context, name, data)
4815 {
4816 }
4817
~ASUpdateCase(void)4818 ASUpdateCase::~ASUpdateCase(void)
4819 {
4820 }
4821
createInstance(Context & context) const4822 TestInstance *ASUpdateCase::createInstance(Context &context) const
4823 {
4824 return new ASUpdateInstance(context, m_data);
4825 }
4826
ASUpdateInstance(Context & context,const TestParams & data)4827 ASUpdateInstance::ASUpdateInstance(Context &context, const TestParams &data)
4828 : RayTracingASBasicTestInstance(context, data)
4829 , m_data(data)
4830 {
4831 }
4832
iterate(void)4833 TestStatus ASUpdateInstance::iterate(void)
4834 {
4835 const InstanceInterface &vki = m_context.getInstanceInterface();
4836 const DeviceInterface &vkd = m_context.getDeviceInterface();
4837 const VkDevice device = m_context.getDevice();
4838 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
4839 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4840 const VkQueue queue = m_context.getUniversalQueue();
4841 Allocator &allocator = m_context.getDefaultAllocator();
4842 const uint32_t pixelCount = m_data.width * m_data.height;
4843 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
4844 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
4845
4846 const Move<VkDescriptorSetLayout> descriptorSetLayout =
4847 DescriptorSetLayoutBuilder()
4848 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4849 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4850 .build(vkd, device);
4851 const Move<VkDescriptorPool> descriptorPool =
4852 DescriptorPoolBuilder()
4853 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
4854 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4855 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4856 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
4857 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
4858
4859 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
4860 m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
4861 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
4862
4863 de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
4864 de::MovePtr<BufferWithMemory> hitShaderBindingTable;
4865 de::MovePtr<BufferWithMemory> missShaderBindingTable;
4866 m_data.testConfiguration->initShaderBindingTables(
4867 rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment,
4868 raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
4869
4870 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
4871 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
4872 shaderGroupHandleSize, shaderGroupHandleSize);
4873 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
4874 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
4875 shaderGroupHandleSize, shaderGroupHandleSize);
4876 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
4877 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
4878 shaderGroupHandleSize, shaderGroupHandleSize);
4879 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
4880
4881 const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat();
4882 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
4883 const VkImageSubresourceRange imageSubresourceRange =
4884 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4885 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
4886 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
4887 const Move<VkImageView> imageView =
4888 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
4889
4890 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
4891 pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4892 const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
4893 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4894 const VkBufferImageCopy resultBufferImageRegion =
4895 makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
4896 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
4897 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
4898
4899 const VkDescriptorImageInfo descriptorImageInfo =
4900 makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL);
4901
4902 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
4903 const Move<VkCommandBuffer> cmdBuffer =
4904 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4905
4906 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
4907 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
4908 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
4909 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
4910 std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
4911 std::vector<de::SharedPtr<SerialStorage>> topSerialized;
4912 std::vector<VkDeviceSize> accelerationCompactedSizes;
4913 std::vector<VkDeviceSize> accelerationSerialSizes;
4914 Move<VkQueryPool> m_queryPoolCompact;
4915 Move<VkQueryPool> m_queryPoolSerial;
4916
4917 beginCommandBuffer(vkd, *cmdBuffer, 0u);
4918 {
4919 const VkImageMemoryBarrier preImageBarrier =
4920 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
4921 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
4922 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
4923 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
4924 const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
4925 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4926 &imageSubresourceRange);
4927 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
4928 VK_ACCESS_TRANSFER_WRITE_BIT,
4929 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
4930 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
4931 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
4932 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
4933
4934 // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
4935 bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
4936 const bool buildWithoutGeom = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
4937 const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
4938 const bool topNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
4939 const bool inactiveInstances = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
4940 bottomLevelAccelerationStructures =
4941 m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
4942 VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
4943 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
4944 VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
4945 VkBuildAccelerationStructureFlagsKHR bottomCompactFlags =
4946 (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
4947 VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
4948 std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
4949 std::vector<VkDeviceSize> bottomBlasCompactSize;
4950 std::vector<VkDeviceSize> bottomBlasSerialSize;
4951
4952 for (auto &blas : bottomLevelAccelerationStructures)
4953 {
4954 blas->setBuildType(m_data.buildType);
4955 blas->setBuildFlags(bottomBuildFlags);
4956 blas->setUseArrayOfPointers(m_data.bottomUsesAOP);
4957 blas->setCreateGeneric(m_data.bottomGeneric);
4958 blas->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
4959 blas->setBuildWithoutGeometries(buildWithoutGeom);
4960 blas->setBuildWithoutPrimitives(bottomNoPrimitives);
4961 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
4962 accelerationStructureHandles.push_back(*(blas->getPtr()));
4963 }
4964
4965 auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
4966 // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
4967 bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
4968 VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
4969 VkBuildAccelerationStructureFlagsKHR topBuildFlags = m_data.buildFlags | topCompactFlags;
4970 std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
4971 std::vector<VkDeviceSize> topBlasCompactSize;
4972 std::vector<VkDeviceSize> topBlasSerialSize;
4973
4974 topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(
4975 m_context, m_data, *bottomLevelAccelerationStructuresPtr);
4976 topLevelAccelerationStructure->setBuildType(m_data.buildType);
4977 topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
4978 topLevelAccelerationStructure->setBuildWithoutPrimitives(topNoPrimitives);
4979 topLevelAccelerationStructure->setUseArrayOfPointers(m_data.topUsesAOP);
4980 topLevelAccelerationStructure->setCreateGeneric(m_data.topGeneric);
4981 topLevelAccelerationStructure->setCreationBufferUnbounded(m_data.topUnboundedCreation);
4982 topLevelAccelerationStructure->setInactiveInstances(inactiveInstances);
4983 topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
4984 topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
4985
4986 const VkMemoryBarrier postBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
4987 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
4988 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
4989 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postBuildBarrier);
4990
4991 if (m_data.updateCase == UpdateCase::VERTICES)
4992 {
4993 for (auto &blas : bottomLevelAccelerationStructures)
4994 {
4995 const std::vector<tcu::Vec3> vertices = {
4996 tcu::Vec3(0.0f, 0.0f, -0.5f),
4997 tcu::Vec3(0.5f, 0.0f, -0.5f),
4998 tcu::Vec3(0.0f, 0.5f, -0.5f),
4999 };
5000 const std::vector<uint32_t> indices = {0, 1, 2};
5001 de::SharedPtr<RaytracedGeometryBase> geometry;
5002 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_data.vertexFormat, m_data.indexType);
5003
5004 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
5005 geometry->addVertex(*it);
5006
5007 if (m_data.indexType != VK_INDEX_TYPE_NONE_KHR)
5008 {
5009 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
5010 geometry->addIndex(*it);
5011 }
5012 blas->updateGeometry(0, geometry);
5013 blas->build(vkd, device, *cmdBuffer, blas.get());
5014 }
5015 }
5016 else if (m_data.updateCase == UpdateCase::INDICES)
5017 {
5018 for (auto &blas : bottomLevelAccelerationStructures)
5019 {
5020 const std::vector<tcu::Vec3> vertices = {
5021 tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(0.5f, 0.0f, 0.0f), tcu::Vec3(0.0f, 0.5f, 0.0f),
5022 tcu::Vec3(0.0f, 0.0f, -0.5f), tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
5023 };
5024
5025 const std::vector<uint32_t> indices = {3, 4, 5};
5026 de::SharedPtr<RaytracedGeometryBase> geometry;
5027 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_data.vertexFormat, m_data.indexType);
5028
5029 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
5030 geometry->addVertex(*it);
5031
5032 if (m_data.indexType != VK_INDEX_TYPE_NONE_KHR)
5033 {
5034 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
5035 geometry->addIndex(*it);
5036 }
5037 blas->updateGeometry(0, geometry);
5038 blas->build(vkd, device, *cmdBuffer, blas.get());
5039 }
5040 }
5041 else if (m_data.updateCase == UpdateCase::TRANSFORM)
5042 {
5043 const VkTransformMatrixKHR translatedMatrix = {
5044 {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, -0.5f}}};
5045 topLevelAccelerationStructure->updateInstanceMatrix(vkd, device, 0, translatedMatrix);
5046 topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
5047 }
5048
5049 const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
5050 const VkMemoryBarrier preTraceMemoryBarrier =
5051 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
5052 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
5053 cmdPipelineMemoryBarrier(
5054 vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
5055 VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
5056
5057 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
5058 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
5059 nullptr, // const void* pNext;
5060 1u, // uint32_t accelerationStructureCount;
5061 topLevelRayTracedPtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
5062 };
5063
5064 DescriptorSetUpdateBuilder()
5065 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
5066 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
5067 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
5068 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
5069 .update(vkd, device);
5070
5071 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
5072 &descriptorSet.get(), 0, nullptr);
5073
5074 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
5075
5076 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
5077 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
5078
5079 const VkMemoryBarrier postTraceMemoryBarrier =
5080 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
5081 const VkMemoryBarrier postCopyMemoryBarrier =
5082 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5083 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
5084 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
5085
5086 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
5087 &resultBufferImageRegion);
5088
5089 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5090 &postCopyMemoryBarrier);
5091 }
5092 endCommandBuffer(vkd, *cmdBuffer);
5093
5094 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
5095
5096 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
5097 resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t));
5098
5099 bool result = m_data.testConfiguration->verifyImage(resultBuffer.get(), m_context, m_data);
5100
5101 if (result)
5102 return tcu::TestStatus::pass("Pass");
5103 else
5104 return tcu::TestStatus::fail("Fail");
5105 }
5106
5107 } // namespace
5108
addBasicBuildingTests(tcu::TestCaseGroup * group)5109 void addBasicBuildingTests(tcu::TestCaseGroup *group)
5110 {
5111 struct
5112 {
5113 vk::VkAccelerationStructureBuildTypeKHR buildType;
5114 const char *name;
5115 } buildTypes[] = {
5116 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5117 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5118 };
5119
5120 struct
5121 {
5122 BottomTestType testType;
5123 bool usesAOP;
5124 const char *name;
5125 } bottomTestTypes[] = {
5126 {BottomTestType::TRIANGLES, false, "triangles"},
5127 {BottomTestType::TRIANGLES, true, "triangles_aop"},
5128 {BottomTestType::AABBS, false, "aabbs"},
5129 {BottomTestType::AABBS, true, "aabbs_aop"},
5130 };
5131
5132 struct
5133 {
5134 TopTestType testType;
5135 bool usesAOP;
5136 const char *name;
5137 } topTestTypes[] = {
5138 {TopTestType::IDENTICAL_INSTANCES, false, "identical_instances"},
5139 {TopTestType::IDENTICAL_INSTANCES, true, "identical_instances_aop"},
5140 {TopTestType::DIFFERENT_INSTANCES, false, "different_instances"},
5141 {TopTestType::DIFFERENT_INSTANCES, true, "different_instances_aop"},
5142 };
5143
5144 struct BuildFlagsData
5145 {
5146 VkBuildAccelerationStructureFlagsKHR flags;
5147 const char *name;
5148 };
5149
5150 BuildFlagsData optimizationTypes[] = {
5151 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5152 {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, "fasttrace"},
5153 {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, "fastbuild"},
5154 };
5155
5156 BuildFlagsData updateTypes[] = {
5157 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5158 {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, "update"},
5159 };
5160
5161 BuildFlagsData compactionTypes[] = {
5162 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5163 {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, "compaction"},
5164 };
5165
5166 BuildFlagsData lowMemoryTypes[] = {
5167 {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5168 {VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, "lowmemory"},
5169 };
5170
5171 struct
5172 {
5173 bool padVertices;
5174 const char *name;
5175 } paddingType[] = {
5176 {false, "nopadding"},
5177 {true, "padded"},
5178 };
5179
5180 struct
5181 {
5182 bool topGeneric;
5183 bool bottomGeneric;
5184 const char *suffix;
5185 } createGenericParams[] = {
5186 {false, false, ""},
5187 {false, true, "_bottomgeneric"},
5188 {true, false, "_topgeneric"},
5189 {true, true, "_bothgeneric"},
5190 };
5191
5192 // In order not to create thousands of new test variants for unbound buffer memory on acceleration structure creation, we will
5193 // set these options on some of the tests.
5194 de::ModCounter32 unboundedCreationBottomCounter(3u);
5195 de::ModCounter32 unboundedCreationTopCounter(7u);
5196
5197 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5198 {
5199 de::MovePtr<tcu::TestCaseGroup> buildGroup(
5200 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5201
5202 for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
5203 {
5204 de::MovePtr<tcu::TestCaseGroup> bottomGroup(
5205 new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name));
5206
5207 for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
5208 {
5209 de::MovePtr<tcu::TestCaseGroup> topGroup(
5210 new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name));
5211
5212 for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
5213 {
5214 de::MovePtr<tcu::TestCaseGroup> paddingGroup(
5215 new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name));
5216
5217 for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes);
5218 ++optimizationNdx)
5219 {
5220 for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
5221 {
5222 for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes);
5223 ++compactionNdx)
5224 {
5225 for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes);
5226 ++lowMemoryNdx)
5227 {
5228 for (int createGenericIdx = 0;
5229 createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams); ++createGenericIdx)
5230 {
5231 std::string testName =
5232 std::string(optimizationTypes[optimizationNdx].name) + "_" +
5233 std::string(updateTypes[updateNdx].name) + "_" +
5234 std::string(compactionTypes[compactionNdx].name) + "_" +
5235 std::string(lowMemoryTypes[lowMemoryNdx].name) +
5236 std::string(createGenericParams[createGenericIdx].suffix);
5237
5238 const bool unboundedCreationBottom =
5239 (static_cast<uint32_t>(unboundedCreationBottomCounter++) == 0u);
5240 const bool unboundedCreationTop =
5241 (static_cast<uint32_t>(unboundedCreationTopCounter++) == 0u);
5242
5243 TestParams testParams{
5244 buildTypes[buildTypeNdx].buildType,
5245 VK_FORMAT_R32G32B32_SFLOAT,
5246 paddingType[paddingTypeIdx].padVertices,
5247 VK_INDEX_TYPE_NONE_KHR,
5248 bottomTestTypes[bottomNdx].testType,
5249 InstanceCullFlags::NONE,
5250 bottomTestTypes[bottomNdx].usesAOP,
5251 createGenericParams[createGenericIdx].bottomGeneric,
5252 unboundedCreationBottom,
5253 topTestTypes[topNdx].testType,
5254 topTestTypes[topNdx].usesAOP,
5255 createGenericParams[createGenericIdx].topGeneric,
5256 unboundedCreationTop,
5257 optimizationTypes[optimizationNdx].flags | updateTypes[updateNdx].flags |
5258 compactionTypes[compactionNdx].flags |
5259 lowMemoryTypes[lowMemoryNdx].flags,
5260 OT_NONE,
5261 OP_NONE,
5262 RTAS_DEFAULT_SIZE,
5263 RTAS_DEFAULT_SIZE,
5264 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5265 0u,
5266 EmptyAccelerationStructureCase::NOT_EMPTY,
5267 InstanceCustomIndexCase::NONE,
5268 false,
5269 0xFFu,
5270 UpdateCase::NONE,
5271 };
5272 paddingGroup->addChild(new RayTracingASBasicTestCase(
5273 group->getTestContext(), testName.c_str(), testParams));
5274 }
5275 }
5276 }
5277 }
5278 }
5279 topGroup->addChild(paddingGroup.release());
5280 }
5281 bottomGroup->addChild(topGroup.release());
5282 }
5283 buildGroup->addChild(bottomGroup.release());
5284 }
5285 group->addChild(buildGroup.release());
5286 }
5287 }
5288
addVertexIndexFormatsTests(tcu::TestCaseGroup * group)5289 void addVertexIndexFormatsTests(tcu::TestCaseGroup *group)
5290 {
5291 struct
5292 {
5293 vk::VkAccelerationStructureBuildTypeKHR buildType;
5294 const char *name;
5295 } buildTypes[] = {
5296 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5297 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5298 };
5299
5300 const VkFormat vertexFormats[] = {
5301 // Mandatory formats.
5302 VK_FORMAT_R32G32_SFLOAT,
5303 VK_FORMAT_R32G32B32_SFLOAT,
5304 VK_FORMAT_R16G16_SFLOAT,
5305 VK_FORMAT_R16G16B16A16_SFLOAT,
5306 VK_FORMAT_R16G16_SNORM,
5307 VK_FORMAT_R16G16B16A16_SNORM,
5308
5309 // Additional formats.
5310 VK_FORMAT_R8G8_SNORM,
5311 VK_FORMAT_R8G8B8_SNORM,
5312 VK_FORMAT_R8G8B8A8_SNORM,
5313 VK_FORMAT_R16G16B16_SNORM,
5314 VK_FORMAT_R16G16B16_SFLOAT,
5315 VK_FORMAT_R32G32B32A32_SFLOAT,
5316 VK_FORMAT_R64G64_SFLOAT,
5317 VK_FORMAT_R64G64B64_SFLOAT,
5318 VK_FORMAT_R64G64B64A64_SFLOAT,
5319 };
5320
5321 struct
5322 {
5323 VkIndexType indexType;
5324 const char *name;
5325 } indexFormats[] = {
5326 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5327 {VK_INDEX_TYPE_UINT16, "index_uint16"},
5328 {VK_INDEX_TYPE_UINT32, "index_uint32"},
5329 };
5330
5331 struct
5332 {
5333 bool padVertices;
5334 const char *name;
5335 } paddingType[] = {
5336 {false, "nopadding"},
5337 {true, "padded"},
5338 };
5339
5340 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5341 {
5342 de::MovePtr<tcu::TestCaseGroup> buildGroup(
5343 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5344
5345 for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
5346 {
5347 const auto format = vertexFormats[vertexFormatNdx];
5348 const auto formatName = getFormatSimpleName(format);
5349
5350 de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(
5351 new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
5352
5353 for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
5354 {
5355 de::MovePtr<tcu::TestCaseGroup> paddingGroup(
5356 new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name));
5357
5358 for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
5359 {
5360 TestParams testParams{
5361 buildTypes[buildTypeNdx].buildType,
5362 format,
5363 paddingType[paddingIdx].padVertices,
5364 indexFormats[indexFormatNdx].indexType,
5365 BottomTestType::TRIANGLES,
5366 InstanceCullFlags::NONE,
5367 false,
5368 false,
5369 false,
5370 TopTestType::IDENTICAL_INSTANCES,
5371 false,
5372 false,
5373 false,
5374 VkBuildAccelerationStructureFlagsKHR(0u),
5375 OT_NONE,
5376 OP_NONE,
5377 RTAS_DEFAULT_SIZE,
5378 RTAS_DEFAULT_SIZE,
5379 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5380 0u,
5381 EmptyAccelerationStructureCase::NOT_EMPTY,
5382 InstanceCustomIndexCase::NONE,
5383 false,
5384 0xFFu,
5385 UpdateCase::NONE,
5386 };
5387 paddingGroup->addChild(new RayTracingASBasicTestCase(
5388 group->getTestContext(), indexFormats[indexFormatNdx].name, testParams));
5389 }
5390 vertexFormatGroup->addChild(paddingGroup.release());
5391 }
5392 buildGroup->addChild(vertexFormatGroup.release());
5393 }
5394 group->addChild(buildGroup.release());
5395 }
5396 }
5397
addOperationTestsImpl(tcu::TestCaseGroup * group,const uint32_t workerThreads)5398 void addOperationTestsImpl(tcu::TestCaseGroup *group, const uint32_t workerThreads)
5399 {
5400 struct
5401 {
5402 OperationType operationType;
5403 const char *name;
5404 } operationTypes[] = {
5405 {OP_COPY, "copy"},
5406 {OP_COMPACT, "compaction"},
5407 {OP_SERIALIZE, "serialization"},
5408 };
5409
5410 struct
5411 {
5412 vk::VkAccelerationStructureBuildTypeKHR buildType;
5413 const char *name;
5414 } buildTypes[] = {
5415 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5416 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5417 };
5418
5419 struct
5420 {
5421 OperationTarget operationTarget;
5422 const char *name;
5423 } operationTargets[] = {
5424 {OT_TOP_ACCELERATION, "top_acceleration_structure"},
5425 {OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure"},
5426 };
5427
5428 struct
5429 {
5430 BottomTestType testType;
5431 const char *name;
5432 } bottomTestTypes[] = {
5433 {BottomTestType::TRIANGLES, "triangles"},
5434 {BottomTestType::AABBS, "aabbs"},
5435 };
5436
5437 for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
5438 {
5439 if (workerThreads > 0)
5440 if (operationTypes[operationTypeNdx].operationType != OP_COPY &&
5441 operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
5442 continue;
5443
5444 de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(
5445 new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name));
5446
5447 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5448 {
5449 if (workerThreads > 0 &&
5450 buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
5451 continue;
5452
5453 de::MovePtr<tcu::TestCaseGroup> buildGroup(
5454 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5455
5456 for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets);
5457 ++operationTargetNdx)
5458 {
5459 de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(
5460 new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name));
5461
5462 for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
5463 {
5464 TopTestType topTest =
5465 (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ?
5466 TopTestType::DIFFERENT_INSTANCES :
5467 TopTestType::IDENTICAL_INSTANCES;
5468
5469 TestParams testParams{
5470 buildTypes[buildTypeNdx].buildType,
5471 VK_FORMAT_R32G32B32_SFLOAT,
5472 false,
5473 VK_INDEX_TYPE_NONE_KHR,
5474 bottomTestTypes[testTypeNdx].testType,
5475 InstanceCullFlags::NONE,
5476 false,
5477 false,
5478 false,
5479 topTest,
5480 false,
5481 false,
5482 false,
5483 VkBuildAccelerationStructureFlagsKHR(0u),
5484 operationTargets[operationTargetNdx].operationTarget,
5485 operationTypes[operationTypeNdx].operationType,
5486 RTAS_DEFAULT_SIZE,
5487 RTAS_DEFAULT_SIZE,
5488 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5489 workerThreads,
5490 EmptyAccelerationStructureCase::NOT_EMPTY,
5491 InstanceCustomIndexCase::NONE,
5492 false,
5493 0xFFu,
5494 UpdateCase::NONE,
5495 };
5496 operationTargetGroup->addChild(new RayTracingASBasicTestCase(
5497 group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams));
5498 }
5499 buildGroup->addChild(operationTargetGroup.release());
5500 }
5501 operationTypeGroup->addChild(buildGroup.release());
5502 }
5503 group->addChild(operationTypeGroup.release());
5504 }
5505 }
5506
addOperationTests(tcu::TestCaseGroup * group)5507 void addOperationTests(tcu::TestCaseGroup *group)
5508 {
5509 addOperationTestsImpl(group, 0);
5510 }
5511
addHostThreadingOperationTests(tcu::TestCaseGroup * group)5512 void addHostThreadingOperationTests(tcu::TestCaseGroup *group)
5513 {
5514 const uint32_t threads[] = {1, 2, 3, 4, 8, std::numeric_limits<uint32_t>::max()};
5515
5516 for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
5517 {
5518 const std::string groupName =
5519 threads[threadsNdx] != std::numeric_limits<uint32_t>::max() ? de::toString(threads[threadsNdx]) : "max";
5520
5521 de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str()));
5522
5523 addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
5524
5525 group->addChild(threadGroup.release());
5526 }
5527 }
5528
addFuncArgTests(tcu::TestCaseGroup * group)5529 void addFuncArgTests(tcu::TestCaseGroup *group)
5530 {
5531 const struct
5532 {
5533 vk::VkAccelerationStructureBuildTypeKHR buildType;
5534 const char *name;
5535 } buildTypes[] = {
5536 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5537 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5538 };
5539
5540 auto &ctx = group->getTestContext();
5541
5542 for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5543 {
5544 TestParams testParams{
5545 buildTypes[buildTypeNdx].buildType,
5546 VK_FORMAT_R32G32B32_SFLOAT,
5547 false,
5548 VK_INDEX_TYPE_NONE_KHR,
5549 BottomTestType::TRIANGLES,
5550 InstanceCullFlags::NONE,
5551 false,
5552 false,
5553 false,
5554 TopTestType::IDENTICAL_INSTANCES,
5555 false,
5556 false,
5557 false,
5558 VkBuildAccelerationStructureFlagsKHR(0u),
5559 OT_NONE,
5560 OP_NONE,
5561 RTAS_DEFAULT_SIZE,
5562 RTAS_DEFAULT_SIZE,
5563 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5564 0u,
5565 EmptyAccelerationStructureCase::NOT_EMPTY,
5566 InstanceCustomIndexCase::NONE,
5567 false,
5568 0xFFu,
5569 UpdateCase::NONE,
5570 };
5571
5572 group->addChild(new RayTracingASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, testParams));
5573 }
5574 }
5575
addInstanceTriangleCullingTests(tcu::TestCaseGroup * group)5576 void addInstanceTriangleCullingTests(tcu::TestCaseGroup *group)
5577 {
5578 const struct
5579 {
5580 InstanceCullFlags cullFlags;
5581 std::string name;
5582 } cullFlags[] = {
5583 {InstanceCullFlags::NONE, "noflags"},
5584 {InstanceCullFlags::COUNTERCLOCKWISE, "ccw"},
5585 {InstanceCullFlags::CULL_DISABLE, "nocull"},
5586 {InstanceCullFlags::ALL, "ccw_nocull"},
5587 };
5588
5589 const struct
5590 {
5591 TopTestType topType;
5592 std::string name;
5593 } topType[] = {
5594 {TopTestType::DIFFERENT_INSTANCES, "transformed"}, // Each instance has its own transformation matrix.
5595 {TopTestType::IDENTICAL_INSTANCES, "notransform"}, // "Identical" instances, different geometries.
5596 };
5597
5598 const struct
5599 {
5600 vk::VkAccelerationStructureBuildTypeKHR buildType;
5601 std::string name;
5602 } buildTypes[] = {
5603 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5604 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5605 };
5606
5607 const struct
5608 {
5609 VkIndexType indexType;
5610 std::string name;
5611 } indexFormats[] = {
5612 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5613 {VK_INDEX_TYPE_UINT16, "index_uint16"},
5614 {VK_INDEX_TYPE_UINT32, "index_uint32"},
5615 };
5616
5617 auto &ctx = group->getTestContext();
5618
5619 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5620 {
5621 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5622 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5623
5624 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
5625 {
5626 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
5627 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
5628
5629 for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
5630 {
5631 for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
5632 {
5633 const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
5634
5635 TestParams testParams{
5636 buildTypes[buildTypeIdx].buildType,
5637 VK_FORMAT_R32G32B32_SFLOAT,
5638 false,
5639 indexFormats[indexFormatIdx].indexType,
5640 BottomTestType::TRIANGLES,
5641 cullFlags[cullFlagsIdx].cullFlags,
5642 false,
5643 false,
5644 false,
5645 topType[topTypeIdx].topType,
5646 false,
5647 false,
5648 false,
5649 VkBuildAccelerationStructureFlagsKHR(0u),
5650 OT_NONE,
5651 OP_NONE,
5652 RTAS_DEFAULT_SIZE,
5653 RTAS_DEFAULT_SIZE,
5654 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5655 0u,
5656 EmptyAccelerationStructureCase::NOT_EMPTY,
5657 InstanceCustomIndexCase::NONE,
5658 false,
5659 0xFFu,
5660 UpdateCase::NONE,
5661 };
5662 indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, testName.c_str(), testParams));
5663 }
5664 }
5665 buildTypeGroup->addChild(indexTypeGroup.release());
5666 }
5667 group->addChild(buildTypeGroup.release());
5668 }
5669 }
5670
addDynamicIndexingTests(tcu::TestCaseGroup * group)5671 void addDynamicIndexingTests(tcu::TestCaseGroup *group)
5672 {
5673 auto &ctx = group->getTestContext();
5674 group->addChild(new RayTracingASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
5675 }
5676
addEmptyAccelerationStructureTests(tcu::TestCaseGroup * group)5677 void addEmptyAccelerationStructureTests(tcu::TestCaseGroup *group)
5678 {
5679 const struct
5680 {
5681 vk::VkAccelerationStructureBuildTypeKHR buildType;
5682 std::string name;
5683 } buildTypes[] = {
5684 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5685 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5686 };
5687
5688 const struct
5689 {
5690 VkIndexType indexType;
5691 std::string name;
5692 } indexFormats[] = {
5693 {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5694 {VK_INDEX_TYPE_UINT16, "index_uint16"},
5695 {VK_INDEX_TYPE_UINT32, "index_uint32"},
5696 };
5697
5698 const struct
5699 {
5700 EmptyAccelerationStructureCase emptyASCase;
5701 std::string name;
5702 } emptyCases[] = {
5703 {EmptyAccelerationStructureCase::INACTIVE_TRIANGLES, "inactive_triangles"},
5704 {EmptyAccelerationStructureCase::INACTIVE_INSTANCES, "inactive_instances"},
5705 {EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM, "no_geometries_bottom"},
5706 {EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP, "no_primitives_top"},
5707 {EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM, "no_primitives_bottom"},
5708 };
5709
5710 auto &ctx = group->getTestContext();
5711
5712 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5713 {
5714 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5715 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5716
5717 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
5718 {
5719 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
5720 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
5721
5722 for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
5723 {
5724
5725 TestParams testParams{
5726 buildTypes[buildTypeIdx].buildType,
5727 VK_FORMAT_R32G32B32_SFLOAT,
5728 false,
5729 indexFormats[indexFormatIdx].indexType,
5730 BottomTestType::TRIANGLES,
5731 InstanceCullFlags::NONE,
5732 false,
5733 false,
5734 false,
5735 TopTestType::IDENTICAL_INSTANCES,
5736 false,
5737 false,
5738 false,
5739 VkBuildAccelerationStructureFlagsKHR(0u),
5740 OT_NONE,
5741 OP_NONE,
5742 RTAS_DEFAULT_SIZE,
5743 RTAS_DEFAULT_SIZE,
5744 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5745 0u,
5746 emptyCases[emptyCaseIdx].emptyASCase,
5747 InstanceCustomIndexCase::NONE,
5748 false,
5749 0xFFu,
5750 UpdateCase::NONE,
5751 };
5752 indexTypeGroup->addChild(
5753 new RayTracingASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), testParams));
5754 }
5755 buildTypeGroup->addChild(indexTypeGroup.release());
5756 }
5757 group->addChild(buildTypeGroup.release());
5758 }
5759 }
5760
addInstanceIndexTests(tcu::TestCaseGroup * group)5761 void addInstanceIndexTests(tcu::TestCaseGroup *group)
5762 {
5763 const struct
5764 {
5765 vk::VkAccelerationStructureBuildTypeKHR buildType;
5766 std::string name;
5767 } buildTypes[] = {
5768 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5769 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5770 };
5771
5772 const struct
5773 {
5774 InstanceCustomIndexCase customIndexCase;
5775 std::string name;
5776 } customIndexCases[] = {
5777 {InstanceCustomIndexCase::NONE, "no_instance_index"},
5778 {InstanceCustomIndexCase::ANY_HIT, "ahit"},
5779 {InstanceCustomIndexCase::CLOSEST_HIT, "chit"},
5780 {InstanceCustomIndexCase::INTERSECTION, "isec"},
5781 };
5782
5783 auto &ctx = group->getTestContext();
5784
5785 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5786 {
5787 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5788 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5789
5790 for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases);
5791 ++customIndexCaseIdx)
5792 {
5793 const auto &idxCase = customIndexCases[customIndexCaseIdx].customIndexCase;
5794 const auto bottomGeometryType =
5795 ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BottomTestType::AABBS :
5796 BottomTestType::TRIANGLES);
5797
5798 TestParams testParams{
5799 buildTypes[buildTypeIdx].buildType,
5800 VK_FORMAT_R32G32B32_SFLOAT,
5801 false,
5802 VK_INDEX_TYPE_NONE_KHR,
5803 bottomGeometryType,
5804 InstanceCullFlags::NONE,
5805 false,
5806 false,
5807 false,
5808 TopTestType::IDENTICAL_INSTANCES,
5809 false,
5810 false,
5811 false,
5812 VkBuildAccelerationStructureFlagsKHR(0u),
5813 OT_NONE,
5814 OP_NONE,
5815 RTAS_DEFAULT_SIZE,
5816 RTAS_DEFAULT_SIZE,
5817 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5818 0u,
5819 EmptyAccelerationStructureCase::NOT_EMPTY,
5820 customIndexCases[customIndexCaseIdx].customIndexCase,
5821 false,
5822 0xFFu,
5823 UpdateCase::NONE,
5824 };
5825 buildTypeGroup->addChild(
5826 new RayTracingASBasicTestCase(ctx, customIndexCases[customIndexCaseIdx].name.c_str(), testParams));
5827 }
5828 group->addChild(buildTypeGroup.release());
5829 }
5830 }
5831
addInstanceUpdateTests(tcu::TestCaseGroup * group)5832 void addInstanceUpdateTests(tcu::TestCaseGroup *group)
5833 {
5834 const struct
5835 {
5836 vk::VkAccelerationStructureBuildTypeKHR buildType;
5837 std::string name;
5838 } buildTypes[] = {
5839 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5840 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5841 };
5842
5843 struct
5844 {
5845 OperationType operationType;
5846 const char *name;
5847 } operationTypes[] = {
5848 {OP_UPDATE, "update"},
5849 {OP_UPDATE_IN_PLACE, "update_in_place"},
5850 };
5851
5852 auto &ctx = group->getTestContext();
5853
5854 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5855 {
5856 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5857 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5858
5859 for (int operationTypesIdx = 0; operationTypesIdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypesIdx)
5860 {
5861 TestParams testParams{
5862 buildTypes[buildTypeIdx].buildType,
5863 VK_FORMAT_R32G32B32_SFLOAT,
5864 false,
5865 VK_INDEX_TYPE_NONE_KHR,
5866 BottomTestType::TRIANGLES,
5867 InstanceCullFlags::NONE,
5868 false,
5869 false,
5870 false,
5871 TopTestType::IDENTICAL_INSTANCES,
5872 false,
5873 false,
5874 false,
5875 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
5876 OT_TOP_ACCELERATION,
5877 operationTypes[operationTypesIdx].operationType,
5878 RTAS_DEFAULT_SIZE,
5879 RTAS_DEFAULT_SIZE,
5880 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5881 0u,
5882 EmptyAccelerationStructureCase::NOT_EMPTY,
5883 InstanceCustomIndexCase::NONE,
5884 false,
5885 0xFFu,
5886 UpdateCase::NONE,
5887 };
5888 buildTypeGroup->addChild(
5889 new RayTracingASBasicTestCase(ctx, operationTypes[operationTypesIdx].name, testParams));
5890 }
5891 group->addChild(buildTypeGroup.release());
5892 }
5893 }
5894
addInstanceRayCullMaskTests(tcu::TestCaseGroup * group)5895 void addInstanceRayCullMaskTests(tcu::TestCaseGroup *group)
5896 {
5897 const struct
5898 {
5899 vk::VkAccelerationStructureBuildTypeKHR buildType;
5900 std::string name;
5901 } buildTypes[] = {
5902 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5903 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5904 };
5905
5906 const struct
5907 {
5908 InstanceCustomIndexCase customIndexCase;
5909 std::string name;
5910 } customIndexCases[] = {
5911 {InstanceCustomIndexCase::ANY_HIT, "ahit"},
5912 {InstanceCustomIndexCase::CLOSEST_HIT, "chit"},
5913 {InstanceCustomIndexCase::INTERSECTION, "isec"},
5914 };
5915
5916 const struct
5917 {
5918 uint32_t cullMask;
5919 std::string name;
5920 } cullMask[] = {
5921 {0x000000AAu, "4_bits"},
5922 {0x00000055u, "4_bits_reverse"},
5923 {0xAAAAAAAAu, "16_bits"},
5924 {0x55555555u, "16_bits_reverse"},
5925 };
5926
5927 auto &ctx = group->getTestContext();
5928
5929 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5930 {
5931 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5932 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5933
5934 for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases);
5935 ++customIndexCaseIdx)
5936 {
5937 de::MovePtr<tcu::TestCaseGroup> customIndexCaseGroup(
5938 new tcu::TestCaseGroup(ctx, customIndexCases[customIndexCaseIdx].name.c_str()));
5939
5940 for (int cullMaskIdx = 0; cullMaskIdx < DE_LENGTH_OF_ARRAY(cullMask); ++cullMaskIdx)
5941 {
5942 const auto &idxCase = customIndexCases[customIndexCaseIdx].customIndexCase;
5943 const auto bottomGeometryType =
5944 ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BottomTestType::AABBS :
5945 BottomTestType::TRIANGLES);
5946
5947 TestParams testParams{
5948 buildTypes[buildTypeIdx].buildType,
5949 VK_FORMAT_R32G32B32_SFLOAT,
5950 false,
5951 VK_INDEX_TYPE_NONE_KHR,
5952 bottomGeometryType,
5953 InstanceCullFlags::NONE,
5954 false,
5955 false,
5956 false,
5957 TopTestType::IDENTICAL_INSTANCES,
5958 false,
5959 false,
5960 false,
5961 VkBuildAccelerationStructureFlagsKHR(0u),
5962 OT_NONE,
5963 OP_NONE,
5964 RTAS_DEFAULT_SIZE,
5965 RTAS_DEFAULT_SIZE,
5966 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5967 0u,
5968 EmptyAccelerationStructureCase::NOT_EMPTY,
5969 customIndexCases[customIndexCaseIdx].customIndexCase,
5970 true,
5971 cullMask[cullMaskIdx].cullMask,
5972 UpdateCase::NONE,
5973 };
5974 customIndexCaseGroup->addChild(
5975 new RayTracingASBasicTestCase(ctx, cullMask[cullMaskIdx].name.c_str(), testParams));
5976 }
5977 buildTypeGroup->addChild(customIndexCaseGroup.release());
5978 }
5979 group->addChild(buildTypeGroup.release());
5980 }
5981 }
5982
addGetDeviceAccelerationStructureCompabilityTests(tcu::TestCaseGroup * group)5983 void addGetDeviceAccelerationStructureCompabilityTests(tcu::TestCaseGroup *group)
5984 {
5985 struct
5986 {
5987 vk::VkAccelerationStructureBuildTypeKHR buildType;
5988 std::string name;
5989 } const buildTypes[] = {
5990 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5991 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5992 };
5993
5994 struct
5995 {
5996 OperationTarget target;
5997 std::string name;
5998 } const targets[] = {
5999 {OT_TOP_ACCELERATION, "top"},
6000 {OT_BOTTOM_ACCELERATION, "bottom"},
6001 };
6002
6003 auto &ctx = group->getTestContext();
6004
6005 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6006 {
6007 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6008 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6009
6010 for (int targetIdx = 0; targetIdx < DE_LENGTH_OF_ARRAY(targets); ++targetIdx)
6011 {
6012 TestParams testParams{
6013 buildTypes[buildTypeIdx].buildType, // buildType - are we making AS on CPU or GPU
6014 VK_FORMAT_R32G32B32_SFLOAT, // vertexFormat
6015 false, // padVertices
6016 VK_INDEX_TYPE_NONE_KHR, // indexType
6017 BottomTestType::TRIANGLES, // bottomTestType - what kind of geometry is stored in bottom AS
6018 InstanceCullFlags::NONE, // cullFlags - Flags for instances, if needed.
6019 false, // bottomUsesAOP - does bottom AS use arrays, or arrays of pointers
6020 false, // bottomGeneric - Bottom created as generic AS type.
6021 false, // bottomUnboundedCreation - Create BLAS using buffers with unbounded memory.
6022 TopTestType::
6023 IDENTICAL_INSTANCES, // topTestType - If instances are identical then bottom geometries must have different vertices/aabbs
6024 false, // topUsesAOP - does top AS use arrays, or arrays of pointers
6025 false, // topGeneric - Top created as generic AS type.
6026 false, // topUnboundedCreation - Create TLAS using buffers with unbounded memory.
6027 VkBuildAccelerationStructureFlagsKHR(0u), // buildFlags
6028 targets[targetIdx].target, // operationTarget
6029 OP_NONE, // operationType
6030 RTAS_DEFAULT_SIZE, // width
6031 RTAS_DEFAULT_SIZE, // height
6032 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()), // testConfiguration
6033 0u, // workerThreadsCount
6034 EmptyAccelerationStructureCase::NOT_EMPTY, // emptyASCase
6035 InstanceCustomIndexCase::NONE, // instanceCustomIndexCase
6036 false, // useCullMask
6037 0xFFu, // cullMask
6038 UpdateCase::NONE, // updateCase
6039 };
6040 buildTypeGroup->addChild(new RayTracingDeviceASCompabilityKHRTestCase(
6041 ctx, targets[targetIdx].name.c_str(), de::SharedPtr<TestParams>(new TestParams(testParams))));
6042 }
6043 group->addChild(buildTypeGroup.release());
6044 }
6045 }
6046
addUpdateHeaderBottomAddressTests(tcu::TestCaseGroup * group)6047 void addUpdateHeaderBottomAddressTests(tcu::TestCaseGroup *group)
6048 {
6049 struct
6050 {
6051 vk::VkAccelerationStructureBuildTypeKHR buildType;
6052 std::string name;
6053 } const buildTypes[] = {
6054 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
6055 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
6056 };
6057
6058 struct
6059 {
6060 TopTestType type;
6061 std::string name;
6062 } const instTypes[] = {
6063 {TopTestType::IDENTICAL_INSTANCES, "the_same_instances"},
6064 {TopTestType::DIFFERENT_INSTANCES, "different_instances"},
6065 {TopTestType::MIX_INSTANCES, "mix_same_diff_instances"},
6066 };
6067
6068 auto &ctx = group->getTestContext();
6069
6070 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6071 {
6072 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6073 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6074
6075 for (int instTypeIdx = 0; instTypeIdx < DE_LENGTH_OF_ARRAY(instTypes); ++instTypeIdx)
6076 {
6077 TestParams testParams{
6078 buildTypes[buildTypeIdx].buildType, // buildType
6079 VK_FORMAT_R32G32B32_SFLOAT, // vertexFormat
6080 false, // padVertices
6081 VK_INDEX_TYPE_NONE_KHR, // indexType
6082 BottomTestType::TRIANGLES, // bottomTestType
6083 InstanceCullFlags::NONE, // cullFlags
6084 false, // bottomUsesAOP
6085 false, // bottomGeneric
6086 false, // bottomUnboundedCreation
6087 instTypes[instTypeIdx].type, // topTestType
6088 false, // topUsesAOP
6089 false, // topGeneric
6090 false, // topUnboundedCreation
6091 VkBuildAccelerationStructureFlagsKHR(0u), // buildFlags
6092 OT_TOP_ACCELERATION, // operationTarget
6093 OP_NONE, // operationType
6094 RTAS_DEFAULT_SIZE, // width
6095 RTAS_DEFAULT_SIZE, // height
6096 de::SharedPtr<TestConfiguration>(nullptr), // testConfiguration
6097 0u, // workerThreadsCount
6098 EmptyAccelerationStructureCase::NOT_EMPTY, // emptyASCase
6099 InstanceCustomIndexCase::NONE, // instanceCustomIndexCase
6100 false, // useCullMask
6101 0xFFu, // cullMask
6102 UpdateCase::NONE, // updateCase
6103 };
6104 buildTypeGroup->addChild(new RayTracingHeaderBottomAddressTestCase(
6105 ctx, instTypes[instTypeIdx].name.c_str(), de::SharedPtr<TestParams>(new TestParams(testParams))));
6106 }
6107 group->addChild(buildTypeGroup.release());
6108 }
6109 }
6110
addQueryPoolResultsTests(TestCaseGroup * group)6111 void addQueryPoolResultsTests(TestCaseGroup *group)
6112 {
6113 std::pair<VkAccelerationStructureBuildTypeKHR, const char *> const buildTypes[]{
6114 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6115 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6116 };
6117
6118 std::pair<bool, const char *> const storeTypes[]{{false, "memory"}, {true, "buffer"}};
6119
6120 std::pair<QueryPoolResultsParams::Type, const char *> const queryTypes[]{
6121 {QueryPoolResultsParams::Type::StructureSize, "structure_size"},
6122 {QueryPoolResultsParams::Type::PointerCount, "pointer_count"}};
6123
6124 std::pair<bool, const char *> const buildWithCompacted[]{{false, "no_compacted"}, {true, "enable_compacted"}};
6125
6126 auto &testContext = group->getTestContext();
6127 for (const auto &buildType : buildTypes)
6128 {
6129 auto buildTypeGroup = makeMovePtr<TestCaseGroup>(testContext, buildType.second);
6130 for (const auto &compacted : buildWithCompacted)
6131 {
6132 auto buildCompactedGroup = makeMovePtr<TestCaseGroup>(testContext, compacted.second);
6133 for (const auto &storeType : storeTypes)
6134 {
6135 auto storeTypeGroup = makeMovePtr<TestCaseGroup>(testContext, storeType.second);
6136 for (const auto &queryType : queryTypes)
6137 {
6138 QueryPoolResultsParams p;
6139 p.buildType = buildType.first;
6140 p.inVkBuffer = storeType.first;
6141 p.queryType = queryType.first;
6142 p.blasCount = 5;
6143 p.compacted = compacted.first;
6144
6145 storeTypeGroup->addChild(
6146 new QueryPoolResultsCase(testContext, queryType.second, makeSharedFrom(p)));
6147 }
6148 buildCompactedGroup->addChild(storeTypeGroup.release());
6149 }
6150 buildTypeGroup->addChild(buildCompactedGroup.release());
6151 }
6152 group->addChild(buildTypeGroup.release());
6153 }
6154 }
6155
addCopyWithinPipelineTests(TestCaseGroup * group)6156 void addCopyWithinPipelineTests(TestCaseGroup *group)
6157 {
6158 std::pair<VkAccelerationStructureBuildTypeKHR, const char *> const buildTypes[]{
6159 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6160 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6161 };
6162 std::pair<CopyWithinPipelineParams::Type, const char *> const testTypes[]{
6163 {CopyWithinPipelineParams::Type::StageASCopyBit, "stage_as_copy_bit"},
6164 {CopyWithinPipelineParams::Type::StageAllTransferBit, "stage_all_transfer"},
6165 {CopyWithinPipelineParams::Type::AccessSBTReadBit, "access_sbt_read"}};
6166
6167 auto &testContext = group->getTestContext();
6168 for (const auto &buildType : buildTypes)
6169 {
6170 auto buildTypeGroup = makeMovePtr<TestCaseGroup>(testContext, buildType.second);
6171 for (const auto &testType : testTypes)
6172 {
6173 CopyWithinPipelineParams p;
6174 p.width = 16;
6175 p.height = 16;
6176 p.build = buildType.first;
6177 p.type = testType.first;
6178
6179 buildTypeGroup->addChild(new PipelineStageASCase(testContext, testType.second, makeSharedFrom(p)));
6180 }
6181 group->addChild(buildTypeGroup.release());
6182 }
6183 }
6184
addUpdateTests(TestCaseGroup * group)6185 void addUpdateTests(TestCaseGroup *group)
6186 {
6187 const struct
6188 {
6189 vk::VkAccelerationStructureBuildTypeKHR buildType;
6190 std::string name;
6191 } buildTypes[] = {
6192 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6193 {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6194 };
6195
6196 struct
6197 {
6198 UpdateCase updateType;
6199 const char *name;
6200 } updateTypes[] = {
6201 {UpdateCase::VERTICES, "vertices"},
6202 {UpdateCase::INDICES, "indices"},
6203 {UpdateCase::TRANSFORM, "transform"},
6204 };
6205
6206 auto &ctx = group->getTestContext();
6207
6208 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6209 {
6210 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6211 new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6212
6213 for (int updateTypesIdx = 0; updateTypesIdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateTypesIdx)
6214 {
6215 TestParams testParams{
6216 buildTypes[buildTypeIdx].buildType,
6217 VK_FORMAT_R32G32B32_SFLOAT,
6218 false,
6219 VK_INDEX_TYPE_UINT16,
6220 BottomTestType::TRIANGLES,
6221 InstanceCullFlags::NONE,
6222 false,
6223 false,
6224 false,
6225 TopTestType::IDENTICAL_INSTANCES,
6226 false,
6227 false,
6228 false,
6229 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
6230 OT_TOP_ACCELERATION,
6231 OP_NONE,
6232 RTAS_DEFAULT_SIZE,
6233 RTAS_DEFAULT_SIZE,
6234 de::SharedPtr<TestConfiguration>(new UpdateableASConfiguration()),
6235 0u,
6236 EmptyAccelerationStructureCase::NOT_EMPTY,
6237 InstanceCustomIndexCase::NONE,
6238 false,
6239 0xFFu,
6240 updateTypes[updateTypesIdx].updateType,
6241 };
6242 buildTypeGroup->addChild(new ASUpdateCase(ctx, updateTypes[updateTypesIdx].name, testParams));
6243 }
6244 group->addChild(buildTypeGroup.release());
6245 }
6246 }
6247
createAccelerationStructuresTests(tcu::TestContext & testCtx)6248 tcu::TestCaseGroup *createAccelerationStructuresTests(tcu::TestContext &testCtx)
6249 {
6250 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures"));
6251
6252 // Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers
6253 addTestGroup(group.get(), "flags", addBasicBuildingTests);
6254 // Test building AS with different vertex and index formats
6255 addTestGroup(group.get(), "format", addVertexIndexFormatsTests);
6256 // Test copying, compaction and serialization of AS
6257 addTestGroup(group.get(), "operations", addOperationTests);
6258 // Test host threading operations
6259 addTestGroup(group.get(), "host_threading", addHostThreadingOperationTests);
6260 // Test using AS as function argument using both pointers and bare values
6261 addTestGroup(group.get(), "function_argument", addFuncArgTests);
6262 // Test building AS with counterclockwise triangles and/or disabling face culling
6263 addTestGroup(group.get(), "instance_triangle_culling", addInstanceTriangleCullingTests);
6264 // Test for CullMaskKHR builtin as a part of VK_KHR_ray_tracing_maintenance1
6265 addTestGroup(group.get(), "ray_cull_mask", addInstanceRayCullMaskTests);
6266 // Exercise dynamic indexing of acceleration structures
6267 addTestGroup(group.get(), "dynamic_indexing", addDynamicIndexingTests);
6268 // Test building empty acceleration structures using different methods
6269 addTestGroup(group.get(), "empty", addEmptyAccelerationStructureTests);
6270 // Test using different values for the instance index and checking them in shaders
6271 addTestGroup(group.get(), "instance_index", addInstanceIndexTests);
6272 // Test updating instance index using both in-place and separate src/dst acceleration structures
6273 addTestGroup(group.get(), "instance_update", addInstanceUpdateTests);
6274 addTestGroup(group.get(), "device_compability_khr", addGetDeviceAccelerationStructureCompabilityTests);
6275 addTestGroup(group.get(), "header_bottom_address", addUpdateHeaderBottomAddressTests);
6276 // Test for a new VkQueryPool queries for VK_KHR_ray_tracing_maintenance1
6277 addTestGroup(group.get(), "query_pool_results", addQueryPoolResultsTests);
6278 // Tests ACCELLERATION_STRUCTURE_COPY and ACCESS_2_SBT_READ with VK_KHR_ray_tracing_maintenance1
6279 addTestGroup(group.get(), "copy_within_pipeline", addCopyWithinPipelineTests);
6280 // Tests updating AS via replacing vertex/index/transform buffers
6281 addTestGroup(group.get(), "update", addUpdateTests);
6282
6283 return group.release();
6284 }
6285
6286 } // namespace RayTracing
6287
6288 } // namespace vkt
6289