• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &micromap));
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, &micromap));
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, &copyMicromapInfo);
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