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 "vktSubgroupsVoteTests.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_ALL			= 0,
42e5c31af7Sopenharmony_ci	OPTYPE_ANY			= 1,
43e5c31af7Sopenharmony_ci	OPTYPE_ALLEQUAL		= 2,
44e5c31af7Sopenharmony_ci	OPTYPE_LAST_NON_ARB	= 3,
45e5c31af7Sopenharmony_ci	OPTYPE_ALL_ARB		= 4,
46e5c31af7Sopenharmony_ci	OPTYPE_ANY_ARB		= 5,
47e5c31af7Sopenharmony_ci	OPTYPE_ALLEQUAL_ARB	= 6,
48e5c31af7Sopenharmony_ci	OPTYPE_LAST
49e5c31af7Sopenharmony_ci};
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_cistruct CaseDefinition
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_ci	OpType				opType;
54e5c31af7Sopenharmony_ci	VkShaderStageFlags	shaderStage;
55e5c31af7Sopenharmony_ci	VkFormat			format;
56e5c31af7Sopenharmony_ci	de::SharedPtr<bool>	geometryPointSizeSupported;
57e5c31af7Sopenharmony_ci	deBool				requiredSubgroupSize;
58e5c31af7Sopenharmony_ci	deBool				requires8BitUniformBuffer;
59e5c31af7Sopenharmony_ci	deBool				requires16BitUniformBuffer;
60e5c31af7Sopenharmony_ci};
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages (const void*			internalData,
63e5c31af7Sopenharmony_ci									   vector<const void*>	datas,
64e5c31af7Sopenharmony_ci									   deUint32				width,
65e5c31af7Sopenharmony_ci									   deUint32)
66e5c31af7Sopenharmony_ci{
67e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci	return subgroups::check(datas, width, 0x1F);
70e5c31af7Sopenharmony_ci}
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_cistatic bool checkFragmentPipelineStages (const void*			internalData,
73e5c31af7Sopenharmony_ci										 vector<const void*>	datas,
74e5c31af7Sopenharmony_ci										 deUint32				width,
75e5c31af7Sopenharmony_ci										 deUint32				height,
76e5c31af7Sopenharmony_ci										 deUint32)
77e5c31af7Sopenharmony_ci{
78e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < width; ++x)
83e5c31af7Sopenharmony_ci	{
84e5c31af7Sopenharmony_ci		for (deUint32 y = 0u; y < height; ++y)
85e5c31af7Sopenharmony_ci		{
86e5c31af7Sopenharmony_ci			const deUint32 ndx = (x * height + y);
87e5c31af7Sopenharmony_ci			const deUint32 val = data[ndx] & 0x1F;
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci			if (data[ndx] & 0x40) //Helper fragment shader invocation was executed
90e5c31af7Sopenharmony_ci			{
91e5c31af7Sopenharmony_ci				if(val != 0x1F)
92e5c31af7Sopenharmony_ci					return false;
93e5c31af7Sopenharmony_ci			}
94e5c31af7Sopenharmony_ci			else //Helper fragment shader invocation was not executed yet
95e5c31af7Sopenharmony_ci			{
96e5c31af7Sopenharmony_ci				if (val != 0x1E)
97e5c31af7Sopenharmony_ci					return false;
98e5c31af7Sopenharmony_ci			}
99e5c31af7Sopenharmony_ci		}
100e5c31af7Sopenharmony_ci	}
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci	return true;
103e5c31af7Sopenharmony_ci}
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_cistatic bool checkComputeOrMesh (const void*			internalData,
106e5c31af7Sopenharmony_ci								vector<const void*>	datas,
107e5c31af7Sopenharmony_ci								const deUint32		numWorkgroups[3],
108e5c31af7Sopenharmony_ci								const deUint32		localSize[3],
109e5c31af7Sopenharmony_ci								deUint32)
110e5c31af7Sopenharmony_ci{
111e5c31af7Sopenharmony_ci	DE_UNREF(internalData);
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 0x1F);
114e5c31af7Sopenharmony_ci}
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_cistring getOpTypeName (int opType)
117e5c31af7Sopenharmony_ci{
118e5c31af7Sopenharmony_ci	switch (opType)
119e5c31af7Sopenharmony_ci	{
120e5c31af7Sopenharmony_ci		case OPTYPE_ALL:			return "subgroupAll";
121e5c31af7Sopenharmony_ci		case OPTYPE_ANY:			return "subgroupAny";
122e5c31af7Sopenharmony_ci		case OPTYPE_ALLEQUAL:		return "subgroupAllEqual";
123e5c31af7Sopenharmony_ci		case OPTYPE_ALL_ARB:		return "allInvocationsARB";
124e5c31af7Sopenharmony_ci		case OPTYPE_ANY_ARB:		return "anyInvocationARB";
125e5c31af7Sopenharmony_ci		case OPTYPE_ALLEQUAL_ARB:	return "allInvocationsEqualARB";
126e5c31af7Sopenharmony_ci		default:					TCU_THROW(InternalError, "Unsupported op type");
127e5c31af7Sopenharmony_ci	}
128e5c31af7Sopenharmony_ci}
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_cibool fmtIsBoolean (VkFormat format)
131e5c31af7Sopenharmony_ci{
132e5c31af7Sopenharmony_ci	// For reasons unknown, the tests use R8_USCALED as the boolean format
133e5c31af7Sopenharmony_ci	return	format == VK_FORMAT_R8_USCALED || format == VK_FORMAT_R8G8_USCALED ||
134e5c31af7Sopenharmony_ci			format == VK_FORMAT_R8G8B8_USCALED || format == VK_FORMAT_R8G8B8A8_USCALED;
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ciconst string getExtensions (bool arbFunctions)
138e5c31af7Sopenharmony_ci{
139e5c31af7Sopenharmony_ci	return arbFunctions	?	"#extension GL_ARB_shader_group_vote: enable\n"
140e5c31af7Sopenharmony_ci							"#extension GL_KHR_shader_subgroup_basic: enable\n"
141e5c31af7Sopenharmony_ci						:	"#extension GL_KHR_shader_subgroup_vote: enable\n";
142e5c31af7Sopenharmony_ci}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ciconst string getStageTestSource (const CaseDefinition& caseDef)
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci	const bool		formatIsBoolean	= fmtIsBoolean(caseDef.format);
147e5c31af7Sopenharmony_ci	const string	op				= getOpTypeName(caseDef.opType);
148e5c31af7Sopenharmony_ci	const string	fmt				= subgroups::getFormatNameForGLSL(caseDef.format);
149e5c31af7Sopenharmony_ci	const string	computePart		= isAllComputeStages(caseDef.shaderStage)
150e5c31af7Sopenharmony_ci									? op + "(data[gl_SubgroupInvocationID] > 0) ? 0x4 : 0x0"
151e5c31af7Sopenharmony_ci									: "0x4";
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_ci	return
154e5c31af7Sopenharmony_ci		(OPTYPE_ALL == caseDef.opType || OPTYPE_ALL_ARB == caseDef.opType) ?
155e5c31af7Sopenharmony_ci			"  tempRes = " + op + "(true) ? 0x1 : 0;\n"
156e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(false) ? 0 : 0x1A;\n"
157e5c31af7Sopenharmony_ci			"  tempRes |= " + computePart + ";\n"
158e5c31af7Sopenharmony_ci		: (OPTYPE_ANY == caseDef.opType || OPTYPE_ANY_ARB == caseDef.opType) ?
159e5c31af7Sopenharmony_ci			"  tempRes = " + op + "(true) ? 0x1 : 0;\n"
160e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(false) ? 0 : 0x1A;\n"
161e5c31af7Sopenharmony_ci			"  tempRes |= " + computePart + ";\n"
162e5c31af7Sopenharmony_ci		: (OPTYPE_ALLEQUAL == caseDef.opType || OPTYPE_ALLEQUAL_ARB == caseDef.opType) ?
163e5c31af7Sopenharmony_ci			"  " + fmt + " valueEqual = " + fmt + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
164e5c31af7Sopenharmony_ci			"  " + fmt + " valueNoEqual = " + fmt + (formatIsBoolean ? "(subgroupElect());\n" : "(gl_SubgroupInvocationID);\n") +
165e5c31af7Sopenharmony_ci			"  tempRes = " + op + "(" + fmt + "(1)) ? 0x1 : 0;\n"
166e5c31af7Sopenharmony_ci			"  tempRes |= "
167e5c31af7Sopenharmony_ci				+ (formatIsBoolean ? "0x2" : op + "(" + fmt + "(gl_SubgroupInvocationID)) ? 0 : 0x2")
168e5c31af7Sopenharmony_ci				+ ";\n"
169e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(data[0]) ? 0x4 : 0;\n"
170e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(valueEqual) ? 0x8 : 0x0;\n"
171e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(valueNoEqual) ? 0x0 : 0x10;\n"
172e5c31af7Sopenharmony_ci			"  if (subgroupElect()) tempRes |= 0x2 | 0x10;\n"
173e5c31af7Sopenharmony_ci		: "";
174e5c31af7Sopenharmony_ci}
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
177e5c31af7Sopenharmony_ci{
178e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
179e5c31af7Sopenharmony_ci	const bool					spirv14required	= isAllRayTracingStages(caseDef.shaderStage);
180e5c31af7Sopenharmony_ci#else
181e5c31af7Sopenharmony_ci	const bool					spirv14required	= false;
182e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
183e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion	= spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
184e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, spirvVersion, 0u);
185e5c31af7Sopenharmony_ci	const bool					arbFunctions	= caseDef.opType > OPTYPE_LAST_NON_ARB;
186e5c31af7Sopenharmony_ci	const string				extensions		= getExtensions(arbFunctions) + subgroups::getAdditionalExtensionForFormat(caseDef.format);
187e5c31af7Sopenharmony_ci	const bool					pointSize		= *caseDef.geometryPointSizeSupported;
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, pointSize, extensions, getStageTestSource(caseDef), "");
190e5c31af7Sopenharmony_ci}
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ciconst string getStageTestSourceFrag (const CaseDefinition& caseDef)
193e5c31af7Sopenharmony_ci{
194e5c31af7Sopenharmony_ci	const bool		formatIsBoolean	= fmtIsBoolean(caseDef.format);
195e5c31af7Sopenharmony_ci	const string	op				= getOpTypeName(caseDef.opType);
196e5c31af7Sopenharmony_ci	const string	fmt				= subgroups::getFormatNameForGLSL(caseDef.format);
197e5c31af7Sopenharmony_ci
198e5c31af7Sopenharmony_ci	return
199e5c31af7Sopenharmony_ci		(OPTYPE_ALL == caseDef.opType || OPTYPE_ALL_ARB == caseDef.opType) ?
200e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(!gl_HelperInvocation) ? 0x0 : 0x1;\n"
201e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(false) ? 0 : 0x1A;\n"
202e5c31af7Sopenharmony_ci			"  tempRes |= 0x4;\n"
203e5c31af7Sopenharmony_ci		: (OPTYPE_ANY == caseDef.opType || OPTYPE_ANY_ARB == caseDef.opType) ?
204e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(gl_HelperInvocation) ? 0x1 : 0x0;\n"
205e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(false) ? 0 : 0x1A;\n"
206e5c31af7Sopenharmony_ci			"  tempRes |= 0x4;\n"
207e5c31af7Sopenharmony_ci		: (OPTYPE_ALLEQUAL == caseDef.opType || OPTYPE_ALLEQUAL_ARB == caseDef.opType) ?
208e5c31af7Sopenharmony_ci			"  " + fmt + " valueEqual = " + fmt + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
209e5c31af7Sopenharmony_ci			"  " + fmt + " valueNoEqual = " + fmt + (formatIsBoolean ? "(subgroupElect());\n" : "(gl_SubgroupInvocationID);\n") +
210e5c31af7Sopenharmony_ci			"  tempRes |= " + getOpTypeName(caseDef.opType) + "("
211e5c31af7Sopenharmony_ci			+ fmt + "(1)) ? 0x10 : 0;\n"
212e5c31af7Sopenharmony_ci			"  tempRes |= "
213e5c31af7Sopenharmony_ci				+ (formatIsBoolean ? "0x2" : op + "(" + fmt + "(gl_SubgroupInvocationID)) ? 0 : 0x2")
214e5c31af7Sopenharmony_ci				+ ";\n"
215e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(data[0]) ? 0x4 : 0;\n"
216e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(valueEqual) ? 0x8 : 0x0;\n"
217e5c31af7Sopenharmony_ci			"  tempRes |= " + op + "(gl_HelperInvocation) ? 0x0 : 0x1;\n"
218e5c31af7Sopenharmony_ci			"  if (subgroupElect()) tempRes |= 0x2 | 0x10;\n"
219e5c31af7Sopenharmony_ci		: "";
220e5c31af7Sopenharmony_ci}
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_civoid initFrameBufferProgramsFrag (SourceCollections& programCollection, CaseDefinition caseDef)
223e5c31af7Sopenharmony_ci{
224e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
225e5c31af7Sopenharmony_ci	const bool					spirv14required	= isAllRayTracingStages(caseDef.shaderStage);
226e5c31af7Sopenharmony_ci#else
227e5c31af7Sopenharmony_ci	const bool					spirv14required	= false;
228e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
229e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion	= spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
230e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, spirvVersion, 0u);
231e5c31af7Sopenharmony_ci	const bool					arbFunctions	= caseDef.opType > OPTYPE_LAST_NON_ARB;
232e5c31af7Sopenharmony_ci	const string				extensions		= getExtensions(arbFunctions) + subgroups::getAdditionalExtensionForFormat(caseDef.format);
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_ci	DE_ASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage);
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci	{
237e5c31af7Sopenharmony_ci		const string	vertex	=
238e5c31af7Sopenharmony_ci			"#version 450\n"
239e5c31af7Sopenharmony_ci			"void main (void)\n"
240e5c31af7Sopenharmony_ci			"{\n"
241e5c31af7Sopenharmony_ci			"  vec2 uv = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
242e5c31af7Sopenharmony_ci			"  gl_Position = vec4(uv * 4.0f -2.0f, 0.0f, 1.0f);\n"
243e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
244e5c31af7Sopenharmony_ci			"}\n";
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci		programCollection.glslSources.add("vert") << glu::VertexSource(vertex) << buildOptions;
247e5c31af7Sopenharmony_ci	}
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ci	{
250e5c31af7Sopenharmony_ci		ostringstream	fragmentSource;
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
253e5c31af7Sopenharmony_ci			<< extensions
254e5c31af7Sopenharmony_ci			<< "layout(location = 0) out uint out_color;\n"
255e5c31af7Sopenharmony_ci			<< "layout(set = 0, binding = 0) uniform Buffer1\n"
256e5c31af7Sopenharmony_ci			<< "{\n"
257e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
258e5c31af7Sopenharmony_ci			<< "};\n"
259e5c31af7Sopenharmony_ci			<< ""
260e5c31af7Sopenharmony_ci			<< "void main()\n"
261e5c31af7Sopenharmony_ci			<< "{\n"
262e5c31af7Sopenharmony_ci			<< "  uint tempRes = 0u;\n"
263e5c31af7Sopenharmony_ci			<< "  if (dFdx(gl_SubgroupInvocationID * gl_FragCoord.x * gl_FragCoord.y) - dFdy(gl_SubgroupInvocationID * gl_FragCoord.x * gl_FragCoord.y) > 0.0f)\n"
264e5c31af7Sopenharmony_ci			<< "  {\n"
265e5c31af7Sopenharmony_ci			<< "    tempRes |= 0x20;\n" // to be sure that compiler doesn't remove dFdx and dFdy executions
266e5c31af7Sopenharmony_ci			<< "  }\n"
267e5c31af7Sopenharmony_ci			<< (arbFunctions ?
268e5c31af7Sopenharmony_ci				"  bool helper = anyInvocationARB(gl_HelperInvocation);\n" :
269e5c31af7Sopenharmony_ci				"  bool helper = subgroupAny(gl_HelperInvocation);\n")
270e5c31af7Sopenharmony_ci			<< "  if (helper)\n"
271e5c31af7Sopenharmony_ci			<< "  {\n"
272e5c31af7Sopenharmony_ci			<< "    tempRes |= 0x40;\n"
273e5c31af7Sopenharmony_ci			<< "  }\n"
274e5c31af7Sopenharmony_ci			<< getStageTestSourceFrag(caseDef)
275e5c31af7Sopenharmony_ci			<< "  out_color = tempRes;\n"
276e5c31af7Sopenharmony_ci			<< "}\n";
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci		programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSource.str())<< buildOptions;
279e5c31af7Sopenharmony_ci	}
280e5c31af7Sopenharmony_ci}
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_civoid initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
283e5c31af7Sopenharmony_ci{
284e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
285e5c31af7Sopenharmony_ci	const bool					spirv14required	= (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
286e5c31af7Sopenharmony_ci#else
287e5c31af7Sopenharmony_ci	const bool					spirv14required	= false;
288e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
289e5c31af7Sopenharmony_ci	const SpirvVersion			spirvVersion	= spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
290e5c31af7Sopenharmony_ci	const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, spirvVersion, 0u, spirv14required);
291e5c31af7Sopenharmony_ci	const bool					arbFunctions	= caseDef.opType > OPTYPE_LAST_NON_ARB;
292e5c31af7Sopenharmony_ci	const string				extensions		= getExtensions(arbFunctions) + subgroups::getAdditionalExtensionForFormat(caseDef.format);
293e5c31af7Sopenharmony_ci	const bool					pointSize		= *caseDef.geometryPointSizeSupported;
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci	subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, pointSize, extensions, getStageTestSource(caseDef), "");
296e5c31af7Sopenharmony_ci}
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
299e5c31af7Sopenharmony_ci{
300e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
301e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_VOTE_BIT))
304e5c31af7Sopenharmony_ci	{
305e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup vote operations");
306e5c31af7Sopenharmony_ci	}
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci	if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
309e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
310e5c31af7Sopenharmony_ci
311e5c31af7Sopenharmony_ci	if (caseDef.requires16BitUniformBuffer)
312e5c31af7Sopenharmony_ci	{
313e5c31af7Sopenharmony_ci		if (!subgroups::is16BitUBOStorageSupported(context))
314e5c31af7Sopenharmony_ci		{
315e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
316e5c31af7Sopenharmony_ci		}
317e5c31af7Sopenharmony_ci	}
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci	if (caseDef.requires8BitUniformBuffer)
320e5c31af7Sopenharmony_ci	{
321e5c31af7Sopenharmony_ci		if (!subgroups::is8BitUBOStorageSupported(context))
322e5c31af7Sopenharmony_ci		{
323e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
324e5c31af7Sopenharmony_ci		}
325e5c31af7Sopenharmony_ci	}
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	if (caseDef.opType > OPTYPE_LAST_NON_ARB)
328e5c31af7Sopenharmony_ci	{
329e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_shader_subgroup_vote");
330e5c31af7Sopenharmony_ci	}
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	if (caseDef.requiredSubgroupSize)
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
337e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeatures&		subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeatures();
338e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
339e5c31af7Sopenharmony_ci#else
340e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&		subgroupSizeControlFeatures	= context.getSubgroupSizeControlFeaturesEXT();
341e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
342e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
343e5c31af7Sopenharmony_ci
344e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
345e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_ci		if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
348e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci		if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
351e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
352e5c31af7Sopenharmony_ci	}
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ci	*caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
357e5c31af7Sopenharmony_ci	if (isAllRayTracingStages(caseDef.shaderStage))
358e5c31af7Sopenharmony_ci	{
359e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci	else if (isAllMeshShadingStages(caseDef.shaderStage))
362e5c31af7Sopenharmony_ci	{
363e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
364e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci		if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
367e5c31af7Sopenharmony_ci		{
368e5c31af7Sopenharmony_ci			const auto& features = context.getMeshShaderFeaturesEXT();
369e5c31af7Sopenharmony_ci			if (!features.taskShader)
370e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Task shaders not supported");
371e5c31af7Sopenharmony_ci		}
372e5c31af7Sopenharmony_ci	}
373e5c31af7Sopenharmony_ci
374e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci	subgroups::supportedCheckShader(context, caseDef.shaderStage);
377e5c31af7Sopenharmony_ci}
378e5c31af7Sopenharmony_ci
379e5c31af7Sopenharmony_ciTestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
380e5c31af7Sopenharmony_ci{
381e5c31af7Sopenharmony_ci	if (caseDef.opType > OPTYPE_LAST_NON_ARB)
382e5c31af7Sopenharmony_ci	{
383e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_EXT_shader_subgroup_vote");
384e5c31af7Sopenharmony_ci	}
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	const subgroups::SSBOData::InputDataInitializeType	initializeType	= (OPTYPE_ALLEQUAL == caseDef.opType || OPTYPE_ALLEQUAL_ARB == caseDef.opType)
387e5c31af7Sopenharmony_ci																		? subgroups::SSBOData::InitializeZero
388e5c31af7Sopenharmony_ci																		: subgroups::SSBOData::InitializeNonZero;
389e5c31af7Sopenharmony_ci	const subgroups::SSBOData							inputData
390e5c31af7Sopenharmony_ci	{
391e5c31af7Sopenharmony_ci		initializeType,							//  InputDataInitializeType		initializeType;
392e5c31af7Sopenharmony_ci		subgroups::SSBOData::LayoutStd140,		//  InputDataLayoutType			layout;
393e5c31af7Sopenharmony_ci		caseDef.format,							//  vk::VkFormat				format;
394e5c31af7Sopenharmony_ci		subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
395e5c31af7Sopenharmony_ci		subgroups::SSBOData::BindingUBO,		//  BindingType					bindingType;
396e5c31af7Sopenharmony_ci	};
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ci	switch (caseDef.shaderStage)
399e5c31af7Sopenharmony_ci	{
400e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_VERTEX_BIT:					return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
401e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_GEOMETRY_BIT:					return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
402e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
403e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
404e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_FRAGMENT_BIT:					return subgroups::makeFragmentFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkFragmentPipelineStages);
405e5c31af7Sopenharmony_ci		default:											TCU_THROW(InternalError, "Unhandled shader stage");
406e5c31af7Sopenharmony_ci	}
407e5c31af7Sopenharmony_ci}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_ciTestStatus test (Context& context, const CaseDefinition caseDef)
410e5c31af7Sopenharmony_ci{
411e5c31af7Sopenharmony_ci	const subgroups::SSBOData::InputDataInitializeType	initializeType	= (OPTYPE_ALLEQUAL == caseDef.opType || OPTYPE_ALLEQUAL_ARB == caseDef.opType)
412e5c31af7Sopenharmony_ci																		? subgroups::SSBOData::InitializeZero
413e5c31af7Sopenharmony_ci																		: subgroups::SSBOData::InitializeNonZero;
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci	const bool isCompute	= isAllComputeStages(caseDef.shaderStage);
416e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
417e5c31af7Sopenharmony_ci	const bool isMesh		= isAllMeshShadingStages(caseDef.shaderStage);
418e5c31af7Sopenharmony_ci#else
419e5c31af7Sopenharmony_ci	const bool isMesh		= false;
420e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
421e5c31af7Sopenharmony_ci	DE_ASSERT(!(isCompute && isMesh));
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci	if (isCompute || isMesh)
424e5c31af7Sopenharmony_ci	{
425e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
426e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
427e5c31af7Sopenharmony_ci#else
428e5c31af7Sopenharmony_ci		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
429e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
430e5c31af7Sopenharmony_ci		TestLog&												log								= context.getTestContext().getLog();
431e5c31af7Sopenharmony_ci		const subgroups::SSBOData								inputData
432e5c31af7Sopenharmony_ci		{
433e5c31af7Sopenharmony_ci			initializeType,							//  InputDataInitializeType		initializeType;
434e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
435e5c31af7Sopenharmony_ci			caseDef.format,							//  vk::VkFormat				format;
436e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
437e5c31af7Sopenharmony_ci		};
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ci		if (caseDef.requiredSubgroupSize == DE_FALSE)
440e5c31af7Sopenharmony_ci		{
441e5c31af7Sopenharmony_ci			if (isCompute)
442e5c31af7Sopenharmony_ci				return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
443e5c31af7Sopenharmony_ci			else
444e5c31af7Sopenharmony_ci				return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
445e5c31af7Sopenharmony_ci		}
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci		log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
448e5c31af7Sopenharmony_ci			<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci		// According to the spec, requiredSubgroupSize must be a power-of-two integer.
451e5c31af7Sopenharmony_ci		for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
452e5c31af7Sopenharmony_ci		{
453e5c31af7Sopenharmony_ci			TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci			if (isCompute)
456e5c31af7Sopenharmony_ci				result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
457e5c31af7Sopenharmony_ci			else
458e5c31af7Sopenharmony_ci				result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci			if (result.getCode() != QP_TEST_RESULT_PASS)
461e5c31af7Sopenharmony_ci			{
462e5c31af7Sopenharmony_ci				log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
463e5c31af7Sopenharmony_ci				return result;
464e5c31af7Sopenharmony_ci			}
465e5c31af7Sopenharmony_ci		}
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_ci		return TestStatus::pass("OK");
468e5c31af7Sopenharmony_ci	}
469e5c31af7Sopenharmony_ci	else if (isAllGraphicsStages(caseDef.shaderStage))
470e5c31af7Sopenharmony_ci	{
471e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages		= subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
472e5c31af7Sopenharmony_ci		const subgroups::SSBOData	inputData	=
473e5c31af7Sopenharmony_ci		{
474e5c31af7Sopenharmony_ci			initializeType,							//  InputDataInitializeType		initializeType;
475e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
476e5c31af7Sopenharmony_ci			caseDef.format,							//  vk::VkFormat				format;
477e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
478e5c31af7Sopenharmony_ci			subgroups::SSBOData::BindingSSBO,		//  bool						isImage;
479e5c31af7Sopenharmony_ci			4u,										//  deUint32					binding;
480e5c31af7Sopenharmony_ci			stages,									//  vk::VkShaderStageFlags		stages;
481e5c31af7Sopenharmony_ci		};
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci		return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
484e5c31af7Sopenharmony_ci	}
485e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
486e5c31af7Sopenharmony_ci	else if (isAllRayTracingStages(caseDef.shaderStage))
487e5c31af7Sopenharmony_ci	{
488e5c31af7Sopenharmony_ci		const VkShaderStageFlags	stages		= subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
489e5c31af7Sopenharmony_ci		const subgroups::SSBOData	inputData	=
490e5c31af7Sopenharmony_ci		{
491e5c31af7Sopenharmony_ci			initializeType,							//  InputDataInitializeType		initializeType;
492e5c31af7Sopenharmony_ci			subgroups::SSBOData::LayoutStd430,		//  InputDataLayoutType			layout;
493e5c31af7Sopenharmony_ci			caseDef.format,							//  vk::VkFormat				format;
494e5c31af7Sopenharmony_ci			subgroups::maxSupportedSubgroupSize(),	//  vk::VkDeviceSize			numElements;
495e5c31af7Sopenharmony_ci			subgroups::SSBOData::BindingSSBO,		//  bool						isImage;
496e5c31af7Sopenharmony_ci			6u,										//  deUint32					binding;
497e5c31af7Sopenharmony_ci			stages,									//  vk::VkShaderStageFlags		stages;
498e5c31af7Sopenharmony_ci		};
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_ci		return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
501e5c31af7Sopenharmony_ci	}
502e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
503e5c31af7Sopenharmony_ci	else
504e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unknown stage or invalid stage set");
505e5c31af7Sopenharmony_ci}
506e5c31af7Sopenharmony_ci}
507e5c31af7Sopenharmony_ci
508e5c31af7Sopenharmony_cinamespace vkt
509e5c31af7Sopenharmony_ci{
510e5c31af7Sopenharmony_cinamespace subgroups
511e5c31af7Sopenharmony_ci{
512e5c31af7Sopenharmony_ciTestCaseGroup* createSubgroupsVoteTests (TestContext& testCtx)
513e5c31af7Sopenharmony_ci{
514e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	group				(new TestCaseGroup(testCtx, "vote", "Subgroup vote category tests"));
515e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	graphicGroup		(new TestCaseGroup(testCtx, "graphics", "Subgroup vote category tests: graphics"));
516e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	computeGroup		(new TestCaseGroup(testCtx, "compute", "Subgroup vote category tests: compute"));
517e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	framebufferGroup	(new TestCaseGroup(testCtx, "framebuffer", "Subgroup vote category tests: framebuffer"));
518e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	fragHelperGroup		(new TestCaseGroup(testCtx, "frag_helper", "Subgroup vote category tests: fragment helper invocation"));
519e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
520e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	raytracingGroup		(new TestCaseGroup(testCtx, "ray_tracing", "Subgroup vote category tests: raytracing"));
521e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	meshGroup			(new TestCaseGroup(testCtx, "mesh", "Subgroup vote category tests: mesh shading"));
522e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	meshGroupARB		(new TestCaseGroup(testCtx, "mesh", "Subgroup vote category tests: mesh shading"));
523e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	groupARB			(new TestCaseGroup(testCtx, "ext_shader_subgroup_vote", "VK_EXT_shader_subgroup_vote category tests"));
526e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	graphicGroupARB		(new TestCaseGroup(testCtx, "graphics", "Subgroup vote category tests: graphics"));
527e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	computeGroupARB		(new TestCaseGroup(testCtx, "compute", "Subgroup vote category tests: compute"));
528e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	framebufferGroupARB	(new TestCaseGroup(testCtx, "framebuffer", "Subgroup vote category tests: framebuffer"));
529e5c31af7Sopenharmony_ci	de::MovePtr<TestCaseGroup>	fragHelperGroupARB	(new TestCaseGroup(testCtx, "frag_helper", "Subgroup vote category tests: fragment helper invocation"));
530e5c31af7Sopenharmony_ci	const deBool				boolValues[]		=
531e5c31af7Sopenharmony_ci	{
532e5c31af7Sopenharmony_ci		DE_FALSE,
533e5c31af7Sopenharmony_ci		DE_TRUE
534e5c31af7Sopenharmony_ci	};
535e5c31af7Sopenharmony_ci
536e5c31af7Sopenharmony_ci	{
537e5c31af7Sopenharmony_ci		const VkShaderStageFlags	fbStages[]		=
538e5c31af7Sopenharmony_ci		{
539e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_VERTEX_BIT,
540e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
541e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
542e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_GEOMETRY_BIT,
543e5c31af7Sopenharmony_ci		};
544e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
545e5c31af7Sopenharmony_ci		const VkShaderStageFlags	meshStages[]	=
546e5c31af7Sopenharmony_ci		{
547e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_MESH_BIT_EXT,
548e5c31af7Sopenharmony_ci			VK_SHADER_STAGE_TASK_BIT_EXT,
549e5c31af7Sopenharmony_ci		};
550e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
551e5c31af7Sopenharmony_ci		const vector<VkFormat>		formats		= subgroups::getAllFormats();
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
554e5c31af7Sopenharmony_ci		{
555e5c31af7Sopenharmony_ci			const VkFormat	format					= formats[formatIndex];
556e5c31af7Sopenharmony_ci			const bool		needs8BitUBOStorage		= isFormat8bitTy(format);
557e5c31af7Sopenharmony_ci			const bool		needs16BitUBOStorage	= isFormat16BitTy(format);
558e5c31af7Sopenharmony_ci			const deBool	formatIsNotVector		=  format == VK_FORMAT_R8_USCALED
559e5c31af7Sopenharmony_ci													|| format == VK_FORMAT_R32_UINT
560e5c31af7Sopenharmony_ci													|| format == VK_FORMAT_R32_SINT
561e5c31af7Sopenharmony_ci													|| format == VK_FORMAT_R32_SFLOAT
562e5c31af7Sopenharmony_ci													|| format == VK_FORMAT_R64_SFLOAT;
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
565e5c31af7Sopenharmony_ci			{
566e5c31af7Sopenharmony_ci				const OpType	opType	= static_cast<OpType>(opTypeIndex);
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ci				// Skip OPTYPE_LAST_NON_ARB because it is not a real op type.
569e5c31af7Sopenharmony_ci				if (opType == OPTYPE_LAST_NON_ARB)
570e5c31af7Sopenharmony_ci					continue;
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci				// Skip the non-nonvector tests because VK_EXT_shader_subgroup_vote functions only supports boolean scalar arguments.
573e5c31af7Sopenharmony_ci				if (opType > OPTYPE_LAST_NON_ARB && !formatIsNotVector)
574e5c31af7Sopenharmony_ci					continue;
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci				// Skip non-boolean formats when testing allInvocationsEqualARB(bool value), because it requires a boolean
577e5c31af7Sopenharmony_ci				// argument that should have the same value for all invocations. For the rest of formats, it won't be a boolean argument,
578e5c31af7Sopenharmony_ci				// so it may give wrong results when converting to bool.
579e5c31af7Sopenharmony_ci				if (opType == OPTYPE_ALLEQUAL_ARB && format != VK_FORMAT_R8_USCALED)
580e5c31af7Sopenharmony_ci					continue;
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ci				// Skip the typed tests for all but subgroupAllEqual() and allInvocationsEqualARB()
583e5c31af7Sopenharmony_ci				if ((VK_FORMAT_R32_UINT != format) && (OPTYPE_ALLEQUAL != opType) && (OPTYPE_ALLEQUAL_ARB != opType))
584e5c31af7Sopenharmony_ci				{
585e5c31af7Sopenharmony_ci					continue;
586e5c31af7Sopenharmony_ci				}
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ci				const string	op					= de::toLower(getOpTypeName(opType));
589e5c31af7Sopenharmony_ci				const string	name				= op + "_" + subgroups::getFormatNameForGLSL(format);
590e5c31af7Sopenharmony_ci				const bool		opNonARB			= (opType < OPTYPE_LAST_NON_ARB);
591e5c31af7Sopenharmony_ci				TestCaseGroup*	computeGroupPtr		= opNonARB ? computeGroup.get() : computeGroupARB.get();
592e5c31af7Sopenharmony_ci				TestCaseGroup*	graphicGroupPtr		= opNonARB ? graphicGroup.get() : graphicGroupARB.get();
593e5c31af7Sopenharmony_ci				TestCaseGroup*	framebufferGroupPtr	= opNonARB ? framebufferGroup.get() : framebufferGroupARB.get();
594e5c31af7Sopenharmony_ci				TestCaseGroup*	fragHelperGroupPtr	= opNonARB ? fragHelperGroup.get() : fragHelperGroupARB.get();
595e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
596e5c31af7Sopenharmony_ci				TestCaseGroup*	meshGroupPtr		= opNonARB ? meshGroup.get() : meshGroupARB.get();
597e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci				for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
600e5c31af7Sopenharmony_ci				{
601e5c31af7Sopenharmony_ci					const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
602e5c31af7Sopenharmony_ci					const string			testName				= name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
603e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef					=
604e5c31af7Sopenharmony_ci					{
605e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
606e5c31af7Sopenharmony_ci						VK_SHADER_STAGE_COMPUTE_BIT,	//  VkShaderStageFlags	shaderStage;
607e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
608e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
609e5c31af7Sopenharmony_ci						requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
610e5c31af7Sopenharmony_ci						deBool(false),					//  deBool				requires8BitUniformBuffer;
611e5c31af7Sopenharmony_ci						deBool(false)					//  deBool				requires16BitUniformBuffer;
612e5c31af7Sopenharmony_ci					};
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(computeGroupPtr, testName,  supportedCheck, initPrograms, test, caseDef);
615e5c31af7Sopenharmony_ci				}
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
618e5c31af7Sopenharmony_ci				for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
619e5c31af7Sopenharmony_ci				{
620e5c31af7Sopenharmony_ci					for (const auto& stage : meshStages)
621e5c31af7Sopenharmony_ci					{
622e5c31af7Sopenharmony_ci						const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
623e5c31af7Sopenharmony_ci						const string			testName				= name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "") + "_" + getShaderStageName(stage);
624e5c31af7Sopenharmony_ci						const CaseDefinition	caseDef					=
625e5c31af7Sopenharmony_ci						{
626e5c31af7Sopenharmony_ci							opType,							//  OpType				opType;
627e5c31af7Sopenharmony_ci							stage,							//  VkShaderStageFlags	shaderStage;
628e5c31af7Sopenharmony_ci							format,							//  VkFormat			format;
629e5c31af7Sopenharmony_ci							de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
630e5c31af7Sopenharmony_ci							requiredSubgroupSize,			//  deBool				requiredSubgroupSize;
631e5c31af7Sopenharmony_ci							deBool(false),					//  deBool				requires8BitUniformBuffer;
632e5c31af7Sopenharmony_ci							deBool(false)					//  deBool				requires16BitUniformBuffer;
633e5c31af7Sopenharmony_ci						};
634e5c31af7Sopenharmony_ci
635e5c31af7Sopenharmony_ci						addFunctionCaseWithPrograms(meshGroupPtr, testName,  supportedCheck, initPrograms, test, caseDef);
636e5c31af7Sopenharmony_ci					}
637e5c31af7Sopenharmony_ci				}
638e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci				{
641e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef		=
642e5c31af7Sopenharmony_ci					{
643e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
644e5c31af7Sopenharmony_ci						VK_SHADER_STAGE_ALL_GRAPHICS,	//  VkShaderStageFlags	shaderStage;
645e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
646e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
647e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
648e5c31af7Sopenharmony_ci						deBool(false),					//  deBool				requires8BitUniformBuffer;
649e5c31af7Sopenharmony_ci						deBool(false)					//  deBool				requires16BitUniformBuffer;
650e5c31af7Sopenharmony_ci					};
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(graphicGroupPtr, name,  supportedCheck, initPrograms, test, caseDef);
653e5c31af7Sopenharmony_ci				}
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_ci				for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
656e5c31af7Sopenharmony_ci				{
657e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef		=
658e5c31af7Sopenharmony_ci					{
659e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
660e5c31af7Sopenharmony_ci						fbStages[stageIndex],			//  VkShaderStageFlags	shaderStage;
661e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
662e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
663e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
664e5c31af7Sopenharmony_ci						deBool(needs8BitUBOStorage),	//  deBool				requires8BitUniformBuffer;
665e5c31af7Sopenharmony_ci						deBool(needs16BitUBOStorage)	//  deBool				requires16BitUniformBuffer;
666e5c31af7Sopenharmony_ci					};
667e5c31af7Sopenharmony_ci					const string			testName	= name + "_" + getShaderStageName(caseDef.shaderStage);
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(framebufferGroupPtr, testName,  supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
670e5c31af7Sopenharmony_ci				}
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci				{
673e5c31af7Sopenharmony_ci					const CaseDefinition	caseDef		=
674e5c31af7Sopenharmony_ci					{
675e5c31af7Sopenharmony_ci						opType,							//  OpType				opType;
676e5c31af7Sopenharmony_ci						VK_SHADER_STAGE_FRAGMENT_BIT,	//  VkShaderStageFlags	shaderStage;
677e5c31af7Sopenharmony_ci						format,							//  VkFormat			format;
678e5c31af7Sopenharmony_ci						de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
679e5c31af7Sopenharmony_ci						DE_FALSE,						//  deBool				requiredSubgroupSize;
680e5c31af7Sopenharmony_ci						deBool(needs8BitUBOStorage),	//  deBool				requires8BitUniformBuffer;
681e5c31af7Sopenharmony_ci						deBool(needs16BitUBOStorage)	//  deBool				requires16BitUniformBuffer;
682e5c31af7Sopenharmony_ci					};
683e5c31af7Sopenharmony_ci					const string			testName	= name + "_" + getShaderStageName(caseDef.shaderStage);
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci					addFunctionCaseWithPrograms(fragHelperGroupPtr, testName,  supportedCheck, initFrameBufferProgramsFrag, noSSBOtest, caseDef);
686e5c31af7Sopenharmony_ci				}
687e5c31af7Sopenharmony_ci			}
688e5c31af7Sopenharmony_ci		}
689e5c31af7Sopenharmony_ci	}
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
692e5c31af7Sopenharmony_ci	{
693e5c31af7Sopenharmony_ci		const vector<VkFormat>	formats		= subgroups::getAllRayTracingFormats();
694e5c31af7Sopenharmony_ci
695e5c31af7Sopenharmony_ci		for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
696e5c31af7Sopenharmony_ci		{
697e5c31af7Sopenharmony_ci			const VkFormat	format	= formats[formatIndex];
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci			for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST_NON_ARB; ++opTypeIndex)
700e5c31af7Sopenharmony_ci			{
701e5c31af7Sopenharmony_ci				const OpType	opType	= static_cast<OpType>(opTypeIndex);
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ci				// Skip the typed tests for all but subgroupAllEqual()
704e5c31af7Sopenharmony_ci				if ((VK_FORMAT_R32_UINT != format) && (OPTYPE_ALLEQUAL != opType))
705e5c31af7Sopenharmony_ci				{
706e5c31af7Sopenharmony_ci					continue;
707e5c31af7Sopenharmony_ci				}
708e5c31af7Sopenharmony_ci
709e5c31af7Sopenharmony_ci				const string			op		= de::toLower(getOpTypeName(opType));
710e5c31af7Sopenharmony_ci				const string			name	= op + "_" + subgroups::getFormatNameForGLSL(format);
711e5c31af7Sopenharmony_ci				const CaseDefinition	caseDef	=
712e5c31af7Sopenharmony_ci				{
713e5c31af7Sopenharmony_ci					opType,							//  OpType				opType;
714e5c31af7Sopenharmony_ci					SHADER_STAGE_ALL_RAY_TRACING,	//  VkShaderStageFlags	shaderStage;
715e5c31af7Sopenharmony_ci					format,							//  VkFormat			format;
716e5c31af7Sopenharmony_ci					de::SharedPtr<bool>(new bool),	//  de::SharedPtr<bool>	geometryPointSizeSupported;
717e5c31af7Sopenharmony_ci					DE_FALSE,						//  deBool				requiredSubgroupSize;
718e5c31af7Sopenharmony_ci					DE_FALSE,						//  deBool				requires8BitUniformBuffer;
719e5c31af7Sopenharmony_ci					DE_FALSE						//  deBool				requires16BitUniformBuffer;
720e5c31af7Sopenharmony_ci				};
721e5c31af7Sopenharmony_ci
722e5c31af7Sopenharmony_ci				addFunctionCaseWithPrograms(raytracingGroup.get(), name,  supportedCheck, initPrograms, test, caseDef);
723e5c31af7Sopenharmony_ci			}
724e5c31af7Sopenharmony_ci		}
725e5c31af7Sopenharmony_ci	}
726e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci	groupARB->addChild(graphicGroupARB.release());
729e5c31af7Sopenharmony_ci	groupARB->addChild(computeGroupARB.release());
730e5c31af7Sopenharmony_ci	groupARB->addChild(framebufferGroupARB.release());
731e5c31af7Sopenharmony_ci	groupARB->addChild(fragHelperGroupARB.release());
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
734e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
735e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
736e5c31af7Sopenharmony_ci	group->addChild(fragHelperGroup.release());
737e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
738e5c31af7Sopenharmony_ci	group->addChild(raytracingGroup.release());
739e5c31af7Sopenharmony_ci	group->addChild(meshGroup.release());
740e5c31af7Sopenharmony_ci	groupARB->addChild(meshGroupARB.release());
741e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
742e5c31af7Sopenharmony_ci
743e5c31af7Sopenharmony_ci	group->addChild(groupARB.release());
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	return group.release();
746e5c31af7Sopenharmony_ci}
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci} // subgroups
749e5c31af7Sopenharmony_ci} // vkt
750