1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief 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 namespace vkt
41 {
42 namespace RayTracing
43 {
44 namespace
45 {
46 using namespace vk;
47 using namespace vkt;
48
49 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR
50 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR
51 | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
52 | VK_SHADER_STAGE_MISS_BIT_KHR
53 | VK_SHADER_STAGE_INTERSECTION_BIT_KHR
54 | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
55
56 constexpr deUint32 kClearColorValue = 0xFFu;
57 constexpr deUint32 kHitColorValue = 2u;
58 constexpr deUint32 kMissColorValue = 1u;
59
60 enum class TraceType
61 {
62 DIRECT = 0,
63 INDIRECT_CPU = 1,
64 INDIRECT_GPU = 2,
65 };
66
67 struct TestParams
68 {
69 TraceType traceType;
70 VkTraceRaysIndirectCommandKHR traceDimensions; // Note: to be used for both direct and indirect variants.
71 };
72
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)73 deUint32 getShaderGroupSize (const InstanceInterface& vki,
74 const VkPhysicalDevice physicalDevice)
75 {
76 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
77
78 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
79 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
80 }
81
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)82 deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki,
83 const VkPhysicalDevice physicalDevice)
84 {
85 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
86
87 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
88 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
89 }
90
isNullTrace(const VkTraceRaysIndirectCommandKHR & cmd)91 bool isNullTrace (const VkTraceRaysIndirectCommandKHR& cmd)
92 {
93 return (cmd.width == 0u || cmd.height == 0u || cmd.depth == 0u);
94 }
95
getImageExtent(const VkTraceRaysIndirectCommandKHR & cmd)96 VkExtent3D getImageExtent (const VkTraceRaysIndirectCommandKHR& cmd)
97 {
98 return (isNullTrace(cmd) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(cmd.width, cmd.height, cmd.depth));
99 }
100
makeImageCreateInfo(deUint32 width,deUint32 height,deUint32 depth,VkFormat format)101 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
102 {
103 const VkImageCreateInfo imageCreateInfo =
104 {
105 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
106 DE_NULL, // const void* pNext;
107 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
108 VK_IMAGE_TYPE_3D, // VkImageType imageType;
109 format, // VkFormat format;
110 makeExtent3D(width, height, depth), // VkExtent3D extent;
111 1u, // deUint32 mipLevels;
112 1u, // deUint32 arrayLayers;
113 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
114 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
115 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
116 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
117 0u, // deUint32 queueFamilyIndexCount;
118 DE_NULL, // const deUint32* pQueueFamilyIndices;
119 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
120 };
121
122 return imageCreateInfo;
123 }
124
125 class RayTracingTraceRaysIndirectTestCase : public TestCase
126 {
127 public:
128 RayTracingTraceRaysIndirectTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
129 ~RayTracingTraceRaysIndirectTestCase (void);
130
131 virtual void checkSupport (Context& context) const;
132 virtual void initPrograms (SourceCollections& programCollection) const;
133 virtual TestInstance* createInstance (Context& context) const;
134 private:
135 TestParams m_data;
136 };
137
138 class RayTracingTraceRaysIndirectTestInstance : public TestInstance
139 {
140 public:
141 RayTracingTraceRaysIndirectTestInstance (Context& context, const TestParams& data);
142 ~RayTracingTraceRaysIndirectTestInstance (void);
143 tcu::TestStatus iterate (void);
144
145 protected:
146 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (VkCommandBuffer cmdBuffer);
147 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (VkCommandBuffer cmdBuffer,
148 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures);
149 de::MovePtr<BufferWithMemory> runTest ();
150 private:
151 TestParams m_data;
152 const VkExtent3D m_imageExtent;
153 };
154
155
RayTracingTraceRaysIndirectTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)156 RayTracingTraceRaysIndirectTestCase::RayTracingTraceRaysIndirectTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
157 : vkt::TestCase (context, name, desc)
158 , m_data (data)
159 {
160 }
161
~RayTracingTraceRaysIndirectTestCase(void)162 RayTracingTraceRaysIndirectTestCase::~RayTracingTraceRaysIndirectTestCase (void)
163 {
164 }
165
checkSupport(Context & context) const166 void RayTracingTraceRaysIndirectTestCase::checkSupport(Context& context) const
167 {
168 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
169 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
170
171 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR& rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
172 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
173 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
174
175 if (rayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect == DE_FALSE)
176 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect");
177
178 const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
179 if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
180 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
181 }
182
initPrograms(SourceCollections & programCollection) const183 void RayTracingTraceRaysIndirectTestCase::initPrograms (SourceCollections& programCollection) const
184 {
185 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
186 {
187 std::stringstream css;
188 css <<
189 "#version 460 core\n"
190 "struct TraceRaysIndirectCommand\n"
191 "{\n"
192 " uint width;\n"
193 " uint height;\n"
194 " uint depth;\n"
195 "};\n"
196 "layout(binding = 0) uniform IndirectCommandsUBO\n"
197 "{\n"
198 " TraceRaysIndirectCommand indirectCommands;\n"
199 "} ubo;\n"
200 "layout(binding = 1) buffer IndirectCommandsSBO\n"
201 "{\n"
202 " TraceRaysIndirectCommand indirectCommands;\n"
203 "};\n"
204 "void main()\n"
205 "{\n"
206 " indirectCommands.width = ubo.indirectCommands.width;\n"
207 " indirectCommands.height = ubo.indirectCommands.height;\n"
208 " indirectCommands.depth = ubo.indirectCommands.depth;\n"
209 "}\n";
210
211 programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(css.str()) << buildOptions;
212 }
213
214 {
215 std::stringstream css;
216 css <<
217 "#version 460 core\n"
218 "#extension GL_EXT_ray_tracing : require\n"
219 "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
220 "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
221 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
222 "\n"
223 "void main()\n"
224 "{\n"
225 " float tmin = 0.0;\n"
226 " float tmax = 1.0;\n"
227 " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, float(gl_LaunchIDEXT.z + 0.5f));\n"
228 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
229 " hitValue = uvec4(0,0,0,0);\n"
230 " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
231 " imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
232 "}\n";
233 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
234 }
235
236 {
237 std::stringstream css;
238 css <<
239 "#version 460 core\n"
240 "#extension GL_EXT_ray_tracing : require\n"
241 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
242 "void main()\n"
243 "{\n"
244 " hitValue = uvec4(" << kHitColorValue << ",0,0,1);\n"
245 "}\n";
246 programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
247 }
248
249 {
250 std::stringstream css;
251 css <<
252 "#version 460 core\n"
253 "#extension GL_EXT_ray_tracing : require\n"
254 "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
255 "void main()\n"
256 "{\n"
257 " hitValue = uvec4(" << kMissColorValue << ",0,0,1);\n"
258 "}\n";
259
260 programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
261 }
262 }
263
createInstance(Context & context) const264 TestInstance* RayTracingTraceRaysIndirectTestCase::createInstance (Context& context) const
265 {
266 return new RayTracingTraceRaysIndirectTestInstance(context, m_data);
267 }
268
RayTracingTraceRaysIndirectTestInstance(Context & context,const TestParams & data)269 RayTracingTraceRaysIndirectTestInstance::RayTracingTraceRaysIndirectTestInstance (Context& context, const TestParams& data)
270 : vkt::TestInstance (context)
271 , m_data (data)
272 , m_imageExtent (getImageExtent(data.traceDimensions))
273 {
274 }
275
~RayTracingTraceRaysIndirectTestInstance(void)276 RayTracingTraceRaysIndirectTestInstance::~RayTracingTraceRaysIndirectTestInstance (void)
277 {
278 }
279
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)280 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingTraceRaysIndirectTestInstance::initBottomAccelerationStructures (VkCommandBuffer cmdBuffer)
281 {
282 const DeviceInterface& vkd = m_context.getDeviceInterface();
283 const VkDevice device = m_context.getDevice();
284 Allocator& allocator = m_context.getDefaultAllocator();
285 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > result;
286
287 tcu::Vec3 v0(0.0, 1.0, 0.0);
288 tcu::Vec3 v1(0.0, 0.0, 0.0);
289 tcu::Vec3 v2(1.0, 1.0, 0.0);
290 tcu::Vec3 v3(1.0, 0.0, 0.0);
291
292 for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
293 for (deUint32 y = 0; y < m_imageExtent.height; ++y)
294 for (deUint32 x = 0; x < m_imageExtent.width; ++x)
295 {
296 // let's build a 3D chessboard of geometries
297 if (((x + y + z) % 2) == 0)
298 continue;
299 tcu::Vec3 xyz((float)x, (float)y, (float)z);
300 std::vector<tcu::Vec3> geometryData;
301
302 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
303 bottomLevelAccelerationStructure->setGeometryCount(1u);
304
305 geometryData.push_back(xyz + v0);
306 geometryData.push_back(xyz + v1);
307 geometryData.push_back(xyz + v2);
308 geometryData.push_back(xyz + v2);
309 geometryData.push_back(xyz + v1);
310 geometryData.push_back(xyz + v3);
311
312 bottomLevelAccelerationStructure->addGeometry(geometryData, true);
313 bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
314 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
315 }
316
317 return result;
318 }
319
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)320 de::MovePtr<TopLevelAccelerationStructure> RayTracingTraceRaysIndirectTestInstance::initTopAccelerationStructure (VkCommandBuffer cmdBuffer,
321 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
322 {
323 const DeviceInterface& vkd = m_context.getDeviceInterface();
324 const VkDevice device = m_context.getDevice();
325 Allocator& allocator = m_context.getDefaultAllocator();
326 const deUint32 instanceCount = m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width / 2;
327
328 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
329 result->setInstanceCount(instanceCount);
330
331 deUint32 currentInstanceIndex = 0;
332
333 for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
334 for (deUint32 y = 0; y < m_imageExtent.height; ++y)
335 for (deUint32 x = 0; x < m_imageExtent.width; ++x)
336 {
337 if (((x + y + z) % 2) == 0)
338 continue;
339 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
340 }
341 result->createAndBuild(vkd, device, cmdBuffer, allocator);
342
343 return result;
344 }
345
runTest()346 de::MovePtr<BufferWithMemory> RayTracingTraceRaysIndirectTestInstance::runTest()
347 {
348 const InstanceInterface& vki = m_context.getInstanceInterface();
349 const DeviceInterface& vkd = m_context.getDeviceInterface();
350 const VkDevice device = m_context.getDevice();
351 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
352 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
353 const VkQueue queue = m_context.getUniversalQueue();
354 Allocator& allocator = m_context.getDefaultAllocator();
355 const deUint32 pixelCount = m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width;
356 const deUint32 shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
357 const deUint32 shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
358
359 Move<VkDescriptorSetLayout> computeDescriptorSetLayout;
360 Move<VkDescriptorPool> computeDescriptorPool;
361 Move<VkDescriptorSet> computeDescriptorSet;
362 Move<VkPipelineLayout> computePipelineLayout;
363 Move<VkShaderModule> computeShader;
364 Move<VkPipeline> computePipeline;
365
366 if (m_data.traceType == TraceType::INDIRECT_GPU)
367 {
368 computeDescriptorSetLayout = DescriptorSetLayoutBuilder()
369 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
370 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
371 .build(vkd, device);
372 computeDescriptorPool = DescriptorPoolBuilder()
373 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
374 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
375 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
376 computeDescriptorSet = makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
377 computePipelineLayout = makePipelineLayout(vkd, device, computeDescriptorSetLayout.get());
378
379 computeShader = createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
380 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
381 {
382 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
383 DE_NULL, // const void* pNext;
384 VkPipelineShaderStageCreateFlags(0u), // VkPipelineShaderStageCreateFlags flags;
385 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
386 *computeShader, // VkShaderModule module;
387 "main", // const char* pName;
388 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
389 };
390 const VkComputePipelineCreateInfo pipelineCreateInfo =
391 {
392 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
393 DE_NULL, // const void* pNext;
394 VkPipelineCreateFlags(0u), // VkPipelineCreateFlags flags;
395 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
396 *computePipelineLayout, // VkPipelineLayout layout;
397 DE_NULL, // VkPipeline basePipelineHandle;
398 0, // deInt32 basePipelineIndex;
399 };
400
401 computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
402 }
403
404 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
405 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
406 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
407 .build(vkd, device);
408 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
409 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
410 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
411 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
412 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
413 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
414
415 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
416 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
417 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
418 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
419 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
420
421 const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
422 const de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
423 const de::MovePtr<BufferWithMemory> missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
424
425 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
426 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
427 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
428 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
429
430 const VkFormat imageFormat = VK_FORMAT_R32_UINT;
431 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, imageFormat);
432 const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
433 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
434 const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
435
436 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(pixelCount*sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
437 const VkImageSubresourceLayers resultBufferImageSubresourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
438 const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(m_imageExtent, resultBufferImageSubresourceLayers);
439 de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
440
441 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
442
443 // create indirect command buffer and fill it with parameter values
444 de::MovePtr<BufferWithMemory> indirectBuffer;
445 de::MovePtr<BufferWithMemory> uniformBuffer;
446
447 if (m_data.traceType != TraceType::DIRECT)
448 {
449 const bool indirectGpu = (m_data.traceType == TraceType::INDIRECT_GPU);
450 VkBufferUsageFlags indirectBufferUsageFlags = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | ( indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT );
451 const VkBufferCreateInfo indirectBufferCreateInfo = makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR), indirectBufferUsageFlags);
452 vk::MemoryRequirement indirectBufferMemoryRequirement = MemoryRequirement::DeviceAddress | ( indirectGpu ? MemoryRequirement::Any : MemoryRequirement::HostVisible );
453 indirectBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
454 }
455
456 if (m_data.traceType == TraceType::INDIRECT_GPU)
457 {
458 const VkBufferCreateInfo uniformBufferCreateInfo = makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
459 uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
460 deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions, sizeof(VkTraceRaysIndirectCommandKHR));
461 flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(), uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
462 }
463 else if (m_data.traceType == TraceType::INDIRECT_CPU)
464 {
465 deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions, sizeof(VkTraceRaysIndirectCommandKHR));
466 flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(), indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
467 }
468
469 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
470 const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
471
472 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelAccelerationStructures;
473 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
474
475 beginCommandBuffer(vkd, *cmdBuffer, 0u);
476 {
477 const VkImageMemoryBarrier preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
478 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
479 **image, imageSubresourceRange);
480 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
481
482 const VkClearValue clearValue = makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
483 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
484
485 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
486 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
487 **image, imageSubresourceRange);
488 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
489
490 bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
491 topLevelAccelerationStructure = initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
492
493 if (m_data.traceType == TraceType::INDIRECT_GPU)
494 {
495 const VkDescriptorBufferInfo uniformBufferDescriptorInfo = makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
496 const VkDescriptorBufferInfo indirectBufferDescriptorInfo = makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
497 DescriptorSetUpdateBuilder()
498 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
499 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
500 .update(vkd, device);
501
502 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
503 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &computeDescriptorSet.get(), 0u, DE_NULL);
504 vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
505
506 const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
507 indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
508 cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
509 }
510
511 const TopLevelAccelerationStructure* topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
512 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
513 {
514 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
515 DE_NULL, // const void* pNext;
516 1u, // deUint32 accelerationStructureCount;
517 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
518 };
519
520 DescriptorSetUpdateBuilder()
521 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
522 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
523 .update(vkd, device);
524
525 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
526
527 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
528
529 // Both calls should give the same results.
530 if (m_data.traceType == TraceType::DIRECT)
531 {
532 cmdTraceRays(vkd,
533 *cmdBuffer,
534 &raygenShaderBindingTableRegion,
535 &missShaderBindingTableRegion,
536 &hitShaderBindingTableRegion,
537 &callableShaderBindingTableRegion,
538 m_data.traceDimensions.width, m_data.traceDimensions.height, m_data.traceDimensions.depth);
539 }
540 else
541 {
542 cmdTraceRaysIndirect(vkd,
543 *cmdBuffer,
544 &raygenShaderBindingTableRegion,
545 &missShaderBindingTableRegion,
546 &hitShaderBindingTableRegion,
547 &callableShaderBindingTableRegion,
548 getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
549 }
550
551 const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
552 const VkMemoryBarrier postCopyMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
553 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
554
555 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
556
557 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
558 }
559 endCommandBuffer(vkd, *cmdBuffer);
560
561 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
562
563 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
564
565 return resultBuffer;
566 }
567
iterate(void)568 tcu::TestStatus RayTracingTraceRaysIndirectTestInstance::iterate (void)
569 {
570 // run test using arrays of pointers
571 const de::MovePtr<BufferWithMemory> buffer = runTest();
572 const deUint32* bufferPtr = (deUint32*)buffer->getAllocation().getHostPtr();
573 const bool noWrites = isNullTrace(m_data.traceDimensions);
574
575 deUint32 failures = 0;
576 deUint32 pos = 0;
577
578 // verify results
579 for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
580 for (deUint32 y = 0; y < m_imageExtent.height; ++y)
581 for (deUint32 x = 0; x < m_imageExtent.width; ++x)
582 {
583 const deUint32 expectedResult = (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
584 if (bufferPtr[pos] != expectedResult)
585 failures++;
586 ++pos;
587 }
588
589 if (failures == 0)
590 return tcu::TestStatus::pass("Pass");
591 else
592 return tcu::TestStatus::fail("Fail (failures=" + de::toString(failures) + ")");
593 }
594
makeDimensionsName(const VkTraceRaysIndirectCommandKHR & cmd)595 std::string makeDimensionsName (const VkTraceRaysIndirectCommandKHR& cmd)
596 {
597 std::ostringstream name;
598 name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
599 return name.str();
600 }
601
602 } // anonymous
603
createTraceRaysTests(tcu::TestContext & testCtx)604 tcu::TestCaseGroup* createTraceRaysTests(tcu::TestContext& testCtx)
605 {
606 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds", "Tests veryfying vkCmdTraceRays* commands"));
607
608 struct BufferSourceTypeData
609 {
610 TraceType traceType;
611 const char* name;
612 } bufferSourceTypes[] =
613 {
614 { TraceType::DIRECT, "direct" },
615 { TraceType::INDIRECT_CPU, "indirect_cpu" },
616 { TraceType::INDIRECT_GPU, "indirect_gpu" },
617 };
618
619 const VkTraceRaysIndirectCommandKHR traceDimensions[] =
620 {
621 { 0, 0, 0 },
622 { 0, 1, 1 },
623 { 1, 0, 1 },
624 { 1, 1, 0 },
625 { 8, 1, 1 },
626 { 8, 8, 1 },
627 { 8, 8, 8 },
628 { 11, 1, 1 },
629 { 11, 13, 1 },
630 { 11, 13, 5 },
631 };
632
633 for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
634 {
635 de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name, ""));
636
637 for (size_t traceDimensionsIdx = 0; traceDimensionsIdx < DE_LENGTH_OF_ARRAY(traceDimensions); ++traceDimensionsIdx)
638 {
639 TestParams testParams
640 {
641 bufferSourceTypes[bufferSourceNdx].traceType,
642 traceDimensions[traceDimensionsIdx],
643 };
644 const auto testName = makeDimensionsName(traceDimensions[traceDimensionsIdx]);
645 bufferSourceGroup->addChild(new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), "", testParams));
646 }
647
648 group->addChild(bufferSourceGroup.release());
649 }
650
651 return group.release();
652 }
653
654 } // RayTracing
655
656 } // vkt
657