1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 NVIDIA Corporation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Ray Query Opacity Micromap Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktRayQueryOpacityMicromapTests.hpp"
26 #include "vktTestCase.hpp"
27
28 #include "vkRayTracingUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36
37 #include "deUniquePtr.hpp"
38 #include "deRandom.hpp"
39
40 #include <sstream>
41 #include <vector>
42 #include <iostream>
43
44 namespace vkt
45 {
46 namespace RayQuery
47 {
48
49 namespace
50 {
51
52 using namespace vk;
53
54 enum ShaderSourcePipeline
55 {
56 SSP_GRAPHICS_PIPELINE,
57 SSP_COMPUTE_PIPELINE,
58 SSP_RAY_TRACING_PIPELINE
59 };
60
61 enum ShaderSourceType
62 {
63 SST_VERTEX_SHADER,
64 SST_COMPUTE_SHADER,
65 SST_RAY_GENERATION_SHADER,
66 };
67
68 enum TestFlagBits
69 {
70 TEST_FLAG_BIT_FORCE_OPAQUE_INSTANCE = 1U << 0,
71 TEST_FLAG_BIT_FORCE_OPAQUE_RAY_FLAG = 1U << 1,
72 TEST_FLAG_BIT_DISABLE_OPACITY_MICROMAP_INSTANCE = 1U << 2,
73 TEST_FLAG_BIT_FORCE_2_STATE_INSTANCE = 1U << 3,
74 TEST_FLAG_BIT_FORCE_2_STATE_RAY_FLAG = 1U << 4,
75 TEST_FLAG_BIT_LAST = 1U << 5,
76 };
77
78 std::vector<std::string> testFlagBitNames = {
79 "force_opaque_instance", "force_opaque_ray_flag", "disable_opacity_micromap_instance",
80 "force_2_state_instance", "force_2_state_ray_flag",
81 };
82
83 enum CopyType
84 {
85 CT_NONE,
86 CT_FIRST_ACTIVE,
87 CT_CLONE = CT_FIRST_ACTIVE,
88 CT_COMPACT,
89 CT_NUM_COPY_TYPES,
90 };
91
92 std::vector<std::string> copyTypeNames{
93 "None",
94 "Clone",
95 "Compact",
96 };
97
98 struct TestParams
99 {
100 ShaderSourceType shaderSourceType;
101 ShaderSourcePipeline shaderSourcePipeline;
102 bool useSpecialIndex;
103 uint32_t testFlagMask;
104 uint32_t subdivisionLevel; // Must be 0 for useSpecialIndex
105 uint32_t mode; // Special index value if useSpecialIndex, 2 or 4 for number of states otherwise
106 uint32_t seed;
107 CopyType copyType;
108 bool useMaintenance5;
109 };
110
111 static constexpr uint32_t kNumThreadsAtOnce = 1024;
112 static constexpr uint32_t kWorkGroupCount = 8;
113 static constexpr uint32_t kLocalSize = 128;
114 DE_STATIC_ASSERT(kWorkGroupCount *kLocalSize == kNumThreadsAtOnce);
115
116 class OpacityMicromapCase : public TestCase
117 {
118 public:
119 OpacityMicromapCase(tcu::TestContext &testCtx, const std::string &name, const TestParams ¶ms);
~OpacityMicromapCase(void)120 virtual ~OpacityMicromapCase(void)
121 {
122 }
123
124 virtual void checkSupport(Context &context) const;
125 virtual void initPrograms(vk::SourceCollections &programCollection) const;
126 virtual TestInstance *createInstance(Context &context) const;
127
128 protected:
129 TestParams m_params;
130 };
131
132 class OpacityMicromapInstance : public TestInstance
133 {
134 public:
135 OpacityMicromapInstance(Context &context, const TestParams ¶ms);
~OpacityMicromapInstance(void)136 virtual ~OpacityMicromapInstance(void)
137 {
138 }
139
140 virtual tcu::TestStatus iterate(void);
141
142 protected:
143 TestParams m_params;
144 };
145
OpacityMicromapCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)146 OpacityMicromapCase::OpacityMicromapCase(tcu::TestContext &testCtx, const std::string &name, const TestParams ¶ms)
147 : TestCase(testCtx, name)
148 , m_params(params)
149 {
150 }
151
checkSupport(Context & context) const152 void OpacityMicromapCase::checkSupport(Context &context) const
153 {
154 context.requireDeviceFunctionality("VK_KHR_ray_query");
155 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
156 context.requireDeviceFunctionality("VK_EXT_opacity_micromap");
157
158 if (m_params.useMaintenance5)
159 context.requireDeviceFunctionality("VK_KHR_maintenance5");
160
161 const VkPhysicalDeviceRayQueryFeaturesKHR &rayQueryFeaturesKHR = context.getRayQueryFeatures();
162 if (rayQueryFeaturesKHR.rayQuery == false)
163 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
164
165 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
166 context.getAccelerationStructureFeatures();
167 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
168 TCU_THROW(TestError,
169 "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
170
171 const VkPhysicalDeviceOpacityMicromapFeaturesEXT &opacityMicromapFeaturesEXT =
172 context.getOpacityMicromapFeaturesEXT();
173 if (opacityMicromapFeaturesEXT.micromap == false)
174 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceOpacityMicromapFeaturesEXT.micromap");
175
176 if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
177 {
178 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
179
180 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
181 context.getRayTracingPipelineFeatures();
182
183 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
184 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
185 }
186
187 switch (m_params.shaderSourceType)
188 {
189 case SST_VERTEX_SHADER:
190 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
191 break;
192 default:
193 break;
194 }
195
196 const VkPhysicalDeviceOpacityMicromapPropertiesEXT &opacityMicromapPropertiesEXT =
197 context.getOpacityMicromapPropertiesEXT();
198
199 if (!m_params.useSpecialIndex)
200 {
201 switch (m_params.mode)
202 {
203 case 2:
204 if (m_params.subdivisionLevel > opacityMicromapPropertiesEXT.maxOpacity2StateSubdivisionLevel)
205 TCU_THROW(NotSupportedError, "Requires a higher supported 2 state subdivision level");
206 break;
207 case 4:
208 if (m_params.subdivisionLevel > opacityMicromapPropertiesEXT.maxOpacity4StateSubdivisionLevel)
209 TCU_THROW(NotSupportedError, "Requires a higher supported 4 state subdivision level");
210 break;
211 default:
212 DE_ASSERT(false);
213 break;
214 }
215 }
216 }
217
levelToSubtriangles(uint32_t level)218 static uint32_t levelToSubtriangles(uint32_t level)
219 {
220 return 1 << (2 * level);
221 }
222
initPrograms(vk::SourceCollections & programCollection) const223 void OpacityMicromapCase::initPrograms(vk::SourceCollections &programCollection) const
224 {
225 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
226
227 uint32_t numRays = levelToSubtriangles(m_params.subdivisionLevel);
228
229 std::string flagsString =
230 (m_params.testFlagMask & TEST_FLAG_BIT_FORCE_OPAQUE_RAY_FLAG) ? "gl_RayFlagsOpaqueEXT" : "gl_RayFlagsNoneEXT";
231
232 if (m_params.testFlagMask & TEST_FLAG_BIT_FORCE_2_STATE_RAY_FLAG)
233 flagsString += " | gl_RayFlagsForceOpacityMicromap2StateEXT";
234
235 std::ostringstream sharedHeader;
236 sharedHeader << "#version 460 core\n"
237 << "#extension GL_EXT_ray_query : require\n"
238 << "#extension GL_EXT_opacity_micromap : require\n"
239 << "\n"
240 << "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
241 << "layout(set=0, binding=1, std430) buffer RayOrigins {\n"
242 << " vec4 values[" << numRays << "];\n"
243 << "} origins;\n"
244 << "layout(set=0, binding=2, std430) buffer OutputModes {\n"
245 << " uint values[" << numRays << "];\n"
246 << "} modes;\n";
247
248 std::ostringstream mainLoop;
249 mainLoop
250 << " while (index < " << numRays << ") {\n"
251 << " const uint cullMask = 0xFF;\n"
252 << " const vec3 origin = origins.values[index].xyz;\n"
253 << " const vec3 direction = vec3(0.0, 0.0, -1.0);\n"
254 << " const float tMin = 0.0f;\n"
255 << " const float tMax = 2.0f;\n"
256 << " uint outputVal = 0;\n" // 0 for miss, 1 for non-opaque, 2 for opaque
257 << " rayQueryEXT rq;\n"
258 << " rayQueryInitializeEXT(rq, topLevelAS, " << flagsString
259 << ", cullMask, origin, tMin, direction, tMax);\n"
260 << " while (rayQueryProceedEXT(rq)) {\n"
261 << " if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT) {\n"
262 << " outputVal = 1;\n"
263 << " }\n"
264 << " }\n"
265 << " if (rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT) {\n"
266 << " outputVal = 2;\n"
267 << " }\n"
268 << " modes.values[index] = outputVal;\n"
269 << " index += " << kNumThreadsAtOnce << ";\n"
270 << " }\n";
271
272 if (m_params.shaderSourceType == SST_VERTEX_SHADER)
273 {
274 std::ostringstream vert;
275 vert << sharedHeader.str() << "void main()\n"
276 << "{\n"
277 << " uint index = gl_VertexIndex.x;\n"
278 << mainLoop.str() << " gl_PointSize = 1.0f;\n"
279 << "}\n";
280
281 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str()) << buildOptions;
282 }
283 else if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
284 {
285 std::ostringstream rgen;
286 rgen << sharedHeader.str() << "#extension GL_EXT_ray_tracing : require\n"
287 << "void main()\n"
288 << "{\n"
289 << " uint index = gl_LaunchIDEXT.x;\n"
290 << mainLoop.str() << "}\n";
291
292 programCollection.glslSources.add("rgen")
293 << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
294 }
295 else
296 {
297 DE_ASSERT(m_params.shaderSourceType == SST_COMPUTE_SHADER);
298 std::ostringstream comp;
299 comp << sharedHeader.str() << "layout(local_size_x=" << kLocalSize << ", local_size_y=1, local_size_z=1) in;\n"
300 << "\n"
301 << "void main()\n"
302 << "{\n"
303 << " uint index = gl_GlobalInvocationID.x;\n"
304 << mainLoop.str() << "}\n";
305
306 programCollection.glslSources.add("comp")
307 << glu::ComputeSource(updateRayTracingGLSL(comp.str())) << buildOptions;
308 }
309 }
310
createInstance(Context & context) const311 TestInstance *OpacityMicromapCase::createInstance(Context &context) const
312 {
313 return new OpacityMicromapInstance(context, m_params);
314 }
315
OpacityMicromapInstance(Context & context,const TestParams & params)316 OpacityMicromapInstance::OpacityMicromapInstance(Context &context, const TestParams ¶ms)
317 : TestInstance(context)
318 , m_params(params)
319 {
320 }
321
calcSubtriangleCentroid(const uint32_t index,const uint32_t subdivisionLevel)322 tcu::Vec2 calcSubtriangleCentroid(const uint32_t index, const uint32_t subdivisionLevel)
323 {
324 if (subdivisionLevel == 0)
325 {
326 return tcu::Vec2(1.0f / 3.0f, 1.0f / 3.0f);
327 }
328
329 uint32_t d = index;
330
331 d = ((d >> 1) & 0x22222222u) | ((d << 1) & 0x44444444u) | (d & 0x99999999u);
332 d = ((d >> 2) & 0x0c0c0c0cu) | ((d << 2) & 0x30303030u) | (d & 0xc3c3c3c3u);
333 d = ((d >> 4) & 0x00f000f0u) | ((d << 4) & 0x0f000f00u) | (d & 0xf00ff00fu);
334 d = ((d >> 8) & 0x0000ff00u) | ((d << 8) & 0x00ff0000u) | (d & 0xff0000ffu);
335
336 uint32_t f = (d & 0xffffu) | ((d << 16) & ~d);
337
338 f ^= (f >> 1) & 0x7fff7fffu;
339 f ^= (f >> 2) & 0x3fff3fffu;
340 f ^= (f >> 4) & 0x0fff0fffu;
341 f ^= (f >> 8) & 0x00ff00ffu;
342
343 uint32_t t = (f ^ d) >> 16;
344
345 uint32_t iu = ((f & ~t) | (d & ~t) | (~d & ~f & t)) & 0xffffu;
346 uint32_t iv = ((f >> 16) ^ d) & 0xffffu;
347 uint32_t iw = ((~f & ~t) | (d & ~t) | (~d & f & t)) & ((1 << subdivisionLevel) - 1);
348
349 const float scale = 1.0f / float(1 << subdivisionLevel);
350
351 float u = (1.0f / 3.0f) * scale;
352 float v = (1.0f / 3.0f) * scale;
353
354 // we need to only look at "subdivisionLevel" bits
355 iu = iu & ((1 << subdivisionLevel) - 1);
356 iv = iv & ((1 << subdivisionLevel) - 1);
357 iw = iw & ((1 << subdivisionLevel) - 1);
358
359 bool upright = (iu & 1) ^ (iv & 1) ^ (iw & 1);
360 if (!upright)
361 {
362 iu = iu + 1;
363 iv = iv + 1;
364 }
365
366 if (upright)
367 {
368 return tcu::Vec2(u + (float)iu * scale, v + (float)iv * scale);
369 }
370 else
371 {
372 return tcu::Vec2((float)iu * scale - u, (float)iv * scale - v);
373 }
374 }
375
makeEmptyRenderPass(const DeviceInterface & vk,const VkDevice device)376 static Move<VkRenderPass> makeEmptyRenderPass(const DeviceInterface &vk, const VkDevice device)
377 {
378 std::vector<VkSubpassDescription> subpassDescriptions;
379 std::vector<VkSubpassDependency> subpassDependencies;
380
381 const VkSubpassDescription description = {
382 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
383 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
384 0u, // uint32_t inputAttachmentCount;
385 DE_NULL, // const VkAttachmentReference* pInputAttachments;
386 0u, // uint32_t colorAttachmentCount;
387 DE_NULL, // const VkAttachmentReference* pColorAttachments;
388 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
389 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
390 0, // uint32_t preserveAttachmentCount;
391 DE_NULL // const uint32_t* pPreserveAttachments;
392 };
393 subpassDescriptions.push_back(description);
394
395 const VkSubpassDependency dependency = {
396 0u, // uint32_t srcSubpass;
397 0u, // uint32_t dstSubpass;
398 VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, // VkPipelineStageFlags srcStageMask;
399 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags dstStageMask;
400 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
401 VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask;
402 0u // VkDependencyFlags dependencyFlags;
403 };
404 subpassDependencies.push_back(dependency);
405
406 const VkRenderPassCreateInfo renderPassInfo = {
407 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
408 DE_NULL, // const void* pNext;
409 static_cast<VkRenderPassCreateFlags>(0u), // VkRenderPassCreateFlags flags;
410 0u, // uint32_t attachmentCount;
411 DE_NULL, // const VkAttachmentDescription* pAttachments;
412 static_cast<uint32_t>(subpassDescriptions.size()), // uint32_t subpassCount;
413 &subpassDescriptions[0], // const VkSubpassDescription* pSubpasses;
414 static_cast<uint32_t>(subpassDependencies.size()), // uint32_t dependencyCount;
415 subpassDependencies.size() > 0 ? &subpassDependencies[0] : DE_NULL // const VkSubpassDependency* pDependencies;
416 };
417
418 return createRenderPass(vk, device, &renderPassInfo);
419 }
420
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const uint32_t subpass)421 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
422 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
423 const VkShaderModule vertexModule, const uint32_t subpass)
424 {
425 VkExtent2D renderSize{256, 256};
426 VkViewport viewport = makeViewport(renderSize);
427 VkRect2D scissor = makeRect2D(renderSize);
428
429 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
430 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
431 DE_NULL, // const void* pNext
432 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
433 1u, // uint32_t viewportCount
434 &viewport, // const VkViewport* pViewports
435 1u, // uint32_t scissorCount
436 &scissor // const VkRect2D* pScissors
437 };
438
439 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
440 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
441 DE_NULL, // const void* pNext
442 0u, // VkPipelineInputAssemblyStateCreateFlags flags
443 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology
444 VK_FALSE // VkBool32 primitiveRestartEnable
445 };
446
447 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
448 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
449 DE_NULL, // const void* pNext
450 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
451 0u, // uint32_t vertexBindingDescriptionCount
452 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
453 0u, // uint32_t vertexAttributeDescriptionCount
454 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
455 };
456
457 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
458 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
459 DE_NULL, // const void* pNext
460 0u, // VkPipelineRasterizationStateCreateFlags flags
461 VK_FALSE, // VkBool32 depthClampEnable
462 VK_TRUE, // VkBool32 rasterizerDiscardEnable
463 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
464 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
465 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
466 VK_FALSE, // VkBool32 depthBiasEnable
467 0.0f, // float depthBiasConstantFactor
468 0.0f, // float depthBiasClamp
469 0.0f, // float depthBiasSlopeFactor
470 1.0f // float lineWidth
471 };
472
473 return makeGraphicsPipeline(
474 vk, // const DeviceInterface& vk
475 device, // const VkDevice device
476 pipelineLayout, // const VkPipelineLayout pipelineLayout
477 vertexModule, // const VkShaderModule vertexShaderModule
478 DE_NULL, // const VkShaderModule tessellationControlModule
479 DE_NULL, // const VkShaderModule tessellationEvalModule
480 DE_NULL, // const VkShaderModule geometryShaderModule
481 DE_NULL, // const VkShaderModule fragmentShaderModule
482 renderPass, // const VkRenderPass renderPass
483 subpass, // const uint32_t subpass
484 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
485 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* inputAssemblyStateCreateInfo
486 DE_NULL, // const VkPipelineTessellationStateCreateInfo* tessStateCreateInfo
487 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* viewportStateCreateInfo
488 &rasterizationStateCreateInfo); // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
489 }
490
iterate(void)491 tcu::TestStatus OpacityMicromapInstance::iterate(void)
492 {
493 const auto &vkd = m_context.getDeviceInterface();
494 const auto device = m_context.getDevice();
495 auto &alloc = m_context.getDefaultAllocator();
496 const auto qIndex = m_context.getUniversalQueueFamilyIndex();
497 const auto queue = m_context.getUniversalQueue();
498
499 // Command pool and buffer.
500 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
501 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
502 const auto cmdBuffer = cmdBufferPtr.get();
503
504 beginCommandBuffer(vkd, cmdBuffer);
505
506 // Build acceleration structures.
507 auto topLevelAS = makeTopLevelAccelerationStructure();
508 auto bottomLevelAS = makeBottomLevelAccelerationStructure();
509
510 uint32_t numSubtriangles = levelToSubtriangles(m_params.subdivisionLevel);
511 uint32_t opacityMicromapBytes = (m_params.mode == 2) ? (numSubtriangles + 3) / 4 : (numSubtriangles + 1) / 2;
512
513 // Generate random micromap data
514 std::vector<uint8_t> opacityMicromapData;
515
516 de::Random rnd(m_params.seed);
517
518 while (opacityMicromapData.size() < opacityMicromapBytes)
519 {
520 opacityMicromapData.push_back(rnd.getUint8());
521 }
522
523 // Build a micromap (ignore infrastructure for now)
524 // Create the buffer with the mask and index data
525 // Allocate a fairly conservative bound for now
526 VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = initVulkanStructure();
527 ;
528 const auto micromapDataBufferSize = static_cast<VkDeviceSize>(1024 + opacityMicromapBytes);
529 auto micromapDataBufferCreateInfo =
530 makeBufferCreateInfo(micromapDataBufferSize, VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT |
531 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
532 if (m_params.useMaintenance5)
533 {
534 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)micromapDataBufferCreateInfo.usage;
535 micromapDataBufferCreateInfo.pNext = &bufferUsageFlags2;
536 micromapDataBufferCreateInfo.usage = 0;
537 }
538
539 BufferWithMemory micromapDataBuffer(vkd, device, alloc, micromapDataBufferCreateInfo,
540 MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress);
541 auto µmapDataBufferAlloc = micromapDataBuffer.getAllocation();
542 void *micromapDataBufferData = micromapDataBufferAlloc.getHostPtr();
543
544 const int TriangleOffset = 0;
545 const int IndexOffset = 256;
546 const int DataOffset = 512;
547
548 // Fill out VkMicromapUsageEXT with size information
549 VkMicromapUsageEXT mmUsage = {};
550 mmUsage.count = 1;
551 mmUsage.subdivisionLevel = m_params.subdivisionLevel;
552 mmUsage.format =
553 m_params.mode == 2 ? VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT : VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT;
554
555 {
556 uint8_t *data = static_cast<uint8_t *>(micromapDataBufferData);
557
558 deMemset(data, 0, size_t(micromapDataBufferCreateInfo.size));
559
560 DE_STATIC_ASSERT(sizeof(VkMicromapTriangleEXT) == 8);
561
562 // Triangle information
563 VkMicromapTriangleEXT *tri = (VkMicromapTriangleEXT *)(&data[TriangleOffset]);
564 tri->dataOffset = 0;
565 tri->subdivisionLevel = uint16_t(mmUsage.subdivisionLevel);
566 tri->format = uint16_t(mmUsage.format);
567
568 // Micromap data
569 {
570 for (size_t i = 0; i < opacityMicromapData.size(); i++)
571 {
572 data[DataOffset + i] = opacityMicromapData[i];
573 }
574 }
575
576 // Index information
577 *((uint32_t *)&data[IndexOffset]) = m_params.useSpecialIndex ? m_params.mode : 0;
578 }
579
580 // Query the size from the build info
581 VkMicromapBuildInfoEXT mmBuildInfo = {
582 VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT, // VkStructureType sType;
583 DE_NULL, // const void* pNext;
584 VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT, // VkMicromapTypeEXT type;
585 0, // VkBuildMicromapFlagsEXT flags;
586 VK_BUILD_MICROMAP_MODE_BUILD_EXT, // VkBuildMicromapModeEXT mode;
587 DE_NULL, // VkMicromapEXT dstMicromap;
588 1, // uint32_t usageCountsCount;
589 &mmUsage, // const VkMicromapUsageEXT* pUsageCounts;
590 DE_NULL, // const VkMicromapUsageEXT* const* ppUsageCounts;
591 makeDeviceOrHostAddressConstKHR(DE_NULL), // VkDeviceOrHostAddressConstKHR data;
592 makeDeviceOrHostAddressKHR(DE_NULL), // VkDeviceOrHostAddressKHR scratchData;
593 makeDeviceOrHostAddressConstKHR(DE_NULL), // VkDeviceOrHostAddressConstKHR triangleArray;
594 0, // VkDeviceSize triangleArrayStride;
595 };
596
597 VkMicromapBuildSizesInfoEXT sizeInfo = {
598 VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 0, // VkDeviceSize micromapSize;
601 0, // VkDeviceSize buildScratchSize;
602 false, // VkBool32 discardable;
603 };
604
605 vkd.getMicromapBuildSizesEXT(device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &mmBuildInfo, &sizeInfo);
606
607 // Create the backing and scratch storage
608 const auto micromapBackingBufferCreateInfo = makeBufferCreateInfo(
609 sizeInfo.micromapSize, VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
610 BufferWithMemory micromapBackingBuffer(vkd, device, alloc, micromapBackingBufferCreateInfo,
611 MemoryRequirement::Local | MemoryRequirement::DeviceAddress);
612
613 auto micromapScratchBufferCreateInfo =
614 makeBufferCreateInfo(sizeInfo.buildScratchSize,
615 VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
616 if (m_params.useMaintenance5)
617 {
618 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)micromapScratchBufferCreateInfo.usage;
619 micromapScratchBufferCreateInfo.pNext = &bufferUsageFlags2;
620 micromapScratchBufferCreateInfo.usage = 0;
621 }
622 BufferWithMemory micromapScratchBuffer(vkd, device, alloc, micromapScratchBufferCreateInfo,
623 MemoryRequirement::Local | MemoryRequirement::DeviceAddress);
624
625 de::MovePtr<BufferWithMemory> copyMicromapBackingBuffer;
626
627 // Create the micromap itself
628 VkMicromapCreateInfoEXT maCreateInfo = {
629 VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT, // VkStructureType sType;
630 DE_NULL, // const void* pNext;
631 0, // VkMicromapCreateFlagsEXT createFlags;
632 micromapBackingBuffer.get(), // VkBuffer buffer;
633 0, // VkDeviceSize offset;
634 sizeInfo.micromapSize, // VkDeviceSize size;
635 VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT, // VkMicromapTypeEXT type;
636 0ull // VkDeviceAddress deviceAddress;
637 };
638
639 VkMicromapEXT micromap = VK_NULL_HANDLE, origMicromap = VK_NULL_HANDLE;
640
641 VK_CHECK(vkd.createMicromapEXT(device, &maCreateInfo, nullptr, µmap));
642
643 // Do the build
644 mmBuildInfo.dstMicromap = micromap;
645 mmBuildInfo.data = makeDeviceOrHostAddressConstKHR(vkd, device, micromapDataBuffer.get(), DataOffset);
646 mmBuildInfo.triangleArray = makeDeviceOrHostAddressConstKHR(vkd, device, micromapDataBuffer.get(), TriangleOffset);
647 mmBuildInfo.scratchData = makeDeviceOrHostAddressKHR(vkd, device, micromapScratchBuffer.get(), 0);
648
649 vkd.cmdBuildMicromapsEXT(cmdBuffer, 1, &mmBuildInfo);
650
651 {
652 VkMemoryBarrier2 memoryBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
653 NULL,
654 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT,
655 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT,
656 m_params.copyType != CT_NONE ?
657 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT :
658 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
659 VK_ACCESS_2_MICROMAP_READ_BIT_EXT};
660 VkDependencyInfoKHR dependencyInfo = {
661 VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR, // VkStructureType sType;
662 DE_NULL, // const void* pNext;
663 0u, // VkDependencyFlags dependencyFlags;
664 1u, // uint32_t memoryBarrierCount;
665 &memoryBarrier, // const VkMemoryBarrier2KHR* pMemoryBarriers;
666 0u, // uint32_t bufferMemoryBarrierCount;
667 DE_NULL, // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers;
668 0u, // uint32_t imageMemoryBarrierCount;
669 DE_NULL, // const VkImageMemoryBarrier2KHR* pImageMemoryBarriers;
670 };
671
672 vkd.cmdPipelineBarrier2(cmdBuffer, &dependencyInfo);
673 }
674
675 if (m_params.copyType != CT_NONE)
676 {
677 copyMicromapBackingBuffer = de::MovePtr<BufferWithMemory>(
678 new BufferWithMemory(vkd, device, alloc, micromapBackingBufferCreateInfo,
679 MemoryRequirement::Local | MemoryRequirement::DeviceAddress));
680
681 origMicromap = micromap;
682
683 maCreateInfo.buffer = copyMicromapBackingBuffer->get();
684
685 VK_CHECK(vkd.createMicromapEXT(device, &maCreateInfo, nullptr, µmap));
686
687 VkCopyMicromapInfoEXT copyMicromapInfo = {
688 VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT, // VkStructureType sType;
689 DE_NULL, // const void* pNext;
690 origMicromap, // VkMicromapEXT src;
691 micromap, // VkMicromapEXT dst;
692 VK_COPY_MICROMAP_MODE_CLONE_EXT // VkCopyMicromapModeEXT mode;
693 };
694
695 vkd.cmdCopyMicromapEXT(cmdBuffer, ©MicromapInfo);
696
697 {
698 VkMemoryBarrier2 memoryBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
699 NULL,
700 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT,
701 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT,
702 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
703 VK_ACCESS_2_MICROMAP_READ_BIT_EXT};
704 VkDependencyInfoKHR dependencyInfo = {
705 VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR, // VkStructureType sType;
706 DE_NULL, // const void* pNext;
707 0u, // VkDependencyFlags dependencyFlags;
708 1u, // uint32_t memoryBarrierCount;
709 &memoryBarrier, // const VkMemoryBarrier2KHR* pMemoryBarriers;
710 0u, // uint32_t bufferMemoryBarrierCount;
711 DE_NULL, // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers;
712 0u, // uint32_t imageMemoryBarrierCount;
713 DE_NULL, // const VkImageMemoryBarrier2KHR* pImageMemoryBarriers;
714 };
715
716 dependencyInfo.memoryBarrierCount = 1;
717 dependencyInfo.pMemoryBarriers = &memoryBarrier;
718
719 vkd.cmdPipelineBarrier2(cmdBuffer, &dependencyInfo);
720 }
721 }
722
723 // Attach the micromap to the geometry
724 VkAccelerationStructureTrianglesOpacityMicromapEXT opacityGeometryMicromap = {
725 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT, //VkStructureType sType;
726 DE_NULL, //void* pNext;
727 VK_INDEX_TYPE_UINT32, //VkIndexType indexType;
728 makeDeviceOrHostAddressConstKHR(vkd, device, micromapDataBuffer.get(),
729 IndexOffset), //VkDeviceOrHostAddressConstKHR indexBuffer;
730 0u, //VkDeviceSize indexStride;
731 0u, //uint32_t baseTriangle;
732 1u, //uint32_t usageCountsCount;
733 &mmUsage, //const VkMicromapUsageEXT* pUsageCounts;
734 DE_NULL, //const VkMicromapUsageEXT* const* ppUsageCounts;
735 micromap //VkMicromapEXT micromap;
736 };
737
738 const std::vector<tcu::Vec3> triangle = {
739 tcu::Vec3(0.0f, 0.0f, 0.0f),
740 tcu::Vec3(1.0f, 0.0f, 0.0f),
741 tcu::Vec3(0.0f, 1.0f, 0.0f),
742 };
743
744 bottomLevelAS->addGeometry(triangle, true /*is triangles*/, 0, &opacityGeometryMicromap);
745 if (m_params.testFlagMask & TEST_FLAG_BIT_DISABLE_OPACITY_MICROMAP_INSTANCE)
746 bottomLevelAS->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT);
747 bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
748 de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr(bottomLevelAS.release());
749
750 VkGeometryInstanceFlagsKHR instanceFlags = 0;
751
752 if (m_params.testFlagMask & TEST_FLAG_BIT_FORCE_2_STATE_INSTANCE)
753 instanceFlags |= VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT;
754 if (m_params.testFlagMask & TEST_FLAG_BIT_FORCE_OPAQUE_INSTANCE)
755 instanceFlags |= VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR;
756 if (m_params.testFlagMask & TEST_FLAG_BIT_DISABLE_OPACITY_MICROMAP_INSTANCE)
757 instanceFlags |= VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT;
758
759 topLevelAS->setInstanceCount(1);
760 topLevelAS->addInstance(blasSharedPtr, identityMatrix3x4, 0, 0xFFu, 0u, instanceFlags);
761 topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
762
763 // One ray per subtriangle for this test
764 uint32_t numRays = numSubtriangles;
765
766 // SSBO buffer for origins.
767 const auto originsBufferSize = static_cast<VkDeviceSize>(sizeof(tcu::Vec4) * numRays);
768 auto originsBufferInfo = makeBufferCreateInfo(originsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
769 if (m_params.useMaintenance5)
770 {
771 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)originsBufferInfo.usage;
772 originsBufferInfo.pNext = &bufferUsageFlags2;
773 originsBufferInfo.usage = 0;
774 }
775 BufferWithMemory originsBuffer(vkd, device, alloc, originsBufferInfo, MemoryRequirement::HostVisible);
776 auto &originsBufferAlloc = originsBuffer.getAllocation();
777 void *originsBufferData = originsBufferAlloc.getHostPtr();
778
779 std::vector<tcu::Vec4> origins;
780 std::vector<uint32_t> expectedOutputModes;
781 origins.reserve(numRays);
782 expectedOutputModes.reserve(numRays);
783
784 // Fill in vector of expected outputs
785 for (uint32_t index = 0; index < numRays; index++)
786 {
787 uint32_t state =
788 m_params.testFlagMask & (TEST_FLAG_BIT_FORCE_OPAQUE_INSTANCE | TEST_FLAG_BIT_FORCE_OPAQUE_RAY_FLAG) ?
789 VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT :
790 VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT;
791
792 if (!(m_params.testFlagMask & TEST_FLAG_BIT_DISABLE_OPACITY_MICROMAP_INSTANCE))
793 {
794 if (m_params.useSpecialIndex)
795 {
796 state = m_params.mode;
797 }
798 else
799 {
800 if (m_params.mode == 2)
801 {
802 uint8_t byte = opacityMicromapData[index / 8];
803 state = (byte >> (index % 8)) & 0x1;
804 }
805 else
806 {
807 DE_ASSERT(m_params.mode == 4);
808 uint8_t byte = opacityMicromapData[index / 4];
809 state = (byte >> 2 * (index % 4)) & 0x3;
810 }
811 // Process in SPECIAL_INDEX number space
812 state = ~state;
813 }
814
815 if (m_params.testFlagMask & (TEST_FLAG_BIT_FORCE_2_STATE_INSTANCE | TEST_FLAG_BIT_FORCE_2_STATE_RAY_FLAG))
816 {
817 if (state == uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT))
818 state = uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT);
819 if (state == uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT))
820 state = uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT);
821 }
822 }
823
824 if (state != uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT))
825 {
826 if (m_params.testFlagMask & (TEST_FLAG_BIT_FORCE_OPAQUE_INSTANCE | TEST_FLAG_BIT_FORCE_OPAQUE_RAY_FLAG))
827 {
828 state = uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT);
829 }
830 else if (state != uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT))
831 {
832 state = uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT);
833 }
834 }
835
836 if (state == uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT))
837 {
838 expectedOutputModes.push_back(0);
839 }
840 else if (state == uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT))
841 {
842 expectedOutputModes.push_back(1);
843 }
844 else if (state == uint32_t(VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT))
845 {
846 expectedOutputModes.push_back(2);
847 }
848 else
849 {
850 DE_ASSERT(false);
851 }
852 }
853
854 for (uint32_t index = 0; index < numRays; index++)
855 {
856 tcu::Vec2 centroid = calcSubtriangleCentroid(index, m_params.subdivisionLevel);
857 origins.push_back(tcu::Vec4(centroid.x(), centroid.y(), 1.0, 0.0));
858 }
859
860 const auto originsBufferSizeSz = static_cast<size_t>(originsBufferSize);
861 deMemcpy(originsBufferData, origins.data(), originsBufferSizeSz);
862 flushAlloc(vkd, device, originsBufferAlloc);
863
864 // Storage buffer for output modes
865 const auto outputModesBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t) * numRays);
866 const auto outputModesBufferInfo = makeBufferCreateInfo(outputModesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
867 BufferWithMemory outputModesBuffer(vkd, device, alloc, outputModesBufferInfo, MemoryRequirement::HostVisible);
868 auto &outputModesBufferAlloc = outputModesBuffer.getAllocation();
869 void *outputModesBufferData = outputModesBufferAlloc.getHostPtr();
870 deMemset(outputModesBufferData, 0xFF, static_cast<size_t>(outputModesBufferSize));
871 flushAlloc(vkd, device, outputModesBufferAlloc);
872
873 // Descriptor set layout.
874 DescriptorSetLayoutBuilder dsLayoutBuilder;
875 dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL);
876 dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
877 dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
878 const auto setLayout = dsLayoutBuilder.build(vkd, device);
879
880 // Pipeline layout.
881 const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
882
883 // Descriptor pool and set.
884 DescriptorPoolBuilder poolBuilder;
885 poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
886 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
887 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
888 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
889 const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
890
891 // Update descriptor set.
892 {
893 const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo = {
894 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
895 nullptr,
896 1u,
897 topLevelAS.get()->getPtr(),
898 };
899 const auto inStorageBufferInfo = makeDescriptorBufferInfo(originsBuffer.get(), 0ull, VK_WHOLE_SIZE);
900 const auto storageBufferInfo = makeDescriptorBufferInfo(outputModesBuffer.get(), 0ull, VK_WHOLE_SIZE);
901
902 DescriptorSetUpdateBuilder updateBuilder;
903 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
904 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
905 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
906 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inStorageBufferInfo);
907 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u),
908 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
909 updateBuilder.update(vkd, device);
910 }
911
912 Move<VkPipeline> pipeline;
913 de::MovePtr<BufferWithMemory> raygenSBT;
914 Move<VkRenderPass> renderPass;
915 Move<VkFramebuffer> framebuffer;
916
917 if (m_params.shaderSourceType == SST_VERTEX_SHADER)
918 {
919 auto vertexModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0);
920
921 renderPass = makeEmptyRenderPass(vkd, device);
922 framebuffer = makeFramebuffer(vkd, device, *renderPass, 0u, DE_NULL, 32, 32);
923 pipeline = makeGraphicsPipeline(vkd, device, *pipelineLayout, *renderPass, *vertexModule, 0);
924
925 beginRenderPass(vkd, cmdBuffer, *renderPass, *framebuffer, makeRect2D(32u, 32u));
926 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
927 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
928 &descriptorSet.get(), 0u, nullptr);
929 vkd.cmdDraw(cmdBuffer, kNumThreadsAtOnce, 1, 0, 0);
930 endRenderPass(vkd, cmdBuffer);
931 }
932 else if (m_params.shaderSourceType == SST_RAY_GENERATION_SHADER)
933 {
934 const auto &vki = m_context.getInstanceInterface();
935 const auto physDev = m_context.getPhysicalDevice();
936
937 // Shader module.
938 auto rgenModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0);
939
940 // Get some ray tracing properties.
941 uint32_t shaderGroupHandleSize = 0u;
942 uint32_t shaderGroupBaseAlignment = 1u;
943 {
944 const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physDev);
945 shaderGroupHandleSize = rayTracingPropertiesKHR->getShaderGroupHandleSize();
946 shaderGroupBaseAlignment = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
947 }
948
949 auto raygenSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
950 auto unusedSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
951
952 {
953 const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
954 rayTracingPipeline->setCreateFlags(VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT);
955 if (m_params.useMaintenance5)
956 rayTracingPipeline->setCreateFlags2(VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT);
957 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0);
958
959 pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
960
961 raygenSBT = rayTracingPipeline->createShaderBindingTable(
962 vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
963 raygenSBTRegion = makeStridedDeviceAddressRegionKHR(
964 getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
965 }
966
967 // Trace rays.
968 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
969 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u,
970 &descriptorSet.get(), 0u, nullptr);
971 vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &unusedSBTRegion, &unusedSBTRegion, &unusedSBTRegion,
972 kNumThreadsAtOnce, 1u, 1u);
973 }
974 else
975 {
976 DE_ASSERT(m_params.shaderSourceType == SST_COMPUTE_SHADER);
977 // Shader module.
978 const auto compModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0);
979
980 // Pipeline.
981 const VkPipelineShaderStageCreateInfo shaderInfo = {
982 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
983 nullptr, // const void* pNext;
984 0u, // VkPipelineShaderStageCreateFlags flags;
985 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
986 compModule.get(), // VkShaderModule module;
987 "main", // const char* pName;
988 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
989 };
990 const VkComputePipelineCreateInfo pipelineInfo = {
991 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
992 nullptr, // const void* pNext;
993 0u, // VkPipelineCreateFlags flags;
994 shaderInfo, // VkPipelineShaderStageCreateInfo stage;
995 pipelineLayout.get(), // VkPipelineLayout layout;
996 DE_NULL, // VkPipeline basePipelineHandle;
997 0, // int32_t basePipelineIndex;
998 };
999 pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);
1000
1001 // Dispatch work with ray queries.
1002 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
1003 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u,
1004 &descriptorSet.get(), 0u, nullptr);
1005 vkd.cmdDispatch(cmdBuffer, kWorkGroupCount, 1u, 1u);
1006 }
1007
1008 // Barrier for the output buffer.
1009 const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1010 vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u,
1011 &bufferBarrier, 0u, nullptr, 0u, nullptr);
1012
1013 endCommandBuffer(vkd, cmdBuffer);
1014 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1015
1016 if (micromap != VK_NULL_HANDLE)
1017 vkd.destroyMicromapEXT(device, micromap, DE_NULL);
1018 if (micromap != VK_NULL_HANDLE)
1019 vkd.destroyMicromapEXT(device, origMicromap, DE_NULL);
1020
1021 // Verify results.
1022 std::vector<uint32_t> outputData(expectedOutputModes.size());
1023 const auto outputModesBufferSizeSz = static_cast<size_t>(outputModesBufferSize);
1024
1025 invalidateAlloc(vkd, device, outputModesBufferAlloc);
1026 DE_ASSERT(de::dataSize(outputData) == outputModesBufferSizeSz);
1027 deMemcpy(outputData.data(), outputModesBufferData, outputModesBufferSizeSz);
1028
1029 for (size_t i = 0; i < outputData.size(); ++i)
1030 {
1031 const auto &outVal = outputData[i];
1032 const auto &expectedVal = expectedOutputModes[i];
1033
1034 if (outVal != expectedVal)
1035 {
1036 std::ostringstream msg;
1037 msg << "Unexpected value found for ray " << i << ": expected " << expectedVal << " and found " << outVal
1038 << ";";
1039 TCU_FAIL(msg.str());
1040 }
1041 #if 0
1042 else
1043 {
1044 std::ostringstream msg;
1045 msg << "Expected value found for ray " << i << ": expected " << expectedVal << " and found " << outVal << ";\n"; // XXX Debug remove
1046 std::cout << msg.str();
1047 }
1048 #endif
1049 }
1050
1051 return tcu::TestStatus::pass("Pass");
1052 }
1053
1054 } // namespace
1055
1056 constexpr uint32_t kMaxSubdivisionLevel = 15;
1057
addBasicTests(tcu::TestCaseGroup * group)1058 void addBasicTests(tcu::TestCaseGroup *group)
1059 {
1060 uint32_t seed = 1614674687u;
1061
1062 const struct
1063 {
1064 ShaderSourceType shaderSourceType;
1065 ShaderSourcePipeline shaderSourcePipeline;
1066 std::string name;
1067 } shaderSourceTypes[] = {
1068 {SST_VERTEX_SHADER, SSP_GRAPHICS_PIPELINE, "vertex_shader"},
1069 {
1070 SST_COMPUTE_SHADER,
1071 SSP_COMPUTE_PIPELINE,
1072 "compute_shader",
1073 },
1074 {
1075 SST_RAY_GENERATION_SHADER,
1076 SSP_RAY_TRACING_PIPELINE,
1077 "rgen_shader",
1078 },
1079 };
1080
1081 const struct
1082 {
1083 bool useSpecialIndex;
1084 std::string name;
1085 } specialIndexUse[] = {
1086 {false, "map_value"},
1087 {true, "special_index"},
1088 };
1089
1090 auto &testCtx = group->getTestContext();
1091
1092 for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
1093 {
1094 de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(
1095 new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name.c_str()));
1096
1097 for (uint32_t testFlagMask = 0; testFlagMask < TEST_FLAG_BIT_LAST; testFlagMask++)
1098 {
1099 std::string maskName = "";
1100
1101 for (uint32_t bit = 0; bit < testFlagBitNames.size(); bit++)
1102 {
1103 if (testFlagMask & (1 << bit))
1104 {
1105 if (maskName != "")
1106 maskName += "_";
1107 maskName += testFlagBitNames[bit];
1108 }
1109 }
1110 if (maskName == "")
1111 maskName = "NoFlags";
1112
1113 de::MovePtr<tcu::TestCaseGroup> testFlagGroup(
1114 new tcu::TestCaseGroup(sourceTypeGroup->getTestContext(), maskName.c_str()));
1115
1116 for (size_t specialIndexNdx = 0; specialIndexNdx < DE_LENGTH_OF_ARRAY(specialIndexUse); ++specialIndexNdx)
1117 {
1118 de::MovePtr<tcu::TestCaseGroup> specialGroup(new tcu::TestCaseGroup(
1119 testFlagGroup->getTestContext(), specialIndexUse[specialIndexNdx].name.c_str()));
1120
1121 if (specialIndexUse[specialIndexNdx].useSpecialIndex)
1122 {
1123 for (uint32_t specialIndex = 0; specialIndex < 4; specialIndex++)
1124 {
1125 TestParams testParams{
1126 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
1127 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
1128 specialIndexUse[specialIndexNdx].useSpecialIndex,
1129 testFlagMask,
1130 0,
1131 ~specialIndex,
1132 seed++,
1133 CT_NONE,
1134 false,
1135 };
1136
1137 std::stringstream css;
1138 css << specialIndex;
1139
1140 specialGroup->addChild(new OpacityMicromapCase(testCtx, css.str().c_str(), testParams));
1141 }
1142 testFlagGroup->addChild(specialGroup.release());
1143 }
1144 else
1145 {
1146 struct
1147 {
1148 uint32_t mode;
1149 std::string name;
1150 } modes[] = {{2, "2"}, {4, "4"}};
1151 for (uint32_t modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(modes); ++modeNdx)
1152 {
1153 de::MovePtr<tcu::TestCaseGroup> modeGroup(
1154 new tcu::TestCaseGroup(testFlagGroup->getTestContext(), modes[modeNdx].name.c_str()));
1155
1156 for (uint32_t level = 0; level <= kMaxSubdivisionLevel; level++)
1157 {
1158 TestParams testParams{
1159 shaderSourceTypes[shaderSourceNdx].shaderSourceType,
1160 shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
1161 specialIndexUse[specialIndexNdx].useSpecialIndex,
1162 testFlagMask,
1163 level,
1164 modes[modeNdx].mode,
1165 seed++,
1166 CT_NONE,
1167 false,
1168 };
1169
1170 std::stringstream css;
1171 css << "level_" << level;
1172
1173 modeGroup->addChild(new OpacityMicromapCase(testCtx, css.str().c_str(), testParams));
1174 }
1175 specialGroup->addChild(modeGroup.release());
1176 }
1177 testFlagGroup->addChild(specialGroup.release());
1178 }
1179 }
1180
1181 sourceTypeGroup->addChild(testFlagGroup.release());
1182 }
1183
1184 group->addChild(sourceTypeGroup.release());
1185 }
1186 }
1187
addCopyTests(tcu::TestCaseGroup * group)1188 void addCopyTests(tcu::TestCaseGroup *group)
1189 {
1190 uint32_t seed = 1614674688u;
1191
1192 auto &testCtx = group->getTestContext();
1193
1194 for (size_t copyTypeNdx = CT_FIRST_ACTIVE; copyTypeNdx < CT_NUM_COPY_TYPES; ++copyTypeNdx)
1195 {
1196 de::MovePtr<tcu::TestCaseGroup> copyTypeGroup(
1197 new tcu::TestCaseGroup(group->getTestContext(), copyTypeNames[copyTypeNdx].c_str()));
1198
1199 struct
1200 {
1201 uint32_t mode;
1202 std::string name;
1203 } modes[] = {{2, "2"}, {4, "4"}};
1204 for (uint32_t modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(modes); ++modeNdx)
1205 {
1206 de::MovePtr<tcu::TestCaseGroup> modeGroup(
1207 new tcu::TestCaseGroup(copyTypeGroup->getTestContext(), modes[modeNdx].name.c_str()));
1208
1209 for (uint32_t level = 0; level <= kMaxSubdivisionLevel; level++)
1210 {
1211 TestParams testParams{
1212 SST_COMPUTE_SHADER,
1213 SSP_COMPUTE_PIPELINE,
1214 false,
1215 0,
1216 level,
1217 modes[modeNdx].mode,
1218 seed++,
1219 (CopyType)copyTypeNdx,
1220 false,
1221 };
1222
1223 std::stringstream css;
1224 css << "level_" << level;
1225
1226 modeGroup->addChild(new OpacityMicromapCase(testCtx, css.str().c_str(), testParams));
1227 }
1228 copyTypeGroup->addChild(modeGroup.release());
1229 }
1230 group->addChild(copyTypeGroup.release());
1231 }
1232
1233 {
1234 TestParams testParams{
1235 SST_COMPUTE_SHADER, SSP_COMPUTE_PIPELINE, false, 0, 0, 2, 1, CT_FIRST_ACTIVE, true,
1236 };
1237 de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(group->getTestContext(), "misc"));
1238 miscGroup->addChild(new OpacityMicromapCase(testCtx, "maintenance5", testParams));
1239 group->addChild(miscGroup.release());
1240 }
1241 }
1242
createOpacityMicromapTests(tcu::TestContext & testCtx)1243 tcu::TestCaseGroup *createOpacityMicromapTests(tcu::TestContext &testCtx)
1244 {
1245 // Test acceleration structures using opacity micromap with ray query
1246 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "opacity_micromap"));
1247
1248 // Test accessing all formats of opacity micromaps
1249 addTestGroup(group.get(), "render", addBasicTests);
1250 // Test copying opacity micromaps
1251 addTestGroup(group.get(), "copy", addCopyTests);
1252
1253 return group.release();
1254 }
1255
1256 } // namespace RayQuery
1257 } // namespace vkt
1258