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