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
47 #include <set>
48
49 namespace vkt
50 {
51 namespace RayTracing
52 {
53 namespace
54 {
55 using namespace vk;
56 using namespace vkt;
57
58 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR
59 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR
60 | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
61 | VK_SHADER_STAGE_MISS_BIT_KHR
62 | VK_SHADER_STAGE_INTERSECTION_BIT_KHR
63 | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
64
65
66 enum BottomTestType
67 {
68 BTT_TRIANGLES,
69 BTT_AABBS
70 };
71
72 enum TopTestType
73 {
74 TTT_IDENTICAL_INSTANCES,
75 TTT_DIFFERENT_INSTANCES
76 };
77
78 enum OperationTarget
79 {
80 OT_NONE,
81 OT_TOP_ACCELERATION,
82 OT_BOTTOM_ACCELERATION
83 };
84
85 enum OperationType
86 {
87 OP_NONE,
88 OP_COPY,
89 OP_COMPACT,
90 OP_SERIALIZE
91 };
92
93 enum class InstanceCullFlags
94 {
95 NONE,
96 CULL_DISABLE,
97 COUNTERCLOCKWISE,
98 ALL,
99 };
100
101 enum class EmptyAccelerationStructureCase
102 {
103 NOT_EMPTY = 0,
104 INACTIVE_TRIANGLES = 1,
105 INACTIVE_INSTANCES = 2,
106 NO_GEOMETRIES_BOTTOM = 3, // geometryCount zero when building.
107 NO_PRIMITIVES_BOTTOM = 4, // primitiveCount zero when building.
108 NO_PRIMITIVES_TOP = 5, // primitiveCount zero when building.
109 };
110
111 enum class InstanceCustomIndexCase
112 {
113 NONE = 0,
114 CLOSEST_HIT = 1,
115 ANY_HIT = 2,
116 INTERSECTION = 3,
117 };
118
119 static const deUint32 RTAS_DEFAULT_SIZE = 8u;
120
121 // Chosen to have the most significant bit set to 1 when represented using 24 bits.
122 // This will make sure the instance custom index will not be sign-extended by mistake.
123 constexpr deUint32 INSTANCE_CUSTOM_INDEX_BASE = 0x807f00u;
124
125 struct TestParams;
126
127 class TestConfiguration
128 {
129 public:
130 virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
131 TestParams& testParams) = 0;
132 virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
133 TestParams& testParams,
134 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) = 0;
135 virtual void initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
136 Context& context,
137 TestParams& testParams) = 0;
138 virtual void initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
139 Context& context,
140 TestParams& testParams,
141 VkPipeline pipeline,
142 deUint32 shaderGroupHandleSize,
143 deUint32 shaderGroupBaseAlignment,
144 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
145 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
146 de::MovePtr<BufferWithMemory>& missShaderBindingTable) = 0;
147 virtual bool verifyImage (BufferWithMemory* resultBuffer,
148 Context& context,
149 TestParams& testParams) = 0;
150 virtual VkFormat getResultImageFormat () = 0;
151 virtual size_t getResultImageFormatSize () = 0;
152 virtual VkClearValue getClearValue () = 0;
153 };
154
155 struct TestParams
156 {
157 vk::VkAccelerationStructureBuildTypeKHR buildType; // are we making AS on CPU or GPU
158 VkFormat vertexFormat;
159 bool padVertices;
160 VkIndexType indexType;
161 BottomTestType bottomTestType; // what kind of geometry is stored in bottom AS
162 InstanceCullFlags cullFlags; // Flags for instances, if needed.
163 bool bottomUsesAOP; // does bottom AS use arrays, or arrays of pointers
164 bool bottomGeneric; // Bottom created as generic AS type.
165 TopTestType topTestType; // If instances are identical then bottom geometries must have different vertices/aabbs
166 bool topUsesAOP; // does top AS use arrays, or arrays of pointers
167 bool topGeneric; // Top created as generic AS type.
168 VkBuildAccelerationStructureFlagsKHR buildFlags;
169 OperationTarget operationTarget;
170 OperationType operationType;
171 deUint32 width;
172 deUint32 height;
173 de::SharedPtr<TestConfiguration> testConfiguration;
174 deUint32 workerThreadsCount;
175 EmptyAccelerationStructureCase emptyASCase;
176 InstanceCustomIndexCase instanceCustomIndexCase;
177 };
178
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)179 deUint32 getShaderGroupSize (const InstanceInterface& vki,
180 const VkPhysicalDevice physicalDevice)
181 {
182 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
183
184 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
185 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
186 }
187
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)188 deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki,
189 const VkPhysicalDevice physicalDevice)
190 {
191 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
192
193 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
194 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
195 }
196
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)197 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
198 {
199 const VkImageCreateInfo imageCreateInfo =
200 {
201 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
202 DE_NULL, // const void* pNext;
203 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
204 VK_IMAGE_TYPE_2D, // VkImageType imageType;
205 format, // VkFormat format;
206 makeExtent3D(width, height, 1u), // VkExtent3D extent;
207 1u, // deUint32 mipLevels;
208 1u, // deUint32 arrayLayers;
209 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
210 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
211 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
212 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
213 0u, // deUint32 queueFamilyIndexCount;
214 DE_NULL, // const deUint32* pQueueFamilyIndices;
215 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
216 };
217
218 return imageCreateInfo;
219 }
220
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,deUint32 queryCount)221 Move<VkQueryPool> makeQueryPool(const DeviceInterface& vk,
222 const VkDevice device,
223 const VkQueryType queryType,
224 deUint32 queryCount)
225 {
226 const VkQueryPoolCreateInfo queryPoolCreateInfo =
227 {
228 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
229 DE_NULL, // pNext
230 (VkQueryPoolCreateFlags)0, // flags
231 queryType, // queryType
232 queryCount, // queryCount
233 0u, // pipelineStatistics
234 };
235 return createQueryPool(vk, device, &queryPoolCreateInfo);
236 }
237
getCullFlags(InstanceCullFlags flags)238 VkGeometryInstanceFlagsKHR getCullFlags (InstanceCullFlags flags)
239 {
240 VkGeometryInstanceFlagsKHR cullFlags = 0u;
241
242 if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
243 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
244
245 if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
246 cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
247
248 return cullFlags;
249 }
250
251 class CheckerboardConfiguration : public TestConfiguration
252 {
253 public:
254 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
255 TestParams& testParams) override;
256 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
257 TestParams& testParams,
258 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) override;
259 void initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
260 Context& context,
261 TestParams& testParams) override;
262 void initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
263 Context& context,
264 TestParams& testParams,
265 VkPipeline pipeline,
266 deUint32 shaderGroupHandleSize,
267 deUint32 shaderGroupBaseAlignment,
268 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
269 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
270 de::MovePtr<BufferWithMemory>& missShaderBindingTable) override;
271 bool verifyImage (BufferWithMemory* resultBuffer,
272 Context& context,
273 TestParams& testParams) override;
274 VkFormat getResultImageFormat () override;
275 size_t getResultImageFormatSize () override;
276 VkClearValue getClearValue () override;
277 };
278
initBottomAccelerationStructures(Context & context,TestParams & testParams)279 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > CheckerboardConfiguration::initBottomAccelerationStructures (Context& context,
280 TestParams& testParams)
281 {
282 DE_UNREF(context);
283
284 // Cull flags can only be used with triangles.
285 DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE || testParams.bottomTestType == BTT_TRIANGLES);
286
287 // Checkerboard configuration does not support empty geometry tests.
288 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
289
290 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > result;
291
292 const auto instanceFlags = getCullFlags(testParams.cullFlags);
293
294 tcu::Vec3 v0(0.0, 1.0, 0.0);
295 tcu::Vec3 v1(0.0, 0.0, 0.0);
296 tcu::Vec3 v2(1.0, 1.0, 0.0);
297 tcu::Vec3 v3(1.0, 0.0, 0.0);
298
299 if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
300 {
301 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
302 bottomLevelAccelerationStructure->setGeometryCount(1u);
303 de::SharedPtr<RaytracedGeometryBase> geometry;
304 if (testParams.bottomTestType == BTT_TRIANGLES)
305 {
306 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
307 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
308 {
309 if (instanceFlags == 0u)
310 {
311 geometry->addVertex(v0);
312 geometry->addVertex(v1);
313 geometry->addVertex(v2);
314 geometry->addVertex(v2);
315 geometry->addVertex(v1);
316 geometry->addVertex(v3);
317 }
318 else // Counterclockwise so the flags will be needed for the geometry to be visible.
319 {
320 geometry->addVertex(v2);
321 geometry->addVertex(v1);
322 geometry->addVertex(v0);
323 geometry->addVertex(v3);
324 geometry->addVertex(v1);
325 geometry->addVertex(v2);
326 }
327 }
328 else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
329 {
330 geometry->addVertex(v0);
331 geometry->addVertex(v1);
332 geometry->addVertex(v2);
333 geometry->addVertex(v3);
334
335 if (instanceFlags == 0u)
336 {
337 geometry->addIndex(0);
338 geometry->addIndex(1);
339 geometry->addIndex(2);
340 geometry->addIndex(2);
341 geometry->addIndex(1);
342 geometry->addIndex(3);
343 }
344 else // Counterclockwise so the flags will be needed for the geometry to be visible.
345 {
346 geometry->addIndex(2);
347 geometry->addIndex(1);
348 geometry->addIndex(0);
349 geometry->addIndex(3);
350 geometry->addIndex(1);
351 geometry->addIndex(2);
352 }
353 }
354 }
355 else // m_data.bottomTestType == BTT_AABBS
356 {
357 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
358
359 if (!testParams.padVertices)
360 {
361 // Single AABB.
362 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
363 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
364 }
365 else
366 {
367 // Multiple AABBs covering the same space.
368 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
369 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, 0.1f));
370
371 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
372 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
373
374 geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
375 geometry->addVertex(tcu::Vec3(0.5f, 1.0f, 0.1f));
376
377 geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
378 geometry->addVertex(tcu::Vec3(1.0f, 0.5f, 0.1f));
379 }
380 }
381
382 bottomLevelAccelerationStructure->addGeometry(geometry);
383
384 if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
385 geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
386
387 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
388 }
389 else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
390 {
391 // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
392 for (deUint32 y = 0; y < testParams.height; ++y)
393 for (deUint32 x = 0; x < testParams.width; ++x)
394 {
395 // let's build a chessboard of geometries
396 if (((x + y) % 2) == 0)
397 continue;
398 tcu::Vec3 xyz((float)x, (float)y, 0.0f);
399
400 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
401 bottomLevelAccelerationStructure->setGeometryCount(1u);
402
403 de::SharedPtr<RaytracedGeometryBase> geometry;
404 if (testParams.bottomTestType == BTT_TRIANGLES)
405 {
406 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
407 if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
408 {
409 if (instanceFlags == 0u)
410 {
411 geometry->addVertex(xyz + v0);
412 geometry->addVertex(xyz + v1);
413 geometry->addVertex(xyz + v2);
414 geometry->addVertex(xyz + v2);
415 geometry->addVertex(xyz + v1);
416 geometry->addVertex(xyz + v3);
417 }
418 else // Counterclockwise so the flags will be needed for the geometry to be visible.
419 {
420 geometry->addVertex(xyz + v2);
421 geometry->addVertex(xyz + v1);
422 geometry->addVertex(xyz + v0);
423 geometry->addVertex(xyz + v3);
424 geometry->addVertex(xyz + v1);
425 geometry->addVertex(xyz + v2);
426 }
427 }
428 else
429 {
430 geometry->addVertex(xyz + v0);
431 geometry->addVertex(xyz + v1);
432 geometry->addVertex(xyz + v2);
433 geometry->addVertex(xyz + v3);
434
435 if (instanceFlags == 0u)
436 {
437 geometry->addIndex(0);
438 geometry->addIndex(1);
439 geometry->addIndex(2);
440 geometry->addIndex(2);
441 geometry->addIndex(1);
442 geometry->addIndex(3);
443 }
444 else // Counterclockwise so the flags will be needed for the geometry to be visible.
445 {
446 geometry->addIndex(2);
447 geometry->addIndex(1);
448 geometry->addIndex(0);
449 geometry->addIndex(3);
450 geometry->addIndex(1);
451 geometry->addIndex(2);
452 }
453 }
454 }
455 else // testParams.bottomTestType == BTT_AABBS
456 {
457 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
458
459 if (!testParams.padVertices)
460 {
461 // Single AABB.
462 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
463 geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
464 }
465 else
466 {
467 // Multiple AABBs covering the same space.
468 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
469 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, 0.1f));
470
471 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, -0.1f));
472 geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
473
474 geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.5f, -0.1f));
475 geometry->addVertex(xyz + tcu::Vec3(0.5f, 1.0f, 0.1f));
476
477 geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.0f, -0.1f));
478 geometry->addVertex(xyz + tcu::Vec3(1.0f, 0.5f, 0.1f));
479 }
480 }
481
482 bottomLevelAccelerationStructure->addGeometry(geometry);
483
484 if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
485 geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
486
487 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
488 }
489 }
490
491 return result;
492 }
493
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)494 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure (Context& context,
495 TestParams& testParams,
496 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
497 {
498 // Checkerboard configuration does not support empty geometry tests.
499 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
500
501 DE_UNREF(context);
502
503 const auto instanceCount = testParams.width * testParams.height / 2u;
504 const auto instanceFlags = getCullFlags(testParams.cullFlags);
505
506 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
507 result->setInstanceCount(instanceCount);
508
509 if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
510 {
511
512 for (deUint32 y = 0; y < testParams.height; ++y)
513 for (deUint32 x = 0; x < testParams.width; ++x)
514 {
515 if (((x + y) % 2) == 0)
516 continue;
517 const VkTransformMatrixKHR transformMatrixKHR =
518 {
519 { // float matrix[3][4];
520 { 1.0f, 0.0f, 0.0f, (float)x },
521 { 0.0f, 1.0f, 0.0f, (float)y },
522 { 0.0f, 0.0f, 1.0f, 0.0f },
523 }
524 };
525 const deUint32 instanceCustomIndex = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? (INSTANCE_CUSTOM_INDEX_BASE + x + y) : 0u);
526 result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, instanceCustomIndex, 0xFFu, 0u, instanceFlags);
527 }
528 }
529 else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
530 {
531 deUint32 currentInstanceIndex = 0;
532
533 for (deUint32 y = 0; y < testParams.height; ++y)
534 for (deUint32 x = 0; x < testParams.width; ++x)
535 {
536 if (((x + y) % 2) == 0)
537 continue;
538 const deUint32 instanceCustomIndex = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? (INSTANCE_CUSTOM_INDEX_BASE + x + y) : 0u);
539 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4, instanceCustomIndex, 0xFFu, 0u, instanceFlags);
540 }
541 }
542
543 return result;
544 }
545
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)546 void CheckerboardConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
547 Context& context,
548 TestParams& testParams)
549 {
550 DE_UNREF(testParams);
551 const DeviceInterface& vkd = context.getDeviceInterface();
552 const VkDevice device = context.getDevice();
553
554 const bool useAnyHit = (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT);
555 const auto hitShaderStage = (useAnyHit ? VK_SHADER_STAGE_ANY_HIT_BIT_KHR : VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
556 const auto hitShaderName = (useAnyHit ? "ahit" : "chit");
557
558 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
559 rayTracingPipeline->addShader(hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 1);
560 rayTracingPipeline->addShader(hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 2);
561 if (testParams.bottomTestType == BTT_AABBS)
562 rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0), 2);
563 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 3);
564 }
565
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)566 void CheckerboardConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
567 Context& context,
568 TestParams& testParams,
569 VkPipeline pipeline,
570 deUint32 shaderGroupHandleSize,
571 deUint32 shaderGroupBaseAlignment,
572 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
573 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
574 de::MovePtr<BufferWithMemory>& missShaderBindingTable)
575 {
576 const DeviceInterface& vkd = context.getDeviceInterface();
577 const VkDevice device = context.getDevice();
578 Allocator& allocator = context.getDefaultAllocator();
579
580 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
581 if(testParams.bottomTestType == BTT_AABBS)
582 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
583 else // testParams.bottomTestType == BTT_TRIANGLES
584 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
585 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1 );
586 }
587
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)588 bool CheckerboardConfiguration::verifyImage(BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
589 {
590 // Checkerboard configuration does not support empty geometry tests.
591 DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
592
593 DE_UNREF(context);
594 const auto* bufferPtr = (deInt32*)resultBuffer->getAllocation().getHostPtr();
595 deUint32 pos = 0;
596 deUint32 failures = 0;
597
598 // verify results - each test case should generate checkerboard pattern
599 for (deUint32 y = 0; y < testParams.height; ++y)
600 for (deUint32 x = 0; x < testParams.width; ++x)
601 {
602 // The hit value should match the shader code.
603 const deInt32 hitValue = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? static_cast<deInt32>(INSTANCE_CUSTOM_INDEX_BASE + x + y) : 2);
604 const deInt32 expectedResult = ((x + y) % 2) ? hitValue : 1;
605
606 if (bufferPtr[pos] != expectedResult)
607 failures++;
608
609 ++pos;
610 }
611 return failures == 0;
612 }
613
getResultImageFormat()614 VkFormat CheckerboardConfiguration::getResultImageFormat()
615 {
616 return VK_FORMAT_R32_SINT;
617 }
618
getResultImageFormatSize()619 size_t CheckerboardConfiguration::getResultImageFormatSize()
620 {
621 return sizeof(deUint32);
622 }
623
getClearValue()624 VkClearValue CheckerboardConfiguration::getClearValue()
625 {
626 return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
627 }
628
629 class SingleTriangleConfiguration : public TestConfiguration
630 {
631 public:
632 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
633 TestParams& testParams) override;
634 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
635 TestParams& testParams,
636 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) override;
637 void initRayTracingShaders (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
638 Context& context,
639 TestParams& testParams) override;
640 void initShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
641 Context& context,
642 TestParams& testParams,
643 VkPipeline pipeline,
644 deUint32 shaderGroupHandleSize,
645 deUint32 shaderGroupBaseAlignment,
646 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
647 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
648 de::MovePtr<BufferWithMemory>& missShaderBindingTable) override;
649 bool verifyImage (BufferWithMemory* resultBuffer,
650 Context& context,
651 TestParams& testParams) override;
652 VkFormat getResultImageFormat () override;
653 size_t getResultImageFormatSize () override;
654 VkClearValue getClearValue () override;
655
656 // well, actually we have 2 triangles, but we ignore the first one ( see raygen shader for this configuration )
657 const std::vector<tcu::Vec3> vertices =
658 {
659 tcu::Vec3(0.0f, 0.0f, -0.1f),
660 tcu::Vec3(-0.1f, 0.0f, 0.0f),
661 tcu::Vec3(0.0f, -0.1f, 0.0f),
662 tcu::Vec3(0.0f, 0.0f, 0.0f),
663 tcu::Vec3(0.5f, 0.0f, -0.5f),
664 tcu::Vec3(0.0f, 0.5f, -0.5f),
665 };
666
667 const std::vector<deUint32> indices =
668 {
669 3,
670 4,
671 5
672 };
673 };
674
initBottomAccelerationStructures(Context & context,TestParams & testParams)675 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > SingleTriangleConfiguration::initBottomAccelerationStructures (Context& context,
676 TestParams& testParams)
677 {
678 DE_UNREF(context);
679
680 // No other cases supported for the single triangle configuration.
681 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
682
683 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > result;
684
685 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
686 bottomLevelAccelerationStructure->setGeometryCount(1u);
687
688 de::SharedPtr<RaytracedGeometryBase> geometry;
689 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
690
691 auto customVertices(vertices);
692
693 if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
694 {
695 const auto nanValue = tcu::Float32::nan().asFloat();
696 for (auto& vtx : customVertices)
697 vtx.x() = nanValue;
698 }
699
700 for (auto it = begin(customVertices), eit = end(customVertices); it != eit; ++it)
701 geometry->addVertex(*it);
702
703 if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
704 {
705 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
706 geometry->addIndex(*it);
707 }
708 bottomLevelAccelerationStructure->addGeometry(geometry);
709 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
710
711 return result;
712 }
713
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)714 de::MovePtr<TopLevelAccelerationStructure> SingleTriangleConfiguration::initTopAccelerationStructure (Context& context,
715 TestParams& testParams,
716 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
717 {
718 DE_UNREF(context);
719 DE_UNREF(testParams);
720
721 // Unsupported in this configuration.
722 DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
723
724 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
725 result->setInstanceCount(1u);
726
727 result->addInstance(bottomLevelAccelerationStructures[0]);
728
729 return result;
730 }
731
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)732 void SingleTriangleConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
733 Context& context,
734 TestParams& testParams)
735 {
736 DE_UNREF(testParams);
737 const DeviceInterface& vkd = context.getDeviceInterface();
738 const VkDevice device = context.getDevice();
739
740 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"), 0), 0);
741 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"), 0), 1);
742 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"), 0), 2);
743 }
744
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)745 void SingleTriangleConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline>& rayTracingPipeline,
746 Context& context,
747 TestParams& testParams,
748 VkPipeline pipeline,
749 deUint32 shaderGroupHandleSize,
750 deUint32 shaderGroupBaseAlignment,
751 de::MovePtr<BufferWithMemory>& raygenShaderBindingTable,
752 de::MovePtr<BufferWithMemory>& hitShaderBindingTable,
753 de::MovePtr<BufferWithMemory>& missShaderBindingTable)
754 {
755 DE_UNREF(testParams);
756 const DeviceInterface& vkd = context.getDeviceInterface();
757 const VkDevice device = context.getDevice();
758 Allocator& allocator = context.getDefaultAllocator();
759
760 raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
761 hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
762 missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
763 }
764
pointInTriangle2D(const tcu::Vec3 & p,const tcu::Vec3 & p0,const tcu::Vec3 & p1,const tcu::Vec3 & p2)765 bool pointInTriangle2D(const tcu::Vec3& p, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::Vec3& p2)
766 {
767 float s = p0.y() * p2.x() - p0.x() * p2.y() + (p2.y() - p0.y()) * p.x() + (p0.x() - p2.x()) * p.y();
768 float t = p0.x() * p1.y() - p0.y() * p1.x() + (p0.y() - p1.y()) * p.x() + (p1.x() - p0.x()) * p.y();
769
770 if ((s < 0) != (t < 0))
771 return false;
772
773 float a = -p1.y() * p2.x() + p0.y() * (p2.x() - p1.x()) + p0.x() * (p1.y() - p2.y()) + p1.x() * p2.y();
774
775 return a < 0 ?
776 (s <= 0 && s + t >= a) :
777 (s >= 0 && s + t <= a);
778 }
779
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)780 bool SingleTriangleConfiguration::verifyImage(BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
781 {
782 tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
783 tcu::TextureFormat vertexFormat = vk::mapVkFormat(testParams.vertexFormat);
784 tcu::ConstPixelBufferAccess resultAccess (imageFormat, testParams.width, testParams.height, 1, resultBuffer->getAllocation().getHostPtr());
785
786 std::vector<float> reference (testParams.width * testParams.height);
787 tcu::PixelBufferAccess referenceAccess (imageFormat, testParams.width, testParams.height, 1, reference.data());
788
789 // verify results
790 tcu::Vec3 v0 = vertices[3];
791 tcu::Vec3 v1 = vertices[4];
792 tcu::Vec3 v2 = vertices[5];
793 const int numChannels = tcu::getNumUsedChannels(vertexFormat.order);
794 if (numChannels < 3)
795 {
796 v0.z() = 0.0f;
797 v1.z() = 0.0f;
798 v2.z() = 0.0f;
799 }
800 tcu::Vec3 abc = tcu::cross((v2 - v0), (v1 - v0));
801
802 for (deUint32 j = 0; j < testParams.height; ++j)
803 {
804 float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
805 for (deUint32 i = 0; i < testParams.width; ++i)
806 {
807 float x = 0.1f + 0.2f * float(i) / float(testParams.width - 1);
808 float z = (abc.x()*x + abc.y()*y) / abc.z();
809 bool inTriangle = pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
810 float refValue = ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f+z : 0.0f);
811 referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
812 }
813 }
814 return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
815 }
816
getResultImageFormat()817 VkFormat SingleTriangleConfiguration::getResultImageFormat()
818 {
819 return VK_FORMAT_R32_SFLOAT;
820 }
821
getResultImageFormatSize()822 size_t SingleTriangleConfiguration::getResultImageFormatSize()
823 {
824 return sizeof(float);
825 }
826
getClearValue()827 VkClearValue SingleTriangleConfiguration::getClearValue()
828 {
829 return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
830 }
831
commonASTestsCheckSupport(Context & context)832 void commonASTestsCheckSupport(Context& context)
833 {
834 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
835 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
836 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
837
838 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR& rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
839 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE)
840 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
841
842 const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
843 if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
844 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
845 }
846
847 class RayTracingASBasicTestCase : public TestCase
848 {
849 public:
850 RayTracingASBasicTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
851 ~RayTracingASBasicTestCase (void);
852
853 void checkSupport (Context& context) const override;
854 void initPrograms (SourceCollections& programCollection) const override;
855 TestInstance* createInstance (Context& context) const override;
856 protected:
857 TestParams m_data;
858 };
859
860 // Same as RayTracingASBasicTestCase but it will only initialize programs for SingleTriangleConfiguration and use hand-tuned SPIR-V
861 // assembly.
862 class RayTracingASFuncArgTestCase : public RayTracingASBasicTestCase
863 {
864 public:
865 RayTracingASFuncArgTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
~RayTracingASFuncArgTestCase(void)866 ~RayTracingASFuncArgTestCase (void) {}
867
868 void initPrograms (SourceCollections& programCollection) const override;
869 };
870
871 class RayTracingASBasicTestInstance : public TestInstance
872 {
873 public:
874 RayTracingASBasicTestInstance (Context& context, const TestParams& data);
875 ~RayTracingASBasicTestInstance (void) = default;
876 tcu::TestStatus iterate (void) override;
877
878 protected:
879 bool iterateNoWorkers (void);
880 bool iterateWithWorkers (void);
881 de::MovePtr<BufferWithMemory> runTest (const deUint32 workerThreadsCount);
882 private:
883 TestParams m_data;
884 };
885
RayTracingASBasicTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams & data)886 RayTracingASBasicTestCase::RayTracingASBasicTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
887 : vkt::TestCase (context, name, desc)
888 , m_data (data)
889 {
890 }
891
~RayTracingASBasicTestCase(void)892 RayTracingASBasicTestCase::~RayTracingASBasicTestCase (void)
893 {
894 }
895
checkSupport(Context & context) const896 void RayTracingASBasicTestCase::checkSupport(Context& context) const
897 {
898 commonASTestsCheckSupport(context);
899
900 const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
901 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
902 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
903
904 // Check supported vertex format.
905 checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_data.vertexFormat);
906 }
907
initPrograms(SourceCollections & programCollection) const908 void RayTracingASBasicTestCase::initPrograms (SourceCollections& programCollection) const
909 {
910 bool storeInRGen = false;
911 bool storeInAHit = false;
912 bool storeInCHit = false;
913 bool storeInISec = false;
914
915 switch (m_data.instanceCustomIndexCase)
916 {
917 case InstanceCustomIndexCase::NONE: storeInRGen = true; break;
918 case InstanceCustomIndexCase::CLOSEST_HIT: storeInCHit = true; break;
919 case InstanceCustomIndexCase::ANY_HIT: storeInAHit = true; break;
920 case InstanceCustomIndexCase::INTERSECTION: storeInISec = true; break;
921 default: DE_ASSERT(false); break;
922 }
923
924 const std::string imageDeclaration = "layout(r32i, set = 0, binding = 0) uniform iimage2D result;\n";
925 const std::string storeCustomIndex = " imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_InstanceCustomIndexEXT, 0, 0, 1));\n";
926 const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
927
928 {
929 std::stringstream css;
930 css
931 << "#version 460 core\n"
932 << "#extension GL_EXT_ray_tracing : require\n"
933 << "layout(location = 0) rayPayloadEXT ivec4 hitValue;\n";
934
935 if (storeInRGen)
936 css << imageDeclaration;
937
938 css
939 << "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
940 << "\n"
941 << "void main()\n"
942 << "{\n"
943 << " float tmin = 0.0;\n"
944 << " float tmax = 1.0;\n"
945 << " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
946 << " vec3 direction = vec3(0.0,0.0,-1.0);\n"
947 << " hitValue = ivec4(0,0,0,0);\n"
948 << " traceRayEXT(topLevelAS, " << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0" : "gl_RayFlagsCullBackFacingTrianglesEXT") << ", 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n";
949
950 if (storeInRGen)
951 css << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
952
953 css << "}\n";
954
955 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
956 }
957
958 {
959 std::stringstream css;
960 css
961 << "#version 460 core\n"
962 << "#extension GL_EXT_ray_tracing : require\n"
963 << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
964
965 if (storeInCHit)
966 css << imageDeclaration;
967
968 css
969 << "void main()\n"
970 << "{\n"
971 << " hitValue = ivec4(2,0,0,1);\n";
972
973 if (storeInCHit)
974 css << storeCustomIndex;
975
976 css << "}\n";
977
978 programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
979 }
980
981 if (storeInAHit)
982 {
983 std::stringstream css;
984 css
985 << "#version 460 core\n"
986 << "#extension GL_EXT_ray_tracing : require\n"
987 << imageDeclaration
988 << "void main()\n"
989 << "{\n"
990 << storeCustomIndex
991 << "}\n";
992
993 programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
994 }
995
996 {
997 std::stringstream css;
998 css
999 << "#version 460 core\n"
1000 << "#extension GL_EXT_ray_tracing : require\n"
1001 << "hitAttributeEXT ivec4 hitAttribute;\n";
1002
1003 if (storeInISec)
1004 css << imageDeclaration;
1005
1006 css
1007 << "void main()\n"
1008 << "{\n"
1009 << " hitAttribute = ivec4(0,0,0,0);\n"
1010 << " reportIntersectionEXT(0.5f, 0);\n";
1011
1012 if (storeInISec)
1013 css << storeCustomIndex;
1014
1015 css << "}\n";
1016
1017 programCollection.glslSources.add("isect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1018 }
1019
1020 {
1021 std::stringstream css;
1022 css
1023 << "#version 460 core\n"
1024 << "#extension GL_EXT_ray_tracing : require\n"
1025 << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1026
1027 if (!storeInRGen)
1028 css << imageDeclaration;
1029
1030 css
1031 << "void main()\n"
1032 << "{\n"
1033 << " hitValue = ivec4(1,0,0,1);\n";
1034
1035 if (!storeInRGen)
1036 css << " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1037
1038 css << "}\n";
1039
1040 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1041 }
1042
1043 {
1044 std::stringstream css;
1045 css <<
1046 "#version 460 core\n"
1047 "#extension GL_EXT_ray_tracing : require\n"
1048 "layout(location = 0) rayPayloadEXT vec4 hitValue;\n"
1049 "layout(r32f, set = 0, binding = 0) uniform image2D result;\n"
1050 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1051 "\n"
1052 "vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)\n"
1053 "{\n"
1054 " return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;\n"
1055 "}\n"
1056 "\n"
1057 "void main()\n"
1058 "{\n"
1059 " float tmin = 0.0;\n"
1060 " float tmax = 2.0;\n"
1061 " 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"
1062 " vec3 direction = vec3(0.0,0.0,-1.0);\n"
1063 " hitValue = vec4(0.0,0.0,0.0,0.0);\n"
1064 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1065 " imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
1066 "}\n";
1067 programCollection.glslSources.add("rgen_depth") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1068 }
1069
1070 {
1071 std::stringstream css;
1072 css <<
1073 "#version 460 core\n"
1074 "#extension GL_EXT_ray_tracing : require\n"
1075 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1076 "void main()\n"
1077 "{\n"
1078 " hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1079 "}\n";
1080
1081 programCollection.glslSources.add("chit_depth") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1082 }
1083
1084 {
1085 std::stringstream css;
1086 css <<
1087 "#version 460 core\n"
1088 "#extension GL_EXT_ray_tracing : require\n"
1089 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1090 "void main()\n"
1091 "{\n"
1092 " hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1093 "}\n";
1094
1095 programCollection.glslSources.add("miss_depth") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1096 }
1097 }
1098
createInstance(Context & context) const1099 TestInstance* RayTracingASBasicTestCase::createInstance (Context& context) const
1100 {
1101 return new RayTracingASBasicTestInstance(context, m_data);
1102 }
1103
RayTracingASFuncArgTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams & data)1104 RayTracingASFuncArgTestCase::RayTracingASFuncArgTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
1105 : RayTracingASBasicTestCase (context, name, desc, data)
1106 {
1107 }
1108
initPrograms(SourceCollections & programCollection) const1109 void RayTracingASFuncArgTestCase::initPrograms (SourceCollections& programCollection) const
1110 {
1111 const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1112 const vk::SpirVAsmBuildOptions spvBuildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1113
1114 {
1115 // The SPIR-V assembly below is based on the following GLSL code. Some
1116 // modifications have been made to make traceRaysBottomWrapper take a bare
1117 // acceleration structure as its argument instead of a pointer to it, so we can
1118 // test passing a pointer and a bare value in the same test.
1119 //
1120 // #version 460 core
1121 // #extension GL_EXT_ray_tracing : require
1122 // layout(location = 0) rayPayloadEXT vec4 hitValue;
1123 // layout(r32f, set = 0, binding = 0) uniform image2D result;
1124 // layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;
1125 //
1126 // void traceRaysBottomWrapper(
1127 // accelerationStructureEXT topLevel,
1128 // uint rayFlags,
1129 // uint cullMask,
1130 // uint sbtRecordOffset,
1131 // uint sbtRecordStride,
1132 // uint missIndex,
1133 // vec3 origin,
1134 // float Tmin,
1135 // vec3 direction,
1136 // float Tmax)
1137 // {
1138 // traceRayEXT(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax, 0);
1139 // }
1140 //
1141 // void traceRaysTopWrapper(
1142 // accelerationStructureEXT topLevel,
1143 // uint rayFlags,
1144 // uint cullMask,
1145 // uint sbtRecordOffset,
1146 // uint sbtRecordStride,
1147 // uint missIndex,
1148 // vec3 origin,
1149 // float Tmin,
1150 // vec3 direction,
1151 // float Tmax)
1152 // {
1153 // traceRaysBottomWrapper(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax);
1154 // }
1155 //
1156 // vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)
1157 // {
1158 // return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;
1159 // }
1160 //
1161 // void main()
1162 // {
1163 // float tmin = 0.0;
1164 // float tmax = 2.0;
1165 // vec3 origin = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );
1166 // vec3 direction = vec3(0.0,0.0,-1.0);
1167 // hitValue = vec4(0.0,0.0,0.0,0.0);
1168 // traceRaysTopWrapper(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax);
1169 // imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);
1170 // }
1171
1172 std::ostringstream rgen;
1173 rgen
1174 << "; SPIR-V\n"
1175 << "; Version: 1.4\n"
1176 << "; Generator: Khronos Glslang Reference Front End; 10\n"
1177 << "; Bound: 156\n"
1178 << "; Schema: 0\n"
1179 << "OpCapability RayTracingKHR\n"
1180 << "OpExtension \"SPV_KHR_ray_tracing\"\n"
1181 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1182 << "OpMemoryModel Logical GLSL450\n"
1183 << "OpEntryPoint RayGenerationKHR %4 \"main\" %59 %82 %88 %130 %148\n"
1184 << "OpDecorate %59 Location 0\n"
1185 << "OpDecorate %82 BuiltIn LaunchIdKHR\n"
1186 << "OpDecorate %88 BuiltIn LaunchSizeKHR\n"
1187 << "OpDecorate %130 DescriptorSet 0\n"
1188 << "OpDecorate %130 Binding 1\n"
1189 << "OpDecorate %148 DescriptorSet 0\n"
1190 << "OpDecorate %148 Binding 0\n"
1191 << "%2 = OpTypeVoid\n"
1192 << "%3 = OpTypeFunction %2\n"
1193
1194 // This is the bare type.
1195 << "%6 = OpTypeAccelerationStructureKHR\n"
1196
1197 // This is the pointer type.
1198 << "%7 = OpTypePointer UniformConstant %6\n"
1199
1200 << "%8 = OpTypeInt 32 0\n"
1201 << "%9 = OpTypePointer Function %8\n"
1202 << "%10 = OpTypeFloat 32\n"
1203 << "%11 = OpTypeVector %10 3\n"
1204 << "%12 = OpTypePointer Function %11\n"
1205 << "%13 = OpTypePointer Function %10\n"
1206
1207 // This is the type for traceRaysTopWrapper and also the original traceRaysBottomWrapper.
1208 << "%14 = OpTypeFunction %2 %7 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1209
1210 // This is the modified type to take a bare AS as the first argument, for the modified version of traceRaysBottomWrapper.
1211 << "%14b = OpTypeFunction %2 %6 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1212
1213 << "%39 = OpTypeFunction %11 %12 %12 %12\n"
1214 << "%55 = OpTypeInt 32 1\n"
1215 << "%56 = OpConstant %55 0\n"
1216 << "%57 = OpTypeVector %10 4\n"
1217 << "%58 = OpTypePointer RayPayloadKHR %57\n"
1218 << "%59 = OpVariable %58 RayPayloadKHR\n"
1219 << "%80 = OpTypeVector %8 3\n"
1220 << "%81 = OpTypePointer Input %80\n"
1221 << "%82 = OpVariable %81 Input\n"
1222 << "%83 = OpConstant %8 0\n"
1223 << "%84 = OpTypePointer Input %8\n"
1224 << "%88 = OpVariable %81 Input\n"
1225 << "%91 = OpConstant %8 1\n"
1226 << "%112 = OpConstant %10 0\n"
1227 << "%114 = OpConstant %10 2\n"
1228 << "%116 = OpConstant %10 0.100000001\n"
1229 << "%117 = OpConstant %10 1\n"
1230 << "%118 = OpConstantComposite %11 %116 %116 %117\n"
1231 << "%119 = OpConstant %10 0.200000003\n"
1232 << "%120 = OpConstantComposite %11 %119 %112 %112\n"
1233 << "%121 = OpConstantComposite %11 %112 %119 %112\n"
1234 << "%127 = OpConstant %10 -1\n"
1235 << "%128 = OpConstantComposite %11 %112 %112 %127\n"
1236 << "%129 = OpConstantComposite %57 %112 %112 %112 %112\n"
1237 << "%130 = OpVariable %7 UniformConstant\n"
1238 << "%131 = OpConstant %8 255\n"
1239 << "%146 = OpTypeImage %10 2D 0 0 0 2 R32f\n"
1240 << "%147 = OpTypePointer UniformConstant %146\n"
1241 << "%148 = OpVariable %147 UniformConstant\n"
1242 << "%150 = OpTypeVector %8 2\n"
1243 << "%153 = OpTypeVector %55 2\n"
1244
1245 // This is main().
1246 << "%4 = OpFunction %2 None %3\n"
1247 << "%5 = OpLabel\n"
1248 << "%111 = OpVariable %13 Function\n"
1249 << "%113 = OpVariable %13 Function\n"
1250 << "%115 = OpVariable %12 Function\n"
1251 << "%122 = OpVariable %12 Function\n"
1252 << "%123 = OpVariable %12 Function\n"
1253 << "%124 = OpVariable %12 Function\n"
1254 << "%126 = OpVariable %12 Function\n"
1255 << "%132 = OpVariable %9 Function\n"
1256 << "%133 = OpVariable %9 Function\n"
1257 << "%134 = OpVariable %9 Function\n"
1258 << "%135 = OpVariable %9 Function\n"
1259 << "%136 = OpVariable %9 Function\n"
1260 << "%137 = OpVariable %12 Function\n"
1261 << "%139 = OpVariable %13 Function\n"
1262 << "%141 = OpVariable %12 Function\n"
1263 << "%143 = OpVariable %13 Function\n"
1264 << "OpStore %111 %112\n"
1265 << "OpStore %113 %114\n"
1266 << "OpStore %122 %118\n"
1267 << "OpStore %123 %120\n"
1268 << "OpStore %124 %121\n"
1269 << "%125 = OpFunctionCall %11 %43 %122 %123 %124\n"
1270 << "OpStore %115 %125\n"
1271 << "OpStore %126 %128\n"
1272 << "OpStore %59 %129\n"
1273 << "OpStore %132 %83\n"
1274 << "OpStore %133 %131\n"
1275 << "OpStore %134 %83\n"
1276 << "OpStore %135 %83\n"
1277 << "OpStore %136 %83\n"
1278 << "%138 = OpLoad %11 %115\n"
1279 << "OpStore %137 %138\n"
1280 << "%140 = OpLoad %10 %111\n"
1281 << "OpStore %139 %140\n"
1282 << "%142 = OpLoad %11 %126\n"
1283 << "OpStore %141 %142\n"
1284 << "%144 = OpLoad %10 %113\n"
1285 << "OpStore %143 %144\n"
1286 << "%145 = OpFunctionCall %2 %37 %130 %132 %133 %134 %135 %136 %137 %139 %141 %143\n"
1287 << "%149 = OpLoad %146 %148\n"
1288 << "%151 = OpLoad %80 %82\n"
1289 << "%152 = OpVectorShuffle %150 %151 %151 0 1\n"
1290 << "%154 = OpBitcast %153 %152\n"
1291 << "%155 = OpLoad %57 %59\n"
1292 << "OpImageWrite %149 %154 %155\n"
1293 << "OpReturn\n"
1294 << "OpFunctionEnd\n"
1295
1296 // This is traceRaysBottomWrapper, doing the OpTraceRayKHR call.
1297 // We have modified the type so it takes a bare AS as the first argument.
1298 // %25 = OpFunction %2 None %14
1299 << "%25 = OpFunction %2 None %14b\n"
1300
1301 // Also the type of the first argument here.
1302 // %15 = OpFunctionParameter %7
1303 << "%15 = OpFunctionParameter %6\n"
1304
1305 << "%16 = OpFunctionParameter %9\n"
1306 << "%17 = OpFunctionParameter %9\n"
1307 << "%18 = OpFunctionParameter %9\n"
1308 << "%19 = OpFunctionParameter %9\n"
1309 << "%20 = OpFunctionParameter %9\n"
1310 << "%21 = OpFunctionParameter %12\n"
1311 << "%22 = OpFunctionParameter %13\n"
1312 << "%23 = OpFunctionParameter %12\n"
1313 << "%24 = OpFunctionParameter %13\n"
1314 << "%26 = OpLabel\n"
1315
1316 // We no longer need to dereference the pointer here.
1317 // %45 = OpLoad %6 %15
1318
1319 << "%46 = OpLoad %8 %16\n"
1320 << "%47 = OpLoad %8 %17\n"
1321 << "%48 = OpLoad %8 %18\n"
1322 << "%49 = OpLoad %8 %19\n"
1323 << "%50 = OpLoad %8 %20\n"
1324 << "%51 = OpLoad %11 %21\n"
1325 << "%52 = OpLoad %10 %22\n"
1326 << "%53 = OpLoad %11 %23\n"
1327 << "%54 = OpLoad %10 %24\n"
1328
1329 // And we can use the first argument here directly.
1330 // OpTraceRayKHR %45 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59
1331 << "OpTraceRayKHR %15 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59\n"
1332
1333 << "OpReturn\n"
1334 << "OpFunctionEnd\n"
1335
1336 // This is traceRaysTopWrapper, which calls traceRaysBottomWrapper.
1337 << "%37 = OpFunction %2 None %14\n"
1338
1339 // First argument, pointer to AS.
1340 << "%27 = OpFunctionParameter %7\n"
1341
1342 << "%28 = OpFunctionParameter %9\n"
1343 << "%29 = OpFunctionParameter %9\n"
1344 << "%30 = OpFunctionParameter %9\n"
1345 << "%31 = OpFunctionParameter %9\n"
1346 << "%32 = OpFunctionParameter %9\n"
1347 << "%33 = OpFunctionParameter %12\n"
1348 << "%34 = OpFunctionParameter %13\n"
1349 << "%35 = OpFunctionParameter %12\n"
1350 << "%36 = OpFunctionParameter %13\n"
1351 << "%38 = OpLabel\n"
1352 << "%60 = OpVariable %9 Function\n"
1353 << "%62 = OpVariable %9 Function\n"
1354 << "%64 = OpVariable %9 Function\n"
1355 << "%66 = OpVariable %9 Function\n"
1356 << "%68 = OpVariable %9 Function\n"
1357 << "%70 = OpVariable %12 Function\n"
1358 << "%72 = OpVariable %13 Function\n"
1359 << "%74 = OpVariable %12 Function\n"
1360 << "%76 = OpVariable %13 Function\n"
1361
1362 // Dereference the pointer to pass the AS as the first argument.
1363 << "%27b = OpLoad %6 %27\n"
1364
1365 << "%61 = OpLoad %8 %28\n"
1366 << "OpStore %60 %61\n"
1367 << "%63 = OpLoad %8 %29\n"
1368 << "OpStore %62 %63\n"
1369 << "%65 = OpLoad %8 %30\n"
1370 << "OpStore %64 %65\n"
1371 << "%67 = OpLoad %8 %31\n"
1372 << "OpStore %66 %67\n"
1373 << "%69 = OpLoad %8 %32\n"
1374 << "OpStore %68 %69\n"
1375 << "%71 = OpLoad %11 %33\n"
1376 << "OpStore %70 %71\n"
1377 << "%73 = OpLoad %10 %34\n"
1378 << "OpStore %72 %73\n"
1379 << "%75 = OpLoad %11 %35\n"
1380 << "OpStore %74 %75\n"
1381 << "%77 = OpLoad %10 %36\n"
1382 << "OpStore %76 %77\n"
1383
1384 // %2 is void, %25 is traceRaysBottomWrapper and %27 was the first argument.
1385 // We need to pass the loaded AS instead.
1386 // %78 = OpFunctionCall %2 %25 %27 %60 %62 %64 %66 %68 %70 %72 %74 %76
1387 << "%78 = OpFunctionCall %2 %25 %27b %60 %62 %64 %66 %68 %70 %72 %74 %76\n"
1388
1389 << "OpReturn\n"
1390 << "OpFunctionEnd\n"
1391
1392 // This is calculateOrigin().
1393 << "%43 = OpFunction %11 None %39\n"
1394 << "%40 = OpFunctionParameter %12\n"
1395 << "%41 = OpFunctionParameter %12\n"
1396 << "%42 = OpFunctionParameter %12\n"
1397 << "%44 = OpLabel\n"
1398 << "%79 = OpLoad %11 %40\n"
1399 << "%85 = OpAccessChain %84 %82 %83\n"
1400 << "%86 = OpLoad %8 %85\n"
1401 << "%87 = OpConvertUToF %10 %86\n"
1402 << "%89 = OpAccessChain %84 %88 %83\n"
1403 << "%90 = OpLoad %8 %89\n"
1404 << "%92 = OpISub %8 %90 %91\n"
1405 << "%93 = OpConvertUToF %10 %92\n"
1406 << "%94 = OpFDiv %10 %87 %93\n"
1407 << "%95 = OpLoad %11 %41\n"
1408 << "%96 = OpVectorTimesScalar %11 %95 %94\n"
1409 << "%97 = OpFAdd %11 %79 %96\n"
1410 << "%98 = OpAccessChain %84 %82 %91\n"
1411 << "%99 = OpLoad %8 %98\n"
1412 << "%100 = OpConvertUToF %10 %99\n"
1413 << "%101 = OpAccessChain %84 %88 %91\n"
1414 << "%102 = OpLoad %8 %101\n"
1415 << "%103 = OpISub %8 %102 %91\n"
1416 << "%104 = OpConvertUToF %10 %103\n"
1417 << "%105 = OpFDiv %10 %100 %104\n"
1418 << "%106 = OpLoad %11 %42\n"
1419 << "%107 = OpVectorTimesScalar %11 %106 %105\n"
1420 << "%108 = OpFAdd %11 %97 %107\n"
1421 << "OpReturnValue %108\n"
1422 << "OpFunctionEnd\n"
1423 ;
1424
1425 programCollection.spirvAsmSources.add("rgen_depth") << spvBuildOptions << rgen.str();
1426 }
1427
1428 // chit_depth and miss_depth below have been left untouched.
1429
1430 {
1431 std::stringstream css;
1432 css <<
1433 "#version 460 core\n"
1434 "#extension GL_EXT_ray_tracing : require\n"
1435 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1436 "void main()\n"
1437 "{\n"
1438 " hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1439 "}\n";
1440
1441 programCollection.glslSources.add("chit_depth") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1442 }
1443
1444 {
1445 std::stringstream css;
1446 css <<
1447 "#version 460 core\n"
1448 "#extension GL_EXT_ray_tracing : require\n"
1449 "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1450 "void main()\n"
1451 "{\n"
1452 " hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1453 "}\n";
1454
1455 programCollection.glslSources.add("miss_depth") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1456 }
1457 }
1458
RayTracingASBasicTestInstance(Context & context,const TestParams & data)1459 RayTracingASBasicTestInstance::RayTracingASBasicTestInstance (Context& context, const TestParams& data)
1460 : vkt::TestInstance (context)
1461 , m_data (data)
1462 {
1463 }
1464
runTest(const deUint32 workerThreadsCount)1465 de::MovePtr<BufferWithMemory> RayTracingASBasicTestInstance::runTest(const deUint32 workerThreadsCount)
1466 {
1467 const InstanceInterface& vki = m_context.getInstanceInterface();
1468 const DeviceInterface& vkd = m_context.getDeviceInterface();
1469 const VkDevice device = m_context.getDevice();
1470 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1471 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1472 const VkQueue queue = m_context.getUniversalQueue();
1473 Allocator& allocator = m_context.getDefaultAllocator();
1474 const deUint32 pixelCount = m_data.width * m_data.height;
1475 const deUint32 shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1476 const deUint32 shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1477 const bool htCopy = (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
1478 const bool htSerialize = (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
1479
1480 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
1481 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1482 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1483 .build(vkd, device);
1484 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1485 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1486 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1487 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1488 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1489 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1490
1491 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1492 m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
1493 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1494
1495 de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
1496 de::MovePtr<BufferWithMemory> hitShaderBindingTable;
1497 de::MovePtr<BufferWithMemory> missShaderBindingTable;
1498 m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment, raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
1499
1500 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1501 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1502 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1503 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1504
1505 const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat();
1506 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
1507 const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1508 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1509 const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
1510
1511 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(pixelCount*m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1512 const VkImageSubresourceLayers resultBufferImageSubresourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1513 const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
1514 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1515
1516 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1517
1518 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1519 const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1520
1521 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
1522 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1523 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
1524 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
1525 std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
1526 std::vector<de::SharedPtr<SerialStorage>> topSerialized;
1527 std::vector<VkDeviceSize> accelerationCompactedSizes;
1528 std::vector<VkDeviceSize> accelerationSerialSizes;
1529 Move<VkQueryPool> m_queryPoolCompact;
1530 Move<VkQueryPool> m_queryPoolSerial;
1531
1532 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1533 {
1534 const VkImageMemoryBarrier preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1535 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1536 **image, imageSubresourceRange);
1537 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1538 const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
1539 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
1540 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1541 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1542 **image, imageSubresourceRange);
1543 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1544
1545 // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1546 bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1547 bool bottomSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1548 const bool buildWithoutGeom = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
1549 const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
1550 const bool topNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
1551 const bool inactiveInstances = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
1552 bottomLevelAccelerationStructures = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1553 VkBuildAccelerationStructureFlagsKHR allowCompactionFlag = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1554 VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
1555 VkBuildAccelerationStructureFlagsKHR bottomCompactFlags = (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1556 VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
1557 std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
1558 std::vector<VkDeviceSize> bottomBlasCompactSize;
1559 std::vector<VkDeviceSize> bottomBlasSerialSize;
1560
1561 for (auto& blas : bottomLevelAccelerationStructures)
1562 {
1563 blas->setBuildType (m_data.buildType);
1564 blas->setBuildFlags (bottomBuildFlags);
1565 blas->setUseArrayOfPointers (m_data.bottomUsesAOP);
1566 blas->setCreateGeneric (m_data.bottomGeneric);
1567 blas->setBuildWithoutGeometries (buildWithoutGeom);
1568 blas->setBuildWithoutPrimitives (bottomNoPrimitives);
1569 blas->createAndBuild (vkd, device, *cmdBuffer, allocator);
1570 accelerationStructureHandles.push_back (*(blas->getPtr()));
1571 }
1572
1573 if (m_data.operationType == OP_COMPACT)
1574 {
1575 deUint32 queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1576 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1577 m_queryPoolCompact = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1578 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1579 queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1580 }
1581 if (m_data.operationType == OP_SERIALIZE)
1582 {
1583 deUint32 queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1584 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1585 m_queryPoolSerial = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1586 if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1587 queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1588 }
1589
1590 // 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
1591 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1592 {
1593 endCommandBuffer(vkd, *cmdBuffer);
1594
1595 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1596
1597 if (bottomCompact)
1598 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(bottomBlasCompactSize.size()), sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1599 if (bottomSerial)
1600 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(bottomBlasSerialSize.size()), sizeof(VkDeviceSize) * bottomBlasSerialSize.size(), bottomBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1601
1602 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1603 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1604 }
1605
1606 auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
1607 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1608 {
1609 switch (m_data.operationType)
1610 {
1611 case OP_COPY:
1612 {
1613 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1614 {
1615 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1616 asCopy->setDeferredOperation(htCopy, workerThreadsCount);
1617 asCopy->setBuildType(m_data.buildType);
1618 asCopy->setBuildFlags(m_data.buildFlags);
1619 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1620 asCopy->setCreateGeneric(m_data.bottomGeneric);
1621 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1622 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1623 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), 0u, 0u);
1624 bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1625 }
1626 break;
1627 }
1628 case OP_COMPACT:
1629 {
1630 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1631 {
1632 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1633 asCopy->setBuildType(m_data.buildType);
1634 asCopy->setBuildFlags(m_data.buildFlags);
1635 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1636 asCopy->setCreateGeneric(m_data.bottomGeneric);
1637 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1638 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1639 asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
1640 bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1641 }
1642 break;
1643 }
1644 case OP_SERIALIZE:
1645 {
1646 //bottomLevelAccelerationStructureCopies = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1647 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1648 {
1649 de::SharedPtr<SerialStorage> storage ( new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
1650
1651 bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
1652 bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
1653 bottomSerialized.push_back(storage);
1654
1655 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1656 {
1657 endCommandBuffer(vkd, *cmdBuffer);
1658
1659 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1660
1661 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1662 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1663 }
1664
1665 de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1666 asCopy->setBuildType(m_data.buildType);
1667 asCopy->setBuildFlags(m_data.buildFlags);
1668 asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1669 asCopy->setCreateGeneric(m_data.bottomGeneric);
1670 asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1671 asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1672 asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
1673 asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
1674 bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1675 }
1676 break;
1677 }
1678 default:
1679 DE_ASSERT(DE_FALSE);
1680 }
1681 bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
1682 }
1683
1684 // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
1685 bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
1686 bool topSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
1687 VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
1688 VkBuildAccelerationStructureFlagsKHR topBuildFlags = m_data.buildFlags | topCompactFlags;
1689 std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
1690 std::vector<VkDeviceSize> topBlasCompactSize;
1691 std::vector<VkDeviceSize> topBlasSerialSize;
1692
1693 topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
1694 topLevelAccelerationStructure->setBuildType (m_data.buildType);
1695 topLevelAccelerationStructure->setBuildFlags (topBuildFlags);
1696 topLevelAccelerationStructure->setBuildWithoutPrimitives (topNoPrimitives);
1697 topLevelAccelerationStructure->setUseArrayOfPointers (m_data.topUsesAOP);
1698 topLevelAccelerationStructure->setCreateGeneric (m_data.topGeneric);
1699 topLevelAccelerationStructure->setInactiveInstances (inactiveInstances);
1700 topLevelAccelerationStructure->createAndBuild (vkd, device, *cmdBuffer, allocator);
1701 topLevelStructureHandles.push_back (*(topLevelAccelerationStructure->getPtr()));
1702
1703 if (topCompact)
1704 queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
1705 if (topSerial)
1706 queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
1707
1708 // 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
1709 if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
1710 {
1711 endCommandBuffer(vkd, *cmdBuffer);
1712
1713 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1714
1715 if (topCompact)
1716 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(topBlasCompactSize.size()), sizeof(VkDeviceSize) * topBlasCompactSize.size(), topBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1717 if (topSerial)
1718 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(topBlasSerialSize.size()), sizeof(VkDeviceSize) * topBlasSerialSize.size(), topBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1719
1720 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1721 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1722 }
1723
1724 const TopLevelAccelerationStructure* topLevelRayTracedPtr = topLevelAccelerationStructure.get();
1725 if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
1726 {
1727 switch (m_data.operationType)
1728 {
1729 case OP_COPY:
1730 {
1731 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1732 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
1733 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1734 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1735 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1736 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1737 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1738 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1739 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), 0u, 0u);
1740 break;
1741 }
1742 case OP_COMPACT:
1743 {
1744 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1745 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1746 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1747 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1748 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1749 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1750 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1751 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
1752 break;
1753 }
1754 case OP_SERIALIZE:
1755 {
1756 de::SharedPtr<SerialStorage> storage = de::SharedPtr<SerialStorage>(new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
1757
1758 topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
1759 topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
1760 topSerialized.push_back(storage);
1761
1762 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1763 {
1764 endCommandBuffer(vkd, *cmdBuffer);
1765
1766 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1767
1768 vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1769 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1770 }
1771
1772 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1773 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1774 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1775 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1776 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1777 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1778 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1779 topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
1780 topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
1781 break;
1782 }
1783 default:
1784 DE_ASSERT(DE_FALSE);
1785 }
1786 topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
1787 }
1788
1789 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
1790 {
1791 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
1792 DE_NULL, // const void* pNext;
1793 1u, // deUint32 accelerationStructureCount;
1794 topLevelRayTracedPtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
1795 };
1796
1797 DescriptorSetUpdateBuilder()
1798 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1799 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1800 .update(vkd, device);
1801
1802 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1803
1804 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1805
1806 cmdTraceRays(vkd,
1807 *cmdBuffer,
1808 &raygenShaderBindingTableRegion,
1809 &missShaderBindingTableRegion,
1810 &hitShaderBindingTableRegion,
1811 &callableShaderBindingTableRegion,
1812 m_data.width, m_data.height, 1);
1813
1814 const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1815 const VkMemoryBarrier postCopyMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1816 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1817
1818 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
1819
1820 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
1821 }
1822 endCommandBuffer(vkd, *cmdBuffer);
1823
1824 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1825
1826 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(deUint32));
1827
1828 return resultBuffer;
1829 }
1830
iterateNoWorkers(void)1831 bool RayTracingASBasicTestInstance::iterateNoWorkers (void)
1832 {
1833 // run test using arrays of pointers
1834 const de::MovePtr<BufferWithMemory> buffer = runTest(0);
1835
1836 return m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data);
1837 }
1838
iterateWithWorkers(void)1839 bool RayTracingASBasicTestInstance::iterateWithWorkers (void)
1840 {
1841 const deUint64 singleThreadTimeStart = deGetMicroseconds();
1842 de::MovePtr<BufferWithMemory> singleThreadBufferCPU = runTest(0);
1843 const bool singleThreadValidation = m_data.testConfiguration->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
1844 const deUint64 singleThreadTime = deGetMicroseconds() - singleThreadTimeStart;
1845
1846 deUint64 multiThreadTimeStart = deGetMicroseconds();
1847 de::MovePtr<BufferWithMemory> multiThreadBufferCPU = runTest(m_data.workerThreadsCount);
1848 const bool multiThreadValidation = m_data.testConfiguration->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
1849 deUint64 multiThreadTime = deGetMicroseconds() - multiThreadTimeStart;
1850 const deUint64 multiThreadTimeOut = 10 * singleThreadTime;
1851
1852 const deUint32 result = singleThreadValidation && multiThreadValidation;
1853
1854 if (multiThreadTime > multiThreadTimeOut)
1855 {
1856 std::string failMsg = "Time of multithreaded test execution " + de::toString(multiThreadTime) +
1857 " that is longer than expected execution time " + de::toString(multiThreadTimeOut);
1858
1859 TCU_FAIL(failMsg);
1860 }
1861
1862 return result;
1863 }
1864
iterate(void)1865 tcu::TestStatus RayTracingASBasicTestInstance::iterate (void)
1866 {
1867 bool result;
1868
1869 if (m_data.workerThreadsCount != 0)
1870 result = iterateWithWorkers();
1871 else
1872 result = iterateNoWorkers();
1873
1874 if (result)
1875 return tcu::TestStatus::pass("Pass");
1876 else
1877 return tcu::TestStatus::fail("Fail");
1878 }
1879
1880 // Tests dynamic indexing of acceleration structures
1881 class RayTracingASDynamicIndexingTestCase : public TestCase
1882 {
1883 public:
1884 RayTracingASDynamicIndexingTestCase (tcu::TestContext& context, const char* name);
1885 ~RayTracingASDynamicIndexingTestCase (void) = default;
1886
1887 void checkSupport (Context& context) const override;
1888 void initPrograms (SourceCollections& programCollection) const override;
1889 TestInstance* createInstance (Context& context) const override;
1890 };
1891
1892 class RayTracingASDynamicIndexingTestInstance : public TestInstance
1893 {
1894 public:
1895 RayTracingASDynamicIndexingTestInstance (Context& context);
1896 ~RayTracingASDynamicIndexingTestInstance (void) = default;
1897 tcu::TestStatus iterate (void) override;
1898 };
1899
RayTracingASDynamicIndexingTestCase(tcu::TestContext & context,const char * name)1900 RayTracingASDynamicIndexingTestCase::RayTracingASDynamicIndexingTestCase(tcu::TestContext& context, const char* name)
1901 : TestCase(context, name, "")
1902 {
1903 }
1904
checkSupport(Context & context) const1905 void RayTracingASDynamicIndexingTestCase::checkSupport(Context& context) const
1906 {
1907 commonASTestsCheckSupport(context);
1908 context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
1909 }
1910
initPrograms(SourceCollections & programCollection) const1911 void RayTracingASDynamicIndexingTestCase::initPrograms(SourceCollections& programCollection) const
1912 {
1913 const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1914 const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1915
1916 // raygen shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
1917 // original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
1918 //
1919 // #version 460 core
1920 // #extension GL_EXT_ray_tracing : require
1921 // #extension GL_EXT_nonuniform_qualifier : enable
1922 // #extension GL_ARB_gpu_shader_int64 : enable // needed only to generate spir-v
1923 // #define ARRAY_SIZE 500
1924 // layout(location = 0) rayPayloadEXT uvec2 payload; // offset and flag indicating if we are using descriptors or pointers
1925
1926 // layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
1927 // layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
1928 // uint64_t ptr[];
1929 // } tlasPointers;
1930 // layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
1931 // uint idx[];
1932 // } tlasIndices;
1933 // layout(set = 0, binding = 3, std430) writeonly buffer Result {
1934 // uint value[];
1935 // } result;
1936
1937 // void main()
1938 // {
1939 // float tmin = 0.0;\n"
1940 // float tmax = 2.0;\n"
1941 // vec3 origin = vec3(0.25f, 0.5f, 1.0);\n"
1942 // vec3 direction = vec3(0.0,0.0,-1.0);\n"
1943 // uint activeTlasIndex = gl_LaunchIDEXT.x;\n"
1944 // uint activeTlasCount = gl_LaunchSizeEXT.x;\n"
1945 // uint tlasIndex = tlasIndices.idx[nonuniformEXT(activeTlasIndex)];\n"
1946
1947 // atomicAdd(result.value[nonuniformEXT(activeTlasIndex)], 2);\n"
1948 // payload = uvec2(activeTlasIndex + activeTlasCount.x, 0);\n"
1949 // traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1950
1951 // atomicAdd(result.value[nonuniformEXT(activeTlasIndex + activeTlasCount * 2)], 5);\n"
1952 // payload = uvec2(activeTlasIndex + activeTlasCount * 3, 1);\n"
1953 // traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0); // used to generate initial spirv
1954 // //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
1955 // };
1956
1957 const std::string rgenSource =
1958 "OpCapability Int64\n"
1959 "OpCapability RayTracingKHR\n"
1960 "OpCapability ShaderNonUniform\n"
1961 "OpExtension \"SPV_EXT_descriptor_indexing\"\n"
1962 "OpExtension \"SPV_KHR_ray_tracing\"\n"
1963 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1964 "OpMemoryModel Logical GLSL450\n"
1965 "OpEntryPoint RayGenerationKHR %4 \"main\" %27 %33 %var_tlas_indices %var_result %60 %var_as_arr_ptr %var_as_pointers_ssbo\n"
1966 "OpDecorate %27 BuiltIn LaunchIdNV\n"
1967 "OpDecorate %33 BuiltIn LaunchSizeNV\n"
1968 "OpDecorate %37 ArrayStride 4\n"
1969 "OpMemberDecorate %38 0 NonWritable\n"
1970 "OpMemberDecorate %38 0 Offset 0\n"
1971 "OpDecorate %38 Block\n"
1972 "OpDecorate %var_tlas_indices DescriptorSet 0\n"
1973 "OpDecorate %var_tlas_indices Binding 2\n"
1974 "OpDecorate %44 NonUniform\n"
1975 "OpDecorate %46 NonUniform\n"
1976 "OpDecorate %47 NonUniform\n"
1977 "OpDecorate %48 ArrayStride 4\n"
1978 "OpMemberDecorate %49 0 NonReadable\n"
1979 "OpMemberDecorate %49 0 Offset 0\n"
1980 "OpDecorate %49 Block\n"
1981 "OpDecorate %var_result DescriptorSet 0\n"
1982 "OpDecorate %var_result Binding 3\n"
1983 "OpDecorate %53 NonUniform\n"
1984 "OpDecorate %60 Location 0\n"
1985 "OpDecorate %var_as_arr_ptr DescriptorSet 0\n"
1986 "OpDecorate %var_as_arr_ptr Binding 0\n"
1987 "OpDecorate %71 NonUniform\n"
1988 "OpDecorate %73 NonUniform\n"
1989 "OpDecorate %74 NonUniform\n"
1990 "OpDecorate %85 NonUniform\n"
1991 "OpDecorate %as_index NonUniform\n"
1992 "OpDecorate %as_device_addres NonUniform\n"
1993 "OpDecorate %104 ArrayStride 8\n"
1994 "OpMemberDecorate %105 0 NonWritable\n"
1995 "OpMemberDecorate %105 0 Offset 0\n"
1996 "OpDecorate %105 Block\n"
1997 "OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
1998 "OpDecorate %var_as_pointers_ssbo Binding 1\n"
1999 // types, constants and variables
2000 "%2 = OpTypeVoid\n"
2001 "%3 = OpTypeFunction %2\n"
2002 "%6 = OpTypeFloat 32\n"
2003 "%7 = OpTypePointer Function %6\n"
2004 "%9 = OpConstant %6 0\n"
2005 "%11 = OpConstant %6 2\n"
2006 "%12 = OpTypeVector %6 3\n"
2007 "%13 = OpTypePointer Function %12\n"
2008 "%15 = OpConstant %6 0.25\n"
2009 "%16 = OpConstant %6 0.5\n"
2010 "%17 = OpConstant %6 1\n"
2011 "%18 = OpConstantComposite %12 %15 %16 %17\n"
2012 "%20 = OpConstant %6 -1\n"
2013 "%21 = OpConstantComposite %12 %9 %9 %20\n"
2014 "%type_uint32 = OpTypeInt 32 0\n"
2015 "%23 = OpTypePointer Function %type_uint32\n"
2016 "%25 = OpTypeVector %type_uint32 3\n"
2017 "%26 = OpTypePointer Input %25\n"
2018 "%27 = OpVariable %26 Input\n"
2019 "%28 = OpConstant %type_uint32 0\n"
2020 "%29 = OpTypePointer Input %type_uint32\n"
2021 "%33 = OpVariable %26 Input\n"
2022 "%37 = OpTypeRuntimeArray %type_uint32\n"
2023 "%38 = OpTypeStruct %37\n"
2024 "%39 = OpTypePointer StorageBuffer %38\n"
2025 "%var_tlas_indices = OpVariable %39 StorageBuffer\n"
2026 "%type_int32 = OpTypeInt 32 1\n"
2027 "%c_int32_0 = OpConstant %type_int32 0\n"
2028 "%45 = OpTypePointer StorageBuffer %type_uint32\n"
2029 "%48 = OpTypeRuntimeArray %type_uint32\n"
2030 "%49 = OpTypeStruct %48\n"
2031 "%50 = OpTypePointer StorageBuffer %49\n"
2032 "%var_result = OpVariable %50 StorageBuffer\n"
2033 "%55 = OpConstant %type_uint32 2\n"
2034 "%56 = OpConstant %type_uint32 1\n"
2035 "%58 = OpTypeVector %type_uint32 2\n"
2036 "%59 = OpTypePointer RayPayloadNV %58\n"
2037 "%60 = OpVariable %59 RayPayloadNV\n"
2038 "%type_as = OpTypeAccelerationStructureKHR\n"
2039 "%66 = OpConstant %type_uint32 500\n"
2040 "%67 = OpTypeArray %type_as %66\n"
2041 "%68 = OpTypePointer UniformConstant %67\n"
2042 "%var_as_arr_ptr = OpVariable %68 UniformConstant\n"
2043 "%72 = OpTypePointer UniformConstant %type_as\n"
2044 "%75 = OpConstant %type_uint32 16\n"
2045 "%76 = OpConstant %type_uint32 255\n"
2046 "%87 = OpConstant %type_uint32 5\n"
2047 "%91 = OpConstant %type_uint32 3\n"
2048
2049 // <changed_section>
2050 "%type_uint64 = OpTypeInt 64 0\n"
2051 "%104 = OpTypeRuntimeArray %type_uint64\n"
2052 "%105 = OpTypeStruct %104\n"
2053 "%106 = OpTypePointer StorageBuffer %105\n"
2054 "%var_as_pointers_ssbo = OpVariable %106 StorageBuffer\n"
2055 "%type_uint64_ssbo_ptr = OpTypePointer StorageBuffer %type_uint64\n"
2056 // </changed_section>
2057
2058 // void main()
2059 "%4 = OpFunction %2 None %3\n"
2060 "%5 = OpLabel\n"
2061 "%8 = OpVariable %7 Function\n"
2062 "%10 = OpVariable %7 Function\n"
2063 "%14 = OpVariable %13 Function\n"
2064 "%19 = OpVariable %13 Function\n"
2065 "%24 = OpVariable %23 Function\n"
2066 "%32 = OpVariable %23 Function\n"
2067 "%36 = OpVariable %23 Function\n"
2068 "OpStore %8 %9\n"
2069 "OpStore %10 %11\n"
2070 "OpStore %14 %18\n"
2071 "OpStore %19 %21\n"
2072 "%30 = OpAccessChain %29 %27 %28\n"
2073 "%31 = OpLoad %type_uint32 %30\n"
2074 "OpStore %24 %31\n"
2075 "%34 = OpAccessChain %29 %33 %28\n"
2076 "%35 = OpLoad %type_uint32 %34\n"
2077 "OpStore %32 %35\n"
2078 "%43 = OpLoad %type_uint32 %24\n"
2079 "%44 = OpCopyObject %type_uint32 %43\n"
2080 "%46 = OpAccessChain %45 %var_tlas_indices %c_int32_0 %44\n"
2081 "%47 = OpLoad %type_uint32 %46\n"
2082 "OpStore %36 %47\n"
2083 // atomicAdd
2084 "%52 = OpLoad %type_uint32 %24\n"
2085 "%53 = OpCopyObject %type_uint32 %52\n"
2086 "%54 = OpAccessChain %45 %var_result %c_int32_0 %53\n"
2087 "%57 = OpAtomicIAdd %type_uint32 %54 %56 %28 %55\n"
2088 // setup payload
2089 "%61 = OpLoad %type_uint32 %24\n"
2090 "%62 = OpLoad %type_uint32 %32\n"
2091 "%63 = OpIAdd %type_uint32 %61 %62\n"
2092 "%64 = OpCompositeConstruct %58 %63 %28\n"
2093 "OpStore %60 %64\n"
2094 // trace rays using tlas from array
2095 "%70 = OpLoad %type_uint32 %36\n"
2096 "%71 = OpCopyObject %type_uint32 %70\n"
2097 "%73 = OpAccessChain %72 %var_as_arr_ptr %71\n"
2098 "%74 = OpLoad %type_as %73\n"
2099 "%77 = OpLoad %12 %14\n"
2100 "%78 = OpLoad %6 %8\n"
2101 "%79 = OpLoad %12 %19\n"
2102 "%80 = OpLoad %6 %10\n"
2103 "OpTraceRayKHR %74 %75 %76 %28 %28 %28 %77 %78 %79 %80 %60\n"
2104 // atomicAdd
2105 "%81 = OpLoad %type_uint32 %24\n"
2106 "%82 = OpLoad %type_uint32 %32\n"
2107 "%83 = OpIMul %type_uint32 %82 %55\n"
2108 "%84 = OpIAdd %type_uint32 %81 %83\n"
2109 "%85 = OpCopyObject %type_uint32 %84\n"
2110 "%86 = OpAccessChain %45 %var_result %c_int32_0 %85\n"
2111 "%88 = OpAtomicIAdd %type_uint32 %86 %56 %28 %87\n"
2112 // setup payload
2113 "%89 = OpLoad %type_uint32 %24\n"
2114 "%90 = OpLoad %type_uint32 %32\n"
2115 "%92 = OpIMul %type_uint32 %90 %91\n"
2116 "%93 = OpIAdd %type_uint32 %89 %92\n"
2117 "%94 = OpCompositeConstruct %58 %93 %56\n"
2118 "OpStore %60 %94\n"
2119 // trace rays using pointers to tlas
2120 "%95 = OpLoad %type_uint32 %36\n"
2121 "%as_index = OpCopyObject %type_uint32 %95\n"
2122
2123 // <changed_section> OLD
2124 "%as_device_addres_ptr = OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 %as_index\n"
2125 "%as_device_addres = OpLoad %type_uint64 %as_device_addres_ptr Aligned 8\n"
2126 "%as_to_use = OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
2127 // </changed_section>
2128
2129 "%99 = OpLoad %12 %14\n"
2130 "%100 = OpLoad %6 %8\n"
2131 "%101 = OpLoad %12 %19\n"
2132 "%102 = OpLoad %6 %10\n"
2133 "OpTraceRayKHR %as_to_use %75 %76 %28 %28 %28 %99 %100 %101 %102 %60\n"
2134 "OpReturn\n"
2135 "OpFunctionEnd\n";
2136 programCollection.spirvAsmSources.add("rgen") << rgenSource << spvBuildOptions;
2137
2138 std::string chitSource =
2139 "#version 460 core\n"
2140 "#extension GL_EXT_ray_tracing : require\n"
2141 "#extension GL_EXT_nonuniform_qualifier : enable\n"
2142 "layout(location = 0) rayPayloadInEXT uvec2 payload;\n"
2143 "\n"
2144 "layout(set = 0, binding = 3) writeonly buffer Result {\n"
2145 " uint value[];\n"
2146 "} result;\n"
2147 "void main()\n"
2148 "{\n"
2149 // payload.y is 0 or 1 so we will add 3 or 7 (just two prime numbers)
2150 " atomicAdd(result.value[nonuniformEXT(payload.x)], 3 + payload.y * 4);\n"
2151 "}\n";
2152 programCollection.glslSources.add("chit") << glu::ClosestHitSource(chitSource) << glslBuildOptions;
2153 }
2154
createInstance(Context & context) const2155 TestInstance* RayTracingASDynamicIndexingTestCase::createInstance(Context& context) const
2156 {
2157 return new RayTracingASDynamicIndexingTestInstance(context);
2158 }
2159
RayTracingASDynamicIndexingTestInstance(Context & context)2160 RayTracingASDynamicIndexingTestInstance::RayTracingASDynamicIndexingTestInstance(Context& context)
2161 : vkt::TestInstance(context)
2162 {
2163 }
2164
iterate(void)2165 tcu::TestStatus RayTracingASDynamicIndexingTestInstance::iterate(void)
2166 {
2167 const InstanceInterface& vki = m_context.getInstanceInterface();
2168 const DeviceInterface& vkd = m_context.getDeviceInterface();
2169 const VkDevice device = m_context.getDevice();
2170 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
2171 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2172 const VkQueue queue = m_context.getUniversalQueue();
2173 Allocator& allocator = m_context.getDefaultAllocator();
2174 const deUint32 shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
2175 const deUint32 shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
2176 const deUint32 tlasCount = 500; // changing this will require also changing shaders
2177 const deUint32 activeTlasCount = 32; // number of tlas out of <tlasCount> that will be active
2178
2179 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
2180 .addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, ALL_RAY_TRACING_STAGES)
2181 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES) // pointers to all acceleration structures
2182 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES) // ssbo with indices of all acceleration structures
2183 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES) // ssbo with result values
2184 .build(vkd, device);
2185
2186 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
2187 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
2188 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2189 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2190 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2191 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2192 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
2193
2194 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
2195 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
2196 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
2197
2198 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
2199 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
2200 de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
2201 de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
2202
2203 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2204 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2205 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2206 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2207
2208 const VkDeviceSize pointerBufferSize = tlasCount * sizeof(VkDeviceAddress);
2209 const VkBufferCreateInfo pointerBufferCreateInfo = makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2210 de::MovePtr<BufferWithMemory> pointerBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
2211
2212 const VkDeviceSize indicesBufferSize = activeTlasCount * sizeof(deUint32);
2213 const VkBufferCreateInfo indicesBufferCreateInfo = makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2214 de::MovePtr<BufferWithMemory> indicesBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
2215
2216 const VkDeviceSize resultBufferSize = activeTlasCount * sizeof(deUint32) * 4;
2217 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2218 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2219
2220 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
2221 const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2222
2223 de::SharedPtr<BottomLevelAccelerationStructure> blas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
2224 std::vector<de::MovePtr<TopLevelAccelerationStructure>> tlasVect(tlasCount);
2225 std::vector<VkDeviceAddress> tlasPtrVect(tlasCount);
2226 std::vector<VkAccelerationStructureKHR> tlasVkVect;
2227
2228 // randomly scatter active AS across the range
2229 deRandom rnd;
2230 deRandom_init(&rnd, 123);
2231 std::set<deUint32> asIndicesSet;
2232 while (asIndicesSet.size() < activeTlasCount)
2233 asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
2234
2235 // fill indices buffer
2236 deUint32 helperIndex = 0;
2237 auto& indicesBufferAlloc = indicesBuffer->getAllocation();
2238 deUint32* indicesBufferPtr = reinterpret_cast<deUint32*>(indicesBufferAlloc.getHostPtr());
2239 std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
2240 [&helperIndex, indicesBufferPtr](const deUint32& index)
2241 {
2242 indicesBufferPtr[helperIndex++] = index;
2243 });
2244 vk::flushAlloc(vkd, device, indicesBufferAlloc);
2245
2246 // clear result buffer
2247 auto& resultBufferAlloc = resultBuffer->getAllocation();
2248 void* resultBufferPtr = resultBufferAlloc.getHostPtr();
2249 deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
2250 vk::flushAlloc(vkd, device, resultBufferAlloc);
2251
2252 beginCommandBuffer(vkd, *cmdBuffer, 0u);
2253 {
2254 // build bottom level acceleration structure
2255 blas->setGeometryData(
2256 {
2257 { 0.0, 0.0, 0.0 },
2258 { 1.0, 0.0, 0.0 },
2259 { 0.0, 1.0, 0.0 },
2260 },
2261 true,
2262 VK_GEOMETRY_OPAQUE_BIT_KHR
2263 );
2264
2265 blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2266
2267 // build top level acceleration structures
2268 for (deUint32 tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
2269 {
2270 auto& tlas = tlasVect[tlasIndex];
2271 tlas = makeTopLevelAccelerationStructure();
2272 tlas->setInstanceCount(1);
2273 tlas->addInstance(blas);
2274 if (!asIndicesSet.count(tlasIndex))
2275 {
2276 // tlas that are not in asIndicesSet should be empty but it is hard to do
2277 // that with current cts utils so we are marking them as inactive instead
2278 tlas->setInactiveInstances(true);
2279 }
2280 tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2281
2282 // get acceleration structure device address
2283 const VkAccelerationStructureDeviceAddressInfoKHR addressInfo =
2284 {
2285 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType
2286 DE_NULL, // const void* pNext
2287 *tlas->getPtr() // VkAccelerationStructureKHR accelerationStructure
2288 };
2289 VkDeviceAddress vkda = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
2290 tlasPtrVect[tlasIndex] = vkda;
2291 }
2292
2293 // fill pointer buffer
2294 vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
2295
2296 // wait for data transfers
2297 const VkMemoryBarrier bufferUploadBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
2298 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &bufferUploadBarrier, 1u);
2299
2300 // wait for as build
2301 const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
2302 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &asBuildBarrier, 1u);
2303
2304 tlasVkVect.reserve(tlasCount);
2305 for (auto& tlas : tlasVect)
2306 tlasVkVect.push_back(*tlas->getPtr());
2307
2308 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
2309 {
2310 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
2311 DE_NULL, // const void* pNext;
2312 tlasCount, // deUint32 accelerationStructureCount;
2313 tlasVkVect.data(), // const VkAccelerationStructureKHR* pAccelerationStructures;
2314 };
2315
2316 const vk::VkDescriptorBufferInfo pointerBufferInfo = makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
2317 const vk::VkDescriptorBufferInfo indicesBufferInfo = makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
2318 const vk::VkDescriptorBufferInfo resultInfo = makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE);
2319
2320 DescriptorSetUpdateBuilder()
2321 .writeArray (*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, &accelerationStructureWriteDescriptorSet)
2322 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
2323 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
2324 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
2325 .update(vkd, device);
2326
2327 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
2328
2329 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2330
2331 cmdTraceRays(vkd,
2332 *cmdBuffer,
2333 &raygenShaderBindingTableRegion,
2334 &missShaderBindingTableRegion,
2335 &hitShaderBindingTableRegion,
2336 &callableShaderBindingTableRegion,
2337 activeTlasCount, 1, 1);
2338
2339 const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2340 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2341 }
2342 endCommandBuffer(vkd, *cmdBuffer);
2343
2344 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2345
2346 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), resultBufferSize);
2347
2348 // verify result buffer
2349 deUint32 failures = 0;
2350 const deUint32* resultPtr = reinterpret_cast<deUint32*>(resultBuffer->getAllocation().getHostPtr());
2351 for (deUint32 index = 0; index < activeTlasCount; ++index)
2352 {
2353 failures += (resultPtr[0 * activeTlasCount + index] != 2) +
2354 (resultPtr[1 * activeTlasCount + index] != 3) +
2355 (resultPtr[2 * activeTlasCount + index] != 5) +
2356 (resultPtr[3 * activeTlasCount + index] != 7);
2357 }
2358
2359 if (failures)
2360 return tcu::TestStatus::fail(de::toString(failures) + " failures, " + de::toString(4 * activeTlasCount - failures) + " are ok");
2361 return tcu::TestStatus::pass("Pass");
2362 }
2363
2364 } // anonymous
2365
addBasicBuildingTests(tcu::TestCaseGroup * group)2366 void addBasicBuildingTests(tcu::TestCaseGroup* group)
2367 {
2368 struct
2369 {
2370 vk::VkAccelerationStructureBuildTypeKHR buildType;
2371 const char* name;
2372 } buildTypes[] =
2373 {
2374 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2375 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2376 };
2377
2378 struct
2379 {
2380 BottomTestType testType;
2381 bool usesAOP;
2382 const char* name;
2383 } bottomTestTypes[] =
2384 {
2385 { BTT_TRIANGLES, false, "triangles" },
2386 { BTT_TRIANGLES, true, "triangles_aop" },
2387 { BTT_AABBS, false, "aabbs" },
2388 { BTT_AABBS, true, "aabbs_aop" },
2389 };
2390
2391 struct
2392 {
2393 TopTestType testType;
2394 bool usesAOP;
2395 const char* name;
2396 } topTestTypes[] =
2397 {
2398 { TTT_IDENTICAL_INSTANCES, false, "identical_instances" },
2399 { TTT_IDENTICAL_INSTANCES, true, "identical_instances_aop" },
2400 { TTT_DIFFERENT_INSTANCES, false, "different_instances" },
2401 { TTT_DIFFERENT_INSTANCES, true, "different_instances_aop" },
2402 };
2403
2404 struct BuildFlagsData
2405 {
2406 VkBuildAccelerationStructureFlagsKHR flags;
2407 const char* name;
2408 };
2409
2410 BuildFlagsData optimizationTypes[] =
2411 {
2412 { VkBuildAccelerationStructureFlagsKHR(0u), "0" },
2413 { VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, "fasttrace" },
2414 { VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, "fastbuild" },
2415 };
2416
2417 BuildFlagsData updateTypes[] =
2418 {
2419 { VkBuildAccelerationStructureFlagsKHR(0u), "0" },
2420 { VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, "update" },
2421 };
2422
2423 BuildFlagsData compactionTypes[] =
2424 {
2425 { VkBuildAccelerationStructureFlagsKHR(0u), "0" },
2426 { VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, "compaction" },
2427 };
2428
2429 BuildFlagsData lowMemoryTypes[] =
2430 {
2431 { VkBuildAccelerationStructureFlagsKHR(0u), "0" },
2432 { VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, "lowmemory" },
2433 };
2434
2435 struct
2436 {
2437 bool padVertices;
2438 const char* name;
2439 } paddingType[] =
2440 {
2441 { false, "nopadding" },
2442 { true, "padded" },
2443 };
2444
2445 struct
2446 {
2447 bool topGeneric;
2448 bool bottomGeneric;
2449 const char* suffix;
2450 } createGenericParams[] =
2451 {
2452 { false, false, "" },
2453 { false, true, "_bottomgeneric" },
2454 { true, false, "_topgeneric" },
2455 { true, true, "_bothgeneric" },
2456 };
2457
2458 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2459 {
2460 de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2461
2462 for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
2463 {
2464 de::MovePtr<tcu::TestCaseGroup> bottomGroup(new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name, ""));
2465
2466 for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
2467 {
2468 de::MovePtr<tcu::TestCaseGroup> topGroup(new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name, ""));
2469
2470 for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
2471 {
2472 de::MovePtr<tcu::TestCaseGroup> paddingGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name, ""));
2473
2474 for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes); ++optimizationNdx)
2475 {
2476 for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
2477 {
2478 for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes); ++compactionNdx)
2479 {
2480 for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes); ++lowMemoryNdx)
2481 {
2482 for (int createGenericIdx = 0; createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams); ++createGenericIdx)
2483 {
2484 std::string testName =
2485 std::string(optimizationTypes[optimizationNdx].name) + "_" +
2486 std::string(updateTypes[updateNdx].name) + "_" +
2487 std::string(compactionTypes[compactionNdx].name) + "_" +
2488 std::string(lowMemoryTypes[lowMemoryNdx].name) +
2489 std::string(createGenericParams[createGenericIdx].suffix);
2490
2491 TestParams testParams
2492 {
2493 buildTypes[buildTypeNdx].buildType,
2494 VK_FORMAT_R32G32B32_SFLOAT,
2495 paddingType[paddingTypeIdx].padVertices,
2496 VK_INDEX_TYPE_NONE_KHR,
2497 bottomTestTypes[bottomNdx].testType,
2498 InstanceCullFlags::NONE,
2499 bottomTestTypes[bottomNdx].usesAOP,
2500 createGenericParams[createGenericIdx].bottomGeneric,
2501 topTestTypes[topNdx].testType,
2502 topTestTypes[topNdx].usesAOP,
2503 createGenericParams[createGenericIdx].topGeneric,
2504 optimizationTypes[optimizationNdx].flags | updateTypes[updateNdx].flags | compactionTypes[compactionNdx].flags | lowMemoryTypes[lowMemoryNdx].flags,
2505 OT_NONE,
2506 OP_NONE,
2507 RTAS_DEFAULT_SIZE,
2508 RTAS_DEFAULT_SIZE,
2509 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2510 0u,
2511 EmptyAccelerationStructureCase::NOT_EMPTY,
2512 InstanceCustomIndexCase::NONE,
2513 };
2514 paddingGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), testName.c_str(), "", testParams));
2515 }
2516 }
2517 }
2518 }
2519 }
2520 topGroup->addChild(paddingGroup.release());
2521 }
2522 bottomGroup->addChild(topGroup.release());
2523 }
2524 buildGroup->addChild(bottomGroup.release());
2525 }
2526 group->addChild(buildGroup.release());
2527 }
2528 }
2529
addVertexIndexFormatsTests(tcu::TestCaseGroup * group)2530 void addVertexIndexFormatsTests(tcu::TestCaseGroup* group)
2531 {
2532 struct
2533 {
2534 vk::VkAccelerationStructureBuildTypeKHR buildType;
2535 const char* name;
2536 } buildTypes[] =
2537 {
2538 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2539 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2540 };
2541
2542 const VkFormat vertexFormats[] =
2543 {
2544 // Mandatory formats.
2545 VK_FORMAT_R32G32_SFLOAT,
2546 VK_FORMAT_R32G32B32_SFLOAT,
2547 VK_FORMAT_R16G16_SFLOAT,
2548 VK_FORMAT_R16G16B16A16_SFLOAT,
2549 VK_FORMAT_R16G16_SNORM,
2550 VK_FORMAT_R16G16B16A16_SNORM,
2551
2552 // Additional formats.
2553 VK_FORMAT_R8G8_SNORM,
2554 VK_FORMAT_R8G8B8_SNORM,
2555 VK_FORMAT_R8G8B8A8_SNORM,
2556 VK_FORMAT_R16G16B16_SNORM,
2557 VK_FORMAT_R16G16B16_SFLOAT,
2558 VK_FORMAT_R32G32B32A32_SFLOAT,
2559 VK_FORMAT_R64G64_SFLOAT,
2560 VK_FORMAT_R64G64B64_SFLOAT,
2561 VK_FORMAT_R64G64B64A64_SFLOAT,
2562 };
2563
2564 struct
2565 {
2566 VkIndexType indexType;
2567 const char* name;
2568 } indexFormats[] =
2569 {
2570 { VK_INDEX_TYPE_NONE_KHR , "index_none" },
2571 { VK_INDEX_TYPE_UINT16 , "index_uint16" },
2572 { VK_INDEX_TYPE_UINT32 , "index_uint32" },
2573 };
2574
2575 struct
2576 {
2577 bool padVertices;
2578 const char* name;
2579 } paddingType[] =
2580 {
2581 { false, "nopadding" },
2582 { true, "padded" },
2583 };
2584
2585 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2586 {
2587 de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2588
2589 for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
2590 {
2591 const auto format = vertexFormats[vertexFormatNdx];
2592 const auto formatName = getFormatSimpleName(format);
2593
2594 de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str(), ""));
2595
2596 for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
2597 {
2598 de::MovePtr<tcu::TestCaseGroup> paddingGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name, ""));
2599
2600 for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
2601 {
2602 TestParams testParams
2603 {
2604 buildTypes[buildTypeNdx].buildType,
2605 format,
2606 paddingType[paddingIdx].padVertices,
2607 indexFormats[indexFormatNdx].indexType,
2608 BTT_TRIANGLES,
2609 InstanceCullFlags::NONE,
2610 false,
2611 false,
2612 TTT_IDENTICAL_INSTANCES,
2613 false,
2614 false,
2615 VkBuildAccelerationStructureFlagsKHR(0u),
2616 OT_NONE,
2617 OP_NONE,
2618 RTAS_DEFAULT_SIZE,
2619 RTAS_DEFAULT_SIZE,
2620 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2621 0u,
2622 EmptyAccelerationStructureCase::NOT_EMPTY,
2623 InstanceCustomIndexCase::NONE,
2624 };
2625 paddingGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), indexFormats[indexFormatNdx].name, "", testParams));
2626 }
2627 vertexFormatGroup->addChild(paddingGroup.release());
2628 }
2629 buildGroup->addChild(vertexFormatGroup.release());
2630 }
2631 group->addChild(buildGroup.release());
2632 }
2633 }
2634
addOperationTestsImpl(tcu::TestCaseGroup * group,const deUint32 workerThreads)2635 void addOperationTestsImpl (tcu::TestCaseGroup* group, const deUint32 workerThreads)
2636 {
2637 struct
2638 {
2639 OperationType operationType;
2640 const char* name;
2641 } operationTypes[] =
2642 {
2643 { OP_COPY, "copy" },
2644 { OP_COMPACT, "compaction" },
2645 { OP_SERIALIZE, "serialization" },
2646 };
2647
2648 struct
2649 {
2650 vk::VkAccelerationStructureBuildTypeKHR buildType;
2651 const char* name;
2652 } buildTypes[] =
2653 {
2654 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2655 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2656 };
2657
2658 struct
2659 {
2660 OperationTarget operationTarget;
2661 const char* name;
2662 } operationTargets[] =
2663 {
2664 { OT_TOP_ACCELERATION, "top_acceleration_structure" },
2665 { OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure" },
2666 };
2667
2668 struct
2669 {
2670 BottomTestType testType;
2671 const char* name;
2672 } bottomTestTypes[] =
2673 {
2674 { BTT_TRIANGLES, "triangles" },
2675 { BTT_AABBS, "aabbs" },
2676 };
2677
2678 for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
2679 {
2680 if (workerThreads > 0)
2681 if (operationTypes[operationTypeNdx].operationType != OP_COPY && operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
2682 continue;
2683
2684 de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name, ""));
2685
2686 for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2687 {
2688 if (workerThreads > 0 && buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
2689 continue;
2690
2691 de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2692
2693 for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets); ++operationTargetNdx)
2694 {
2695 de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name, ""));
2696
2697 for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
2698 {
2699 TopTestType topTest = (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ? TTT_DIFFERENT_INSTANCES : TTT_IDENTICAL_INSTANCES;
2700
2701 TestParams testParams
2702 {
2703 buildTypes[buildTypeNdx].buildType,
2704 VK_FORMAT_R32G32B32_SFLOAT,
2705 false,
2706 VK_INDEX_TYPE_NONE_KHR,
2707 bottomTestTypes[testTypeNdx].testType,
2708 InstanceCullFlags::NONE,
2709 false,
2710 false,
2711 topTest,
2712 false,
2713 false,
2714 VkBuildAccelerationStructureFlagsKHR(0u),
2715 operationTargets[operationTargetNdx].operationTarget,
2716 operationTypes[operationTypeNdx].operationType,
2717 RTAS_DEFAULT_SIZE,
2718 RTAS_DEFAULT_SIZE,
2719 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2720 workerThreads,
2721 EmptyAccelerationStructureCase::NOT_EMPTY,
2722 InstanceCustomIndexCase::NONE,
2723 };
2724 operationTargetGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), bottomTestTypes[testTypeNdx].name, "", testParams));
2725 }
2726 buildGroup->addChild(operationTargetGroup.release());
2727 }
2728 operationTypeGroup->addChild(buildGroup.release());
2729 }
2730 group->addChild(operationTypeGroup.release());
2731 }
2732 }
2733
addOperationTests(tcu::TestCaseGroup * group)2734 void addOperationTests (tcu::TestCaseGroup* group)
2735 {
2736 addOperationTestsImpl(group, 0);
2737 }
2738
addHostThreadingOperationTests(tcu::TestCaseGroup * group)2739 void addHostThreadingOperationTests (tcu::TestCaseGroup* group)
2740 {
2741 const deUint32 threads[] = { 1, 2, 3, 4, 8, std::numeric_limits<deUint32>::max() };
2742
2743 for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
2744 {
2745 const std::string groupName = threads[threadsNdx] != std::numeric_limits<deUint32>::max()
2746 ? de::toString(threads[threadsNdx])
2747 : "max";
2748
2749 de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str(), ""));
2750
2751 addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
2752
2753 group->addChild(threadGroup.release());
2754 }
2755 }
2756
addFuncArgTests(tcu::TestCaseGroup * group)2757 void addFuncArgTests (tcu::TestCaseGroup* group)
2758 {
2759 const struct
2760 {
2761 vk::VkAccelerationStructureBuildTypeKHR buildType;
2762 const char* name;
2763 } buildTypes[] =
2764 {
2765 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2766 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2767 };
2768
2769 auto& ctx = group->getTestContext();
2770
2771 for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2772 {
2773 TestParams testParams
2774 {
2775 buildTypes[buildTypeNdx].buildType,
2776 VK_FORMAT_R32G32B32_SFLOAT,
2777 false,
2778 VK_INDEX_TYPE_NONE_KHR,
2779 BTT_TRIANGLES,
2780 InstanceCullFlags::NONE,
2781 false,
2782 false,
2783 TTT_IDENTICAL_INSTANCES,
2784 false,
2785 false,
2786 VkBuildAccelerationStructureFlagsKHR(0u),
2787 OT_NONE,
2788 OP_NONE,
2789 RTAS_DEFAULT_SIZE,
2790 RTAS_DEFAULT_SIZE,
2791 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2792 0u,
2793 EmptyAccelerationStructureCase::NOT_EMPTY,
2794 InstanceCustomIndexCase::NONE,
2795 };
2796
2797 group->addChild(new RayTracingASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, "", testParams));
2798 }
2799 }
2800
addInstanceTriangleCullingTests(tcu::TestCaseGroup * group)2801 void addInstanceTriangleCullingTests (tcu::TestCaseGroup* group)
2802 {
2803 const struct
2804 {
2805 InstanceCullFlags cullFlags;
2806 std::string name;
2807 } cullFlags[] =
2808 {
2809 { InstanceCullFlags::NONE, "noflags" },
2810 { InstanceCullFlags::COUNTERCLOCKWISE, "ccw" },
2811 { InstanceCullFlags::CULL_DISABLE, "nocull" },
2812 { InstanceCullFlags::ALL, "ccw_nocull" },
2813 };
2814
2815 const struct
2816 {
2817 TopTestType topType;
2818 std::string name;
2819 } topType[] =
2820 {
2821 { TTT_DIFFERENT_INSTANCES, "transformed" }, // Each instance has its own transformation matrix.
2822 { TTT_IDENTICAL_INSTANCES, "notransform" }, // "Identical" instances, different geometries.
2823 };
2824
2825 const struct
2826 {
2827 vk::VkAccelerationStructureBuildTypeKHR buildType;
2828 std::string name;
2829 } buildTypes[] =
2830 {
2831 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2832 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2833 };
2834
2835 const struct
2836 {
2837 VkIndexType indexType;
2838 std::string name;
2839 } indexFormats[] =
2840 {
2841 { VK_INDEX_TYPE_NONE_KHR , "index_none" },
2842 { VK_INDEX_TYPE_UINT16 , "index_uint16" },
2843 { VK_INDEX_TYPE_UINT32 , "index_uint32" },
2844 };
2845
2846 auto& ctx = group->getTestContext();
2847
2848 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
2849 {
2850 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
2851
2852 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
2853 {
2854 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str(), ""));
2855
2856 for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
2857 {
2858 for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
2859 {
2860 const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
2861
2862 TestParams testParams
2863 {
2864 buildTypes[buildTypeIdx].buildType,
2865 VK_FORMAT_R32G32B32_SFLOAT,
2866 false,
2867 indexFormats[indexFormatIdx].indexType,
2868 BTT_TRIANGLES,
2869 cullFlags[cullFlagsIdx].cullFlags,
2870 false,
2871 false,
2872 topType[topTypeIdx].topType,
2873 false,
2874 false,
2875 VkBuildAccelerationStructureFlagsKHR(0u),
2876 OT_NONE,
2877 OP_NONE,
2878 RTAS_DEFAULT_SIZE,
2879 RTAS_DEFAULT_SIZE,
2880 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2881 0u,
2882 EmptyAccelerationStructureCase::NOT_EMPTY,
2883 InstanceCustomIndexCase::NONE,
2884 };
2885 indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, testName.c_str(), "", testParams));
2886 }
2887 }
2888 buildTypeGroup->addChild(indexTypeGroup.release());
2889 }
2890 group->addChild(buildTypeGroup.release());
2891 }
2892 }
2893
addDynamicIndexingTests(tcu::TestCaseGroup * group)2894 void addDynamicIndexingTests (tcu::TestCaseGroup* group)
2895 {
2896 auto& ctx = group->getTestContext();
2897 group->addChild(new RayTracingASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
2898 }
2899
addEmptyAccelerationStructureTests(tcu::TestCaseGroup * group)2900 void addEmptyAccelerationStructureTests (tcu::TestCaseGroup* group)
2901 {
2902 const struct
2903 {
2904 vk::VkAccelerationStructureBuildTypeKHR buildType;
2905 std::string name;
2906 } buildTypes[] =
2907 {
2908 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2909 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2910 };
2911
2912 const struct
2913 {
2914 VkIndexType indexType;
2915 std::string name;
2916 } indexFormats[] =
2917 {
2918 { VK_INDEX_TYPE_NONE_KHR, "index_none" },
2919 { VK_INDEX_TYPE_UINT16, "index_uint16" },
2920 { VK_INDEX_TYPE_UINT32, "index_uint32" },
2921 };
2922
2923 const struct
2924 {
2925 EmptyAccelerationStructureCase emptyASCase;
2926 std::string name;
2927 } emptyCases[] =
2928 {
2929 { EmptyAccelerationStructureCase::INACTIVE_TRIANGLES, "inactive_triangles" },
2930 { EmptyAccelerationStructureCase::INACTIVE_INSTANCES, "inactive_instances" },
2931 { EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM, "no_geometries_bottom" },
2932 { EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP, "no_primitives_top" },
2933 { EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM, "no_primitives_bottom" },
2934 };
2935
2936 auto& ctx = group->getTestContext();
2937
2938 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
2939 {
2940 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
2941
2942 for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
2943 {
2944 de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str(), ""));
2945
2946 for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
2947 {
2948 TestParams testParams
2949 {
2950 buildTypes[buildTypeIdx].buildType,
2951 VK_FORMAT_R32G32B32_SFLOAT,
2952 false,
2953 indexFormats[indexFormatIdx].indexType,
2954 BTT_TRIANGLES,
2955 InstanceCullFlags::NONE,
2956 false,
2957 false,
2958 TTT_IDENTICAL_INSTANCES,
2959 false,
2960 false,
2961 VkBuildAccelerationStructureFlagsKHR(0u),
2962 OT_NONE,
2963 OP_NONE,
2964 RTAS_DEFAULT_SIZE,
2965 RTAS_DEFAULT_SIZE,
2966 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2967 0u,
2968 emptyCases[emptyCaseIdx].emptyASCase,
2969 InstanceCustomIndexCase::NONE,
2970 };
2971 indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), "", testParams));
2972 }
2973 buildTypeGroup->addChild(indexTypeGroup.release());
2974 }
2975 group->addChild(buildTypeGroup.release());
2976 }
2977 }
2978
addInstanceIndexTests(tcu::TestCaseGroup * group)2979 void addInstanceIndexTests (tcu::TestCaseGroup* group)
2980 {
2981 const struct
2982 {
2983 vk::VkAccelerationStructureBuildTypeKHR buildType;
2984 std::string name;
2985 } buildTypes[] =
2986 {
2987 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built" },
2988 { VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built" },
2989 };
2990
2991 const struct
2992 {
2993 InstanceCustomIndexCase customIndexCase;
2994 std::string name;
2995 } customIndexCases[] =
2996 {
2997 { InstanceCustomIndexCase::NONE, "no_instance_index" },
2998 { InstanceCustomIndexCase::ANY_HIT, "ahit" },
2999 { InstanceCustomIndexCase::CLOSEST_HIT, "chit" },
3000 { InstanceCustomIndexCase::INTERSECTION, "isec" },
3001 };
3002
3003 auto& ctx = group->getTestContext();
3004
3005 for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
3006 {
3007 de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
3008
3009 for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases); ++customIndexCaseIdx)
3010 {
3011 const auto& idxCase = customIndexCases[customIndexCaseIdx].customIndexCase;
3012 const auto bottomGeometryType = ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BTT_AABBS : BTT_TRIANGLES);
3013
3014 TestParams testParams
3015 {
3016 buildTypes[buildTypeIdx].buildType,
3017 VK_FORMAT_R32G32B32_SFLOAT,
3018 false,
3019 VK_INDEX_TYPE_NONE_KHR,
3020 bottomGeometryType,
3021 InstanceCullFlags::NONE,
3022 false,
3023 false,
3024 TTT_IDENTICAL_INSTANCES,
3025 false,
3026 false,
3027 VkBuildAccelerationStructureFlagsKHR(0u),
3028 OT_NONE,
3029 OP_NONE,
3030 RTAS_DEFAULT_SIZE,
3031 RTAS_DEFAULT_SIZE,
3032 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
3033 0u,
3034 EmptyAccelerationStructureCase::NOT_EMPTY,
3035 customIndexCases[customIndexCaseIdx].customIndexCase,
3036 };
3037 buildTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, customIndexCases[customIndexCaseIdx].name.c_str(), "", testParams));
3038 }
3039 group->addChild(buildTypeGroup.release());
3040 }
3041 }
3042
createAccelerationStructuresTests(tcu::TestContext & testCtx)3043 tcu::TestCaseGroup* createAccelerationStructuresTests(tcu::TestContext& testCtx)
3044 {
3045 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures", "Acceleration structure tests"));
3046
3047 addTestGroup(group.get(), "flags", "Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers", addBasicBuildingTests);
3048 addTestGroup(group.get(), "format", "Test building AS with different vertex and index formats", addVertexIndexFormatsTests);
3049 addTestGroup(group.get(), "operations", "Test copying, compaction and serialization of AS", addOperationTests);
3050 addTestGroup(group.get(), "host_threading", "Test host threading operations", addHostThreadingOperationTests);
3051 addTestGroup(group.get(), "function_argument", "Test using AS as function argument using both pointers and bare values", addFuncArgTests);
3052 addTestGroup(group.get(), "instance_triangle_culling", "Test building AS with counterclockwise triangles and/or disabling face culling", addInstanceTriangleCullingTests);
3053 addTestGroup(group.get(), "dynamic_indexing", "Exercise dynamic indexing of acceleration structures", addDynamicIndexingTests);
3054 addTestGroup(group.get(), "empty", "Test building empty acceleration structures using different methods", addEmptyAccelerationStructureTests);
3055 addTestGroup(group.get(), "instance_index", "Test using different values for the instance index and checking them in shaders", addInstanceIndexTests);
3056
3057 return group.release();
3058 }
3059
3060 } // RayTracing
3061
3062 } // vkt
3063