1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2019 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2019 Google Inc.
7e5c31af7Sopenharmony_ci * Copyright (c) 2017 Codeplay Software Ltd.
8e5c31af7Sopenharmony_ci *
9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci *
15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci * limitations under the License.
20e5c31af7Sopenharmony_ci *
21e5c31af7Sopenharmony_ci */ /*!
22e5c31af7Sopenharmony_ci * \file
23e5c31af7Sopenharmony_ci * \brief Subgroups Tests
24e5c31af7Sopenharmony_ci */ /*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vktSubgroupsQuadTests.hpp"
27e5c31af7Sopenharmony_ci#include "vktSubgroupsTestsUtils.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include <string>
30e5c31af7Sopenharmony_ci#include <vector>
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ciusing namespace tcu;
33e5c31af7Sopenharmony_ciusing namespace std;
34e5c31af7Sopenharmony_ciusing namespace vk;
35e5c31af7Sopenharmony_ciusing namespace vkt;
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_cinamespace
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_cienum OpType
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_ci	OPTYPE_QUAD_BROADCAST = 0,
42e5c31af7Sopenharmony_ci	OPTYPE_QUAD_BROADCAST_NONCONST,
43e5c31af7Sopenharmony_ci	OPTYPE_QUAD_SWAP_HORIZONTAL,
44e5c31af7Sopenharmony_ci	OPTYPE_QUAD_SWAP_VERTICAL,
45e5c31af7Sopenharmony_ci	OPTYPE_QUAD_SWAP_DIAGONAL,
46e5c31af7Sopenharmony_ci	OPTYPE_LAST
47e5c31af7Sopenharmony_ci};
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cistruct CaseDefinition
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci	OpType				opType;
52e5c31af7Sopenharmony_ci	VkShaderStageFlags	shaderStage;
53e5c31af7Sopenharmony_ci	VkFormat			format;
54e5c31af7Sopenharmony_ci	de::SharedPtr<bool>	geometryPointSizeSupported;
55e5c31af7Sopenharmony_ci	deBool				requiredSubgroupSize;
56e5c31af7Sopenharmony_ci	deBool				requires8BitUniformBuffer;
57e5c31af7Sopenharmony_ci	deBool				requires16BitUniformBuffer;
58e5c31af7Sopenharmony_ci};
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages (const void*			internalData,
61e5c31af7Sopenharmony_ci									   vector<const void*>	datas,
62e5c31af7Sopenharmony_ci									   deUint32				width,
63e5c31af7Sopenharmony_ci									   deUint32)
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	return subgroups::check(datas, width, 1);
68e5c31af7Sopenharmony_ci}
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_cistatic bool checkComputeOrMesh (const void*			internalData,
71e5c31af7Sopenharmony_ci								vector<const void*>	datas,
72e5c31af7Sopenharmony_ci								const deUint32		numWorkgroups[3],
73e5c31af7Sopenharmony_ci								const deUint32		localSize[3],
74e5c31af7Sopenharmony_ci								deUint32)
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci	return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 1);
79e5c31af7Sopenharmony_ci}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_cistring getOpTypeName (OpType opType)
82e5c31af7Sopenharmony_ci{
83e5c31af7Sopenharmony_ci	switch (opType)
84e5c31af7Sopenharmony_ci	{
85e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_BROADCAST:				return "subgroupQuadBroadcast";
86e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_BROADCAST_NONCONST:	return "subgroupQuadBroadcast";
87e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_HORIZONTAL:		return "subgroupQuadSwapHorizontal";
88e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_VERTICAL:			return "subgroupQuadSwapVertical";
89e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_DIAGONAL:			return "subgroupQuadSwapDiagonal";
90e5c31af7Sopenharmony_ci		default:								TCU_THROW(InternalError, "Unsupported op type");
91e5c31af7Sopenharmony_ci	}
92e5c31af7Sopenharmony_ci}
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_cistring getOpTypeCaseName (OpType opType)
95e5c31af7Sopenharmony_ci{
96e5c31af7Sopenharmony_ci	switch (opType)
97e5c31af7Sopenharmony_ci	{
98e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_BROADCAST:				return "subgroupquadbroadcast";
99e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_BROADCAST_NONCONST:	return "subgroupquadbroadcast_nonconst";
100e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_HORIZONTAL:		return "subgroupquadswaphorizontal";
101e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_VERTICAL:			return "subgroupquadswapvertical";
102e5c31af7Sopenharmony_ci		case OPTYPE_QUAD_SWAP_DIAGONAL:			return "subgroupquadswapdiagonal";
103e5c31af7Sopenharmony_ci		default:								TCU_THROW(InternalError, "Unsupported op type");
104e5c31af7Sopenharmony_ci	}
105e5c31af7Sopenharmony_ci}
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_cistring getExtHeader (VkFormat format)
108e5c31af7Sopenharmony_ci{
109e5c31af7Sopenharmony_ci	return	"#extension GL_KHR_shader_subgroup_quad: enable\n"
110e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n" +
111e5c31af7Sopenharmony_ci			subgroups::getAdditionalExtensionForFormat(format);
112e5c31af7Sopenharmony_ci}
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_cistring getTestSrc (const CaseDefinition &caseDef)
115e5c31af7Sopenharmony_ci{
116e5c31af7Sopenharmony_ci	const string	swapTable[OPTYPE_LAST]	=
117e5c31af7Sopenharmony_ci	{
118e5c31af7Sopenharmony_ci		"",
119e5c31af7Sopenharmony_ci		"",
120e5c31af7Sopenharmony_ci		"  const uint swapTable[4] = {1, 0, 3, 2};\n",
121e5c31af7Sopenharmony_ci		"  const uint swapTable[4] = {2, 3, 0, 1};\n",
122e5c31af7Sopenharmony_ci		"  const uint swapTable[4] = {3, 2, 1, 0};\n",
123e5c31af7Sopenharmony_ci	};
124e5c31af7Sopenharmony_ci	const string	validate				=
125e5c31af7Sopenharmony_ci		"  if (subgroupBallotBitExtract(mask, otherID) && op !=data[otherID])\n"
126e5c31af7Sopenharmony_ci		"    tempRes = 0;\n";
127e5c31af7Sopenharmony_ci	const string	fmt						= subgroups::getFormatNameForGLSL(caseDef.format);
128e5c31af7Sopenharmony_ci	const string	op						= getOpTypeName(caseDef.opType);
129e5c31af7Sopenharmony_ci	ostringstream	testSrc;
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	testSrc	<< "  uvec4 mask = subgroupBallot(true);\n"
132e5c31af7Sopenharmony_ci			<< swapTable[caseDef.opType]
133e5c31af7Sopenharmony_ci			<< "  tempRes = 1;\n";
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ci	if (caseDef.opType == OPTYPE_QUAD_BROADCAST)
136e5c31af7Sopenharmony_ci	{
137e5c31af7Sopenharmony_ci		for (int i=0; i<4; i++)
138e5c31af7Sopenharmony_ci		{
139e5c31af7Sopenharmony_ci			testSrc << "  {\n"
140e5c31af7Sopenharmony_ci					<< "  " << fmt << " op = " << op << "(data[gl_SubgroupInvocationID], " << i << ");\n"
141e5c31af7Sopenharmony_ci					<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << i << ";\n"
142e5c31af7Sopenharmony_ci					<< validate
143e5c31af7Sopenharmony_ci					<< "  }\n";
144e5c31af7Sopenharmony_ci		}
145e5c31af7Sopenharmony_ci	}
146e5c31af7Sopenharmony_ci	else if (caseDef.opType == OPTYPE_QUAD_BROADCAST_NONCONST)
147e5c31af7Sopenharmony_ci	{
148e5c31af7Sopenharmony_ci		testSrc << "  for (int i=0; i<4; i++)"
149e5c31af7Sopenharmony_ci				<< "  {\n"
150e5c31af7Sopenharmony_ci				<< "  " << fmt << " op = " << op << "(data[gl_SubgroupInvocationID], i);\n"
151e5c31af7Sopenharmony_ci				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + i;\n"
152e5c31af7Sopenharmony_ci				<< validate
153e5c31af7Sopenharmony_ci				<< "  }\n"
154e5c31af7Sopenharmony_ci				<< "  uint quadID = gl_SubgroupInvocationID >> 2;\n"
155e5c31af7Sopenharmony_ci				<< "  uint quadInvocation = gl_SubgroupInvocationID & 0x3;\n"
156e5c31af7Sopenharmony_ci				<< "  // Test lane ID that is only uniform in active lanes\n"
157e5c31af7Sopenharmony_ci				<< "  if (quadInvocation >= 2)\n"
158e5c31af7Sopenharmony_ci				<< "  {\n"
159e5c31af7Sopenharmony_ci				<< "    uint id = quadInvocation & ~1;\n"
160e5c31af7Sopenharmony_ci				<< "    " << fmt << " op = " << op << "(data[gl_SubgroupInvocationID], id);\n"
161e5c31af7Sopenharmony_ci				<< "    uint otherID = 4*quadID + id;\n"
162e5c31af7Sopenharmony_ci				<< validate
163e5c31af7Sopenharmony_ci				<< "  }\n"
164e5c31af7Sopenharmony_ci				<< "  // Test lane ID that is only quad uniform, not subgroup uniform\n"
165e5c31af7Sopenharmony_ci				<< "  {\n"
166e5c31af7Sopenharmony_ci				<< "    uint id = quadID & 0x3;\n"
167e5c31af7Sopenharmony_ci				<< "    " << fmt << " op = " << op << "(data[gl_SubgroupInvocationID], id);\n"
168e5c31af7Sopenharmony_ci				<< "    uint otherID = 4*quadID + id;\n"
169e5c31af7Sopenharmony_ci				<< validate
170e5c31af7Sopenharmony_ci				<< "  }\n";
171e5c31af7Sopenharmony_ci	}
172e5c31af7Sopenharmony_ci	else
173e5c31af7Sopenharmony_ci	{
174e5c31af7Sopenharmony_ci		testSrc << "  " << fmt << " op = " << op << "(data[gl_SubgroupInvocationID]);\n"
175e5c31af7Sopenharmony_ci				<< "  uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n"
176e5c31af7Sopenharmony_ci				<< validate;
177e5c31af7Sopenharmony_ci	}
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci	return testSrc.str();
180e5c31af7Sopenharmony_ci}
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
183e5c31af7Sopenharmony_ci{
184e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion	= (caseDef.opType == OPTYPE_QUAD_BROADCAST_NONCONST) ? SPIRV_VERSION_1_5 : SPIRV_VERSION_1_3;
185e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, spirvVersion, 0u);
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci	subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, getExtHeader(caseDef.format), getTestSrc(caseDef), "");
188e5c31af7Sopenharmony_ci}
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_civoid initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
191e5c31af7Sopenharmony_ci{
192e5c31af7Sopenharmony_ci	const bool					spirv15required	= caseDef.opType == OPTYPE_QUAD_BROADCAST_NONCONST;
193e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
194e5c31af7Sopenharmony_ci	const bool					spirv14required	= (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
195e5c31af7Sopenharmony_ci#else
196e5c31af7Sopenharmony_ci	const bool					spirv14required	= false;
197e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
198e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion	= spirv15required ? SPIRV_VERSION_1_5
199e5c31af7Sopenharmony_ci												: spirv14required ? SPIRV_VERSION_1_4
200e5c31af7Sopenharmony_ci												: SPIRV_VERSION_1_3;
201e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, spirvVersion, 0u, (spirv14required && !spirv15required));
202e5c31af7Sopenharmony_ci	const string				extHeader		= getExtHeader(caseDef.format);
203e5c31af7Sopenharmony_ci	const string				testSrc			= getTestSrc(caseDef);
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, extHeader, testSrc, "");
206e5c31af7Sopenharmony_ci}
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
209e5c31af7Sopenharmony_ci{
210e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
211e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci	if (!subgroups::areQuadOperationsSupportedForStages(context, caseDef.shaderStage))
214e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup quad operations in this shader stage");
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci	if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
217e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci	if (caseDef.requires16BitUniformBuffer)
220e5c31af7Sopenharmony_ci	{
221e5c31af7Sopenharmony_ci		if (!subgroups::is16BitUBOStorageSupported(context))
222e5c31af7Sopenharmony_ci		{
223e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
224e5c31af7Sopenharmony_ci		}
225e5c31af7Sopenharmony_ci	}
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	if (caseDef.requires8BitUniformBuffer)
228e5c31af7Sopenharmony_ci	{
229e5c31af7Sopenharmony_ci		if (!subgroups::is8BitUBOStorageSupported(context))
230e5c31af7Sopenharmony_ci		{
231e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
232e5c31af7Sopenharmony_ci		}
233e5c31af7Sopenharmony_ci	}
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci	if ((caseDef.opType == OPTYPE_QUAD_BROADCAST_NONCONST) && !subgroups::isSubgroupBroadcastDynamicIdSupported(context))
236e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support SubgroupBroadcastDynamicId");
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci	if (caseDef.requiredSubgroupSize)
239e5c31af7Sopenharmony_ci	{
240e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
243e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeatures&		subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeatures();
244e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
245e5c31af7Sopenharmony_ci#else
246e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&	subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeaturesEXT();
247e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
248e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
251e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
254e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
255e5c31af7Sopenharmony_ci
256e5c31af7Sopenharmony_ci		if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
257e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
258e5c31af7Sopenharmony_ci	}
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ci	*caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
263e5c31af7Sopenharmony_ci	if (isAllRayTracingStages(caseDef.shaderStage))
264e5c31af7Sopenharmony_ci	{
265e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
266e5c31af7Sopenharmony_ci	}
267e5c31af7Sopenharmony_ci	else if (isAllMeshShadingStages(caseDef.shaderStage))
268e5c31af7Sopenharmony_ci	{
269e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
270e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
271e5c31af7Sopenharmony_ci
272e5c31af7Sopenharmony_ci		if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
273e5c31af7Sopenharmony_ci		{
274e5c31af7Sopenharmony_ci			const auto& features = context.getMeshShaderFeaturesEXT();
275e5c31af7Sopenharmony_ci			if (!features.taskShader)
276e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Task shaders not supported");
277e5c31af7Sopenharmony_ci		}
278e5c31af7Sopenharmony_ci	}
279e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	subgroups::supportedCheckShader(context, caseDef.shaderStage);
282e5c31af7Sopenharmony_ci}
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ciTestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
285e5c31af7Sopenharmony_ci{
286e5c31af7Sopenharmony_ci	subgroups::SSBOData inputData;
287e5c31af7Sopenharmony_ci	inputData.format = caseDef.format;
288e5c31af7Sopenharmony_ci	inputData.layout = subgroups::SSBOData::LayoutStd140;
289e5c31af7Sopenharmony_ci	inputData.numElements = subgroups::maxSupportedSubgroupSize();
290e5c31af7Sopenharmony_ci	inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
291e5c31af7Sopenharmony_ci	inputData.bindingType = subgroups::SSBOData::BindingUBO;
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ci	switch (caseDef.shaderStage)
294e5c31af7Sopenharmony_ci	{
295e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_VERTEX_BIT:					return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
296e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_GEOMETRY_BIT:					return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
297e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
298e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
299e5c31af7Sopenharmony_ci		default:											TCU_THROW(InternalError, "Unhandled shader stage");
300e5c31af7Sopenharmony_ci	}
301e5c31af7Sopenharmony_ci}
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ciTestStatus test (Context& context, const CaseDefinition caseDef)
304e5c31af7Sopenharmony_ci{
305e5c31af7Sopenharmony_ci	const bool isCompute	= isAllComputeStages(caseDef.shaderStage);
306e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
307e5c31af7Sopenharmony_ci	const bool isMesh		= isAllMeshShadingStages(caseDef.shaderStage);
308e5c31af7Sopenharmony_ci#else
309e5c31af7Sopenharmony_ci	const bool isMesh		= false;
310e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
311e5c31af7Sopenharmony_ci	DE_ASSERT(!(isCompute && isMesh));
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci	if (isCompute || isMesh)
314e5c31af7Sopenharmony_ci	{
315e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
316e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
317e5c31af7Sopenharmony_ci#else
318e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
319e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
320e5c31af7Sopenharmony_ci		TestLog&												log								= context.getTestContext().getLog();
321e5c31af7Sopenharmony_ci		const subgroups::SSBOData								inputData
322e5c31af7Sopenharmony_ci		{
323e5c31af7Sopenharmony_ci			subgroups::SSBOData::InitializeNonZero,	// InputDataInitializeType		initializeType;
324e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd430,		// InputDataLayoutType			layout;
325e5c31af7Sopenharmony_ci			caseDef.format,							// vk::VkFormat				format;
326e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	// vk::VkDeviceSize			numElements;
327e5c31af7Sopenharmony_ci		};
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci		if (caseDef.requiredSubgroupSize == DE_FALSE)
330e5c31af7Sopenharmony_ci		{
331e5c31af7Sopenharmony_ci			if (isCompute)
332e5c31af7Sopenharmony_ci				return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
333e5c31af7Sopenharmony_ci			else
334e5c31af7Sopenharmony_ci				return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
335e5c31af7Sopenharmony_ci		}
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci		log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
338e5c31af7Sopenharmony_ci			<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci		// According to the spec, requiredSubgroupSize must be a power-of-two integer.
341e5c31af7Sopenharmony_ci		for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
342e5c31af7Sopenharmony_ci		{
343e5c31af7Sopenharmony_ci			TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci			if (isCompute)
346e5c31af7Sopenharmony_ci				result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
347e5c31af7Sopenharmony_ci			else
348e5c31af7Sopenharmony_ci				result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci			if (result.getCode() != QP_TEST_RESULT_PASS)
351e5c31af7Sopenharmony_ci			{
352e5c31af7Sopenharmony_ci				log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
353e5c31af7Sopenharmony_ci				return result;
354e5c31af7Sopenharmony_ci			}
355e5c31af7Sopenharmony_ci		}
356e5c31af7Sopenharmony_ci
357e5c31af7Sopenharmony_ci		return TestStatus::pass("OK");
358e5c31af7Sopenharmony_ci	}
359e5c31af7Sopenharmony_ci	else if (isAllGraphicsStages(caseDef.shaderStage))
360e5c31af7Sopenharmony_ci	{
361e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages		= subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
362e5c31af7Sopenharmony_ci		subgroups::SSBOData			inputData;
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci		inputData.format			= caseDef.format;
365e5c31af7Sopenharmony_ci		inputData.layout			= subgroups::SSBOData::LayoutStd430;
366e5c31af7Sopenharmony_ci		inputData.numElements		= subgroups::maxSupportedSubgroupSize();
367e5c31af7Sopenharmony_ci		inputData.initializeType	= subgroups::SSBOData::InitializeNonZero;
368e5c31af7Sopenharmony_ci		inputData.binding			= 4u;
369e5c31af7Sopenharmony_ci		inputData.stages			= stages;
370e5c31af7Sopenharmony_ci
371e5c31af7Sopenharmony_ci		return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
372e5c31af7Sopenharmony_ci	}
373e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
374e5c31af7Sopenharmony_ci	else if (isAllRayTracingStages(caseDef.shaderStage))
375e5c31af7Sopenharmony_ci	{
376e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages		= subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
377e5c31af7Sopenharmony_ci		const subgroups::SSBOData	inputData	=
378e5c31af7Sopenharmony_ci		{
379e5c31af7Sopenharmony_ci			subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
380e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
381e5c31af7Sopenharmony_ci			caseDef.format,							//  vk::VkFormat				format;
382e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
383e5c31af7Sopenharmony_ci			subgroups::SSBOData::BindingSSBO,		//  bool						isImage;
384e5c31af7Sopenharmony_ci			6u,										//  deUint32					binding;
385e5c31af7Sopenharmony_ci			stages,									//  vk::VkShaderStageFlags		stages;
386e5c31af7Sopenharmony_ci		};
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci		return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
389e5c31af7Sopenharmony_ci	}
390e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
391e5c31af7Sopenharmony_ci	else
392e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unknown stage or invalid stage set");
393e5c31af7Sopenharmony_ci}
394e5c31af7Sopenharmony_ci}
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_cinamespace vkt
397e5c31af7Sopenharmony_ci{
398e5c31af7Sopenharmony_cinamespace subgroups
399e5c31af7Sopenharmony_ci{
400e5c31af7Sopenharmony_ciTestCaseGroup* createSubgroupsQuadTests (TestContext& testCtx)
401e5c31af7Sopenharmony_ci{
402e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	group				(new TestCaseGroup(testCtx, "quad", "Subgroup quad category tests"));
403e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	graphicGroup		(new TestCaseGroup(testCtx, "graphics", "Subgroup arithmetic category tests: graphics"));
404e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	computeGroup		(new TestCaseGroup(testCtx, "compute", "Subgroup arithmetic category tests: compute"));
405e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	framebufferGroup	(new TestCaseGroup(testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer"));
406e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
407e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	raytracingGroup		(new TestCaseGroup(testCtx, "ray_tracing", "Subgroup arithmetic category tests: ray tracing"));
408e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	meshGroup			(new TestCaseGroup(testCtx, "mesh", "Subgroup arithmetic category tests: mesh shading"));
409e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
410e5c31af7Sopenharmony_ci	const VkShaderStageFlags	fbStages[]			=
411e5c31af7Sopenharmony_ci	{
412e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_VERTEX_BIT,
413e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
414e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
415e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_GEOMETRY_BIT,
416e5c31af7Sopenharmony_ci	};
417e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
418e5c31af7Sopenharmony_ci	const VkShaderStageFlags	meshStages[]		=
419e5c31af7Sopenharmony_ci	{
420e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_MESH_BIT_EXT,
421e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TASK_BIT_EXT,
422e5c31af7Sopenharmony_ci	};
423e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
424e5c31af7Sopenharmony_ci	const deBool				boolValues[]		=
425e5c31af7Sopenharmony_ci	{
426e5c31af7Sopenharmony_ci		DE_FALSE,
427e5c31af7Sopenharmony_ci		DE_TRUE
428e5c31af7Sopenharmony_ci	};
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci	{
431e5c31af7Sopenharmony_ci		const vector<VkFormat>	formats	= subgroups::getAllFormats();
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
434e5c31af7Sopenharmony_ci		{
435e5c31af7Sopenharmony_ci			const VkFormat	format					= formats[formatIndex];
436e5c31af7Sopenharmony_ci			const string	formatName				= subgroups::getFormatNameForGLSL(format);
437e5c31af7Sopenharmony_ci			const bool		needs8BitUBOStorage		= isFormat8bitTy(format);
438e5c31af7Sopenharmony_ci			const bool		needs16BitUBOStorage	= isFormat16BitTy(format);
439e5c31af7Sopenharmony_ci
440e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
441e5c31af7Sopenharmony_ci			{
442e5c31af7Sopenharmony_ci				const OpType	opType	= static_cast<OpType>(opTypeIndex);
443e5c31af7Sopenharmony_ci				const string	name	= getOpTypeCaseName(opType) + "_" + formatName;
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ci				for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
446e5c31af7Sopenharmony_ci				{
447e5c31af7Sopenharmony_ci					const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
448e5c31af7Sopenharmony_ci					const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
449e5c31af7Sopenharmony_ci					const string			testName				= name + testNameSuffix;
450e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef					=
451e5c31af7Sopenharmony_ci					{
452e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
453e5c31af7Sopenharmony_ci						VK_SHADER_STAGE_COMPUTE_BIT,	//  VkShaderStageFlags	shaderStage;
454e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
455e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
456e5c31af7Sopenharmony_ci						requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
457e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requires8BitUniformBuffer;
458e5c31af7Sopenharmony_ci						DE_FALSE						//  deBool				requires16BitUniformBuffer;
459e5c31af7Sopenharmony_ci					};
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(computeGroup.get(), testName,supportedCheck, initPrograms, test, caseDef);
462e5c31af7Sopenharmony_ci				}
463e5c31af7Sopenharmony_ci
464e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
465e5c31af7Sopenharmony_ci				for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
466e5c31af7Sopenharmony_ci				{
467e5c31af7Sopenharmony_ci					for (const auto& stage : meshStages)
468e5c31af7Sopenharmony_ci					{
469e5c31af7Sopenharmony_ci						const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
470e5c31af7Sopenharmony_ci						const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
471e5c31af7Sopenharmony_ci						const string			testName				= name + testNameSuffix + "_" + getShaderStageName(stage);
472e5c31af7Sopenharmony_ci						const CaseDefinition	caseDef					=
473e5c31af7Sopenharmony_ci						{
474e5c31af7Sopenharmony_ci							opType,							//  OpType				opType;
475e5c31af7Sopenharmony_ci							stage,							//  VkShaderStageFlags	shaderStage;
476e5c31af7Sopenharmony_ci							format,							//  VkFormat			format;
477e5c31af7Sopenharmony_ci							de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
478e5c31af7Sopenharmony_ci							requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
479e5c31af7Sopenharmony_ci							DE_FALSE,						//  deBool				requires8BitUniformBuffer;
480e5c31af7Sopenharmony_ci							DE_FALSE						//  deBool				requires16BitUniformBuffer;
481e5c31af7Sopenharmony_ci						};
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci						addFunctionCaseWithPrograms(meshGroup.get(), testName,supportedCheck, initPrograms, test, caseDef);
484e5c31af7Sopenharmony_ci					}
485e5c31af7Sopenharmony_ci				}
486e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_ci				{
489e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef		=
490e5c31af7Sopenharmony_ci					{
491e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
492e5c31af7Sopenharmony_ci						VK_SHADER_STAGE_ALL_GRAPHICS,	//  VkShaderStageFlags	shaderStage;
493e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
494e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
495e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
496e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requires8BitUniformBuffer;
497e5c31af7Sopenharmony_ci						DE_FALSE						//  deBool				requires16BitUniformBuffer;
498e5c31af7Sopenharmony_ci					};
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(graphicGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
501e5c31af7Sopenharmony_ci				}
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci				for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
504e5c31af7Sopenharmony_ci				{
505e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef		=
506e5c31af7Sopenharmony_ci					{
507e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
508e5c31af7Sopenharmony_ci						fbStages[stageIndex],			//  VkShaderStageFlags	shaderStage;
509e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
510e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
511e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
512e5c31af7Sopenharmony_ci						deBool(needs8BitUBOStorage),	//  deBool				requires8BitUniformBuffer;
513e5c31af7Sopenharmony_ci						deBool(needs16BitUBOStorage)	//  deBool				requires16BitUniformBuffer;
514e5c31af7Sopenharmony_ci					};
515e5c31af7Sopenharmony_ci					const string			testName	= name + "_" + getShaderStageName(caseDef.shaderStage);
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(framebufferGroup.get(), testName,supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
518e5c31af7Sopenharmony_ci				}
519e5c31af7Sopenharmony_ci			}
520e5c31af7Sopenharmony_ci		}
521e5c31af7Sopenharmony_ci	}
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
524e5c31af7Sopenharmony_ci	{
525e5c31af7Sopenharmony_ci		const vector<VkFormat>	formats	= subgroups::getAllRayTracingFormats();
526e5c31af7Sopenharmony_ci
527e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
528e5c31af7Sopenharmony_ci		{
529e5c31af7Sopenharmony_ci			const VkFormat	format		= formats[formatIndex];
530e5c31af7Sopenharmony_ci			const string	formatName	= subgroups::getFormatNameForGLSL(format);
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
533e5c31af7Sopenharmony_ci			{
534e5c31af7Sopenharmony_ci				const OpType			opType		= static_cast<OpType>(opTypeIndex);
535e5c31af7Sopenharmony_ci				const string			testName	= getOpTypeCaseName(opType) + "_" + formatName;
536e5c31af7Sopenharmony_ci				const CaseDefinition	caseDef		=
537e5c31af7Sopenharmony_ci				{
538e5c31af7Sopenharmony_ci					opType,							//  OpType				opType;
539e5c31af7Sopenharmony_ci					SHADER_STAGE_ALL_RAY_TRACING,	//  VkShaderStageFlags	shaderStage;
540e5c31af7Sopenharmony_ci					format,							//  VkFormat			format;
541e5c31af7Sopenharmony_ci					de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
542e5c31af7Sopenharmony_ci					DE_FALSE,						//  deBool				requiredSubgroupSize;
543e5c31af7Sopenharmony_ci					DE_FALSE,						//  deBool				requires8BitUniformBuffer;
544e5c31af7Sopenharmony_ci					DE_FALSE						//  deBool				requires16BitUniformBuffer;
545e5c31af7Sopenharmony_ci				};
546e5c31af7Sopenharmony_ci
547e5c31af7Sopenharmony_ci				addFunctionCaseWithPrograms(raytracingGroup.get(), testName,supportedCheck, initPrograms, test, caseDef);
548e5c31af7Sopenharmony_ci			}
549e5c31af7Sopenharmony_ci		}
550e5c31af7Sopenharmony_ci	}
551e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
554e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
555e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
556e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
557e5c31af7Sopenharmony_ci	group->addChild(raytracingGroup.release());
558e5c31af7Sopenharmony_ci	group->addChild(meshGroup.release());
559e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ci	return group.release();
562e5c31af7Sopenharmony_ci}
563e5c31af7Sopenharmony_ci} // subgroups
564e5c31af7Sopenharmony_ci} // vkt
565