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 "vktSubgroupsShuffleTests.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_SHUFFLE = 0,
42e5c31af7Sopenharmony_ci	OPTYPE_SHUFFLE_XOR,
43e5c31af7Sopenharmony_ci	OPTYPE_SHUFFLE_UP,
44e5c31af7Sopenharmony_ci	OPTYPE_SHUFFLE_DOWN,
45e5c31af7Sopenharmony_ci	OPTYPE_LAST
46e5c31af7Sopenharmony_ci};
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ci// For the second arguments of Xor, Up and Down.
49e5c31af7Sopenharmony_cienum class ArgType
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci	DYNAMIC = 0,
52e5c31af7Sopenharmony_ci	DYNAMICALLY_UNIFORM,
53e5c31af7Sopenharmony_ci	CONSTANT
54e5c31af7Sopenharmony_ci};
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_cistruct CaseDefinition
57e5c31af7Sopenharmony_ci{
58e5c31af7Sopenharmony_ci	OpType				opType;
59e5c31af7Sopenharmony_ci	VkShaderStageFlags	shaderStage;
60e5c31af7Sopenharmony_ci	VkFormat			format;
61e5c31af7Sopenharmony_ci	de::SharedPtr<bool>	geometryPointSizeSupported;
62e5c31af7Sopenharmony_ci	deBool				requiredSubgroupSize;
63e5c31af7Sopenharmony_ci	ArgType				argType;
64e5c31af7Sopenharmony_ci	deBool				requires8BitUniformBuffer;
65e5c31af7Sopenharmony_ci	deBool				requires16BitUniformBuffer;
66e5c31af7Sopenharmony_ci};
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages (const void*			internalData,
69e5c31af7Sopenharmony_ci									   vector<const void*>	datas,
70e5c31af7Sopenharmony_ci									   deUint32				width,
71e5c31af7Sopenharmony_ci									   deUint32)
72e5c31af7Sopenharmony_ci{
73e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ci	return subgroups::check(datas, width, 1);
76e5c31af7Sopenharmony_ci}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_cistatic bool checkComputeOrMesh (const void*			internalData,
79e5c31af7Sopenharmony_ci								vector<const void*>	datas,
80e5c31af7Sopenharmony_ci								const deUint32		numWorkgroups[3],
81e5c31af7Sopenharmony_ci								const deUint32		localSize[3],
82e5c31af7Sopenharmony_ci								deUint32)
83e5c31af7Sopenharmony_ci{
84e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci	return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 1);
87e5c31af7Sopenharmony_ci}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_cistring getOpTypeName (OpType opType)
90e5c31af7Sopenharmony_ci{
91e5c31af7Sopenharmony_ci	switch (opType)
92e5c31af7Sopenharmony_ci	{
93e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE:		return "subgroupShuffle";
94e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE_XOR:	return "subgroupShuffleXor";
95e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE_UP:		return "subgroupShuffleUp";
96e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE_DOWN:	return "subgroupShuffleDown";
97e5c31af7Sopenharmony_ci		default:					TCU_THROW(InternalError, "Unsupported op type");
98e5c31af7Sopenharmony_ci	}
99e5c31af7Sopenharmony_ci}
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_cistring getExtHeader (const CaseDefinition& caseDef)
102e5c31af7Sopenharmony_ci{
103e5c31af7Sopenharmony_ci	const string	eSource		= (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType)
104e5c31af7Sopenharmony_ci								? "#extension GL_KHR_shader_subgroup_shuffle: enable\n"
105e5c31af7Sopenharmony_ci								: "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	return	eSource
108e5c31af7Sopenharmony_ci			+ "#extension GL_KHR_shader_subgroup_ballot: enable\n"
109e5c31af7Sopenharmony_ci			+ subgroups::getAdditionalExtensionForFormat(caseDef.format);
110e5c31af7Sopenharmony_ci}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_civector<string> getPerStageHeadDeclarations (const CaseDefinition& caseDef)
113e5c31af7Sopenharmony_ci{
114e5c31af7Sopenharmony_ci	const string	formatName	= subgroups::getFormatNameForGLSL(caseDef.format);
115e5c31af7Sopenharmony_ci	const deUint32	stageCount	= subgroups::getStagesCount(caseDef.shaderStage);
116e5c31af7Sopenharmony_ci	const bool		fragment	= (caseDef.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT) != 0;
117e5c31af7Sopenharmony_ci	const size_t	resultSize	= stageCount + (fragment ? 1 : 0);
118e5c31af7Sopenharmony_ci	vector<string>	result		(resultSize, string());
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < result.size(); ++i)
121e5c31af7Sopenharmony_ci	{
122e5c31af7Sopenharmony_ci		const deUint32	binding0	= i;
123e5c31af7Sopenharmony_ci		const deUint32	binding1	= stageCount;
124e5c31af7Sopenharmony_ci		const deUint32	binding2	= stageCount + 1;
125e5c31af7Sopenharmony_ci		const string	buffer1		= (i == stageCount)
126e5c31af7Sopenharmony_ci									? "layout(location = 0) out uint result;\n"
127e5c31af7Sopenharmony_ci									: "layout(set = 0, binding = " + de::toString(binding0) + ", std430) buffer Buffer1\n"
128e5c31af7Sopenharmony_ci									  "{\n"
129e5c31af7Sopenharmony_ci									  "  uint result[];\n"
130e5c31af7Sopenharmony_ci									  "};\n";
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ci		const string	b2Layout	= ((caseDef.argType == ArgType::DYNAMIC) ? "std430"				: "std140");
133e5c31af7Sopenharmony_ci		const string	b2Type		= ((caseDef.argType == ArgType::DYNAMIC) ? "readonly buffer"	: "uniform");
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ci		result[i] =
136e5c31af7Sopenharmony_ci			buffer1 +
137e5c31af7Sopenharmony_ci			"layout(set = 0, binding = " + de::toString(binding1) + ", std430) readonly buffer Buffer2\n"
138e5c31af7Sopenharmony_ci			"{\n"
139e5c31af7Sopenharmony_ci			"  " + formatName + " data1[];\n"
140e5c31af7Sopenharmony_ci			"};\n"
141e5c31af7Sopenharmony_ci			"layout(set = 0, binding = " + de::toString(binding2) + ", " + b2Layout + ") " + b2Type + " Buffer3\n"
142e5c31af7Sopenharmony_ci			"{\n"
143e5c31af7Sopenharmony_ci			"  uint data2[];\n"
144e5c31af7Sopenharmony_ci			"};\n";
145e5c31af7Sopenharmony_ci	}
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_ci	return result;
148e5c31af7Sopenharmony_ci}
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_civector<string> getFramebufferPerStageHeadDeclarations (const CaseDefinition& caseDef)
151e5c31af7Sopenharmony_ci{
152e5c31af7Sopenharmony_ci	const string	formatName	= subgroups::getFormatNameForGLSL(caseDef.format);
153e5c31af7Sopenharmony_ci	const deUint32	stageCount	= subgroups::getStagesCount(caseDef.shaderStage);
154e5c31af7Sopenharmony_ci	vector<string>	result		(stageCount, string());
155e5c31af7Sopenharmony_ci	const auto		b2Len		= ((caseDef.argType == ArgType::DYNAMIC) ? subgroups::maxSupportedSubgroupSize() : 1u);
156e5c31af7Sopenharmony_ci	const string	buffer2
157e5c31af7Sopenharmony_ci	{
158e5c31af7Sopenharmony_ci		"layout(set = 0, binding = 0) uniform Buffer1\n"
159e5c31af7Sopenharmony_ci		"{\n"
160e5c31af7Sopenharmony_ci		"  " + formatName + " data1[" + de::toString(subgroups::maxSupportedSubgroupSize()) + "];\n"
161e5c31af7Sopenharmony_ci		"};\n"
162e5c31af7Sopenharmony_ci		"layout(set = 0, binding = 1) uniform Buffer2\n"
163e5c31af7Sopenharmony_ci		"{\n"
164e5c31af7Sopenharmony_ci		"  uint data2[" + de::toString(b2Len) + "];\n"
165e5c31af7Sopenharmony_ci		"};\n"
166e5c31af7Sopenharmony_ci	};
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ci	for (size_t i = 0; i < result.size(); ++i)
169e5c31af7Sopenharmony_ci	{
170e5c31af7Sopenharmony_ci		switch (i)
171e5c31af7Sopenharmony_ci		{
172e5c31af7Sopenharmony_ci			case 0: result[i] = "layout(location = 0) out float result;\n" + buffer2;		break;
173e5c31af7Sopenharmony_ci			case 1: result[i] = "layout(location = 0) out float out_color;\n" + buffer2;	break;
174e5c31af7Sopenharmony_ci			case 2: result[i] = "layout(location = 0) out float out_color[];\n" + buffer2;	break;
175e5c31af7Sopenharmony_ci			case 3: result[i] = "layout(location = 0) out float out_color;\n" + buffer2;	break;
176e5c31af7Sopenharmony_ci			default: TCU_THROW(InternalError, "Unknown stage");
177e5c31af7Sopenharmony_ci		}
178e5c31af7Sopenharmony_ci	}
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci	return result;
181e5c31af7Sopenharmony_ci}
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ciconst string getTestSource (const CaseDefinition& caseDef)
184e5c31af7Sopenharmony_ci{
185e5c31af7Sopenharmony_ci	const string	id			= caseDef.opType == OPTYPE_SHUFFLE		? "id_in"
186e5c31af7Sopenharmony_ci								: caseDef.opType == OPTYPE_SHUFFLE_XOR	? "gl_SubgroupInvocationID ^ id_in"
187e5c31af7Sopenharmony_ci								: caseDef.opType == OPTYPE_SHUFFLE_UP	? "gl_SubgroupInvocationID - id_in"
188e5c31af7Sopenharmony_ci								: caseDef.opType == OPTYPE_SHUFFLE_DOWN	? "gl_SubgroupInvocationID + id_in"
189e5c31af7Sopenharmony_ci								: "";
190e5c31af7Sopenharmony_ci	const string	idInSource	= caseDef.argType == ArgType::DYNAMIC				? "data2[gl_SubgroupInvocationID] & (gl_SubgroupSize - 1)"
191e5c31af7Sopenharmony_ci								: caseDef.argType == ArgType::DYNAMICALLY_UNIFORM	? "data2[0] % 32"
192e5c31af7Sopenharmony_ci								: caseDef.argType == ArgType::CONSTANT				? "5"
193e5c31af7Sopenharmony_ci								: "";
194e5c31af7Sopenharmony_ci	const string	testSource	=
195e5c31af7Sopenharmony_ci		"  uint temp_res;\n"
196e5c31af7Sopenharmony_ci		"  uvec4 mask = subgroupBallot(true);\n"
197e5c31af7Sopenharmony_ci		"  uint id_in = " + idInSource + ";\n"
198e5c31af7Sopenharmony_ci		"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " op = "
199e5c31af7Sopenharmony_ci		+ getOpTypeName(caseDef.opType) + "(data1[gl_SubgroupInvocationID], id_in);\n"
200e5c31af7Sopenharmony_ci		"  uint id = " + id + ";\n"
201e5c31af7Sopenharmony_ci		"  if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
202e5c31af7Sopenharmony_ci		"  {\n"
203e5c31af7Sopenharmony_ci		"    temp_res = (op == data1[id]) ? 1 : 0;\n"
204e5c31af7Sopenharmony_ci		"  }\n"
205e5c31af7Sopenharmony_ci		"  else\n"
206e5c31af7Sopenharmony_ci		"  {\n"
207e5c31af7Sopenharmony_ci		"    temp_res = 1; // Invocation we read from was inactive, so we can't verify results!\n"
208e5c31af7Sopenharmony_ci		"  }\n"
209e5c31af7Sopenharmony_ci		"  tempRes = temp_res;\n";
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci	return testSource;
212e5c31af7Sopenharmony_ci}
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
215e5c31af7Sopenharmony_ci{
216e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
217e5c31af7Sopenharmony_ci	const string				extHeader			= getExtHeader(caseDef);
218e5c31af7Sopenharmony_ci	const string				testSrc				= getTestSource(caseDef);
219e5c31af7Sopenharmony_ci	const vector<string>		headDeclarations	= getFramebufferPerStageHeadDeclarations(caseDef);
220e5c31af7Sopenharmony_ci	const bool					pointSizeSupported	= *caseDef.geometryPointSizeSupported;
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci	subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
223e5c31af7Sopenharmony_ci}
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_civoid initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
226e5c31af7Sopenharmony_ci{
227e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
228e5c31af7Sopenharmony_ci	const bool					spirv14required		= (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
229e5c31af7Sopenharmony_ci#else
230e5c31af7Sopenharmony_ci	const bool					spirv14required		= false;
231e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
232e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion		= spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
233e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, spirvVersion, 0u, spirv14required);
234e5c31af7Sopenharmony_ci	const string				extHeader			= getExtHeader(caseDef);
235e5c31af7Sopenharmony_ci	const string				testSrc				= getTestSource(caseDef);
236e5c31af7Sopenharmony_ci	const vector<string>		headDeclarations	= getPerStageHeadDeclarations(caseDef);
237e5c31af7Sopenharmony_ci	const bool					pointSizeSupported	= *caseDef.geometryPointSizeSupported;
238e5c31af7Sopenharmony_ci
239e5c31af7Sopenharmony_ci	subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
240e5c31af7Sopenharmony_ci}
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
243e5c31af7Sopenharmony_ci{
244e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
245e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci	switch (caseDef.opType)
248e5c31af7Sopenharmony_ci	{
249e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE:
250e5c31af7Sopenharmony_ci		case OPTYPE_SHUFFLE_XOR:
251e5c31af7Sopenharmony_ci			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_SHUFFLE_BIT))
252e5c31af7Sopenharmony_ci			{
253e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
254e5c31af7Sopenharmony_ci			}
255e5c31af7Sopenharmony_ci			break;
256e5c31af7Sopenharmony_ci		default:
257e5c31af7Sopenharmony_ci			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
258e5c31af7Sopenharmony_ci			{
259e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
260e5c31af7Sopenharmony_ci			}
261e5c31af7Sopenharmony_ci			break;
262e5c31af7Sopenharmony_ci	}
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_ci	if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
265e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci	if (caseDef.requires16BitUniformBuffer)
268e5c31af7Sopenharmony_ci	{
269e5c31af7Sopenharmony_ci		if (!subgroups::is16BitUBOStorageSupported(context))
270e5c31af7Sopenharmony_ci		{
271e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
272e5c31af7Sopenharmony_ci		}
273e5c31af7Sopenharmony_ci	}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ci	if (caseDef.requires8BitUniformBuffer)
276e5c31af7Sopenharmony_ci	{
277e5c31af7Sopenharmony_ci		if (!subgroups::is8BitUBOStorageSupported(context))
278e5c31af7Sopenharmony_ci		{
279e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
280e5c31af7Sopenharmony_ci		}
281e5c31af7Sopenharmony_ci	}
282e5c31af7Sopenharmony_ci
283e5c31af7Sopenharmony_ci	if (caseDef.requiredSubgroupSize)
284e5c31af7Sopenharmony_ci	{
285e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
288e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeatures&		subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeatures();
289e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
290e5c31af7Sopenharmony_ci#else
291e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&	subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeaturesEXT();
292e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
293e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
296e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
299e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci		if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
302e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
303e5c31af7Sopenharmony_ci	}
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ci	*caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
308e5c31af7Sopenharmony_ci	if (isAllRayTracingStages(caseDef.shaderStage))
309e5c31af7Sopenharmony_ci	{
310e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
311e5c31af7Sopenharmony_ci	}
312e5c31af7Sopenharmony_ci	else if (isAllMeshShadingStages(caseDef.shaderStage))
313e5c31af7Sopenharmony_ci	{
314e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
315e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ci		if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
318e5c31af7Sopenharmony_ci		{
319e5c31af7Sopenharmony_ci			const auto& features = context.getMeshShaderFeaturesEXT();
320e5c31af7Sopenharmony_ci			if (!features.taskShader)
321e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Task shaders not supported");
322e5c31af7Sopenharmony_ci		}
323e5c31af7Sopenharmony_ci	}
324e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	subgroups::supportedCheckShader(context, caseDef.shaderStage);
327e5c31af7Sopenharmony_ci}
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ciTestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
330e5c31af7Sopenharmony_ci{
331e5c31af7Sopenharmony_ci	const VkDeviceSize			secondBufferSize = ((caseDef.argType == ArgType::DYNAMIC) ? subgroups::maxSupportedSubgroupSize() : 1u);
332e5c31af7Sopenharmony_ci	const subgroups::SSBOData	inputData[2]
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		{
335e5c31af7Sopenharmony_ci			subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
336e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd140,		//  InputDataLayoutType			layout;
337e5c31af7Sopenharmony_ci			caseDef.format,							//  vk::VkFormat				format;
338e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
339e5c31af7Sopenharmony_ci			subgroups::SSBOData::BindingUBO,		//  BindingType					bindingType;
340e5c31af7Sopenharmony_ci		},
341e5c31af7Sopenharmony_ci		{
342e5c31af7Sopenharmony_ci			subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
343e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd140,		//  InputDataLayoutType			layout;
344e5c31af7Sopenharmony_ci			VK_FORMAT_R32_UINT,						//  vk::VkFormat				format;
345e5c31af7Sopenharmony_ci			secondBufferSize,						//  vk::VkDeviceSize			numElements;
346e5c31af7Sopenharmony_ci			subgroups::SSBOData::BindingUBO,		//  BindingType					bindingType;
347e5c31af7Sopenharmony_ci		}
348e5c31af7Sopenharmony_ci	};
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci	switch (caseDef.shaderStage)
351e5c31af7Sopenharmony_ci	{
352e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_VERTEX_BIT:					return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages);
353e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_GEOMETRY_BIT:					return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages);
354e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
355e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return subgroups::makeTessellationEvaluationFrameBufferTest(context,  VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
356e5c31af7Sopenharmony_ci		default:											TCU_THROW(InternalError, "Unhandled shader stage");
357e5c31af7Sopenharmony_ci	}
358e5c31af7Sopenharmony_ci}
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_ciTestStatus test (Context& context, const CaseDefinition caseDef)
361e5c31af7Sopenharmony_ci{
362e5c31af7Sopenharmony_ci	const auto			secondBufferLayout	= ((caseDef.argType == ArgType::DYNAMIC)
363e5c31af7Sopenharmony_ci											? subgroups::SSBOData::LayoutStd430
364e5c31af7Sopenharmony_ci											: subgroups::SSBOData::LayoutStd140);
365e5c31af7Sopenharmony_ci	const VkDeviceSize	secondBufferElems	= ((caseDef.argType == ArgType::DYNAMIC)
366e5c31af7Sopenharmony_ci											? subgroups::maxSupportedSubgroupSize()
367e5c31af7Sopenharmony_ci											: 1u);
368e5c31af7Sopenharmony_ci	const auto			secondBufferType	= ((caseDef.argType == ArgType::DYNAMIC)
369e5c31af7Sopenharmony_ci											? subgroups::SSBOData::BindingSSBO
370e5c31af7Sopenharmony_ci											: subgroups::SSBOData::BindingUBO);
371e5c31af7Sopenharmony_ci
372e5c31af7Sopenharmony_ci	const bool			isCompute			= isAllComputeStages(caseDef.shaderStage);
373e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
374e5c31af7Sopenharmony_ci	const bool			isMesh				= isAllMeshShadingStages(caseDef.shaderStage);
375e5c31af7Sopenharmony_ci#else
376e5c31af7Sopenharmony_ci	const bool			isMesh				= false;
377e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
378e5c31af7Sopenharmony_ci	DE_ASSERT(!(isCompute && isMesh));
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci	if (isCompute || isMesh)
381e5c31af7Sopenharmony_ci	{
382e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
383e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
384e5c31af7Sopenharmony_ci#else
385e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
386e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
387e5c31af7Sopenharmony_ci		TestLog&												log								= context.getTestContext().getLog();
388e5c31af7Sopenharmony_ci		const subgroups::SSBOData								inputData[2]
389e5c31af7Sopenharmony_ci		{
390e5c31af7Sopenharmony_ci			{
391e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
392e5c31af7Sopenharmony_ci				subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
393e5c31af7Sopenharmony_ci				caseDef.format,							//  vk::VkFormat				format;
394e5c31af7Sopenharmony_ci				subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
395e5c31af7Sopenharmony_ci			},
396e5c31af7Sopenharmony_ci			{
397e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
398e5c31af7Sopenharmony_ci				secondBufferLayout,						//  InputDataLayoutType			layout;
399e5c31af7Sopenharmony_ci				VK_FORMAT_R32_UINT,						//  vk::VkFormat				format;
400e5c31af7Sopenharmony_ci				secondBufferElems,						//  vk::VkDeviceSize			numElements;
401e5c31af7Sopenharmony_ci				secondBufferType,
402e5c31af7Sopenharmony_ci			},
403e5c31af7Sopenharmony_ci		};
404e5c31af7Sopenharmony_ci
405e5c31af7Sopenharmony_ci		if (caseDef.requiredSubgroupSize == DE_FALSE)
406e5c31af7Sopenharmony_ci		{
407e5c31af7Sopenharmony_ci			if (isCompute)
408e5c31af7Sopenharmony_ci				return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkComputeOrMesh);
409e5c31af7Sopenharmony_ci			else
410e5c31af7Sopenharmony_ci				return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkComputeOrMesh);
411e5c31af7Sopenharmony_ci		}
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_ci		log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
414e5c31af7Sopenharmony_ci			<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci		// According to the spec, requiredSubgroupSize must be a power-of-two integer.
417e5c31af7Sopenharmony_ci		for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
418e5c31af7Sopenharmony_ci		{
419e5c31af7Sopenharmony_ci			TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci			if (isCompute)
422e5c31af7Sopenharmony_ci				result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkComputeOrMesh, size);
423e5c31af7Sopenharmony_ci			else
424e5c31af7Sopenharmony_ci				result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkComputeOrMesh, size);
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci			if (result.getCode() != QP_TEST_RESULT_PASS)
427e5c31af7Sopenharmony_ci			{
428e5c31af7Sopenharmony_ci				log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
429e5c31af7Sopenharmony_ci				return result;
430e5c31af7Sopenharmony_ci			}
431e5c31af7Sopenharmony_ci		}
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci		return TestStatus::pass("OK");
434e5c31af7Sopenharmony_ci	}
435e5c31af7Sopenharmony_ci	else if (isAllGraphicsStages(caseDef.shaderStage))
436e5c31af7Sopenharmony_ci	{
437e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages			= subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
438e5c31af7Sopenharmony_ci		const subgroups::SSBOData	inputData[2]
439e5c31af7Sopenharmony_ci		{
440e5c31af7Sopenharmony_ci			{
441e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
442e5c31af7Sopenharmony_ci				subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
443e5c31af7Sopenharmony_ci				caseDef.format,							//  vk::VkFormat				format;
444e5c31af7Sopenharmony_ci				subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
445e5c31af7Sopenharmony_ci				subgroups::SSBOData::BindingSSBO,		//  bool						isImage;
446e5c31af7Sopenharmony_ci				4u,										//  deUint32					binding;
447e5c31af7Sopenharmony_ci				stages,									//  vk::VkShaderStageFlags		stages;
448e5c31af7Sopenharmony_ci			},
449e5c31af7Sopenharmony_ci			{
450e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
451e5c31af7Sopenharmony_ci				secondBufferLayout,						//  InputDataLayoutType			layout;
452e5c31af7Sopenharmony_ci				VK_FORMAT_R32_UINT,						//  vk::VkFormat				format;
453e5c31af7Sopenharmony_ci				secondBufferElems,						//  vk::VkDeviceSize			numElements;
454e5c31af7Sopenharmony_ci				secondBufferType,						//  bool						isImage;
455e5c31af7Sopenharmony_ci				5u,										//  deUint32					binding;
456e5c31af7Sopenharmony_ci				stages,									//  vk::VkShaderStageFlags		stages;
457e5c31af7Sopenharmony_ci			},
458e5c31af7Sopenharmony_ci		};
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci		return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, stages);
461e5c31af7Sopenharmony_ci	}
462e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
463e5c31af7Sopenharmony_ci	else if (isAllRayTracingStages(caseDef.shaderStage))
464e5c31af7Sopenharmony_ci	{
465e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages			= subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
466e5c31af7Sopenharmony_ci		const subgroups::SSBOData	inputData[2]
467e5c31af7Sopenharmony_ci		{
468e5c31af7Sopenharmony_ci			{
469e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
470e5c31af7Sopenharmony_ci				subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
471e5c31af7Sopenharmony_ci				caseDef.format,							//  vk::VkFormat				format;
472e5c31af7Sopenharmony_ci				subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
473e5c31af7Sopenharmony_ci				subgroups::SSBOData::BindingSSBO,		//  bool						isImage;
474e5c31af7Sopenharmony_ci				6u,										//  deUint32					binding;
475e5c31af7Sopenharmony_ci				stages,									//  vk::VkShaderStageFlags		stages;
476e5c31af7Sopenharmony_ci			},
477e5c31af7Sopenharmony_ci			{
478e5c31af7Sopenharmony_ci				subgroups::SSBOData::InitializeNonZero,	//  InputDataInitializeType		initializeType;
479e5c31af7Sopenharmony_ci				secondBufferLayout,						//  InputDataLayoutType			layout;
480e5c31af7Sopenharmony_ci				VK_FORMAT_R32_UINT,						//  vk::VkFormat				format;
481e5c31af7Sopenharmony_ci				secondBufferElems,						//  vk::VkDeviceSize			numElements;
482e5c31af7Sopenharmony_ci				secondBufferType,						//  bool						isImage;
483e5c31af7Sopenharmony_ci				7u,										//  deUint32					binding;
484e5c31af7Sopenharmony_ci				stages,									//  vk::VkShaderStageFlags		stages;
485e5c31af7Sopenharmony_ci			},
486e5c31af7Sopenharmony_ci		};
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_ci		return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, stages);
489e5c31af7Sopenharmony_ci	}
490e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
491e5c31af7Sopenharmony_ci	else
492e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unknown stage or invalid stage set");
493e5c31af7Sopenharmony_ci}
494e5c31af7Sopenharmony_ci}
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_cinamespace vkt
497e5c31af7Sopenharmony_ci{
498e5c31af7Sopenharmony_cinamespace subgroups
499e5c31af7Sopenharmony_ci{
500e5c31af7Sopenharmony_ciTestCaseGroup* createSubgroupsShuffleTests (TestContext& testCtx)
501e5c31af7Sopenharmony_ci{
502e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	group				(new TestCaseGroup(testCtx, "shuffle", "Subgroup shuffle category tests"));
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	graphicGroup		(new TestCaseGroup(testCtx, "graphics", "Subgroup shuffle category tests: graphics"));
505e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	computeGroup		(new TestCaseGroup(testCtx, "compute", "Subgroup shuffle category tests: compute"));
506e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	framebufferGroup	(new TestCaseGroup(testCtx, "framebuffer", "Subgroup shuffle category tests: framebuffer"));
507e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
508e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	raytracingGroup		(new TestCaseGroup(testCtx, "ray_tracing", "Subgroup shuffle category tests: ray tracing"));
509e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	meshGroup			(new TestCaseGroup(testCtx, "mesh", "Subgroup shuffle category tests: mesh shading"));
510e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_ci	const VkShaderStageFlags	fbStages[]			=
513e5c31af7Sopenharmony_ci	{
514e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_VERTEX_BIT,
515e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
516e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
517e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_GEOMETRY_BIT,
518e5c31af7Sopenharmony_ci	};
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
521e5c31af7Sopenharmony_ci	const VkShaderStageFlags	meshStages[]		=
522e5c31af7Sopenharmony_ci	{
523e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_MESH_BIT_EXT,
524e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_TASK_BIT_EXT,
525e5c31af7Sopenharmony_ci	};
526e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
527e5c31af7Sopenharmony_ci
528e5c31af7Sopenharmony_ci	const deBool				boolValues[]		=
529e5c31af7Sopenharmony_ci	{
530e5c31af7Sopenharmony_ci		DE_FALSE,
531e5c31af7Sopenharmony_ci		DE_TRUE
532e5c31af7Sopenharmony_ci	};
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci	const struct
535e5c31af7Sopenharmony_ci	{
536e5c31af7Sopenharmony_ci		ArgType		argType;
537e5c31af7Sopenharmony_ci		const char*	suffix;
538e5c31af7Sopenharmony_ci	} argCases[] =
539e5c31af7Sopenharmony_ci	{
540e5c31af7Sopenharmony_ci		{	ArgType::DYNAMIC,				""						},
541e5c31af7Sopenharmony_ci		{	ArgType::DYNAMICALLY_UNIFORM,	"_dynamically_uniform"	},
542e5c31af7Sopenharmony_ci		{	ArgType::CONSTANT,				"_constant"				},
543e5c31af7Sopenharmony_ci	};
544e5c31af7Sopenharmony_ci
545e5c31af7Sopenharmony_ci	{
546e5c31af7Sopenharmony_ci		const vector<VkFormat>	formats	= subgroups::getAllFormats();
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
549e5c31af7Sopenharmony_ci		{
550e5c31af7Sopenharmony_ci			const VkFormat	format					= formats[formatIndex];
551e5c31af7Sopenharmony_ci			const string	formatName				= subgroups::getFormatNameForGLSL(format);
552e5c31af7Sopenharmony_ci			const bool		needs8BitUBOStorage		= isFormat8bitTy(format);
553e5c31af7Sopenharmony_ci			const bool		needs16BitUBOStorage	= isFormat16BitTy(format);
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
556e5c31af7Sopenharmony_ci			{
557e5c31af7Sopenharmony_ci				for (const auto& argCase : argCases)
558e5c31af7Sopenharmony_ci				{
559e5c31af7Sopenharmony_ci					const OpType opType = static_cast<OpType>(opTypeIndex);
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ci					if (opType == OPTYPE_SHUFFLE && argCase.argType != ArgType::DYNAMIC)
562e5c31af7Sopenharmony_ci						continue;
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ci					const string name = de::toLower(getOpTypeName(opType)) + "_" + formatName + argCase.suffix;
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_ci					{
567e5c31af7Sopenharmony_ci						const CaseDefinition	caseDef		=
568e5c31af7Sopenharmony_ci						{
569e5c31af7Sopenharmony_ci							opType,							//  OpType				opType;
570e5c31af7Sopenharmony_ci							VK_SHADER_STAGE_ALL_GRAPHICS,	//  VkShaderStageFlags	shaderStage;
571e5c31af7Sopenharmony_ci							format,							//  VkFormat			format;
572e5c31af7Sopenharmony_ci							de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
573e5c31af7Sopenharmony_ci							DE_FALSE,						//  deBool				requiredSubgroupSize;
574e5c31af7Sopenharmony_ci							argCase.argType,				//  ArgType				argType;
575e5c31af7Sopenharmony_ci							DE_FALSE,						//  deBool				requires8BitUniformBuffer;
576e5c31af7Sopenharmony_ci							DE_FALSE						//  deBool				requires16BitUniformBuffer;
577e5c31af7Sopenharmony_ci						};
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci						addFunctionCaseWithPrograms(graphicGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
580e5c31af7Sopenharmony_ci					}
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ci					for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
583e5c31af7Sopenharmony_ci					{
584e5c31af7Sopenharmony_ci						const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
585e5c31af7Sopenharmony_ci						const string			testName				= name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
586e5c31af7Sopenharmony_ci						const CaseDefinition	caseDef					=
587e5c31af7Sopenharmony_ci						{
588e5c31af7Sopenharmony_ci							opType,							//  OpType				opType;
589e5c31af7Sopenharmony_ci							VK_SHADER_STAGE_COMPUTE_BIT,	//  VkShaderStageFlags	shaderStage;
590e5c31af7Sopenharmony_ci							format,							//  VkFormat			format;
591e5c31af7Sopenharmony_ci							de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
592e5c31af7Sopenharmony_ci							requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
593e5c31af7Sopenharmony_ci							argCase.argType,				//  ArgType				argType;
594e5c31af7Sopenharmony_ci							DE_FALSE,						//  deBool				requires8BitUniformBuffer;
595e5c31af7Sopenharmony_ci							DE_FALSE						//  deBool				requires16BitUniformBuffer;
596e5c31af7Sopenharmony_ci						};
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci						addFunctionCaseWithPrograms(computeGroup.get(), testName,supportedCheck, initPrograms, test, caseDef);
599e5c31af7Sopenharmony_ci					}
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
602e5c31af7Sopenharmony_ci					for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
603e5c31af7Sopenharmony_ci					{
604e5c31af7Sopenharmony_ci						for (const auto& stage : meshStages)
605e5c31af7Sopenharmony_ci						{
606e5c31af7Sopenharmony_ci							const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
607e5c31af7Sopenharmony_ci							const string			testName				= name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "") + "_" + getShaderStageName(stage);
608e5c31af7Sopenharmony_ci							const CaseDefinition	caseDef					=
609e5c31af7Sopenharmony_ci							{
610e5c31af7Sopenharmony_ci								opType,							//  OpType				opType;
611e5c31af7Sopenharmony_ci								stage,							//  VkShaderStageFlags	shaderStage;
612e5c31af7Sopenharmony_ci								format,							//  VkFormat			format;
613e5c31af7Sopenharmony_ci								de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
614e5c31af7Sopenharmony_ci								requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
615e5c31af7Sopenharmony_ci								argCase.argType,				//  ArgType				argType;
616e5c31af7Sopenharmony_ci								DE_FALSE,						//  deBool				requires8BitUniformBuffer;
617e5c31af7Sopenharmony_ci								DE_FALSE,						//  deBool				requires16BitUniformBuffer;
618e5c31af7Sopenharmony_ci							};
619e5c31af7Sopenharmony_ci
620e5c31af7Sopenharmony_ci							addFunctionCaseWithPrograms(meshGroup.get(), testName,supportedCheck, initPrograms, test, caseDef);
621e5c31af7Sopenharmony_ci						}
622e5c31af7Sopenharmony_ci					}
623e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
624e5c31af7Sopenharmony_ci
625e5c31af7Sopenharmony_ci					for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
626e5c31af7Sopenharmony_ci					{
627e5c31af7Sopenharmony_ci						const CaseDefinition	caseDef		=
628e5c31af7Sopenharmony_ci						{
629e5c31af7Sopenharmony_ci							opType,							//  OpType				opType;
630e5c31af7Sopenharmony_ci							fbStages[stageIndex],			//  VkShaderStageFlags	shaderStage;
631e5c31af7Sopenharmony_ci							format,							//  VkFormat			format;
632e5c31af7Sopenharmony_ci							de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
633e5c31af7Sopenharmony_ci							DE_FALSE,						//  deBool				requiredSubgroupSize;
634e5c31af7Sopenharmony_ci							argCase.argType,				//  ArgType				argType;
635e5c31af7Sopenharmony_ci							deBool(needs8BitUBOStorage),	//  deBool				requires8BitUniformBuffer;
636e5c31af7Sopenharmony_ci							deBool(needs16BitUBOStorage)	//  deBool				requires16BitUniformBuffer;
637e5c31af7Sopenharmony_ci						};
638e5c31af7Sopenharmony_ci						const string			testName	= name + "_" + getShaderStageName(caseDef.shaderStage);
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci						addFunctionCaseWithPrograms(framebufferGroup.get(), testName,supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
641e5c31af7Sopenharmony_ci					}
642e5c31af7Sopenharmony_ci				}
643e5c31af7Sopenharmony_ci			}
644e5c31af7Sopenharmony_ci		}
645e5c31af7Sopenharmony_ci	}
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
648e5c31af7Sopenharmony_ci	{
649e5c31af7Sopenharmony_ci		const vector<VkFormat>	formats	= subgroups::getAllRayTracingFormats();
650e5c31af7Sopenharmony_ci
651e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
652e5c31af7Sopenharmony_ci		{
653e5c31af7Sopenharmony_ci			const VkFormat	format		= formats[formatIndex];
654e5c31af7Sopenharmony_ci			const string	formatName	= subgroups::getFormatNameForGLSL(format);
655e5c31af7Sopenharmony_ci
656e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
657e5c31af7Sopenharmony_ci			{
658e5c31af7Sopenharmony_ci				for (const auto& argCase : argCases)
659e5c31af7Sopenharmony_ci				{
660e5c31af7Sopenharmony_ci					const OpType opType = static_cast<OpType>(opTypeIndex);
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ci					if (opType == OPTYPE_SHUFFLE && argCase.argType != ArgType::DYNAMIC)
663e5c31af7Sopenharmony_ci						continue;
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci					const string			name	= de::toLower(getOpTypeName(opType)) + "_" + formatName + argCase.suffix;
666e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef	=
667e5c31af7Sopenharmony_ci					{
668e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
669e5c31af7Sopenharmony_ci						SHADER_STAGE_ALL_RAY_TRACING,	//  VkShaderStageFlags	shaderStage;
670e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
671e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
672e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
673e5c31af7Sopenharmony_ci						argCase.argType,				//  ArgType				argType;
674e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requires8BitUniformBuffer;
675e5c31af7Sopenharmony_ci						DE_FALSE						//  deBool				requires16BitUniformBuffer;
676e5c31af7Sopenharmony_ci					};
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(raytracingGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
679e5c31af7Sopenharmony_ci				}
680e5c31af7Sopenharmony_ci			}
681e5c31af7Sopenharmony_ci		}
682e5c31af7Sopenharmony_ci	}
683e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
686e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
687e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
688e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
689e5c31af7Sopenharmony_ci	group->addChild(raytracingGroup.release());
690e5c31af7Sopenharmony_ci	group->addChild(meshGroup.release());
691e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
692e5c31af7Sopenharmony_ci
693e5c31af7Sopenharmony_ci	return group.release();
694e5c31af7Sopenharmony_ci}
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci} // subgroups
697e5c31af7Sopenharmony_ci} // vkt
698