1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020-2022 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 Basic cmdTraceRays* tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayTracingTraceRaysTests.hpp"
25
26 #include "vkDefs.hpp"
27
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37
38 #include "vkRayTracingUtil.hpp"
39
40 #include <limits>
41 #include <tuple>
42
43 namespace vkt
44 {
45 namespace RayTracing
46 {
47 namespace
48 {
49 using namespace vk;
50 using namespace vkt;
51
52 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
53 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
54 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
55
56 constexpr uint32_t kClearColorValue = 0xFFu;
57 constexpr uint32_t kHitColorValue = 2u;
58 constexpr uint32_t kMissColorValue = 1u;
59
60 enum class TraceType
61 {
62 DIRECT = 0,
63 INDIRECT_CPU = 1,
64 INDIRECT_GPU = 2,
65 INDIRECT2_GPU = 3,
66 INDIRECT2_CPU = 4,
67 };
68
69 struct TestParams
70 {
71 TraceType traceType;
72 VkTraceRaysIndirectCommandKHR traceDimensions; // Note: to be used for both direct and indirect variants.
73 bool useKhrMaintenance1Semantics;
74 VkTraceRaysIndirectCommand2KHR extendedTraceDimensions;
75 };
76 struct TestParams2
77 {
78 TraceType traceType;
79 VkExtent3D traceDimensions;
80 bool partialCopy;
81 VkQueueFlagBits submitQueue;
82 };
83
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)84 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
85 {
86 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
87
88 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
89 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
90 }
91
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)92 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
93 {
94 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
95
96 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
97 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
98 }
99
100 template <typename T>
isNullTrace(const T cmd)101 bool isNullTrace(const T cmd)
102 {
103 return (cmd.width == 0u || cmd.height == 0u || cmd.depth == 0u);
104 }
105
106 template <typename T>
getImageExtent(const T cmd)107 VkExtent3D getImageExtent(const T cmd)
108 {
109 return (isNullTrace(cmd) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(cmd.width, cmd.height, cmd.depth));
110 }
111
isNullExtent(const VkExtent3D & extent)112 bool isNullExtent(const VkExtent3D &extent)
113 {
114 return (extent.width == 0u || extent.height == 0u || extent.depth == 0u);
115 }
116
getNonNullImageExtent(const VkExtent3D & extent)117 VkExtent3D getNonNullImageExtent(const VkExtent3D &extent)
118 {
119 return (isNullExtent(extent) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(extent.width, extent.height, extent.depth));
120 }
121
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)122 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
123 {
124 const VkImageCreateInfo imageCreateInfo = {
125 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
126 DE_NULL, // const void* pNext;
127 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
128 VK_IMAGE_TYPE_3D, // VkImageType imageType;
129 format, // VkFormat format;
130 makeExtent3D(width, height, depth), // VkExtent3D extent;
131 1u, // uint32_t mipLevels;
132 1u, // uint32_t arrayLayers;
133 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
134 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
135 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
136 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
137 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
138 0u, // uint32_t queueFamilyIndexCount;
139 DE_NULL, // const uint32_t* pQueueFamilyIndices;
140 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
141 };
142
143 return imageCreateInfo;
144 }
145
getQueueFamilyIndexAtExact(const DeviceInterface & vkd,const InstanceInterface & vki,VkPhysicalDevice physDevice,VkDevice device,VkQueueFlagBits bits,uint32_t queueIndex=0)146 std::tuple<bool, VkQueue, uint32_t> getQueueFamilyIndexAtExact(const DeviceInterface &vkd, const InstanceInterface &vki,
147 VkPhysicalDevice physDevice, VkDevice device,
148 VkQueueFlagBits bits, uint32_t queueIndex = 0)
149 {
150 bool found = false;
151 VkQueue queue = 0;
152 uint32_t queueFamilyCount = 0;
153 uint32_t queueFamilyIndex = std::numeric_limits<uint32_t>::max();
154
155 vki.getPhysicalDeviceQueueFamilyProperties(physDevice, &queueFamilyCount, nullptr);
156
157 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
158 vki.getPhysicalDeviceQueueFamilyProperties(physDevice, &queueFamilyCount, queueFamilies.data());
159
160 for (uint32_t index = 0; index < queueFamilyCount; ++index)
161 {
162 if ((queueFamilies[index].queueFlags & bits) == bits)
163 {
164 queueFamilyIndex = index;
165 break;
166 }
167 }
168
169 if (std::numeric_limits<uint32_t>::max() != queueFamilyIndex)
170 {
171 found = true;
172 vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
173 }
174 #ifdef __cpp_lib_constexpr_tuple
175 return {found, queue, queueFamilyIndex};
176 #else
177 return std::tuple<bool, VkQueue, uint32_t>(found, queue, queueFamilyIndex);
178 #endif
179 }
180
181 typedef std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> BlasVec;
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,const BlasVec & bottomLevelAccelerationStructures,Context & context,const VkExtent3D & imageExtent)182 auto initTopAccelerationStructure(VkCommandBuffer cmdBuffer, const BlasVec &bottomLevelAccelerationStructures,
183 Context &context, const VkExtent3D &imageExtent)
184 -> de::MovePtr<TopLevelAccelerationStructure>
185 {
186 const DeviceInterface &vkd = context.getDeviceInterface();
187 const VkDevice device = context.getDevice();
188 Allocator &allocator = context.getDefaultAllocator();
189 const uint32_t instanceCount = imageExtent.depth * imageExtent.height * imageExtent.width / 2;
190
191 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
192 result->setInstanceCount(instanceCount);
193
194 uint32_t currentInstanceIndex = 0;
195
196 for (uint32_t z = 0; z < imageExtent.depth; ++z)
197 for (uint32_t y = 0; y < imageExtent.height; ++y)
198 for (uint32_t x = 0; x < imageExtent.width; ++x)
199 {
200 if (((x + y + z) % 2) == 0)
201 continue;
202 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
203 }
204 result->createAndBuild(vkd, device, cmdBuffer, allocator);
205
206 return result;
207 }
208
209 class RayTracingTraceRaysIndirectTestCase : public TestCase
210 {
211 public:
212 RayTracingTraceRaysIndirectTestCase(tcu::TestContext &context, const char *name, const TestParams data);
213 ~RayTracingTraceRaysIndirectTestCase(void);
214
215 virtual void checkSupport(Context &context) const;
216 virtual void initPrograms(SourceCollections &programCollection) const;
217 virtual TestInstance *createInstance(Context &context) const;
218
219 private:
220 TestParams m_data;
221 };
222
223 class RayTracingTraceRaysIndirectTestInstance : public TestInstance
224 {
225 public:
226 RayTracingTraceRaysIndirectTestInstance(Context &context, const TestParams &data);
227 ~RayTracingTraceRaysIndirectTestInstance(void);
228 tcu::TestStatus iterate(void);
229
230 protected:
231 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
232 VkCommandBuffer cmdBuffer);
233 de::MovePtr<BufferWithMemory> runTest();
234
235 private:
236 TestParams m_data;
237 VkExtent3D m_imageExtent;
238 };
239
RayTracingTraceRaysIndirectTestCase(tcu::TestContext & context,const char * name,const TestParams data)240 RayTracingTraceRaysIndirectTestCase::RayTracingTraceRaysIndirectTestCase(tcu::TestContext &context, const char *name,
241 const TestParams data)
242 : vkt::TestCase(context, name)
243 , m_data(data)
244 {
245 }
246
~RayTracingTraceRaysIndirectTestCase(void)247 RayTracingTraceRaysIndirectTestCase::~RayTracingTraceRaysIndirectTestCase(void)
248 {
249 }
250
checkSupport(Context & context) const251 void RayTracingTraceRaysIndirectTestCase::checkSupport(Context &context) const
252 {
253 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
254 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
255
256 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
257 context.getRayTracingPipelineFeatures();
258 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
259 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
260
261 if (rayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect == false)
262 TCU_THROW(NotSupportedError,
263 "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect");
264
265 if (m_data.useKhrMaintenance1Semantics)
266 {
267 context.requireDeviceFunctionality("VK_KHR_ray_tracing_maintenance1");
268
269 const VkPhysicalDeviceFeatures deviceFeatures =
270 getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
271 if (!deviceFeatures.shaderInt64)
272 {
273 TCU_THROW(NotSupportedError, "Device feature shaderInt64 is not supported");
274 }
275 }
276
277 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
278 context.getAccelerationStructureFeatures();
279 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
280 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
281 "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
282 }
283
initPrograms(SourceCollections & programCollection) const284 void RayTracingTraceRaysIndirectTestCase::initPrograms(SourceCollections &programCollection) const
285 {
286 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
287 {
288 std::stringstream css;
289 css << "#version 460 core\n"
290 << (m_data.useKhrMaintenance1Semantics ? "#extension GL_ARB_gpu_shader_int64: enable\n" : "\n")
291 << "struct TraceRaysIndirectCommand\n"
292 "{\n";
293 if (m_data.useKhrMaintenance1Semantics)
294 {
295 css << " uint64_t raygenShaderRecordAddress;\n"
296 " uint64_t raygenShaderRecordSize;\n"
297 " uint64_t missShaderBindingTableAddress;\n"
298 " uint64_t missShaderBindingTableSize;\n"
299 " uint64_t missShaderBindingTableStride;\n"
300 " uint64_t hitShaderBindingTableAddress;\n"
301 " uint64_t hitShaderBindingTableSize;\n"
302 " uint64_t hitShaderBindingTableStride;\n"
303 " uint64_t callableShaderBindingTableAddress;\n"
304 " uint64_t callableShaderBindingTableSize;\n"
305 " uint64_t callableShaderBindingTableStride;\n";
306 }
307 css << " uint width;\n"
308 " uint height;\n"
309 " uint depth;\n"
310 "};\n"
311 "layout(binding = 0) uniform IndirectCommandsUBO\n"
312 "{\n"
313 " TraceRaysIndirectCommand indirectCommands;\n"
314 "} ubo;\n"
315 "layout(binding = 1) buffer IndirectCommandsSBO\n"
316 "{\n"
317 " TraceRaysIndirectCommand indirectCommands;\n"
318 "};\n"
319 "void main()\n"
320 "{\n";
321 if (m_data.useKhrMaintenance1Semantics)
322 {
323 css << " indirectCommands.raygenShaderRecordAddress = "
324 "ubo.indirectCommands.raygenShaderRecordAddress;\n"
325 " indirectCommands.raygenShaderRecordSize = "
326 "ubo.indirectCommands.raygenShaderRecordSize;\n"
327 " indirectCommands.missShaderBindingTableAddress = "
328 "ubo.indirectCommands.missShaderBindingTableAddress;\n"
329 " indirectCommands.missShaderBindingTableSize = "
330 "ubo.indirectCommands.missShaderBindingTableSize;\n"
331 " indirectCommands.missShaderBindingTableStride = "
332 "ubo.indirectCommands.missShaderBindingTableStride;\n"
333 " indirectCommands.hitShaderBindingTableAddress = "
334 "ubo.indirectCommands.hitShaderBindingTableAddress;\n"
335 " indirectCommands.hitShaderBindingTableSize = "
336 "ubo.indirectCommands.hitShaderBindingTableSize;\n"
337 " indirectCommands.hitShaderBindingTableStride = "
338 "ubo.indirectCommands.hitShaderBindingTableStride;\n"
339 " indirectCommands.callableShaderBindingTableAddress = "
340 "ubo.indirectCommands.callableShaderBindingTableAddress;\n"
341 " indirectCommands.callableShaderBindingTableSize = "
342 "ubo.indirectCommands.callableShaderBindingTableSize;\n"
343 " indirectCommands.callableShaderBindingTableStride = "
344 "ubo.indirectCommands.callableShaderBindingTableStride;\n";
345 }
346 css << " indirectCommands.width = ubo.indirectCommands.width;\n"
347 " indirectCommands.height = ubo.indirectCommands.height;\n"
348 " indirectCommands.depth = ubo.indirectCommands.depth;\n"
349 "}\n";
350
351 programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(css.str()) << buildOptions;
352 }
353
354 {
355 std::stringstream css;
356 css << "#version 460 core\n"
357 "#extension GL_EXT_ray_tracing : require\n"
358 "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
359 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
360 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
361 "\n"
362 "void main()\n"
363 "{\n"
364 " float tmin = 0.0;\n"
365 " float tmax = 1.0;\n"
366 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, "
367 "float(gl_LaunchIDEXT.z + 0.5f));\n"
368 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
369 " hitValue = uvec4(0,0,0,0);\n"
370 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
371 " imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
372 "}\n";
373 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
374 }
375
376 {
377 std::stringstream css;
378 css << "#version 460 core\n"
379 "#extension GL_EXT_ray_tracing : require\n"
380 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
381 "void main()\n"
382 "{\n"
383 " hitValue = uvec4("
384 << kHitColorValue
385 << ",0,0,1);\n"
386 "}\n";
387 programCollection.glslSources.add("chit")
388 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
389 }
390
391 {
392 std::stringstream css;
393 css << "#version 460 core\n"
394 "#extension GL_EXT_ray_tracing : require\n"
395 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
396 "void main()\n"
397 "{\n"
398 " hitValue = uvec4("
399 << kMissColorValue
400 << ",0,0,1);\n"
401 "}\n";
402
403 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
404 }
405 }
406
createInstance(Context & context) const407 TestInstance *RayTracingTraceRaysIndirectTestCase::createInstance(Context &context) const
408 {
409 return new RayTracingTraceRaysIndirectTestInstance(context, m_data);
410 }
411
RayTracingTraceRaysIndirectTestInstance(Context & context,const TestParams & data)412 RayTracingTraceRaysIndirectTestInstance::RayTracingTraceRaysIndirectTestInstance(Context &context,
413 const TestParams &data)
414 : vkt::TestInstance(context)
415 , m_data(data)
416 {
417 m_imageExtent = data.useKhrMaintenance1Semantics ? getImageExtent(data.extendedTraceDimensions) :
418 getImageExtent(data.traceDimensions);
419 }
420
~RayTracingTraceRaysIndirectTestInstance(void)421 RayTracingTraceRaysIndirectTestInstance::~RayTracingTraceRaysIndirectTestInstance(void)
422 {
423 }
424
425 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingTraceRaysIndirectTestInstance::
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)426 initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)
427 {
428 const DeviceInterface &vkd = m_context.getDeviceInterface();
429 const VkDevice device = m_context.getDevice();
430 Allocator &allocator = m_context.getDefaultAllocator();
431 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
432
433 tcu::Vec3 v0(0.0, 1.0, 0.0);
434 tcu::Vec3 v1(0.0, 0.0, 0.0);
435 tcu::Vec3 v2(1.0, 1.0, 0.0);
436 tcu::Vec3 v3(1.0, 0.0, 0.0);
437
438 for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
439 for (uint32_t y = 0; y < m_imageExtent.height; ++y)
440 for (uint32_t x = 0; x < m_imageExtent.width; ++x)
441 {
442 // let's build a 3D chessboard of geometries
443 if (((x + y + z) % 2) == 0)
444 continue;
445 tcu::Vec3 xyz((float)x, (float)y, (float)z);
446 std::vector<tcu::Vec3> geometryData;
447
448 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
449 makeBottomLevelAccelerationStructure();
450 bottomLevelAccelerationStructure->setGeometryCount(1u);
451
452 geometryData.push_back(xyz + v0);
453 geometryData.push_back(xyz + v1);
454 geometryData.push_back(xyz + v2);
455 geometryData.push_back(xyz + v2);
456 geometryData.push_back(xyz + v1);
457 geometryData.push_back(xyz + v3);
458
459 bottomLevelAccelerationStructure->addGeometry(geometryData, true);
460 bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
461 result.push_back(
462 de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
463 }
464
465 return result;
466 }
467
runTest()468 de::MovePtr<BufferWithMemory> RayTracingTraceRaysIndirectTestInstance::runTest()
469 {
470 const InstanceInterface &vki = m_context.getInstanceInterface();
471 const DeviceInterface &vkd = m_context.getDeviceInterface();
472 const VkDevice device = m_context.getDevice();
473 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
474 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
475 const VkQueue queue = m_context.getUniversalQueue();
476 Allocator &allocator = m_context.getDefaultAllocator();
477 const uint32_t pixelCount = m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width;
478 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
479 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
480
481 Move<VkDescriptorSetLayout> computeDescriptorSetLayout;
482 Move<VkDescriptorPool> computeDescriptorPool;
483 Move<VkDescriptorSet> computeDescriptorSet;
484 Move<VkPipelineLayout> computePipelineLayout;
485 Move<VkShaderModule> computeShader;
486 Move<VkPipeline> computePipeline;
487
488 if (m_data.traceType == TraceType::INDIRECT_GPU || m_data.traceType == TraceType::INDIRECT2_GPU)
489 {
490 computeDescriptorSetLayout =
491 DescriptorSetLayoutBuilder()
492 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
493 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
494 .build(vkd, device);
495 computeDescriptorPool = DescriptorPoolBuilder()
496 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
497 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
498 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
499 computeDescriptorSet = makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
500 computePipelineLayout = makePipelineLayout(vkd, device, computeDescriptorSetLayout.get());
501
502 computeShader =
503 createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
504 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
505 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
506 DE_NULL, // const void* pNext;
507 VkPipelineShaderStageCreateFlags(0u), // VkPipelineShaderStageCreateFlags flags;
508 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
509 *computeShader, // VkShaderModule module;
510 "main", // const char* pName;
511 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
512 };
513 const VkComputePipelineCreateInfo pipelineCreateInfo = {
514 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
515 DE_NULL, // const void* pNext;
516 VkPipelineCreateFlags(0u), // VkPipelineCreateFlags flags;
517 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
518 *computePipelineLayout, // VkPipelineLayout layout;
519 DE_NULL, // VkPipeline basePipelineHandle;
520 0, // int32_t basePipelineIndex;
521 };
522
523 computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
524 }
525
526 const Move<VkDescriptorSetLayout> descriptorSetLayout =
527 DescriptorSetLayoutBuilder()
528 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
529 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
530 .build(vkd, device);
531 const Move<VkDescriptorPool> descriptorPool =
532 DescriptorPoolBuilder()
533 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
534 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
535 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
536 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
537 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
538
539 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
540 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
541 createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
542 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
543 createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
544 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
545 createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
546 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
547
548 const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
549 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
550 const de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
551 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
552 const de::MovePtr<BufferWithMemory> missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
553 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
554
555 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
556 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
557 shaderGroupHandleSize, shaderGroupHandleSize);
558 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
559 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
560 shaderGroupHandleSize, shaderGroupHandleSize);
561 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
562 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
563 shaderGroupHandleSize, shaderGroupHandleSize);
564 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
565 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
566
567 const VkFormat imageFormat = VK_FORMAT_R32_UINT;
568 const VkImageCreateInfo imageCreateInfo =
569 makeImageCreateInfo(m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, imageFormat);
570 const VkImageSubresourceRange imageSubresourceRange =
571 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
572 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
573 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
574 const Move<VkImageView> imageView =
575 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
576
577 const VkBufferCreateInfo resultBufferCreateInfo =
578 makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
579 const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
580 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
581 const VkBufferImageCopy resultBufferImageRegion =
582 makeBufferImageCopy(m_imageExtent, resultBufferImageSubresourceLayers);
583 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
584 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
585
586 const VkDescriptorImageInfo descriptorImageInfo =
587 makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
588
589 // create indirect command buffer and fill it with parameter values
590 de::MovePtr<BufferWithMemory> indirectBuffer;
591 de::MovePtr<BufferWithMemory> uniformBuffer;
592
593 // Update trace details according to VK_KHR_ray_tracing_maintenance1 semantics
594 m_data.extendedTraceDimensions.raygenShaderRecordAddress = raygenShaderBindingTableRegion.deviceAddress;
595 m_data.extendedTraceDimensions.raygenShaderRecordSize = raygenShaderBindingTableRegion.size;
596 m_data.extendedTraceDimensions.missShaderBindingTableAddress = missShaderBindingTableRegion.deviceAddress;
597 m_data.extendedTraceDimensions.missShaderBindingTableSize = missShaderBindingTableRegion.size;
598 m_data.extendedTraceDimensions.missShaderBindingTableStride = missShaderBindingTableRegion.stride;
599 m_data.extendedTraceDimensions.hitShaderBindingTableAddress = hitShaderBindingTableRegion.deviceAddress;
600 m_data.extendedTraceDimensions.hitShaderBindingTableSize = hitShaderBindingTableRegion.size;
601 m_data.extendedTraceDimensions.hitShaderBindingTableStride = hitShaderBindingTableRegion.stride;
602 m_data.extendedTraceDimensions.callableShaderBindingTableAddress = callableShaderBindingTableRegion.deviceAddress;
603 m_data.extendedTraceDimensions.callableShaderBindingTableSize = callableShaderBindingTableRegion.size;
604 m_data.extendedTraceDimensions.callableShaderBindingTableStride = callableShaderBindingTableRegion.stride;
605
606 if (m_data.traceType != TraceType::DIRECT)
607 {
608 const bool indirectGpu =
609 (m_data.traceType == TraceType::INDIRECT_GPU || m_data.traceType == TraceType::INDIRECT2_GPU);
610 VkDeviceSize bufferSize = m_data.useKhrMaintenance1Semantics ? sizeof(VkTraceRaysIndirectCommand2KHR) :
611 sizeof(VkTraceRaysIndirectCommandKHR);
612 VkBufferUsageFlags indirectBufferUsageFlags =
613 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
614 (indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
615 const VkBufferCreateInfo indirectBufferCreateInfo = makeBufferCreateInfo(bufferSize, indirectBufferUsageFlags);
616 vk::MemoryRequirement indirectBufferMemoryRequirement =
617 MemoryRequirement::DeviceAddress | (indirectGpu ? MemoryRequirement::Any : MemoryRequirement::HostVisible);
618 indirectBuffer = de::MovePtr<BufferWithMemory>(
619 new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
620 }
621
622 if (m_data.traceType == TraceType::INDIRECT_GPU)
623 {
624 const VkBufferCreateInfo uniformBufferCreateInfo =
625 makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR),
626 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
627 uniformBuffer = de::MovePtr<BufferWithMemory>(
628 new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
629 deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions,
630 sizeof(VkTraceRaysIndirectCommandKHR));
631 flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(),
632 uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
633 }
634 else if (m_data.traceType == TraceType::INDIRECT_CPU)
635 {
636 deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions,
637 sizeof(VkTraceRaysIndirectCommandKHR));
638 flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(),
639 indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
640 }
641 else if (m_data.traceType == TraceType::INDIRECT2_GPU)
642 {
643 const VkBufferCreateInfo uniformBufferCreateInfo =
644 makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommand2KHR),
645 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
646 uniformBuffer = de::MovePtr<BufferWithMemory>(
647 new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
648 deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.extendedTraceDimensions,
649 sizeof(VkTraceRaysIndirectCommand2KHR));
650 flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(),
651 uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
652 }
653 else if (m_data.traceType == TraceType::INDIRECT2_CPU)
654 {
655 deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.extendedTraceDimensions,
656 sizeof(VkTraceRaysIndirectCommand2KHR));
657 flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(),
658 indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
659 }
660
661 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
662 const Move<VkCommandBuffer> cmdBuffer =
663 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
664
665 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
666 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
667
668 beginCommandBuffer(vkd, *cmdBuffer, 0u);
669 {
670 const VkImageMemoryBarrier preImageBarrier =
671 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
672 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
673 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
674 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
675
676 const VkClearValue clearValue = makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
677 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
678 &imageSubresourceRange);
679
680 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
681 VK_ACCESS_TRANSFER_WRITE_BIT,
682 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
683 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
684 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
685 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
686
687 bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
688 topLevelAccelerationStructure =
689 initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures, m_context, m_imageExtent);
690
691 if (m_data.traceType == TraceType::INDIRECT_GPU)
692 {
693 const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
694 makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
695 const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
696 makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
697
698 DescriptorSetUpdateBuilder()
699 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
700 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
701 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
702 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
703 .update(vkd, device);
704
705 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
706 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
707 &computeDescriptorSet.get(), 0u, DE_NULL);
708 vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
709
710 const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier =
711 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
712 indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
713 cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
714 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
715 }
716 else if (m_data.traceType == TraceType::INDIRECT2_GPU)
717 {
718 const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
719 makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
720 const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
721 makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
722
723 DescriptorSetUpdateBuilder()
724 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
725 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
726 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
727 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
728 .update(vkd, device);
729
730 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
731 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
732 &computeDescriptorSet.get(), 0u, DE_NULL);
733 vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
734
735 const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier =
736 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
737 indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
738 cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
739 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
740 }
741
742 const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
743 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
744 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
745 DE_NULL, // const void* pNext;
746 1u, // uint32_t accelerationStructureCount;
747 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
748 };
749
750 DescriptorSetUpdateBuilder()
751 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
752 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
753 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
754 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
755 .update(vkd, device);
756
757 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
758 &descriptorSet.get(), 0, DE_NULL);
759
760 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
761
762 // Both calls should give the same results.
763 if (m_data.traceType == TraceType::DIRECT)
764 {
765 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
766 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.traceDimensions.width,
767 m_data.traceDimensions.height, m_data.traceDimensions.depth);
768 }
769 else if (m_data.traceType == TraceType::INDIRECT_CPU || m_data.traceType == TraceType::INDIRECT_GPU)
770 {
771 cmdTraceRaysIndirect(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
772 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion,
773 getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
774 }
775 else if (m_data.traceType == TraceType::INDIRECT2_CPU || m_data.traceType == TraceType::INDIRECT2_GPU)
776 {
777 vkd.cmdTraceRaysIndirect2KHR(*cmdBuffer, getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
778 }
779
780 const VkMemoryBarrier postTraceMemoryBarrier =
781 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
782 const VkMemoryBarrier postCopyMemoryBarrier =
783 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
784 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
785 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
786
787 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
788 &resultBufferImageRegion);
789
790 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
791 &postCopyMemoryBarrier);
792 }
793 endCommandBuffer(vkd, *cmdBuffer);
794
795 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
796
797 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
798 resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
799
800 return resultBuffer;
801 }
802
iterate(void)803 tcu::TestStatus RayTracingTraceRaysIndirectTestInstance::iterate(void)
804 {
805 // run test using arrays of pointers
806 const de::MovePtr<BufferWithMemory> buffer = runTest();
807 const uint32_t *bufferPtr = (uint32_t *)buffer->getAllocation().getHostPtr();
808 const bool noWrites = m_data.useKhrMaintenance1Semantics ? isNullTrace(m_data.extendedTraceDimensions) :
809 isNullTrace(m_data.traceDimensions);
810
811 uint32_t failures = 0;
812 uint32_t pos = 0;
813
814 // verify results
815 for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
816 for (uint32_t y = 0; y < m_imageExtent.height; ++y)
817 for (uint32_t x = 0; x < m_imageExtent.width; ++x)
818 {
819 const uint32_t expectedResult =
820 (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
821 if (bufferPtr[pos] != expectedResult)
822 failures++;
823 ++pos;
824 }
825
826 if (failures == 0)
827 return tcu::TestStatus::pass("Pass");
828 else
829 return tcu::TestStatus::fail("Fail (failures=" + de::toString(failures) + ")");
830 }
831
832 template <typename T>
makeDimensionsName(const T cmd)833 std::string makeDimensionsName(const T cmd)
834 {
835 std::ostringstream name;
836 name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
837 return name.str();
838 }
839
840 using namespace tcu;
841
842 class TraceRaysIndirect2Instance : public TestInstance
843 {
844 public:
845 TraceRaysIndirect2Instance(Context &context, const TestParams2 ¶ms);
846 virtual ~TraceRaysIndirect2Instance(void) override = default;
847 virtual TestStatus iterate(void) override;
848
849 protected:
850 void makeIndirectStructAndFlush(BufferWithMemory &buffer, const bool source, const BufferWithMemory &rgenSbt,
851 const BufferWithMemory &hitSbt, const BufferWithMemory &missSbt,
852 const BufferWithMemory &callSbt) const;
853 void initBottomAccellStructures(VkCommandBuffer cmdBuffer, BottomLevelAccelerationStructurePool &pool,
854 const uint32_t &batchStructCount) const;
855
856 private:
857 TestParams2 m_params;
858 const VkExtent3D m_imageExtent;
859 };
860
861 class TraceRaysIndirect2Case : public TestCase
862 {
863 public:
864 TraceRaysIndirect2Case(TestContext &testCtx, const std::string &name, const TestParams2 ¶ms);
865 virtual ~TraceRaysIndirect2Case(void) override = default;
866 virtual void initPrograms(SourceCollections &programCollection) const override;
867 virtual TestInstance *createInstance(Context &context) const override;
868 virtual void checkSupport(Context &context) const override;
869
870 private:
871 TestParams2 m_params;
872 };
873
TraceRaysIndirect2Case(TestContext & testCtx,const std::string & name,const TestParams2 & params)874 TraceRaysIndirect2Case::TraceRaysIndirect2Case(TestContext &testCtx, const std::string &name, const TestParams2 ¶ms)
875 : TestCase(testCtx, name)
876 , m_params(params)
877 {
878 }
879
createInstance(Context & context) const880 TestInstance *TraceRaysIndirect2Case::createInstance(Context &context) const
881 {
882 return new TraceRaysIndirect2Instance(context, m_params);
883 }
884
checkSupport(Context & context) const885 void TraceRaysIndirect2Case::checkSupport(Context &context) const
886 {
887 context.requireInstanceFunctionality(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
888 context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
889 context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
890
891 const VkPhysicalDeviceFeatures &features = context.getDeviceFeatures();
892 if (features.shaderInt64 == VK_FALSE)
893 TCU_THROW(NotSupportedError, "64-bit integers not supported by device");
894
895 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
896 context.getAccelerationStructureFeatures();
897 if (accelerationStructureFeaturesKHR.accelerationStructure == VK_FALSE)
898 TCU_THROW(NotSupportedError,
899 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure");
900
901 const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
902 context.getRayTracingMaintenance1Features();
903 if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
904 TCU_THROW(NotSupportedError,
905 "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
906 if (maintenance1FeaturesKHR.rayTracingPipelineTraceRaysIndirect2 == VK_FALSE)
907 TCU_THROW(NotSupportedError,
908 "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingPipelineTraceRaysIndirect2");
909
910 auto desiredQueue =
911 getQueueFamilyIndexAtExact(context.getDeviceInterface(), context.getInstanceInterface(),
912 context.getPhysicalDevice(), context.getDevice(), m_params.submitQueue);
913 if (!std::get<0>(desiredQueue))
914 {
915 std::stringstream errorMsg;
916 errorMsg << "Desired queue " << m_params.submitQueue << " is not supported by device";
917 errorMsg.flush();
918 TCU_THROW(NotSupportedError, errorMsg.str());
919 }
920 }
921
initPrograms(SourceCollections & programCollection) const922 void TraceRaysIndirect2Case::initPrograms(SourceCollections &programCollection) const
923 {
924 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
925 {
926 std::stringstream css;
927 std::string comp(R"(
928 #version 460 core
929 #extension GL_ARB_gpu_shader_int64: enable
930 struct TraceRaysIndirectCommand
931 {
932 uint64_t raygenShaderRecordAddress;
933 uint64_t raygenShaderRecordSize;
934 uint64_t missShaderBindingTableAddress;
935 uint64_t missShaderBindingTableSize;
936 uint64_t missShaderBindingTableStride;
937 uint64_t hitShaderBindingTableAddress;
938 uint64_t hitShaderBindingTableSize;
939 uint64_t hitShaderBindingTableStride;
940 uint64_t callableShaderBindingTableAddress;
941 uint64_t callableShaderBindingTableSize;
942 uint64_t callableShaderBindingTableStride;
943 uint width;
944 uint height;
945 uint depth;
946 };
947 layout(push_constant) uniform CopyStyle {
948 uint full;
949 } cs;
950 layout(binding = 0) uniform IndirectCommandsUBO {
951 TraceRaysIndirectCommand indirectCommands;
952 } ubo;
953 layout(binding = 1) buffer IndirectCommandsSBO {
954 TraceRaysIndirectCommand indirectCommands;
955 };
956 void main()
957 {
958 if (cs.full != 0) {
959 indirectCommands.raygenShaderRecordAddress = ubo.indirectCommands.raygenShaderRecordAddress;
960 indirectCommands.raygenShaderRecordSize = ubo.indirectCommands.raygenShaderRecordSize;
961 indirectCommands.missShaderBindingTableAddress = ubo.indirectCommands.missShaderBindingTableAddress;
962 indirectCommands.missShaderBindingTableSize = ubo.indirectCommands.missShaderBindingTableSize;
963 indirectCommands.missShaderBindingTableStride = ubo.indirectCommands.missShaderBindingTableStride;
964 indirectCommands.hitShaderBindingTableAddress = ubo.indirectCommands.hitShaderBindingTableAddress;
965 indirectCommands.hitShaderBindingTableSize = ubo.indirectCommands.hitShaderBindingTableSize;
966 indirectCommands.hitShaderBindingTableStride = ubo.indirectCommands.hitShaderBindingTableStride;
967 indirectCommands.callableShaderBindingTableAddress = ubo.indirectCommands.callableShaderBindingTableAddress;
968 indirectCommands.callableShaderBindingTableSize = ubo.indirectCommands.callableShaderBindingTableSize;
969 indirectCommands.callableShaderBindingTableStride = ubo.indirectCommands.callableShaderBindingTableStride;
970 }
971 else {
972 indirectCommands.raygenShaderRecordAddress = ubo.indirectCommands.raygenShaderRecordAddress;
973
974 indirectCommands.missShaderBindingTableStride = ubo.indirectCommands.missShaderBindingTableStride;
975
976 indirectCommands.hitShaderBindingTableSize = ubo.indirectCommands.hitShaderBindingTableSize;
977
978 indirectCommands.callableShaderBindingTableAddress = ubo.indirectCommands.callableShaderBindingTableAddress;
979 indirectCommands.callableShaderBindingTableStride = ubo.indirectCommands.callableShaderBindingTableStride;
980 }
981
982 indirectCommands.width = ubo.indirectCommands.width;
983 indirectCommands.height = ubo.indirectCommands.height;
984 indirectCommands.depth = ubo.indirectCommands.depth;
985
986 })");
987
988 programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(comp) << buildOptions;
989 }
990
991 {
992 std::stringstream css;
993 css << "#version 460 core\n"
994 "#extension GL_EXT_ray_tracing : require\n"
995 "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
996 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
997 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
998 "\n"
999 "void main()\n"
1000 "{\n"
1001 " float tmin = 0.0;\n"
1002 " float tmax = 1.0;\n"
1003 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, "
1004 "float(gl_LaunchIDEXT.z + 0.5f));\n"
1005 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
1006 " hitValue = uvec4(0,0,0,0);\n"
1007 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
1008 " imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
1009 "}\n";
1010 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1011 }
1012
1013 {
1014 std::stringstream css;
1015 css << "#version 460 core\n"
1016 "#extension GL_EXT_ray_tracing : require\n"
1017 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
1018 "void main()\n"
1019 "{\n"
1020 " hitValue = uvec4("
1021 << kHitColorValue
1022 << ",0,0,1);\n"
1023 "}\n";
1024 programCollection.glslSources.add("chit")
1025 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1026 }
1027
1028 {
1029 std::stringstream css;
1030 css << "#version 460 core\n"
1031 "#extension GL_EXT_ray_tracing : require\n"
1032 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
1033 "void main()\n"
1034 "{\n"
1035 " hitValue = uvec4("
1036 << kMissColorValue
1037 << ",0,0,1);\n"
1038 "}\n";
1039
1040 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1041 }
1042 }
1043
TraceRaysIndirect2Instance(Context & context,const TestParams2 & params)1044 TraceRaysIndirect2Instance::TraceRaysIndirect2Instance(Context &context, const TestParams2 ¶ms)
1045 : TestInstance(context)
1046 , m_params(params)
1047 , m_imageExtent(getNonNullImageExtent(params.traceDimensions))
1048 {
1049 }
1050
makeIndirectStructAndFlush(BufferWithMemory & buffer,const bool source,const BufferWithMemory & rgenSbt,const BufferWithMemory & hitSbt,const BufferWithMemory & missSbt,const BufferWithMemory & callSbt) const1051 void TraceRaysIndirect2Instance::makeIndirectStructAndFlush(BufferWithMemory &buffer, const bool source,
1052 const BufferWithMemory &rgenSbt,
1053 const BufferWithMemory &hitSbt,
1054 const BufferWithMemory &missSbt,
1055 const BufferWithMemory &callSbt) const
1056 {
1057 DE_UNREF(callSbt);
1058
1059 const DeviceInterface &vkd = m_context.getDeviceInterface();
1060 const InstanceInterface &vki = m_context.getInstanceInterface();
1061 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1062 const VkDevice device = m_context.getDevice();
1063 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1064 Allocation &alloc = buffer.getAllocation();
1065
1066 VkTraceRaysIndirectCommand2KHR data{};
1067
1068 if (m_params.traceType == TraceType::INDIRECT_GPU && m_params.partialCopy)
1069 {
1070 if (source)
1071 {
1072 data.raygenShaderRecordAddress = getBufferDeviceAddress(vkd, device, *rgenSbt, 0);
1073 data.missShaderBindingTableStride = shaderGroupHandleSize;
1074 data.hitShaderBindingTableSize = shaderGroupHandleSize;
1075 data.callableShaderBindingTableAddress = 0;
1076 data.callableShaderBindingTableStride = 0;
1077 }
1078 else
1079 {
1080 data.raygenShaderRecordSize = shaderGroupHandleSize;
1081 data.missShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *missSbt, 0);
1082 data.missShaderBindingTableSize = shaderGroupHandleSize;
1083 data.hitShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *hitSbt, 0);
1084 data.hitShaderBindingTableStride = shaderGroupHandleSize;
1085 data.callableShaderBindingTableSize = 0;
1086 }
1087 }
1088 else
1089 {
1090 data.raygenShaderRecordAddress = getBufferDeviceAddress(vkd, device, *rgenSbt, 0);
1091 data.raygenShaderRecordSize = shaderGroupHandleSize;
1092
1093 data.missShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *missSbt, 0);
1094 data.missShaderBindingTableSize = shaderGroupHandleSize;
1095 data.missShaderBindingTableStride = shaderGroupHandleSize;
1096
1097 data.hitShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *hitSbt, 0);
1098 data.hitShaderBindingTableSize = shaderGroupHandleSize;
1099 data.hitShaderBindingTableStride = shaderGroupHandleSize;
1100
1101 data.callableShaderBindingTableAddress = 0;
1102 data.callableShaderBindingTableSize = 0;
1103 data.callableShaderBindingTableStride = 0;
1104 }
1105
1106 data.width = m_params.traceDimensions.width;
1107 data.height = m_params.traceDimensions.height;
1108 data.depth = m_params.traceDimensions.depth;
1109
1110 deMemcpy(alloc.getHostPtr(), &data, sizeof(data));
1111 flushMappedMemoryRange(vkd, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
1112 }
1113
initBottomAccellStructures(VkCommandBuffer cmdBuffer,BottomLevelAccelerationStructurePool & pool,const uint32_t & batchStructCount) const1114 void TraceRaysIndirect2Instance::initBottomAccellStructures(VkCommandBuffer cmdBuffer,
1115 BottomLevelAccelerationStructurePool &pool,
1116 const uint32_t &batchStructCount) const
1117 {
1118 const DeviceInterface &vkd = m_context.getDeviceInterface();
1119 const VkDevice device = m_context.getDevice();
1120 Allocator &allocator = m_context.getDefaultAllocator();
1121
1122 pool.batchStructCount(batchStructCount);
1123 pool.batchGeomCount(batchStructCount * 8);
1124
1125 tcu::Vec3 v0(0.0, 1.0, 0.0);
1126 tcu::Vec3 v1(0.0, 0.0, 0.0);
1127 tcu::Vec3 v2(1.0, 1.0, 0.0);
1128 tcu::Vec3 v3(1.0, 0.0, 0.0);
1129
1130 for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
1131 for (uint32_t y = 0; y < m_imageExtent.height; ++y)
1132 for (uint32_t x = 0; x < m_imageExtent.width; ++x)
1133 {
1134 // let's build a 3D chessboard of geometries
1135 if (((x + y + z) % 2) == 0)
1136 continue;
1137 tcu::Vec3 xyz((float)x, (float)y, (float)z);
1138 std::vector<tcu::Vec3> geometryData;
1139
1140 auto bottomLevelAccelerationStructure = pool.add();
1141 bottomLevelAccelerationStructure->setGeometryCount(1u);
1142
1143 geometryData.push_back(xyz + v0);
1144 geometryData.push_back(xyz + v1);
1145 geometryData.push_back(xyz + v2);
1146 geometryData.push_back(xyz + v2);
1147 geometryData.push_back(xyz + v1);
1148 geometryData.push_back(xyz + v3);
1149
1150 bottomLevelAccelerationStructure->addGeometry(geometryData, true);
1151 }
1152
1153 pool.batchCreate(vkd, device, allocator);
1154 pool.batchBuild(vkd, device, cmdBuffer);
1155 }
1156
iterate(void)1157 TestStatus TraceRaysIndirect2Instance::iterate(void)
1158 {
1159 const InstanceInterface &vki = m_context.getInstanceInterface();
1160 const DeviceInterface &vkd = m_context.getDeviceInterface();
1161 const VkDevice device = m_context.getDevice();
1162 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1163 const auto queueAndFamilyIndex = getQueueFamilyIndexAtExact(vkd, vki, physicalDevice, device, m_params.submitQueue);
1164 const VkQueue queue = std::get<1>(queueAndFamilyIndex);
1165 const uint32_t queueFamilyIndex = std::get<2>(queueAndFamilyIndex);
1166 Allocator &allocator = m_context.getDefaultAllocator();
1167 const uint32_t width = m_imageExtent.width;
1168 const uint32_t height = m_imageExtent.height;
1169 const uint32_t depth = m_imageExtent.depth;
1170 const uint32_t pixelCount = width * height * depth;
1171 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1172 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1173
1174 Move<VkDescriptorSetLayout> computeDescriptorSetLayout;
1175 Move<VkDescriptorPool> computeDescriptorPool;
1176 Move<VkDescriptorSet> computeDescriptorSet;
1177 Move<VkPipelineLayout> computePipelineLayout;
1178 Move<VkShaderModule> computeShader;
1179 Move<VkPipeline> computePipeline;
1180
1181 if (m_params.traceType == TraceType::INDIRECT_GPU)
1182 {
1183 computeDescriptorSetLayout =
1184 DescriptorSetLayoutBuilder()
1185 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1186 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1187 .build(vkd, device);
1188 computeDescriptorPool = DescriptorPoolBuilder()
1189 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1190 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1191 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1192 const VkPushConstantRange full{VK_SHADER_STAGE_COMPUTE_BIT, 0, uint32_t(sizeof(uint32_t))};
1193 computeDescriptorSet = makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
1194 computePipelineLayout = makePipelineLayout(vkd, device, 1, &computeDescriptorSetLayout.get(), 1, &full);
1195
1196 computeShader =
1197 createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
1198 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
1199 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1200 DE_NULL, // const void* pNext;
1201 VkPipelineShaderStageCreateFlags(0u), // VkPipelineShaderStageCreateFlags flags;
1202 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1203 *computeShader, // VkShaderModule module;
1204 "main", // const char* pName;
1205 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1206 };
1207 const VkComputePipelineCreateInfo pipelineCreateInfo = {
1208 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1209 DE_NULL, // const void* pNext;
1210 VkPipelineCreateFlags(0u), // VkPipelineCreateFlags flags;
1211 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
1212 *computePipelineLayout, // VkPipelineLayout layout;
1213 DE_NULL, // VkPipeline basePipelineHandle;
1214 0, // int32_t basePipelineIndex;
1215 };
1216
1217 computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
1218 }
1219
1220 const Move<VkDescriptorSetLayout> descriptorSetLayout =
1221 DescriptorSetLayoutBuilder()
1222 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1223 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1224 .build(vkd, device);
1225 const Move<VkDescriptorPool> descriptorPool =
1226 DescriptorPoolBuilder()
1227 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1228 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1229 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1230 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1231 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1232
1233 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1234 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1235 createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
1236 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1237 createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
1238 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
1239 createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
1240 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1241
1242 const de::MovePtr<BufferWithMemory> rgenSbt = rayTracingPipeline->createShaderBindingTable(
1243 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1244 const de::MovePtr<BufferWithMemory> hitSbt = rayTracingPipeline->createShaderBindingTable(
1245 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1246 const de::MovePtr<BufferWithMemory> missSbt = rayTracingPipeline->createShaderBindingTable(
1247 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1248
1249 const VkFormat imageFormat = VK_FORMAT_R32_UINT;
1250 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(width, height, depth, imageFormat);
1251 const VkImageSubresourceRange imageSubresourceRange =
1252 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1253 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1254 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1255 const Move<VkImageView> imageView =
1256 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
1257
1258 const VkBufferCreateInfo resultBufferCreateInfo =
1259 makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1260 const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
1261 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1262 const VkBufferImageCopy resultBufferImageRegion =
1263 makeBufferImageCopy(m_params.traceDimensions, resultBufferImageSubresourceLayers);
1264 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
1265 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1266 Allocation &resultBufferAllocation = resultBuffer->getAllocation();
1267
1268 const VkDescriptorImageInfo descriptorImageInfo =
1269 makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1270
1271 // create indirect command buffer and fill it with parameter values
1272 const VkDeviceSize bufferSize = sizeof(VkTraceRaysIndirectCommand2KHR);
1273 de::MovePtr<BufferWithMemory> indirectBuffer;
1274 de::MovePtr<BufferWithMemory> uniformBuffer;
1275
1276 const bool indirectGpu = (m_params.traceType == TraceType::INDIRECT_GPU);
1277 VkBufferUsageFlags indirectBufferUsageFlags =
1278 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
1279 (indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1280 const VkBufferCreateInfo indirectBufferCreateInfo = makeBufferCreateInfo(bufferSize, indirectBufferUsageFlags);
1281 vk::MemoryRequirement indirectBufferMemoryRequirement =
1282 MemoryRequirement::DeviceAddress | MemoryRequirement::HostVisible;
1283 indirectBuffer = de::MovePtr<BufferWithMemory>(
1284 new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
1285
1286 if (m_params.traceType == TraceType::INDIRECT_GPU)
1287 {
1288 const VkBufferCreateInfo uniformBufferCreateInfo =
1289 makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1290 uniformBuffer = de::MovePtr<BufferWithMemory>(
1291 new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1292 makeIndirectStructAndFlush(*uniformBuffer, true, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1293 makeIndirectStructAndFlush(*indirectBuffer, false, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1294 }
1295 else if (m_params.traceType == TraceType::INDIRECT_CPU)
1296 {
1297 makeIndirectStructAndFlush(*indirectBuffer, true, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1298 }
1299 else
1300 {
1301 TCU_THROW(NotSupportedError, "Invalid test parameters");
1302 }
1303
1304 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1305 BottomLevelAccelerationStructurePool blasPool;
1306 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1307 const Move<VkCommandBuffer> cmdBuffer =
1308 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1309
1310 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1311 {
1312 const VkImageMemoryBarrier preImageBarrier =
1313 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1314 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1315 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1316 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1317
1318 const VkClearValue clearValue = makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
1319 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1320 &imageSubresourceRange);
1321
1322 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1323 VK_ACCESS_TRANSFER_WRITE_BIT,
1324 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1325 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1326 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1327 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1328
1329 initBottomAccellStructures(*cmdBuffer, blasPool, 4);
1330 topLevelAccelerationStructure =
1331 initTopAccelerationStructure(*cmdBuffer, blasPool.structures(), m_context, m_imageExtent);
1332
1333 if (m_params.traceType == TraceType::INDIRECT_GPU)
1334 {
1335 const uint32_t fullCopyStyle = m_params.partialCopy ? 0 : 1;
1336 const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
1337 makeDescriptorBufferInfo(**uniformBuffer, 0ull, bufferSize);
1338 const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
1339 makeDescriptorBufferInfo(**indirectBuffer, 0ull, bufferSize);
1340 DescriptorSetUpdateBuilder()
1341 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1342 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
1343 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1344 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
1345 .update(vkd, device);
1346
1347 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1348 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
1349 &computeDescriptorSet.get(), 0u, DE_NULL);
1350 vkd.cmdPushConstants(*cmdBuffer, *computePipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1351 uint32_t(sizeof(uint32_t)), &fullCopyStyle);
1352 vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
1353
1354 const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier = makeBufferMemoryBarrier(
1355 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, **indirectBuffer, 0ull, bufferSize);
1356 cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1357 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
1358 }
1359
1360 const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
1361 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
1362 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
1363 DE_NULL, // const void* pNext;
1364 1u, // uint32_t accelerationStructureCount;
1365 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
1366 };
1367
1368 DescriptorSetUpdateBuilder()
1369 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1370 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1371 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1372 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1373 .update(vkd, device);
1374
1375 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
1376 &descriptorSet.get(), 0, DE_NULL);
1377
1378 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1379
1380 cmdTraceRaysIndirect2(vkd, *cmdBuffer, getBufferDeviceAddress(vkd, device, **indirectBuffer, 0));
1381
1382 const VkMemoryBarrier postTraceMemoryBarrier =
1383 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1384 const VkMemoryBarrier postCopyMemoryBarrier =
1385 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1386 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
1387 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1388
1389 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
1390 &resultBufferImageRegion);
1391
1392 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1393 &postCopyMemoryBarrier);
1394 }
1395 endCommandBuffer(vkd, *cmdBuffer);
1396
1397 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1398
1399 invalidateMappedMemoryRange(vkd, device, resultBufferAllocation.getMemory(), resultBufferAllocation.getOffset(),
1400 VK_WHOLE_SIZE);
1401
1402 // run test using arrays of pointers
1403 const uint32_t *bufferPtr = (uint32_t *)resultBufferAllocation.getHostPtr();
1404 const bool noWrites = isNullExtent(m_params.traceDimensions);
1405
1406 const auto allocationCount = blasPool.getAllocationCount();
1407 uint32_t failures = 0;
1408 uint32_t pos = 0;
1409 uint32_t all = 0;
1410
1411 // verify results
1412 for (uint32_t z = 0; z < depth; ++z)
1413 for (uint32_t y = 0; y < height; ++y)
1414 for (uint32_t x = 0; x < width; ++x)
1415 {
1416 const uint32_t expectedResult =
1417 (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
1418 if (bufferPtr[pos] != expectedResult)
1419 failures++;
1420 ++pos;
1421 ++all;
1422 }
1423
1424 if (failures == 0)
1425 return tcu::TestStatus::pass(std::to_string(allocationCount) + " allocations");
1426 else
1427 {
1428 const auto msg = std::to_string(allocationCount) + " allocations, " + std::to_string(failures) +
1429 " failures from " + std::to_string(all);
1430 return tcu::TestStatus::fail(msg);
1431 }
1432 }
1433
makeDimensionsName(const VkTraceRaysIndirectCommandKHR & cmd)1434 std::string makeDimensionsName(const VkTraceRaysIndirectCommandKHR &cmd)
1435 {
1436 std::ostringstream name;
1437 name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
1438 return name.str();
1439 }
1440
makeDimensionsName(const VkExtent3D & extent)1441 std::string makeDimensionsName(const VkExtent3D &extent)
1442 {
1443 std::ostringstream name;
1444 name << extent.width << "x" << extent.height << "x" << extent.depth;
1445 return name.str();
1446 }
1447
1448 } // namespace
1449
createTraceRaysTests(tcu::TestContext & testCtx)1450 tcu::TestCaseGroup *createTraceRaysTests(tcu::TestContext &testCtx)
1451 {
1452 // Tests veryfying vkCmdTraceRays* commands
1453 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds"));
1454
1455 struct BufferSourceTypeData
1456 {
1457 TraceType traceType;
1458 const char *name;
1459 } bufferSourceTypes[] = {
1460 {TraceType::DIRECT, "direct"},
1461 {TraceType::INDIRECT_CPU, "indirect_cpu"},
1462 {TraceType::INDIRECT_GPU, "indirect_gpu"},
1463 };
1464
1465 const VkTraceRaysIndirectCommandKHR traceDimensions[] = {
1466 {0, 0, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {8, 1, 1},
1467 {8, 8, 1}, {8, 8, 8}, {11, 1, 1}, {11, 13, 1}, {11, 13, 5},
1468 };
1469
1470 for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
1471 {
1472 de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(
1473 new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name));
1474
1475 for (size_t traceDimensionsIdx = 0; traceDimensionsIdx < DE_LENGTH_OF_ARRAY(traceDimensions);
1476 ++traceDimensionsIdx)
1477 {
1478 TestParams testParams{
1479 bufferSourceTypes[bufferSourceNdx].traceType,
1480 traceDimensions[traceDimensionsIdx],
1481 false,
1482 {/* Intentionally empty */},
1483 };
1484 const auto testName = makeDimensionsName(traceDimensions[traceDimensionsIdx]);
1485 bufferSourceGroup->addChild(
1486 new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), testParams));
1487 }
1488
1489 group->addChild(bufferSourceGroup.release());
1490 }
1491
1492 return group.release();
1493 }
1494
createTraceRaysMaintenance1Tests(tcu::TestContext & testCtx)1495 tcu::TestCaseGroup *createTraceRaysMaintenance1Tests(tcu::TestContext &testCtx)
1496 {
1497 // Tests veryfying vkCmdTraceRays* commands
1498 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds_maintenance_1"));
1499
1500 struct BufferSourceTypeData
1501 {
1502 TraceType traceType;
1503 const char *name;
1504 } bufferSourceTypes[] = {
1505 {TraceType::INDIRECT2_CPU, "indirect2_cpu"},
1506 {TraceType::INDIRECT2_GPU, "indirect2_gpu"},
1507 };
1508
1509 const VkTraceRaysIndirectCommand2KHR extendedTraceDimensions[] = {
1510 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
1511 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
1512 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 1},
1513 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 1, 1},
1514 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 13, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 13, 5},
1515 };
1516
1517 for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
1518 {
1519 de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(
1520 new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name));
1521
1522 for (size_t extendedTraceDimensionsIdx = 0;
1523 extendedTraceDimensionsIdx < DE_LENGTH_OF_ARRAY(extendedTraceDimensions); ++extendedTraceDimensionsIdx)
1524 {
1525 TestParams testParams{
1526 bufferSourceTypes[bufferSourceNdx].traceType,
1527 {/* Intentionally empty */},
1528 true,
1529 extendedTraceDimensions[extendedTraceDimensionsIdx],
1530 };
1531 const auto testName = makeDimensionsName(extendedTraceDimensions[extendedTraceDimensionsIdx]);
1532 bufferSourceGroup->addChild(
1533 new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), testParams));
1534 }
1535
1536 group->addChild(bufferSourceGroup.release());
1537 }
1538
1539 return group.release();
1540 }
1541
createTraceRays2Tests(tcu::TestContext & testCtx)1542 tcu::TestCaseGroup *createTraceRays2Tests(tcu::TestContext &testCtx)
1543 {
1544 auto group = new tcu::TestCaseGroup(testCtx, "trace_rays_indirect2");
1545
1546 std::pair<TraceType, const char *> const bufferSources[]{
1547 {TraceType::INDIRECT_CPU, "indirect_cpu"},
1548 {TraceType::INDIRECT_GPU, "indirect_gpu"},
1549 };
1550
1551 std::pair<bool, const char *> const copyStyles[]{{true, "full_copy"}, {false, "partial_copy"}};
1552
1553 std::pair<VkQueueFlagBits, const char *> submitQueues[]{{VK_QUEUE_GRAPHICS_BIT, "submit_graphics"},
1554 {VK_QUEUE_COMPUTE_BIT, "submit_compute"}};
1555
1556 const VkExtent3D traceDimensions[] = {{11, 17, 1}, {19, 11, 2}, {23, 47, 3}, {47, 19, 4}};
1557
1558 for (const auto &bufferSource : bufferSources)
1559 {
1560 auto bufferSourceGroup = new TestCaseGroup(testCtx, bufferSource.second);
1561
1562 for (const auto ©Style : copyStyles)
1563 {
1564 auto copyStyleGroup = new TestCaseGroup(testCtx, copyStyle.second);
1565
1566 for (const auto &submitQueue : submitQueues)
1567 {
1568 auto submitQueueGroup = new TestCaseGroup(testCtx, submitQueue.second);
1569
1570 for (const auto &traceDimension : traceDimensions)
1571 {
1572 TestParams2 testParams{bufferSource.first, traceDimension, copyStyle.first, submitQueue.first};
1573 const auto testName = makeDimensionsName(traceDimension);
1574 submitQueueGroup->addChild(new TraceRaysIndirect2Case(testCtx, testName.c_str(), testParams));
1575 }
1576 copyStyleGroup->addChild(submitQueueGroup);
1577 }
1578 bufferSourceGroup->addChild(copyStyleGroup);
1579 }
1580 group->addChild(bufferSourceGroup);
1581 }
1582
1583 return group;
1584 }
1585
1586 } // namespace RayTracing
1587
1588 } // namespace vkt
1589