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