1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2017-2019 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2017 Codeplay Software Ltd.
7e5c31af7Sopenharmony_ci * Copyright (c) 2019 NVIDIA Corporation.
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 "glcSubgroupsVoteTests.hpp"
27e5c31af7Sopenharmony_ci#include "glcSubgroupsTestsUtils.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include <string>
30e5c31af7Sopenharmony_ci#include <vector>
31e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ciusing namespace tcu;
34e5c31af7Sopenharmony_ciusing namespace std;
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_cinamespace glc
37e5c31af7Sopenharmony_ci{
38e5c31af7Sopenharmony_cinamespace subgroups
39e5c31af7Sopenharmony_ci{
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_cinamespace
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_cienum OpType
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_ci	OPTYPE_ALL = 0,
47e5c31af7Sopenharmony_ci	OPTYPE_ANY,
48e5c31af7Sopenharmony_ci	OPTYPE_ALLEQUAL,
49e5c31af7Sopenharmony_ci	OPTYPE_LAST
50e5c31af7Sopenharmony_ci};
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages(std::vector<const void*> datas,
53e5c31af7Sopenharmony_ci									  deUint32 width, deUint32)
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_ci	return glc::subgroups::check(datas, width, 0x1F);
56e5c31af7Sopenharmony_ci}
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_cistatic bool checkFragmentPipelineStages(std::vector<const void*> datas,
59e5c31af7Sopenharmony_ci									  deUint32 width, deUint32 height, deUint32)
60e5c31af7Sopenharmony_ci{
61e5c31af7Sopenharmony_ci	const deUint32* data =
62e5c31af7Sopenharmony_ci		reinterpret_cast<const deUint32*>(datas[0]);
63e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < width; ++x)
64e5c31af7Sopenharmony_ci	{
65e5c31af7Sopenharmony_ci		for (deUint32 y = 0u; y < height; ++y)
66e5c31af7Sopenharmony_ci		{
67e5c31af7Sopenharmony_ci			const deUint32 ndx = (x * height + y);
68e5c31af7Sopenharmony_ci			deUint32 val = data[ndx] & 0x1F;
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci			if (data[ndx] & 0x40) //Helper fragment shader invocation was executed
71e5c31af7Sopenharmony_ci			{
72e5c31af7Sopenharmony_ci				if(val != 0x1F)
73e5c31af7Sopenharmony_ci					return false;
74e5c31af7Sopenharmony_ci			}
75e5c31af7Sopenharmony_ci			else //Helper fragment shader invocation was not executed yet
76e5c31af7Sopenharmony_ci			{
77e5c31af7Sopenharmony_ci				if (val != 0x1E)
78e5c31af7Sopenharmony_ci					return false;
79e5c31af7Sopenharmony_ci			}
80e5c31af7Sopenharmony_ci		}
81e5c31af7Sopenharmony_ci	}
82e5c31af7Sopenharmony_ci	return true;
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_cistatic bool checkComputeStage(std::vector<const void*> datas,
86e5c31af7Sopenharmony_ci						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
87e5c31af7Sopenharmony_ci						 deUint32)
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_ci	return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x1F);
90e5c31af7Sopenharmony_ci}
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_cistd::string getOpTypeName(int opType)
93e5c31af7Sopenharmony_ci{
94e5c31af7Sopenharmony_ci	switch (opType)
95e5c31af7Sopenharmony_ci	{
96e5c31af7Sopenharmony_ci		default:
97e5c31af7Sopenharmony_ci			DE_FATAL("Unsupported op type");
98e5c31af7Sopenharmony_ci			return "";
99e5c31af7Sopenharmony_ci		case OPTYPE_ALL:
100e5c31af7Sopenharmony_ci			return "subgroupAll";
101e5c31af7Sopenharmony_ci		case OPTYPE_ANY:
102e5c31af7Sopenharmony_ci			return "subgroupAny";
103e5c31af7Sopenharmony_ci		case OPTYPE_ALLEQUAL:
104e5c31af7Sopenharmony_ci			return "subgroupAllEqual";
105e5c31af7Sopenharmony_ci	}
106e5c31af7Sopenharmony_ci}
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_cistruct CaseDefinition
109e5c31af7Sopenharmony_ci{
110e5c31af7Sopenharmony_ci	int					opType;
111e5c31af7Sopenharmony_ci	ShaderStageFlags	shaderStage;
112e5c31af7Sopenharmony_ci	Format				format;
113e5c31af7Sopenharmony_ci};
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
116e5c31af7Sopenharmony_ci{
117e5c31af7Sopenharmony_ci	const bool formatIsBoolean =
118e5c31af7Sopenharmony_ci		FORMAT_R32_BOOL == caseDef.format || FORMAT_R32G32_BOOL == caseDef.format || FORMAT_R32G32B32_BOOL == caseDef.format || FORMAT_R32G32B32A32_BOOL == caseDef.format;
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	if (SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
121e5c31af7Sopenharmony_ci		subgroups::setFragmentShaderFrameBuffer(programCollection);
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci	if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
124e5c31af7Sopenharmony_ci	{
125e5c31af7Sopenharmony_ci		const string vertex	= "${VERSION_DECL}\n"
126e5c31af7Sopenharmony_ci			"void main (void)\n"
127e5c31af7Sopenharmony_ci			"{\n"
128e5c31af7Sopenharmony_ci			"  vec2 uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));\n"
129e5c31af7Sopenharmony_ci			"  gl_Position = vec4(uv * 4.0f -2.0f, 0.0f, 1.0f);\n"
130e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
131e5c31af7Sopenharmony_ci			"}\n";
132e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertex);
133e5c31af7Sopenharmony_ci	}
134e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
135e5c31af7Sopenharmony_ci		subgroups::setVertexShaderFrameBuffer(programCollection);
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ci	const string source =
138e5c31af7Sopenharmony_ci		(OPTYPE_ALL == caseDef.opType) ?
139e5c31af7Sopenharmony_ci			"  result = " + getOpTypeName(caseDef.opType) +
140e5c31af7Sopenharmony_ci			"(true) ? 0x1u : 0u;\n"
141e5c31af7Sopenharmony_ci			"  result |= " + getOpTypeName(caseDef.opType) +
142e5c31af7Sopenharmony_ci			"(false) ? 0u : 0x1Au;\n"
143e5c31af7Sopenharmony_ci			"  result |= 0x4u;\n"
144e5c31af7Sopenharmony_ci		: (OPTYPE_ANY == caseDef.opType) ?
145e5c31af7Sopenharmony_ci				"  result = " + getOpTypeName(caseDef.opType) +
146e5c31af7Sopenharmony_ci				"(true) ? 0x1u : 0u;\n"
147e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
148e5c31af7Sopenharmony_ci				"(false) ? 0u : 0x1Au;\n"
149e5c31af7Sopenharmony_ci				"  result |= 0x4u;\n"
150e5c31af7Sopenharmony_ci		: (OPTYPE_ALLEQUAL == caseDef.opType) ?
151e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
152e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect())\n;" : "(12.0 * float(data[gl_SubgroupInvocationID]) + float(gl_SubgroupInvocationID));\n") +
153e5c31af7Sopenharmony_ci				"  result = " + getOpTypeName(caseDef.opType) + "("
154e5c31af7Sopenharmony_ci				+ subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1u : 0u;\n"
155e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
156e5c31af7Sopenharmony_ci				"(gl_SubgroupInvocationID) ? 0u : 0x2u;\n"
157e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
158e5c31af7Sopenharmony_ci				"(data[0]) ? 0x4u : 0u;\n"
159e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
160e5c31af7Sopenharmony_ci				"(valueEqual) ? 0x8u : 0x0u;\n"
161e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
162e5c31af7Sopenharmony_ci				"(valueNoEqual) ? 0x0u : 0x10u;\n"
163e5c31af7Sopenharmony_ci				"  if (subgroupElect()) result |= 0x2u | 0x10u;\n"
164e5c31af7Sopenharmony_ci		: "";
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
167e5c31af7Sopenharmony_ci	{
168e5c31af7Sopenharmony_ci		std::ostringstream vertexSrc;
169e5c31af7Sopenharmony_ci		vertexSrc << "${VERSION_DECL}\n"
170e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
171e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
172e5c31af7Sopenharmony_ci			<< "layout(location = 0) in highp vec4 in_position;\n"
173e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer1\n"
174e5c31af7Sopenharmony_ci			<< "{\n"
175e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
176e5c31af7Sopenharmony_ci			<< "};\n"
177e5c31af7Sopenharmony_ci			<< "\n"
178e5c31af7Sopenharmony_ci			<< "void main (void)\n"
179e5c31af7Sopenharmony_ci			<< "{\n"
180e5c31af7Sopenharmony_ci			<< "  uint result;\n"
181e5c31af7Sopenharmony_ci			<< source
182e5c31af7Sopenharmony_ci			<< "  out_color = float(result);\n"
183e5c31af7Sopenharmony_ci			<< "  gl_Position = in_position;\n"
184e5c31af7Sopenharmony_ci			<< "  gl_PointSize = 1.0f;\n"
185e5c31af7Sopenharmony_ci			<< "}\n";
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
188e5c31af7Sopenharmony_ci	}
189e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		std::ostringstream geometry;
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_ci		geometry << "${VERSION_DECL}\n"
194e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
195e5c31af7Sopenharmony_ci			<< "layout(points) in;\n"
196e5c31af7Sopenharmony_ci			<< "layout(points, max_vertices = 1) out;\n"
197e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
198e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer1\n"
199e5c31af7Sopenharmony_ci			<< "{\n"
200e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
201e5c31af7Sopenharmony_ci			<< "};\n"
202e5c31af7Sopenharmony_ci			<< "\n"
203e5c31af7Sopenharmony_ci			<< "void main (void)\n"
204e5c31af7Sopenharmony_ci			<< "{\n"
205e5c31af7Sopenharmony_ci			<< "  uint result;\n"
206e5c31af7Sopenharmony_ci			<< source
207e5c31af7Sopenharmony_ci			<< "  out_color = float(result);\n"
208e5c31af7Sopenharmony_ci			<< "  gl_Position = gl_in[0].gl_Position;\n"
209e5c31af7Sopenharmony_ci			<< "  EmitVertex();\n"
210e5c31af7Sopenharmony_ci			<< "  EndPrimitive();\n"
211e5c31af7Sopenharmony_ci			<< "}\n";
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci		programCollection.add("geometry") << glu::GeometrySource(geometry.str());
214e5c31af7Sopenharmony_ci	}
215e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
216e5c31af7Sopenharmony_ci	{
217e5c31af7Sopenharmony_ci		std::ostringstream controlSource;
218e5c31af7Sopenharmony_ci		controlSource << "${VERSION_DECL}\n"
219e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
220e5c31af7Sopenharmony_ci			<< "layout(vertices = 2) out;\n"
221e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color[];\n"
222e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer1\n"
223e5c31af7Sopenharmony_ci			<< "{\n"
224e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
225e5c31af7Sopenharmony_ci			<< "};\n"
226e5c31af7Sopenharmony_ci			<< "\n"
227e5c31af7Sopenharmony_ci			<< "void main (void)\n"
228e5c31af7Sopenharmony_ci			<< "{\n"
229e5c31af7Sopenharmony_ci			<< "  uint result;\n"
230e5c31af7Sopenharmony_ci			<< "  if (gl_InvocationID == 0)\n"
231e5c31af7Sopenharmony_ci			<<"  {\n"
232e5c31af7Sopenharmony_ci			<< "    gl_TessLevelOuter[0] = 1.0f;\n"
233e5c31af7Sopenharmony_ci			<< "    gl_TessLevelOuter[1] = 1.0f;\n"
234e5c31af7Sopenharmony_ci			<< "  }\n"
235e5c31af7Sopenharmony_ci			<< source
236e5c31af7Sopenharmony_ci			<< "  out_color[gl_InvocationID] = float(result);"
237e5c31af7Sopenharmony_ci			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
238e5c31af7Sopenharmony_ci			<< "}\n";
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
241e5c31af7Sopenharmony_ci		subgroups::setTesEvalShaderFrameBuffer(programCollection);
242e5c31af7Sopenharmony_ci	}
243e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
244e5c31af7Sopenharmony_ci	{
245e5c31af7Sopenharmony_ci		std::ostringstream evaluationSource;
246e5c31af7Sopenharmony_ci		evaluationSource << "${VERSION_DECL}\n"
247e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
248e5c31af7Sopenharmony_ci			<< "${TESS_EXTENSION}\n"
249e5c31af7Sopenharmony_ci			<< "layout(isolines, equal_spacing, ccw ) in;\n"
250e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
251e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer1\n"
252e5c31af7Sopenharmony_ci			<< "{\n"
253e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
254e5c31af7Sopenharmony_ci			<< "};\n"
255e5c31af7Sopenharmony_ci			<< "\n"
256e5c31af7Sopenharmony_ci			<< "void main (void)\n"
257e5c31af7Sopenharmony_ci			<< "{\n"
258e5c31af7Sopenharmony_ci			<< "  uint result;\n"
259e5c31af7Sopenharmony_ci			<< "  highp uint offset = uint(gl_PrimitiveID) * 2u + uint(gl_TessCoord.x + 0.5);\n"
260e5c31af7Sopenharmony_ci			<< source
261e5c31af7Sopenharmony_ci			<< "  out_color = float(result);\n"
262e5c31af7Sopenharmony_ci			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
263e5c31af7Sopenharmony_ci			<< "}\n";
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
266e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
267e5c31af7Sopenharmony_ci	}
268e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
269e5c31af7Sopenharmony_ci	{
270e5c31af7Sopenharmony_ci		const string sourceFragment =
271e5c31af7Sopenharmony_ci		(OPTYPE_ALL == caseDef.opType) ?
272e5c31af7Sopenharmony_ci			"  result |= " + getOpTypeName(caseDef.opType) +
273e5c31af7Sopenharmony_ci			"(!gl_HelperInvocation) ? 0x0u : 0x1u;\n"
274e5c31af7Sopenharmony_ci			"  result |= " + getOpTypeName(caseDef.opType) +
275e5c31af7Sopenharmony_ci			"(false) ? 0u : 0x1Au;\n"
276e5c31af7Sopenharmony_ci			"  result |= 0x4u;\n"
277e5c31af7Sopenharmony_ci		: (OPTYPE_ANY == caseDef.opType) ?
278e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
279e5c31af7Sopenharmony_ci				"(gl_HelperInvocation) ? 0x1u : 0x0u;\n"
280e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
281e5c31af7Sopenharmony_ci				"(false) ? 0u : 0x1Au;\n"
282e5c31af7Sopenharmony_ci				"  result |= 0x4u;\n"
283e5c31af7Sopenharmony_ci		: (OPTYPE_ALLEQUAL == caseDef.opType) ?
284e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
285e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + gl_FragCoord.x * float(gl_SubgroupInvocationID));\n") +
286e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) + "("
287e5c31af7Sopenharmony_ci				+ subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x10u : 0u;\n"
288e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
289e5c31af7Sopenharmony_ci				"(gl_SubgroupInvocationID) ? 0u : 0x2u;\n"
290e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
291e5c31af7Sopenharmony_ci				"(data[0]) ? 0x4u : 0u;\n"
292e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
293e5c31af7Sopenharmony_ci				"(valueEqual) ? 0x8u : 0x0u;\n"
294e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
295e5c31af7Sopenharmony_ci				"(gl_HelperInvocation) ? 0x0u : 0x1u;\n"
296e5c31af7Sopenharmony_ci				"  if (subgroupElect()) result |= 0x2u | 0x10u;\n"
297e5c31af7Sopenharmony_ci		: "";
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci		std::ostringstream fragmentSource;
300e5c31af7Sopenharmony_ci		fragmentSource << "${VERSION_DECL}\n"
301e5c31af7Sopenharmony_ci		<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
302e5c31af7Sopenharmony_ci		<< "precision highp float;\n"
303e5c31af7Sopenharmony_ci		<< "layout(location = 0) out uint out_color;\n"
304e5c31af7Sopenharmony_ci		<< "layout(binding = 0, std140) uniform Buffer1\n"
305e5c31af7Sopenharmony_ci		<< "{\n"
306e5c31af7Sopenharmony_ci		<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
307e5c31af7Sopenharmony_ci		<< "};\n"
308e5c31af7Sopenharmony_ci		<< ""
309e5c31af7Sopenharmony_ci		<< "void main()\n"
310e5c31af7Sopenharmony_ci		<< "{\n"
311e5c31af7Sopenharmony_ci		<< "  uint result = 0u;\n"
312e5c31af7Sopenharmony_ci		<< "  if (dFdx(float(gl_SubgroupInvocationID) * gl_FragCoord.x * gl_FragCoord.y) - dFdy(float(gl_SubgroupInvocationID) * gl_FragCoord.x * gl_FragCoord.y) > 0.0f)\n"
313e5c31af7Sopenharmony_ci		<< "  {\n"
314e5c31af7Sopenharmony_ci		<< "    result |= 0x20u;\n" // to be sure that compiler doesn't remove dFdx and dFdy executions
315e5c31af7Sopenharmony_ci		<< "  }\n"
316e5c31af7Sopenharmony_ci		<< "  bool helper = subgroupAny(gl_HelperInvocation);\n"
317e5c31af7Sopenharmony_ci		<< "  if (helper)\n"
318e5c31af7Sopenharmony_ci		<< "  {\n"
319e5c31af7Sopenharmony_ci		<< "    result |= 0x40u;\n"
320e5c31af7Sopenharmony_ci		<< "  }\n"
321e5c31af7Sopenharmony_ci		<< sourceFragment
322e5c31af7Sopenharmony_ci		<< "  out_color = result;\n"
323e5c31af7Sopenharmony_ci		<< "}\n";
324e5c31af7Sopenharmony_ci
325e5c31af7Sopenharmony_ci		programCollection.add("fragment") << glu::FragmentSource(fragmentSource.str());
326e5c31af7Sopenharmony_ci	}
327e5c31af7Sopenharmony_ci	else
328e5c31af7Sopenharmony_ci	{
329e5c31af7Sopenharmony_ci		DE_FATAL("Unsupported shader stage");
330e5c31af7Sopenharmony_ci	}
331e5c31af7Sopenharmony_ci}
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
334e5c31af7Sopenharmony_ci{
335e5c31af7Sopenharmony_ci	const bool formatIsBoolean =
336e5c31af7Sopenharmony_ci		FORMAT_R32_BOOL == caseDef.format || FORMAT_R32G32_BOOL == caseDef.format || FORMAT_R32G32B32_BOOL == caseDef.format || FORMAT_R32G32B32A32_BOOL == caseDef.format;
337e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
338e5c31af7Sopenharmony_ci	{
339e5c31af7Sopenharmony_ci		std::ostringstream src;
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci		src << "${VERSION_DECL}\n"
342e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_vote: enable\n"
343e5c31af7Sopenharmony_ci			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
344e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std430) buffer Buffer1\n"
345e5c31af7Sopenharmony_ci			<< "{\n"
346e5c31af7Sopenharmony_ci			<< "  uint result[];\n"
347e5c31af7Sopenharmony_ci			<< "};\n"
348e5c31af7Sopenharmony_ci			<< "layout(binding = 1, std430) buffer Buffer2\n"
349e5c31af7Sopenharmony_ci			<< "{\n"
350e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
351e5c31af7Sopenharmony_ci			<< "};\n"
352e5c31af7Sopenharmony_ci			<< "\n"
353e5c31af7Sopenharmony_ci			<< "void main (void)\n"
354e5c31af7Sopenharmony_ci			<< "{\n"
355e5c31af7Sopenharmony_ci			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
356e5c31af7Sopenharmony_ci			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
357e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
358e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.x;\n";
359e5c31af7Sopenharmony_ci		if (OPTYPE_ALL == caseDef.opType)
360e5c31af7Sopenharmony_ci		{
361e5c31af7Sopenharmony_ci			src << "  result[offset] = " << getOpTypeName(caseDef.opType)
362e5c31af7Sopenharmony_ci				<< "(true) ? 0x1u : 0u;\n"
363e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
364e5c31af7Sopenharmony_ci				<< "(false) ? 0u : 0x1Au;\n"
365e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
366e5c31af7Sopenharmony_ci				<< "(data[gl_SubgroupInvocationID] > 0u) ? 0x4u : 0u;\n";
367e5c31af7Sopenharmony_ci		}
368e5c31af7Sopenharmony_ci		else if (OPTYPE_ANY == caseDef.opType)
369e5c31af7Sopenharmony_ci		{
370e5c31af7Sopenharmony_ci			src << "  result[offset] = " << getOpTypeName(caseDef.opType)
371e5c31af7Sopenharmony_ci				<< "(true) ? 0x1u : 0u;\n"
372e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
373e5c31af7Sopenharmony_ci				<< "(false) ? 0u : 0x1Au;\n"
374e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
375e5c31af7Sopenharmony_ci				<< "(data[gl_SubgroupInvocationID] == data[0]) ? 0x4u : 0u;\n";
376e5c31af7Sopenharmony_ci		}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci		else if (OPTYPE_ALLEQUAL == caseDef.opType)
379e5c31af7Sopenharmony_ci		{
380e5c31af7Sopenharmony_ci			src << "  " << subgroups::getFormatNameForGLSL(caseDef.format) <<" valueEqual = " << subgroups::getFormatNameForGLSL(caseDef.format) << "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n"
381e5c31af7Sopenharmony_ci				<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) <<" valueNoEqual = " << subgroups::getFormatNameForGLSL(caseDef.format) << (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + float(offset));\n")
382e5c31af7Sopenharmony_ci				<<"  result[offset] = " << getOpTypeName(caseDef.opType) << "("
383e5c31af7Sopenharmony_ci				<< subgroups::getFormatNameForGLSL(caseDef.format) << "(1)) ? 0x1u : 0x0u;\n"
384e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
385e5c31af7Sopenharmony_ci				<< "(gl_SubgroupInvocationID) ? 0x0u : 0x2u;\n"
386e5c31af7Sopenharmony_ci				<< "  result[offset] |= " << getOpTypeName(caseDef.opType)
387e5c31af7Sopenharmony_ci				<< "(data[0]) ? 0x4u : 0x0u;\n"
388e5c31af7Sopenharmony_ci				<< "  result[offset] |= "<< getOpTypeName(caseDef.opType)
389e5c31af7Sopenharmony_ci				<< "(valueEqual) ? 0x8u : 0x0u;\n"
390e5c31af7Sopenharmony_ci				<< "  result[offset] |= "<< getOpTypeName(caseDef.opType)
391e5c31af7Sopenharmony_ci				<< "(valueNoEqual) ? 0x0u : 0x10u;\n"
392e5c31af7Sopenharmony_ci				<< "  if (subgroupElect()) result[offset] |= 0x2u | 0x10u;\n";
393e5c31af7Sopenharmony_ci		}
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci		src << "}\n";
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci		programCollection.add("comp") << glu::ComputeSource(src.str());
398e5c31af7Sopenharmony_ci	}
399e5c31af7Sopenharmony_ci	else
400e5c31af7Sopenharmony_ci	{
401e5c31af7Sopenharmony_ci		const string source =
402e5c31af7Sopenharmony_ci		(OPTYPE_ALL == caseDef.opType) ?
403e5c31af7Sopenharmony_ci			"  b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) +
404e5c31af7Sopenharmony_ci			"(true) ? 0x1u : 0u;\n"
405e5c31af7Sopenharmony_ci			"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
406e5c31af7Sopenharmony_ci			"(false) ? 0u : 0x1Au;\n"
407e5c31af7Sopenharmony_ci			"  b${SSBO1}.result[offset] |= 0x4u;\n"
408e5c31af7Sopenharmony_ci		: (OPTYPE_ANY == caseDef.opType) ?
409e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) +
410e5c31af7Sopenharmony_ci				"(true) ? 0x1u : 0u;\n"
411e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
412e5c31af7Sopenharmony_ci				"(false) ? 0u : 0x1Au;\n"
413e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= 0x4u;\n"
414e5c31af7Sopenharmony_ci		: (OPTYPE_ALLEQUAL == caseDef.opType) ?
415e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
416e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + float(gl_SubgroupInvocationID));\n") +
417e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) + "("
418e5c31af7Sopenharmony_ci				+ subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1u : 0u;\n"
419e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
420e5c31af7Sopenharmony_ci				"(gl_SubgroupInvocationID) ? 0u : 0x2u;\n"
421e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
422e5c31af7Sopenharmony_ci				"(data[0]) ? 0x4u : 0u;\n"
423e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
424e5c31af7Sopenharmony_ci				"(valueEqual) ? 0x8u : 0x0u;\n"
425e5c31af7Sopenharmony_ci				"  b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
426e5c31af7Sopenharmony_ci				"(valueNoEqual) ? 0x0u : 0x10u;\n"
427e5c31af7Sopenharmony_ci				"  if (subgroupElect()) b${SSBO1}.result[offset] |= 0x2u | 0x10u;\n"
428e5c31af7Sopenharmony_ci		: "";
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci		tcu::StringTemplate sourceTemplate(source);
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci		const string formatString = subgroups::getFormatNameForGLSL(caseDef.format);
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci		{
435e5c31af7Sopenharmony_ci			map<string, string> bufferNameMapping;
436e5c31af7Sopenharmony_ci			bufferNameMapping.insert(pair<string, string>("SSBO1", "0"));
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci			const string vertex =
439e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
440e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_vote: enable\n"
441e5c31af7Sopenharmony_ci				"layout(binding = 0, std430) buffer Buffer0\n"
442e5c31af7Sopenharmony_ci				"{\n"
443e5c31af7Sopenharmony_ci				"  uint result[];\n"
444e5c31af7Sopenharmony_ci				"} b0;\n"
445e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
446e5c31af7Sopenharmony_ci				"{\n"
447e5c31af7Sopenharmony_ci				"  " + formatString + " data[];\n"
448e5c31af7Sopenharmony_ci				"};\n"
449e5c31af7Sopenharmony_ci				"\n"
450e5c31af7Sopenharmony_ci				"void main (void)\n"
451e5c31af7Sopenharmony_ci				"{\n"
452e5c31af7Sopenharmony_ci				"  highp int offset = gl_VertexID;\n"
453e5c31af7Sopenharmony_ci				+ sourceTemplate.specialize(bufferNameMapping) +
454e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
455e5c31af7Sopenharmony_ci				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
456e5c31af7Sopenharmony_ci				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
457e5c31af7Sopenharmony_ci				"  gl_PointSize = 1.0f;\n"
458e5c31af7Sopenharmony_ci				"}\n";
459e5c31af7Sopenharmony_ci			programCollection.add("vert") << glu::VertexSource(vertex);
460e5c31af7Sopenharmony_ci		}
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_ci		{
463e5c31af7Sopenharmony_ci			map<string, string> bufferNameMapping;
464e5c31af7Sopenharmony_ci			bufferNameMapping.insert(pair<string, string>("SSBO1", "1"));
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci			const string tesc =
467e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
468e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_vote: enable\n"
469e5c31af7Sopenharmony_ci				"layout(vertices=1) out;\n"
470e5c31af7Sopenharmony_ci				"layout(binding = 1, std430) buffer Buffer1\n"
471e5c31af7Sopenharmony_ci				"{\n"
472e5c31af7Sopenharmony_ci				"  uint result[];\n"
473e5c31af7Sopenharmony_ci				"} b1;\n"
474e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
475e5c31af7Sopenharmony_ci				"{\n"
476e5c31af7Sopenharmony_ci				"  " + formatString + " data[];\n"
477e5c31af7Sopenharmony_ci				"};\n"
478e5c31af7Sopenharmony_ci				"\n"
479e5c31af7Sopenharmony_ci				"void main (void)\n"
480e5c31af7Sopenharmony_ci				"{\n"
481e5c31af7Sopenharmony_ci				"  highp int offset = gl_PrimitiveID;\n"
482e5c31af7Sopenharmony_ci				+ sourceTemplate.specialize(bufferNameMapping) +
483e5c31af7Sopenharmony_ci				"  if (gl_InvocationID == 0)\n"
484e5c31af7Sopenharmony_ci				"  {\n"
485e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[0] = 1.0f;\n"
486e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[1] = 1.0f;\n"
487e5c31af7Sopenharmony_ci				"  }\n"
488e5c31af7Sopenharmony_ci				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
489e5c31af7Sopenharmony_ci				"}\n";
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci			programCollection.add("tesc") << glu::TessellationControlSource(tesc);
492e5c31af7Sopenharmony_ci		}
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci		{
495e5c31af7Sopenharmony_ci			map<string, string> bufferNameMapping;
496e5c31af7Sopenharmony_ci			bufferNameMapping.insert(pair<string, string>("SSBO1", "2"));
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci			const string tese =
499e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
500e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_vote: enable\n"
501e5c31af7Sopenharmony_ci				"layout(isolines) in;\n"
502e5c31af7Sopenharmony_ci				"layout(binding = 2, std430) buffer Buffer2\n"
503e5c31af7Sopenharmony_ci				"{\n"
504e5c31af7Sopenharmony_ci				"  uint result[];\n"
505e5c31af7Sopenharmony_ci				"} b2;\n"
506e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
507e5c31af7Sopenharmony_ci				"{\n"
508e5c31af7Sopenharmony_ci				"  " + formatString + " data[];\n"
509e5c31af7Sopenharmony_ci				"};\n"
510e5c31af7Sopenharmony_ci				"\n"
511e5c31af7Sopenharmony_ci				"void main (void)\n"
512e5c31af7Sopenharmony_ci				"{\n"
513e5c31af7Sopenharmony_ci				"  highp uint offset = uint(gl_PrimitiveID * 2) + uint(gl_TessCoord.x + 0.5);\n"
514e5c31af7Sopenharmony_ci				+ sourceTemplate.specialize(bufferNameMapping) +
515e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
516e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
517e5c31af7Sopenharmony_ci				"}\n";
518e5c31af7Sopenharmony_ci
519e5c31af7Sopenharmony_ci			programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
520e5c31af7Sopenharmony_ci		}
521e5c31af7Sopenharmony_ci
522e5c31af7Sopenharmony_ci		{
523e5c31af7Sopenharmony_ci			map<string, string> bufferNameMapping;
524e5c31af7Sopenharmony_ci			bufferNameMapping.insert(pair<string, string>("SSBO1", "3"));
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci			const string geometry =
527e5c31af7Sopenharmony_ci				// version string added by addGeometryShadersFromTemplate
528e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_vote: enable\n"
529e5c31af7Sopenharmony_ci				"layout(${TOPOLOGY}) in;\n"
530e5c31af7Sopenharmony_ci				"layout(points, max_vertices = 1) out;\n"
531e5c31af7Sopenharmony_ci				"layout(binding = 3, std430) buffer Buffer3\n"
532e5c31af7Sopenharmony_ci				"{\n"
533e5c31af7Sopenharmony_ci				"  uint result[];\n"
534e5c31af7Sopenharmony_ci				"} b3;\n"
535e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
536e5c31af7Sopenharmony_ci				"{\n"
537e5c31af7Sopenharmony_ci				"  " + formatString + " data[];\n"
538e5c31af7Sopenharmony_ci				"};\n"
539e5c31af7Sopenharmony_ci				"\n"
540e5c31af7Sopenharmony_ci				"void main (void)\n"
541e5c31af7Sopenharmony_ci				"{\n"
542e5c31af7Sopenharmony_ci				"  highp int offset = gl_PrimitiveIDIn;\n"
543e5c31af7Sopenharmony_ci				+ sourceTemplate.specialize(bufferNameMapping) +
544e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position;\n"
545e5c31af7Sopenharmony_ci				"  EmitVertex();\n"
546e5c31af7Sopenharmony_ci				"  EndPrimitive();\n"
547e5c31af7Sopenharmony_ci				"}\n";
548e5c31af7Sopenharmony_ci
549e5c31af7Sopenharmony_ci			subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
550e5c31af7Sopenharmony_ci		}
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci		{
553e5c31af7Sopenharmony_ci			const string sourceFragment =
554e5c31af7Sopenharmony_ci			(OPTYPE_ALL == caseDef.opType) ?
555e5c31af7Sopenharmony_ci				"  result = " + getOpTypeName(caseDef.opType) +
556e5c31af7Sopenharmony_ci				"(true) ? 0x1u : 0u;\n"
557e5c31af7Sopenharmony_ci				"  result |= " + getOpTypeName(caseDef.opType) +
558e5c31af7Sopenharmony_ci				"(false) ? 0u : 0x1Au;\n"
559e5c31af7Sopenharmony_ci				"  result |= 0x4u;\n"
560e5c31af7Sopenharmony_ci			: (OPTYPE_ANY == caseDef.opType) ?
561e5c31af7Sopenharmony_ci					"  result = " + getOpTypeName(caseDef.opType) +
562e5c31af7Sopenharmony_ci					"(true) ? 0x1u : 0u;\n"
563e5c31af7Sopenharmony_ci					"  result |= " + getOpTypeName(caseDef.opType) +
564e5c31af7Sopenharmony_ci					"(false) ? 0u : 0x1Au;\n"
565e5c31af7Sopenharmony_ci					"  result |= 0x4u;\n"
566e5c31af7Sopenharmony_ci			: (OPTYPE_ALLEQUAL == caseDef.opType) ?
567e5c31af7Sopenharmony_ci					"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
568e5c31af7Sopenharmony_ci					"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + gl_FragCoord.x * float(gl_SubgroupInvocationID));\n") +
569e5c31af7Sopenharmony_ci					"  result = " + getOpTypeName(caseDef.opType) + "("
570e5c31af7Sopenharmony_ci					+ subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1u : 0u;\n"
571e5c31af7Sopenharmony_ci					"  result |= " + getOpTypeName(caseDef.opType) +
572e5c31af7Sopenharmony_ci					"(gl_SubgroupInvocationID) ? 0u : 0x2u;\n"
573e5c31af7Sopenharmony_ci					"  result |= " + getOpTypeName(caseDef.opType) +
574e5c31af7Sopenharmony_ci					"(data[0]) ? 0x4u : 0u;\n"
575e5c31af7Sopenharmony_ci					"  result |= " + getOpTypeName(caseDef.opType) +
576e5c31af7Sopenharmony_ci					"(valueEqual) ? 0x8u : 0x0u;\n"
577e5c31af7Sopenharmony_ci					"  result |= " + getOpTypeName(caseDef.opType) +
578e5c31af7Sopenharmony_ci					"(valueNoEqual) ? 0x0u : 0x10u;\n"
579e5c31af7Sopenharmony_ci					"  if (subgroupElect()) result |= 0x2u | 0x10u;\n"
580e5c31af7Sopenharmony_ci			: "";
581e5c31af7Sopenharmony_ci			const string fragment =
582e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
583e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_vote: enable\n"
584e5c31af7Sopenharmony_ci				"precision highp float;\n"
585e5c31af7Sopenharmony_ci				"layout(location = 0) out uint result;\n"
586e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
587e5c31af7Sopenharmony_ci				"{\n"
588e5c31af7Sopenharmony_ci				"  " + formatString + " data[];\n"
589e5c31af7Sopenharmony_ci				"};\n"
590e5c31af7Sopenharmony_ci				"void main (void)\n"
591e5c31af7Sopenharmony_ci				"{\n"
592e5c31af7Sopenharmony_ci				+ sourceFragment +
593e5c31af7Sopenharmony_ci				"}\n";
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci			programCollection.add("fragment") << glu::FragmentSource(fragment);
596e5c31af7Sopenharmony_ci		}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci		subgroups::addNoSubgroupShader(programCollection);
599e5c31af7Sopenharmony_ci	}
600e5c31af7Sopenharmony_ci}
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
603e5c31af7Sopenharmony_ci{
604e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
605e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_VOTE_BIT))
608e5c31af7Sopenharmony_ci	{
609e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup vote operations");
610e5c31af7Sopenharmony_ci	}
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci	if (subgroups::isDoubleFormat(caseDef.format) &&
613e5c31af7Sopenharmony_ci			!subgroups::isDoubleSupportedForDevice(context))
614e5c31af7Sopenharmony_ci	{
615e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
616e5c31af7Sopenharmony_ci	}
617e5c31af7Sopenharmony_ci}
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
620e5c31af7Sopenharmony_ci{
621e5c31af7Sopenharmony_ci	if (!subgroups::areSubgroupOperationsSupportedForStage(
622e5c31af7Sopenharmony_ci				context, caseDef.shaderStage))
623e5c31af7Sopenharmony_ci	{
624e5c31af7Sopenharmony_ci		if (subgroups::areSubgroupOperationsRequiredForStage(
625e5c31af7Sopenharmony_ci					caseDef.shaderStage))
626e5c31af7Sopenharmony_ci		{
627e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
628e5c31af7Sopenharmony_ci					   "Shader stage " +
629e5c31af7Sopenharmony_ci					   subgroups::getShaderStageName(caseDef.shaderStage) +
630e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
631e5c31af7Sopenharmony_ci		}
632e5c31af7Sopenharmony_ci		else
633e5c31af7Sopenharmony_ci		{
634e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
635e5c31af7Sopenharmony_ci		}
636e5c31af7Sopenharmony_ci	}
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_ci	subgroups::SSBOData inputData;
639e5c31af7Sopenharmony_ci	inputData.format = caseDef.format;
640e5c31af7Sopenharmony_ci	inputData.layout = subgroups::SSBOData::LayoutStd140;
641e5c31af7Sopenharmony_ci	inputData.numElements = subgroups::maxSupportedSubgroupSize();
642e5c31af7Sopenharmony_ci	inputData.initializeType = OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
645e5c31af7Sopenharmony_ci		return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
646e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
647e5c31af7Sopenharmony_ci		return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
648e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
649e5c31af7Sopenharmony_ci		return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
650e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
651e5c31af7Sopenharmony_ci		return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
652e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
653e5c31af7Sopenharmony_ci		return subgroups::makeFragmentFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkFragmentPipelineStages);
654e5c31af7Sopenharmony_ci	else
655e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unhandled shader stage");
656e5c31af7Sopenharmony_ci}
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci
659e5c31af7Sopenharmony_citcu::TestStatus test(Context& context, const CaseDefinition caseDef)
660e5c31af7Sopenharmony_ci{
661e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
662e5c31af7Sopenharmony_ci	{
663e5c31af7Sopenharmony_ci		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
664e5c31af7Sopenharmony_ci		{
665e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
666e5c31af7Sopenharmony_ci					   "Shader stage " +
667e5c31af7Sopenharmony_ci					   subgroups::getShaderStageName(caseDef.shaderStage) +
668e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
669e5c31af7Sopenharmony_ci		}
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci		subgroups::SSBOData inputData;
672e5c31af7Sopenharmony_ci		inputData.format = caseDef.format;
673e5c31af7Sopenharmony_ci		inputData.layout = subgroups::SSBOData::LayoutStd430;
674e5c31af7Sopenharmony_ci		inputData.numElements = subgroups::maxSupportedSubgroupSize();
675e5c31af7Sopenharmony_ci		inputData.initializeType = OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
676e5c31af7Sopenharmony_ci		inputData.binding = 1u;
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_ci		return subgroups::makeComputeTest(context, FORMAT_R32_UINT, &inputData,
679e5c31af7Sopenharmony_ci										  1, checkComputeStage);
680e5c31af7Sopenharmony_ci	}
681e5c31af7Sopenharmony_ci	else
682e5c31af7Sopenharmony_ci	{
683e5c31af7Sopenharmony_ci		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci		ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
686e5c31af7Sopenharmony_ci
687e5c31af7Sopenharmony_ci		if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
688e5c31af7Sopenharmony_ci		{
689e5c31af7Sopenharmony_ci			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
690e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
691e5c31af7Sopenharmony_ci			else
692e5c31af7Sopenharmony_ci				stages = SHADER_STAGE_FRAGMENT_BIT;
693e5c31af7Sopenharmony_ci		}
694e5c31af7Sopenharmony_ci
695e5c31af7Sopenharmony_ci		if ((ShaderStageFlags)0u == stages)
696e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci		subgroups::SSBOData inputData;
699e5c31af7Sopenharmony_ci		inputData.format			= caseDef.format;
700e5c31af7Sopenharmony_ci		inputData.layout			= subgroups::SSBOData::LayoutStd430;
701e5c31af7Sopenharmony_ci		inputData.numElements		= subgroups::maxSupportedSubgroupSize();
702e5c31af7Sopenharmony_ci		inputData.initializeType	= OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
703e5c31af7Sopenharmony_ci		inputData.binding			= 4u;
704e5c31af7Sopenharmony_ci		inputData.stages			= stages;
705e5c31af7Sopenharmony_ci
706e5c31af7Sopenharmony_ci		return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
707e5c31af7Sopenharmony_ci	}
708e5c31af7Sopenharmony_ci}
709e5c31af7Sopenharmony_ci
710e5c31af7Sopenharmony_ci} // namespace
711e5c31af7Sopenharmony_ci
712e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsVoteTests(deqp::Context& testCtx)
713e5c31af7Sopenharmony_ci{
714e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
715e5c31af7Sopenharmony_ci		testCtx, "graphics", "Subgroup arithmetic category tests: graphics"));
716e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
717e5c31af7Sopenharmony_ci		testCtx, "compute", "Subgroup arithmetic category tests: compute"));
718e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
719e5c31af7Sopenharmony_ci		testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer"));
720e5c31af7Sopenharmony_ci
721e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> fragHelperGroup(new deqp::TestCaseGroup(
722e5c31af7Sopenharmony_ci		testCtx, "frag_helper", "Subgroup arithmetic category tests: fragment helper invocation"));
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_ci	const ShaderStageFlags stages[] =
725e5c31af7Sopenharmony_ci	{
726e5c31af7Sopenharmony_ci		SHADER_STAGE_VERTEX_BIT,
727e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_EVALUATION_BIT,
728e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_CONTROL_BIT,
729e5c31af7Sopenharmony_ci		SHADER_STAGE_GEOMETRY_BIT,
730e5c31af7Sopenharmony_ci	};
731e5c31af7Sopenharmony_ci
732e5c31af7Sopenharmony_ci	const Format formats[] =
733e5c31af7Sopenharmony_ci	{
734e5c31af7Sopenharmony_ci		FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
735e5c31af7Sopenharmony_ci		FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
736e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
737e5c31af7Sopenharmony_ci		FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
738e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
739e5c31af7Sopenharmony_ci		FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
740e5c31af7Sopenharmony_ci		FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
741e5c31af7Sopenharmony_ci		FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
742e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
743e5c31af7Sopenharmony_ci	};
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
746e5c31af7Sopenharmony_ci	{
747e5c31af7Sopenharmony_ci		const Format format = formats[formatIndex];
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ci		for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
750e5c31af7Sopenharmony_ci		{
751e5c31af7Sopenharmony_ci			// Skip the typed tests for all but subgroupAllEqual()
752e5c31af7Sopenharmony_ci			if ((FORMAT_R32_UINT != format) && (OPTYPE_ALLEQUAL != opTypeIndex))
753e5c31af7Sopenharmony_ci			{
754e5c31af7Sopenharmony_ci				continue;
755e5c31af7Sopenharmony_ci			}
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci			const std::string op = de::toLower(getOpTypeName(opTypeIndex));
758e5c31af7Sopenharmony_ci
759e5c31af7Sopenharmony_ci			{
760e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
761e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(),
762e5c31af7Sopenharmony_ci											op + "_" + subgroups::getFormatNameForGLSL(format),
763e5c31af7Sopenharmony_ci											"", supportedCheck, initPrograms, test, caseDef);
764e5c31af7Sopenharmony_ci			}
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ci			{
767e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
768e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
769e5c31af7Sopenharmony_ci											op + "_" + subgroups::getFormatNameForGLSL(format),
770e5c31af7Sopenharmony_ci											"", supportedCheck, initPrograms, test, caseDef);
771e5c31af7Sopenharmony_ci			}
772e5c31af7Sopenharmony_ci
773e5c31af7Sopenharmony_ci			for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
774e5c31af7Sopenharmony_ci			{
775e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
776e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
777e5c31af7Sopenharmony_ci							op + "_" +
778e5c31af7Sopenharmony_ci							subgroups::getFormatNameForGLSL(format)
779e5c31af7Sopenharmony_ci							+ "_" + getShaderStageName(caseDef.shaderStage), "",
780e5c31af7Sopenharmony_ci							supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
781e5c31af7Sopenharmony_ci			}
782e5c31af7Sopenharmony_ci
783e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_FRAGMENT_BIT, format};
784e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(fragHelperGroup.get(),
785e5c31af7Sopenharmony_ci						op + "_" +
786e5c31af7Sopenharmony_ci						subgroups::getFormatNameForGLSL(format)
787e5c31af7Sopenharmony_ci						+ "_" + getShaderStageName(caseDef.shaderStage), "",
788e5c31af7Sopenharmony_ci						supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
789e5c31af7Sopenharmony_ci		}
790e5c31af7Sopenharmony_ci	}
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
793e5c31af7Sopenharmony_ci		testCtx, "vote", "Subgroup vote category tests"));
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
796e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
797e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
798e5c31af7Sopenharmony_ci	group->addChild(fragHelperGroup.release());
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_ci	return group.release();
801e5c31af7Sopenharmony_ci}
802e5c31af7Sopenharmony_ci
803e5c31af7Sopenharmony_ci} // subgroups
804e5c31af7Sopenharmony_ci} // glc
805