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