xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingNullASTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 Acceleration Structure Null Handle Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingNullASTests.hpp"
25 
26 #include "vkDefs.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vktCustomInstancesDevices.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "vkRayTracingUtil.hpp"
39 
40 #include "tcuCommandLine.hpp"
41 
42 #include "deClock.h"
43 
44 namespace vkt
45 {
46 namespace RayTracing
47 {
48 namespace
49 {
50 using namespace vk;
51 using namespace std;
52 
53 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
54                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
55                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
56 
57 struct CaseDef
58 {
59     uint32_t width;
60     uint32_t height;
61 };
62 
63 enum ShaderGroups
64 {
65     FIRST_GROUP  = 0,
66     RAYGEN_GROUP = FIRST_GROUP,
67     MISS_GROUP,
68     HIT_GROUP,
69     GROUP_COUNT
70 };
71 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)72 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
73 {
74     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
75 
76     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
77     return rayTracingPropertiesKHR->getShaderGroupHandleSize();
78 }
79 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)80 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
81 {
82     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
83 
84     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
85     return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
86 }
87 
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)88 Move<VkPipeline> makePipeline(const DeviceInterface &vkd, const VkDevice device, vk::BinaryCollection &collection,
89                               de::MovePtr<RayTracingPipeline> &rayTracingPipeline, VkPipelineLayout pipelineLayout,
90                               const uint32_t raygenGroup, const uint32_t missGroup, const uint32_t hitGroup)
91 {
92     Move<VkShaderModule> raygenShader       = createShaderModule(vkd, device, collection.get("rgen"), 0);
93     Move<VkShaderModule> hitShader          = createShaderModule(vkd, device, collection.get("ahit"), 0);
94     Move<VkShaderModule> missShader         = createShaderModule(vkd, device, collection.get("miss"), 0);
95     Move<VkShaderModule> intersectionShader = createShaderModule(vkd, device, collection.get("sect"), 0);
96 
97     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, raygenShader, raygenGroup);
98     rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR, hitShader, hitGroup);
99     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missShader, missGroup);
100     rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR, intersectionShader, hitGroup);
101 
102     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
103 
104     return pipeline;
105 }
106 
makeImageCreateInfo(uint32_t width,uint32_t height,VkFormat format)107 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, VkFormat format)
108 {
109     const VkImageUsageFlags usage =
110         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
111     const VkImageCreateInfo imageCreateInfo = {
112         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
113         DE_NULL,                             // const void* pNext;
114         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
115         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
116         format,                              // VkFormat format;
117         makeExtent3D(width, height, 1u),     // VkExtent3D extent;
118         1u,                                  // uint32_t mipLevels;
119         1u,                                  // uint32_t arrayLayers;
120         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
121         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
122         usage,                               // VkImageUsageFlags usage;
123         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
124         0u,                                  // uint32_t queueFamilyIndexCount;
125         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
126         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
127     };
128 
129     return imageCreateInfo;
130 }
131 
132 struct TestDeviceFeatures
133 {
134     VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
135     VkPhysicalDeviceRayTracingPipelineFeaturesKHR rayTracingPipelineFeatures;
136     VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures;
137     VkPhysicalDeviceBufferDeviceAddressFeaturesKHR deviceAddressFeatures;
138     VkPhysicalDeviceFeatures2 deviceFeatures;
139 
linkStructuresvkt::RayTracing::__anone37731020111::TestDeviceFeatures140     void linkStructures()
141     {
142         robustness2Features.pNext           = nullptr;
143         rayTracingPipelineFeatures.pNext    = &robustness2Features;
144         accelerationStructureFeatures.pNext = &rayTracingPipelineFeatures;
145         deviceAddressFeatures.pNext         = &accelerationStructureFeatures;
146         deviceFeatures.pNext                = &deviceAddressFeatures;
147     }
148 
TestDeviceFeaturesvkt::RayTracing::__anone37731020111::TestDeviceFeatures149     TestDeviceFeatures(const InstanceInterface &vki, VkPhysicalDevice physicalDevice)
150     {
151         robustness2Features.sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
152         rayTracingPipelineFeatures.sType    = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
153         accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
154         deviceAddressFeatures.sType         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
155         deviceFeatures.sType                = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
156 
157         linkStructures();
158         vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
159     }
160 };
161 
162 struct DeviceHelper
163 {
164     Move<VkDevice> device;
165     de::MovePtr<DeviceDriver> vkd;
166     uint32_t queueFamilyIndex;
167     VkQueue queue;
168     de::MovePtr<SimpleAllocator> allocator;
169 
DeviceHelpervkt::RayTracing::__anone37731020111::DeviceHelper170     DeviceHelper(Context &context)
171     {
172         const auto &vkp           = context.getPlatformInterface();
173         const auto &vki           = context.getInstanceInterface();
174         const auto instance       = context.getInstance();
175         const auto physicalDevice = context.getPhysicalDevice();
176         const auto queuePriority  = 1.0f;
177 
178         // Queue index first.
179         queueFamilyIndex = context.getUniversalQueueFamilyIndex();
180 
181         // Get device features (these have already been checked in the test case).
182         TestDeviceFeatures features(vki, physicalDevice);
183         features.linkStructures();
184 
185         // Make sure uneeded robustness features are disabled.
186         features.deviceFeatures.features.robustBufferAccess = VK_FALSE;
187         features.robustness2Features.robustBufferAccess2    = VK_FALSE;
188         features.robustness2Features.robustImageAccess2     = VK_FALSE;
189 
190         const VkDeviceQueueCreateInfo queueInfo = {
191             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
192             nullptr,                                    // const void* pNext;
193             0u,                                         // VkDeviceQueueCreateFlags flags;
194             queueFamilyIndex,                           // uint32_t queueFamilyIndex;
195             1u,                                         // uint32_t queueCount;
196             &queuePriority,                             // const float* pQueuePriorities;
197         };
198 
199         // Required extensions.
200         std::vector<const char *> requiredExtensions;
201         requiredExtensions.push_back("VK_KHR_ray_tracing_pipeline");
202         requiredExtensions.push_back("VK_KHR_acceleration_structure");
203         requiredExtensions.push_back("VK_KHR_buffer_device_address");
204         requiredExtensions.push_back("VK_KHR_deferred_host_operations");
205         requiredExtensions.push_back("VK_EXT_descriptor_indexing");
206         requiredExtensions.push_back("VK_KHR_spirv_1_4");
207         requiredExtensions.push_back("VK_KHR_shader_float_controls");
208         requiredExtensions.push_back("VK_EXT_robustness2");
209 
210         const VkDeviceCreateInfo createInfo = {
211             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,             // VkStructureType sType;
212             features.deviceFeatures.pNext,                    // const void* pNext;
213             0u,                                               // VkDeviceCreateFlags flags;
214             1u,                                               // uint32_t queueCreateInfoCount;
215             &queueInfo,                                       // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
216             0u,                                               // uint32_t enabledLayerCount;
217             nullptr,                                          // const char* const* ppEnabledLayerNames;
218             static_cast<uint32_t>(requiredExtensions.size()), // uint32_t enabledExtensionCount;
219             requiredExtensions.data(),                        // const char* const* ppEnabledExtensionNames;
220             &features.deviceFeatures.features,                // const VkPhysicalDeviceFeatures* pEnabledFeatures;
221         };
222 
223         // Create custom device and related objects.
224         device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki,
225                                     physicalDevice, &createInfo);
226         vkd    = de::MovePtr<DeviceDriver>(new DeviceDriver(vkp, instance, device.get(), context.getUsedApiVersion(),
227                                                             context.getTestContext().getCommandLine()));
228         queue  = getDeviceQueue(*vkd, *device, queueFamilyIndex, 0u);
229         allocator = de::MovePtr<SimpleAllocator>(
230             new SimpleAllocator(*vkd, device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
231     }
232 };
233 
234 class RayTracingBuildTestInstance : public TestInstance
235 {
236 public:
237     RayTracingBuildTestInstance(Context &context, const CaseDef &data);
238     ~RayTracingBuildTestInstance(void);
239     tcu::TestStatus iterate(void);
240 
241 protected:
242     uint32_t validateBuffer(de::MovePtr<BufferWithMemory> buffer);
243     de::MovePtr<BufferWithMemory> runTest(DeviceHelper &deviceHelper);
244 
245 private:
246     CaseDef m_data;
247 };
248 
RayTracingBuildTestInstance(Context & context,const CaseDef & data)249 RayTracingBuildTestInstance::RayTracingBuildTestInstance(Context &context, const CaseDef &data)
250     : vkt::TestInstance(context)
251     , m_data(data)
252 {
253 }
254 
~RayTracingBuildTestInstance(void)255 RayTracingBuildTestInstance::~RayTracingBuildTestInstance(void)
256 {
257 }
258 
259 class RayTracingTestCase : public TestCase
260 {
261 public:
262     RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
263     ~RayTracingTestCase(void);
264 
265     virtual void initPrograms(SourceCollections &programCollection) const;
266     virtual TestInstance *createInstance(Context &context) const;
267     virtual void checkSupport(Context &context) const;
268 
269 private:
270     CaseDef m_data;
271 };
272 
RayTracingTestCase(tcu::TestContext & context,const char * name,const CaseDef data)273 RayTracingTestCase::RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
274     : vkt::TestCase(context, name)
275     , m_data(data)
276 {
277 }
278 
~RayTracingTestCase(void)279 RayTracingTestCase::~RayTracingTestCase(void)
280 {
281 }
282 
checkSupport(Context & context) const283 void RayTracingTestCase::checkSupport(Context &context) const
284 {
285     const auto &vki           = context.getInstanceInterface();
286     const auto physicalDevice = context.getPhysicalDevice();
287 
288     if (!context.isDeviceFunctionalitySupported("VK_KHR_ray_tracing_pipeline"))
289         TCU_THROW(NotSupportedError, "VK_KHR_ray_tracing_pipeline not supported");
290 
291     // VK_KHR_acceleration_structure is required by VK_KHR_ray_tracing_pipeline.
292     if (!context.isDeviceFunctionalitySupported("VK_KHR_acceleration_structure"))
293         TCU_FAIL("VK_KHR_acceleration_structure not supported but VK_KHR_ray_tracing_pipeline supported");
294 
295     // VK_KHR_deferred_host_operations is required by VK_KHR_ray_tracing_pipeline.
296     if (!context.isDeviceFunctionalitySupported("VK_KHR_deferred_host_operations"))
297         TCU_FAIL("VK_KHR_deferred_host_operations not supported but VK_KHR_ray_tracing_pipeline supported");
298 
299     // VK_KHR_buffer_device_address is required by VK_KHR_acceleration_structure.
300     if (!context.isDeviceFunctionalitySupported("VK_KHR_buffer_device_address"))
301         TCU_FAIL("VK_KHR_buffer_device_address not supported but VK_KHR_acceleration_structure supported");
302 
303     if (!context.isDeviceFunctionalitySupported("VK_EXT_robustness2"))
304         TCU_THROW(NotSupportedError, "VK_EXT_robustness2 not supported");
305 
306     // Required extensions supported: check features.
307     TestDeviceFeatures testFeatures(vki, physicalDevice);
308 
309     if (!testFeatures.rayTracingPipelineFeatures.rayTracingPipeline)
310         TCU_THROW(NotSupportedError, "Ray tracing pipelines not supported");
311 
312     if (!testFeatures.robustness2Features.nullDescriptor)
313         TCU_THROW(NotSupportedError, "Null descriptors not supported");
314 }
315 
initPrograms(SourceCollections & programCollection) const316 void RayTracingTestCase::initPrograms(SourceCollections &programCollection) const
317 {
318     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
319 
320     programCollection.glslSources.add("rgen")
321         << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
322 
323     {
324         std::stringstream css;
325         css << "#version 460 core\n"
326                "#extension GL_EXT_nonuniform_qualifier : enable\n"
327                "#extension GL_EXT_ray_tracing : require\n"
328                "layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
329                "hitAttributeEXT vec3 hitAttribute;\n"
330                "void main()\n"
331                "{\n"
332                "  reportIntersectionEXT(1.0f, 0);\n"
333                "  uvec4 color = uvec4(1,0,0,1);\n"
334                "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), color);\n"
335                "}\n";
336 
337         programCollection.glslSources.add("sect")
338             << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
339     }
340 
341     {
342         std::stringstream css;
343         css << "#version 460 core\n"
344                "#extension GL_EXT_nonuniform_qualifier : enable\n"
345                "#extension GL_EXT_ray_tracing : require\n"
346                "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
347                "hitAttributeEXT vec3 attribs;\n"
348                "layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
349                "void main()\n"
350                "{\n"
351                "  uvec4 color = uvec4(2,0,0,1);\n"
352                "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), color);\n"
353                "}\n";
354 
355         programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
356     }
357 
358     {
359         std::stringstream css;
360         css << "#version 460 core\n"
361                "#extension GL_EXT_nonuniform_qualifier : enable\n"
362                "#extension GL_EXT_ray_tracing : require\n"
363                "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
364                "hitAttributeEXT vec3 attribs;\n"
365                "layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
366                "void main()\n"
367                "{\n"
368                "  uvec4 color = uvec4(3,0,0,1);\n"
369                "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), color);\n"
370                "}\n";
371 
372         programCollection.glslSources.add("chit")
373             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
374     }
375 
376     {
377         std::stringstream css;
378         css << "#version 460 core\n"
379                "#extension GL_EXT_nonuniform_qualifier : enable\n"
380                "#extension GL_EXT_ray_tracing : require\n"
381                "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
382                "layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
383                "void main()\n"
384                "{\n"
385                "  uvec4 color = uvec4(4,0,0,1);\n"
386                "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), color);\n"
387                "}\n";
388 
389         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
390     }
391 }
392 
createInstance(Context & context) const393 TestInstance *RayTracingTestCase::createInstance(Context &context) const
394 {
395     return new RayTracingBuildTestInstance(context, m_data);
396 }
397 
runTest(DeviceHelper & deviceHelper)398 de::MovePtr<BufferWithMemory> RayTracingBuildTestInstance::runTest(DeviceHelper &deviceHelper)
399 {
400     const InstanceInterface &vki            = m_context.getInstanceInterface();
401     const VkPhysicalDevice physicalDevice   = m_context.getPhysicalDevice();
402     const DeviceDriver &vkd                 = *deviceHelper.vkd;
403     const VkDevice device                   = *deviceHelper.device;
404     const uint32_t queueFamilyIndex         = deviceHelper.queueFamilyIndex;
405     const VkQueue queue                     = deviceHelper.queue;
406     SimpleAllocator &allocator              = *deviceHelper.allocator;
407     const VkFormat format                   = VK_FORMAT_R32_UINT;
408     const uint32_t pixelCount               = m_data.width * m_data.height;
409     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
410     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
411 
412     const Move<VkDescriptorSetLayout> descriptorSetLayout =
413         DescriptorSetLayoutBuilder()
414             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
415             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
416             .build(vkd, device);
417     const Move<VkDescriptorPool> descriptorPool =
418         DescriptorPoolBuilder()
419             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
420             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
421             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
422     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
423     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
424     const Move<VkCommandPool> cmdPool           = createCommandPool(vkd, device, 0, queueFamilyIndex);
425     const Move<VkCommandBuffer> cmdBuffer =
426         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
427 
428     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
429     const Move<VkPipeline> pipeline = makePipeline(vkd, device, m_context.getBinaryCollection(), rayTracingPipeline,
430                                                    *pipelineLayout, RAYGEN_GROUP, MISS_GROUP, HIT_GROUP);
431     const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
432         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, RAYGEN_GROUP, 1u);
433     const de::MovePtr<BufferWithMemory> missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
434         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, MISS_GROUP, 1u);
435     const de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
436         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, HIT_GROUP, 1u);
437 
438     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
439         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
440                                           shaderGroupHandleSize, shaderGroupHandleSize);
441     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
442         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
443                                           shaderGroupHandleSize, shaderGroupHandleSize);
444     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
445         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
446                                           shaderGroupHandleSize, shaderGroupHandleSize);
447     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
448         makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
449 
450     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, format);
451     const VkImageSubresourceRange imageSubresourceRange =
452         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
453     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
454         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
455     const Move<VkImageView> imageView =
456         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
457 
458     const VkBufferCreateInfo bufferCreateInfo =
459         makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
460     const VkImageSubresourceLayers bufferImageSubresourceLayers =
461         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
462     const VkBufferImageCopy bufferImageRegion =
463         makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), bufferImageSubresourceLayers);
464     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
465         new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
466 
467     const VkDescriptorImageInfo descriptorImageInfo =
468         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
469 
470     const VkImageMemoryBarrier preImageBarrier =
471         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
472                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
473     const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
474         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
475         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
476     const VkMemoryBarrier postTraceMemoryBarrier =
477         makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
478     const VkMemoryBarrier postCopyMemoryBarrier =
479         makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
480     const VkClearValue clearValue                                  = makeClearValueColorU32(5u, 5u, 5u, 255u);
481     const VkAccelerationStructureKHR topLevelAccelerationStructure = DE_NULL;
482 
483     beginCommandBuffer(vkd, *cmdBuffer, 0u);
484     {
485         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
486                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
487         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
488                                &imageSubresourceRange);
489         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
490                                       VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &postImageBarrier);
491 
492         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
493             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
494             DE_NULL,                                                           //  const void* pNext;
495             1u,                                                                //  uint32_t accelerationStructureCount;
496             &topLevelAccelerationStructure, //  const VkAccelerationStructureKHR* pAccelerationStructures;
497         };
498 
499         DescriptorSetUpdateBuilder()
500             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
501                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
502             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
503                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
504             .update(vkd, device);
505 
506         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
507                                   &descriptorSet.get(), 0, DE_NULL);
508 
509         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
510 
511         cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
512                      &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
513 
514         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
515                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
516 
517         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
518 
519         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
520                                  &postCopyMemoryBarrier);
521     }
522     endCommandBuffer(vkd, *cmdBuffer);
523 
524     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
525 
526     invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
527                                 pixelCount * sizeof(uint32_t));
528 
529     return buffer;
530 }
531 
validateBuffer(de::MovePtr<BufferWithMemory> buffer)532 uint32_t RayTracingBuildTestInstance::validateBuffer(de::MovePtr<BufferWithMemory> buffer)
533 {
534     const uint32_t *bufferPtr    = (uint32_t *)buffer->getAllocation().getHostPtr();
535     const uint32_t expectedValue = 4;
536     uint32_t failures            = 0;
537     uint32_t pos                 = 0;
538 
539     for (uint32_t y = 0; y < m_data.height; ++y)
540         for (uint32_t x = 0; x < m_data.width; ++x)
541         {
542             if (bufferPtr[pos] != expectedValue)
543                 failures++;
544 
545             ++pos;
546         }
547 
548     return failures;
549 }
550 
iterate(void)551 tcu::TestStatus RayTracingBuildTestInstance::iterate(void)
552 {
553     DeviceHelper deviceHelper(m_context);
554     de::MovePtr<BufferWithMemory> buffer = runTest(deviceHelper);
555     const uint32_t failures              = validateBuffer(buffer);
556 
557     if (failures == 0)
558         return tcu::TestStatus::pass("Pass");
559     else
560         return tcu::TestStatus::fail("failures=" + de::toString(failures));
561 }
562 
563 } // namespace
564 
createNullAccelerationStructureTests(tcu::TestContext & testCtx)565 tcu::TestCaseGroup *createNullAccelerationStructureTests(tcu::TestContext &testCtx)
566 {
567     // Null Acceleration Structure is accepted as 'always miss' case
568     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "null_as"));
569 
570     const CaseDef caseDef = {
571         8, //  uint32_t width;
572         8, //  uint32_t height;
573     };
574     group->addChild(new RayTracingTestCase(testCtx, "test", caseDef));
575 
576     return group.release();
577 }
578 
579 } // namespace RayTracing
580 } // namespace vkt
581