1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 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 Build Large Shader Set tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayTracingBuildIndirectTests.hpp"
25
26 #include "vkDefs.hpp"
27
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36
37 #include "vkRayTracingUtil.hpp"
38
39 namespace vkt
40 {
41 namespace RayTracing
42 {
43 namespace
44 {
45 using namespace vk;
46 using namespace std;
47
48 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
49 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
50 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
51
52 struct CaseDef
53 {
54 uint32_t width;
55 uint32_t height;
56 uint32_t depth;
57 uint32_t squaresGroupCount;
58 uint32_t geometriesGroupCount;
59 uint32_t instancesGroupCount;
60 };
61
62 enum ShaderGroups
63 {
64 FIRST_GROUP = 0,
65 RAYGEN_GROUP = FIRST_GROUP,
66 MISS_GROUP,
67 HIT_GROUP,
68 GROUP_COUNT
69 };
70
71 const uint32_t HIT = 1;
72 const uint32_t MISS = 2;
73 const uint32_t HIT_MISS_PATTERN = 7;
74
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)75 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
76 {
77 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
78
79 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
80
81 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
82 }
83
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)84 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
85 {
86 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
87
88 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
89
90 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
91 }
92
makePipeline(const DeviceInterface & vkd,const VkDevice device,vk::BinaryCollection & collection,de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout,const std::string & shaderName)93 Move<VkPipeline> makePipeline(const DeviceInterface &vkd, const VkDevice device, vk::BinaryCollection &collection,
94 de::MovePtr<RayTracingPipeline> &rayTracingPipeline, VkPipelineLayout pipelineLayout,
95 const std::string &shaderName)
96 {
97 Move<VkShaderModule> raygenShader = createShaderModule(vkd, device, collection.get(shaderName), 0);
98
99 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, raygenShader, 0);
100
101 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
102
103 return pipeline;
104 }
105
makePipeline(const DeviceInterface & vkd,const VkDevice device,vk::BinaryCollection & collection,de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout,const uint32_t raygenGroup,const uint32_t missGroup,const uint32_t hitGroup)106 Move<VkPipeline> makePipeline(const DeviceInterface &vkd, const VkDevice device, vk::BinaryCollection &collection,
107 de::MovePtr<RayTracingPipeline> &rayTracingPipeline, VkPipelineLayout pipelineLayout,
108 const uint32_t raygenGroup, const uint32_t missGroup, const uint32_t hitGroup)
109 {
110 Move<VkShaderModule> raygenShader = createShaderModule(vkd, device, collection.get("rgen"), 0);
111 Move<VkShaderModule> hitShader = createShaderModule(vkd, device, collection.get("chit"), 0);
112 Move<VkShaderModule> missShader = createShaderModule(vkd, device, collection.get("miss"), 0);
113
114 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, raygenShader, raygenGroup);
115 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, hitShader, hitGroup);
116 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missShader, missGroup);
117
118 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
119
120 return pipeline;
121 }
122
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)123 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
124 {
125 const VkImageUsageFlags usage =
126 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
127 const VkImageCreateInfo imageCreateInfo = {
128 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
129 DE_NULL, // const void* pNext;
130 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
131 VK_IMAGE_TYPE_3D, // VkImageType imageType;
132 format, // VkFormat format;
133 makeExtent3D(width, height, depth), // VkExtent3D extent;
134 1u, // uint32_t mipLevels;
135 1u, // uint32_t arrayLayers;
136 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
137 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
138 usage, // VkImageUsageFlags usage;
139 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
140 0u, // uint32_t queueFamilyIndexCount;
141 DE_NULL, // const uint32_t* pQueueFamilyIndices;
142 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
143 };
144
145 return imageCreateInfo;
146 }
147
148 class RayTracingBuildIndirectTestInstance : public TestInstance
149 {
150 public:
151 RayTracingBuildIndirectTestInstance(Context &context, const CaseDef &data);
152 ~RayTracingBuildIndirectTestInstance(void);
153 tcu::TestStatus iterate(void);
154
155 protected:
156 void checkSupportInInstance(void) const;
157 de::MovePtr<BufferWithMemory> prepareBuffer(VkDeviceSize bufferSizeBytes, const std::string &shaderName);
158 de::MovePtr<BufferWithMemory> runTest(const VkBuffer indirectBottomAccelerationStructure,
159 const VkBuffer indirectTopAccelerationStructure);
160 de::SharedPtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
161 VkCommandBuffer cmdBuffer, de::SharedPtr<BottomLevelAccelerationStructure> &bottomLevelAccelerationStructure,
162 const VkBuffer indirectBuffer, const VkDeviceSize indirectBufferOffset, const uint32_t indirectBufferStride);
163 de::SharedPtr<BottomLevelAccelerationStructure> initBottomAccelerationStructure(
164 VkCommandBuffer cmdBuffer, const VkBuffer indirectBuffer, const VkDeviceSize indirectBufferOffset,
165 const uint32_t indirectBufferStride);
166 VkBuffer initIndirectTopAccelerationStructure(void);
167 VkBuffer initIndirectBottomAccelerationStructure(void);
168
169 private:
170 CaseDef m_data;
171 de::MovePtr<BufferWithMemory> m_indirectAccelerationStructureBottom;
172 de::MovePtr<BufferWithMemory> m_indirectAccelerationStructureTop;
173 };
174
RayTracingBuildIndirectTestInstance(Context & context,const CaseDef & data)175 RayTracingBuildIndirectTestInstance::RayTracingBuildIndirectTestInstance(Context &context, const CaseDef &data)
176 : vkt::TestInstance(context)
177 , m_data(data)
178 , m_indirectAccelerationStructureBottom()
179 , m_indirectAccelerationStructureTop()
180 {
181 }
182
~RayTracingBuildIndirectTestInstance(void)183 RayTracingBuildIndirectTestInstance::~RayTracingBuildIndirectTestInstance(void)
184 {
185 }
186
187 class RayTracingTestCase : public TestCase
188 {
189 public:
190 RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
191 ~RayTracingTestCase(void);
192
193 virtual void initPrograms(SourceCollections &programCollection) const;
194 virtual TestInstance *createInstance(Context &context) const;
195 virtual void checkSupport(Context &context) const;
196
197 private:
198 CaseDef m_data;
199 };
200
RayTracingTestCase(tcu::TestContext & context,const char * name,const CaseDef data)201 RayTracingTestCase::RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
202 : vkt::TestCase(context, name)
203 , m_data(data)
204 {
205 DE_ASSERT((m_data.width * m_data.height * m_data.depth) ==
206 (m_data.squaresGroupCount * m_data.geometriesGroupCount * m_data.instancesGroupCount));
207 }
208
~RayTracingTestCase(void)209 RayTracingTestCase::~RayTracingTestCase(void)
210 {
211 }
212
checkSupport(Context & context) const213 void RayTracingTestCase::checkSupport(Context &context) const
214 {
215 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
216 context.getAccelerationStructureFeatures();
217 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
218 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
219
220 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
221 context.getRayTracingPipelineFeatures();
222 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
223 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
224
225 if (accelerationStructureFeaturesKHR.accelerationStructureIndirectBuild == false)
226 TCU_THROW(NotSupportedError,
227 "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureIndirectBuild");
228 }
229
initPrograms(SourceCollections & programCollection) const230 void RayTracingTestCase::initPrograms(SourceCollections &programCollection) const
231 {
232 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
233 {
234 std::stringstream css;
235 css << "#version 460 core\n"
236 "#extension GL_EXT_ray_tracing : require\n"
237 "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
238 "{\n"
239 " uvec4 accelerationStructureBuildOffsetInfoKHR["
240 << m_data.depth
241 << "];\n"
242 "} b_out;\n"
243 "\n"
244 "void main()\n"
245 "{\n"
246 " for (uint i = 0; i < "
247 << m_data.depth
248 << "; i++)\n"
249 " {\n"
250 " uint primitiveCount = "
251 << m_data.width * m_data.height
252 << "u;\n"
253 " uint primitiveOffset = "
254 << m_data.width * m_data.height * 3u * sizeof(tcu::Vec3)
255 << "u * i;\n"
256 " uint firstVertex = "
257 << 0
258 << "u;\n"
259 " uint transformOffset = "
260 << 0
261 << "u;\n"
262 "\n"
263 " b_out.accelerationStructureBuildOffsetInfoKHR[i] = uvec4(primitiveCount, primitiveOffset, "
264 "firstVertex, transformOffset);\n"
265 " }\n"
266 "}\n";
267
268 programCollection.glslSources.add("wr-asb")
269 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
270 }
271
272 {
273 std::stringstream css;
274 css << "#version 460 core\n"
275 "#extension GL_EXT_ray_tracing : require\n"
276 "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
277 "{\n"
278 " uvec4 accelerationStructureBuildOffsetInfoKHR;\n"
279 "} b_out;\n"
280 "\n"
281 "void main()\n"
282 "{\n"
283 " uint primitiveCount = "
284 << m_data.instancesGroupCount
285 << "u;\n"
286 " uint primitiveOffset = "
287 << 0
288 << "u;\n"
289 " uint firstVertex = "
290 << 0
291 << "u;\n"
292 " uint transformOffset = "
293 << 0
294 << "u;\n"
295 "\n"
296 " b_out.accelerationStructureBuildOffsetInfoKHR = uvec4(primitiveCount, primitiveOffset, firstVertex, "
297 "transformOffset);\n"
298 "}\n";
299
300 programCollection.glslSources.add("wr-ast")
301 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
302 }
303
304 {
305 std::stringstream css;
306 css << "#version 460 core\n"
307 "#extension GL_EXT_ray_tracing : require\n"
308 "layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
309 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
310 "\n"
311 "void main()\n"
312 "{\n"
313 " uint rayFlags = 0;\n"
314 " uint cullMask = 0xFF;\n"
315 " float tmin = 0.0;\n"
316 " float tmax = 9.0;\n"
317 " float x = (float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x);\n"
318 " float y = (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y);\n"
319 " float z = (float(gl_LaunchIDEXT.z) + 0.5f) / float(gl_LaunchSizeEXT.z);\n"
320 " vec3 origin = vec3(x, y, z);\n"
321 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
322 " traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
323 "}\n";
324
325 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
326 }
327
328 {
329 std::stringstream css;
330 css << "#version 460 core\n"
331 "#extension GL_EXT_ray_tracing : require\n"
332 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
333 "hitAttributeEXT vec3 attribs;\n"
334 "layout(set = 0, binding = 0, r32ui) uniform uimage3D result;\n"
335 "void main()\n"
336 "{\n"
337 " uvec4 color = uvec4("
338 << HIT
339 << ",0,0,1);\n"
340 " imageStore(result, ivec3(gl_LaunchIDEXT.xyz), color);\n"
341 "}\n";
342
343 programCollection.glslSources.add("chit")
344 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
345 }
346
347 {
348 std::stringstream css;
349 css << "#version 460 core\n"
350 "#extension GL_EXT_ray_tracing : require\n"
351 "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
352 "layout(set = 0, binding = 0, r32ui) uniform uimage3D result;\n"
353 "void main()\n"
354 "{\n"
355 " uvec4 color = uvec4("
356 << MISS
357 << ",0,0,1);\n"
358 " imageStore(result, ivec3(gl_LaunchIDEXT.xyz), color);\n"
359 "}\n";
360
361 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
362 }
363 }
364
createInstance(Context & context) const365 TestInstance *RayTracingTestCase::createInstance(Context &context) const
366 {
367 return new RayTracingBuildIndirectTestInstance(context, m_data);
368 }
369
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,de::SharedPtr<BottomLevelAccelerationStructure> & bottomLevelAccelerationStructure,const VkBuffer indirectBuffer,const VkDeviceSize indirectBufferOffset,const uint32_t indirectBufferStride)370 de::SharedPtr<TopLevelAccelerationStructure> RayTracingBuildIndirectTestInstance::initTopAccelerationStructure(
371 VkCommandBuffer cmdBuffer, de::SharedPtr<BottomLevelAccelerationStructure> &bottomLevelAccelerationStructure,
372 const VkBuffer indirectBuffer, const VkDeviceSize indirectBufferOffset, const uint32_t indirectBufferStride)
373 {
374 const DeviceInterface &vkd = m_context.getDeviceInterface();
375 const VkDevice device = m_context.getDevice();
376 Allocator &allocator = m_context.getDefaultAllocator();
377 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
378
379 result->setInstanceCount(1);
380 result->addInstance(bottomLevelAccelerationStructure);
381 result->setIndirectBuildParameters(indirectBuffer, indirectBufferOffset, indirectBufferStride);
382
383 result->createAndBuild(vkd, device, cmdBuffer, allocator);
384
385 return de::SharedPtr<TopLevelAccelerationStructure>(result.release());
386 }
387
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,const VkBuffer indirectBuffer,const VkDeviceSize indirectBufferOffset,const uint32_t indirectBufferStride)388 de::SharedPtr<BottomLevelAccelerationStructure> RayTracingBuildIndirectTestInstance::initBottomAccelerationStructure(
389 VkCommandBuffer cmdBuffer, const VkBuffer indirectBuffer, const VkDeviceSize indirectBufferOffset,
390 const uint32_t indirectBufferStride)
391 {
392 const DeviceInterface &vkd = m_context.getDeviceInterface();
393 const VkDevice device = m_context.getDevice();
394 Allocator &allocator = m_context.getDefaultAllocator();
395 de::MovePtr<BottomLevelAccelerationStructure> result = makeBottomLevelAccelerationStructure();
396
397 result->setGeometryCount(m_data.geometriesGroupCount);
398 result->setIndirectBuildParameters(indirectBuffer, indirectBufferOffset, indirectBufferStride);
399
400 for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
401 {
402 std::vector<tcu::Vec3> geometryData;
403
404 geometryData.reserve(m_data.squaresGroupCount * 3u);
405
406 tcu::UVec2 startPos = tcu::UVec2(0u, 0u);
407
408 for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
409 {
410 const uint32_t n = m_data.width * startPos.y() + startPos.x();
411 const float x0 = float(startPos.x() + 0) / float(m_data.width);
412 const float y0 = float(startPos.y() + 0) / float(m_data.height);
413 const float x1 = float(startPos.x() + 1) / float(m_data.width);
414 const float y1 = float(startPos.y() + 1) / float(m_data.height);
415 const float xm = (x0 + x1) / 2.0f;
416 const float ym = (y0 + y1) / 2.0f;
417 const float z =
418 (n % HIT_MISS_PATTERN == 0) ? +1.0f : (float(geometryNdx) + 0.25f) / float(m_data.geometriesGroupCount);
419
420 geometryData.push_back(tcu::Vec3(x0, y0, z));
421 geometryData.push_back(tcu::Vec3(xm, y1, z));
422 geometryData.push_back(tcu::Vec3(x1, ym, z));
423
424 startPos.y() = (n + 1) / m_data.width;
425 startPos.x() = (n + 1) % m_data.width;
426 }
427
428 result->addGeometry(geometryData, true);
429 }
430
431 result->createAndBuild(vkd, device, cmdBuffer, allocator);
432
433 return de::SharedPtr<BottomLevelAccelerationStructure>(result.release());
434 }
435
prepareBuffer(VkDeviceSize bufferSizeBytes,const std::string & shaderName)436 de::MovePtr<BufferWithMemory> RayTracingBuildIndirectTestInstance::prepareBuffer(VkDeviceSize bufferSizeBytes,
437 const std::string &shaderName)
438 {
439 const InstanceInterface &vki = m_context.getInstanceInterface();
440 const DeviceInterface &vkd = m_context.getDeviceInterface();
441 const VkDevice device = m_context.getDevice();
442 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
443 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
444 const VkQueue queue = m_context.getUniversalQueue();
445 Allocator &allocator = m_context.getDefaultAllocator();
446 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
447 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
448
449 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(
450 bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
451 de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
452 vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
453
454 const Move<VkDescriptorSetLayout> descriptorSetLayout =
455 DescriptorSetLayoutBuilder()
456 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)
457 .build(vkd, device);
458 const Move<VkDescriptorPool> descriptorPool =
459 DescriptorPoolBuilder()
460 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
461 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
462 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
463 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
464 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
465 const Move<VkCommandBuffer> cmdBuffer =
466 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
467
468 const vk::VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(**buffer, 0ull, bufferSizeBytes);
469
470 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
471 const Move<VkPipeline> pipeline =
472 makePipeline(vkd, device, m_context.getBinaryCollection(), rayTracingPipeline, *pipelineLayout, shaderName);
473 const de::MovePtr<BufferWithMemory> shaderBindingTable = rayTracingPipeline->createShaderBindingTable(
474 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
475 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
476 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, shaderBindingTable->get(), 0),
477 shaderGroupHandleSize, shaderGroupHandleSize);
478 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
479 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
480 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
481 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
482 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
483 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
484
485 beginCommandBuffer(vkd, *cmdBuffer, 0u);
486 {
487 DescriptorSetUpdateBuilder()
488 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
489 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
490 .update(vkd, device);
491
492 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
493 &descriptorSet.get(), 0, DE_NULL);
494
495 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
496
497 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
498 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, 1u, 1u, 1u);
499 }
500 endCommandBuffer(vkd, *cmdBuffer);
501
502 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
503
504 return buffer;
505 }
506
runTest(const VkBuffer indirectBottomAccelerationStructure,const VkBuffer indirectTopAccelerationStructure)507 de::MovePtr<BufferWithMemory> RayTracingBuildIndirectTestInstance::runTest(
508 const VkBuffer indirectBottomAccelerationStructure, const VkBuffer indirectTopAccelerationStructure)
509 {
510 const InstanceInterface &vki = m_context.getInstanceInterface();
511 const DeviceInterface &vkd = m_context.getDeviceInterface();
512 const VkDevice device = m_context.getDevice();
513 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
514 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
515 const VkQueue queue = m_context.getUniversalQueue();
516 Allocator &allocator = m_context.getDefaultAllocator();
517 const VkFormat format = VK_FORMAT_R32_UINT;
518 const uint32_t pixelCount = m_data.width * m_data.height * m_data.depth;
519 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
520 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
521
522 const Move<VkDescriptorSetLayout> descriptorSetLayout =
523 DescriptorSetLayoutBuilder()
524 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
525 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
526 .build(vkd, device);
527 const Move<VkDescriptorPool> descriptorPool =
528 DescriptorPoolBuilder()
529 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
530 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
531 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
532 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
533 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
534 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
535 const Move<VkCommandBuffer> cmdBuffer =
536 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
537
538 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
539 const Move<VkPipeline> pipeline = makePipeline(vkd, device, m_context.getBinaryCollection(), rayTracingPipeline,
540 *pipelineLayout, RAYGEN_GROUP, MISS_GROUP, HIT_GROUP);
541 const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
542 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, RAYGEN_GROUP, 1u);
543 const de::MovePtr<BufferWithMemory> missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
544 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, MISS_GROUP, 1u);
545 const de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
546 vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, HIT_GROUP, 1u);
547 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
548 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
549 shaderGroupHandleSize, shaderGroupHandleSize);
550 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
551 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
552 shaderGroupHandleSize, shaderGroupHandleSize);
553 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
554 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
555 shaderGroupHandleSize, shaderGroupHandleSize);
556 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
557 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
558
559 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, m_data.depth, format);
560 const VkImageSubresourceRange imageSubresourceRange =
561 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
562 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
563 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
564 const Move<VkImageView> imageView =
565 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, format, imageSubresourceRange);
566
567 const VkBufferCreateInfo bufferCreateInfo =
568 makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
569 const VkImageSubresourceLayers bufferImageSubresourceLayers =
570 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
571 const VkBufferImageCopy bufferImageRegion =
572 makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, m_data.depth), bufferImageSubresourceLayers);
573 de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
574 new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
575
576 const VkDescriptorImageInfo descriptorImageInfo =
577 makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
578
579 const VkImageMemoryBarrier preImageBarrier =
580 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
581 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
582 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
583 VK_ACCESS_TRANSFER_WRITE_BIT,
584 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
585 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
586 const VkMemoryBarrier postTraceMemoryBarrier =
587 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
588 const VkMemoryBarrier postCopyMemoryBarrier =
589 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
590 const VkClearValue clearValue = makeClearValueColorU32(5u, 5u, 5u, 255u);
591 const uint32_t indirectAccelerationStructureStride = sizeof(VkAccelerationStructureBuildRangeInfoKHR);
592
593 de::SharedPtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure;
594 de::SharedPtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
595
596 beginCommandBuffer(vkd, *cmdBuffer, 0u);
597 {
598 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
599 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
600 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
601 &imageSubresourceRange);
602 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
603 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
604
605 bottomLevelAccelerationStructure = initBottomAccelerationStructure(
606 *cmdBuffer, indirectBottomAccelerationStructure, 0, indirectAccelerationStructureStride);
607 topLevelAccelerationStructure =
608 initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructure, indirectTopAccelerationStructure,
609 0, indirectAccelerationStructureStride);
610
611 const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
612 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
613 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
614 DE_NULL, // const void* pNext;
615 1u, // uint32_t accelerationStructureCount;
616 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
617 };
618
619 DescriptorSetUpdateBuilder()
620 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
621 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
622 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
623 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
624 .update(vkd, device);
625
626 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
627 &descriptorSet.get(), 0, DE_NULL);
628
629 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
630
631 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
632 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height,
633 m_data.depth);
634
635 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
636 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
637
638 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
639
640 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
641 &postCopyMemoryBarrier);
642 }
643 endCommandBuffer(vkd, *cmdBuffer);
644
645 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
646
647 invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
648 pixelCount * sizeof(uint32_t));
649
650 return buffer;
651 }
652
checkSupportInInstance(void) const653 void RayTracingBuildIndirectTestInstance::checkSupportInInstance(void) const
654 {
655 const InstanceInterface &vki = m_context.getInstanceInterface();
656 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
657 de::MovePtr<RayTracingProperties> rayTracingProperties = makeRayTracingProperties(vki, physicalDevice);
658
659 if (rayTracingProperties->getMaxPrimitiveCount() < m_data.squaresGroupCount)
660 TCU_THROW(NotSupportedError, "Triangles required more than supported");
661
662 if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
663 TCU_THROW(NotSupportedError, "Geometries required more than supported");
664
665 if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
666 TCU_THROW(NotSupportedError, "Instances required more than supported");
667 }
668
initIndirectTopAccelerationStructure(void)669 VkBuffer RayTracingBuildIndirectTestInstance::initIndirectTopAccelerationStructure(void)
670 {
671 VkBuffer result = DE_NULL;
672
673 m_indirectAccelerationStructureTop = prepareBuffer(sizeof(VkAccelerationStructureBuildRangeInfoKHR), "wr-ast");
674 result = **m_indirectAccelerationStructureTop;
675
676 return result;
677 }
678
initIndirectBottomAccelerationStructure(void)679 VkBuffer RayTracingBuildIndirectTestInstance::initIndirectBottomAccelerationStructure(void)
680 {
681 VkBuffer result = DE_NULL;
682
683 m_indirectAccelerationStructureBottom =
684 prepareBuffer(sizeof(VkAccelerationStructureBuildRangeInfoKHR) * m_data.geometriesGroupCount, "wr-asb");
685 result = **m_indirectAccelerationStructureBottom;
686
687 return result;
688 }
689
iterate(void)690 tcu::TestStatus RayTracingBuildIndirectTestInstance::iterate(void)
691 {
692 checkSupportInInstance();
693
694 const VkBuffer indirectAccelerationStructureBottom = initIndirectBottomAccelerationStructure();
695 const VkBuffer indirectAccelerationStructureTop = initIndirectTopAccelerationStructure();
696 const de::MovePtr<BufferWithMemory> buffer =
697 runTest(indirectAccelerationStructureBottom, indirectAccelerationStructureTop);
698 const uint32_t *bufferPtr = (uint32_t *)buffer->getAllocation().getHostPtr();
699 uint32_t failures = 0;
700
701 for (uint32_t z = 0; z < m_data.depth; ++z)
702 {
703 const uint32_t *bufferPtrLevel = &bufferPtr[z * m_data.height * m_data.width];
704
705 for (uint32_t y = 0; y < m_data.height; ++y)
706 for (uint32_t x = 0; x < m_data.width; ++x)
707 {
708 const uint32_t n = m_data.width * y + x;
709 const uint32_t expectedValue = (n % HIT_MISS_PATTERN == 0) ? MISS : HIT;
710
711 if (bufferPtrLevel[n] != expectedValue)
712 failures++;
713 }
714 }
715
716 if (failures == 0)
717 return tcu::TestStatus::pass("Pass");
718 else
719 return tcu::TestStatus::fail("failures=" + de::toString(failures));
720 }
721
722 } // namespace
723
createBuildIndirectTests(tcu::TestContext & testCtx)724 tcu::TestCaseGroup *createBuildIndirectTests(tcu::TestContext &testCtx)
725 {
726 // Build acceleration structure indirect ray tracing tests
727 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "indirect"));
728
729 const uint32_t width = 512u;
730 const uint32_t height = 128u;
731 const uint32_t depth = 4u;
732 const uint32_t largestGroup = width * height;
733 const uint32_t squaresGroupCount = largestGroup;
734 const uint32_t geometriesGroupCount = depth;
735 const uint32_t instancesGroupCount = 1;
736 const CaseDef caseDef = {
737 width, height, depth, squaresGroupCount, geometriesGroupCount, instancesGroupCount,
738 };
739 const std::string testName = "build_structure";
740
741 group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
742
743 return group.release();
744 }
745
746 } // namespace RayTracing
747 } // namespace vkt
748