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
44namespace vkt
45{
46namespace RayQuery
47{
48
49namespace
50{
51
52using namespace vk;
53
54enum ShaderSourcePipeline
55{
56	SSP_GRAPHICS_PIPELINE,
57	SSP_COMPUTE_PIPELINE,
58	SSP_RAY_TRACING_PIPELINE
59};
60
61enum ShaderSourceType
62{
63	SST_VERTEX_SHADER,
64	SST_COMPUTE_SHADER,
65	SST_RAY_GENERATION_SHADER,
66};
67
68enum 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
78std::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
87enum CopyType {
88	CT_NONE,
89	CT_FIRST_ACTIVE,
90	CT_CLONE = CT_FIRST_ACTIVE,
91	CT_COMPACT,
92	CT_NUM_COPY_TYPES,
93};
94
95std::vector<std::string> copyTypeNames
96{
97	"None",
98	"Clone",
99	"Compact",
100};
101
102struct 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
115static constexpr deUint32 kNumThreadsAtOnce = 1024;
116
117
118class OpacityMicromapCase : public TestCase
119{
120public:
121							OpacityMicromapCase		(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
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
128protected:
129	TestParams				m_params;
130};
131
132class OpacityMicromapInstance : public TestInstance
133{
134public:
135								OpacityMicromapInstance		(Context& context, const TestParams& params);
136	virtual						~OpacityMicromapInstance	(void) {}
137
138	virtual tcu::TestStatus		iterate							(void);
139
140protected:
141	TestParams					m_params;
142};
143
144OpacityMicromapCase::OpacityMicromapCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
145	: TestCase	(testCtx, name)
146	, m_params	(params)
147{}
148
149void 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
210static deUint32 levelToSubtriangles(deUint32 level)
211{
212	return 1 << (2 * level);
213}
214
215void 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
311TestInstance* OpacityMicromapCase::createInstance (Context& context) const
312{
313	return new OpacityMicromapInstance(context, m_params);
314}
315
316OpacityMicromapInstance::OpacityMicromapInstance (Context& context, const TestParams& params)
317	: TestInstance	(context)
318	, m_params		(params)
319{}
320
321tcu::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
379static 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
428Move<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
505tcu::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
1033constexpr deUint32 kMaxSubdivisionLevel = 15;
1034
1035void 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
1158void 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
1224tcu::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