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 "glcSubgroupsBuiltinMaskVarTests.hpp"
27e5c31af7Sopenharmony_ci#include "glcSubgroupsTestsUtils.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include <string>
30e5c31af7Sopenharmony_ci#include <vector>
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ciusing namespace tcu;
33e5c31af7Sopenharmony_ciusing namespace std;
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_cinamespace glc
36e5c31af7Sopenharmony_ci{
37e5c31af7Sopenharmony_cinamespace subgroups
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages(std::vector<const void*> datas,
41e5c31af7Sopenharmony_ci									  deUint32 width, deUint32)
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci	return check(datas, width, 1);
44e5c31af7Sopenharmony_ci}
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cistatic bool checkComputeStage(std::vector<const void*> datas,
47e5c31af7Sopenharmony_ci						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
48e5c31af7Sopenharmony_ci						 deUint32)
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_ci	return checkCompute(datas, numWorkgroups, localSize, 1);
51e5c31af7Sopenharmony_ci}
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cinamespace
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_cistruct CaseDefinition
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci	std::string			varName;
58e5c31af7Sopenharmony_ci	ShaderStageFlags	shaderStage;
59e5c31af7Sopenharmony_ci};
60e5c31af7Sopenharmony_ci}
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_cistd::string subgroupMask (const CaseDefinition& caseDef)
63e5c31af7Sopenharmony_ci{
64e5c31af7Sopenharmony_ci	std::ostringstream bdy;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ci	bdy << "  uint tempResult = 0x1u;\n"
67e5c31af7Sopenharmony_ci		<< "  uint bit        = 0x1u;\n"
68e5c31af7Sopenharmony_ci		<< "  uint bitCount   = 0x0u;\n"
69e5c31af7Sopenharmony_ci		<< "  uvec4 mask = subgroupBallot(true);\n"
70e5c31af7Sopenharmony_ci		<< "  uvec4 var = " << caseDef.varName << ";\n"
71e5c31af7Sopenharmony_ci		<< "  for (uint i = 0u; i < gl_SubgroupSize; i++)\n"
72e5c31af7Sopenharmony_ci		<< "  {\n";
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci	if ("gl_SubgroupEqMask" == caseDef.varName)
75e5c31af7Sopenharmony_ci	{
76e5c31af7Sopenharmony_ci		bdy << "    if ((i == gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
77e5c31af7Sopenharmony_ci			<< "    {\n"
78e5c31af7Sopenharmony_ci			<< "      tempResult = 0u;\n"
79e5c31af7Sopenharmony_ci			<< "    }\n";
80e5c31af7Sopenharmony_ci	}
81e5c31af7Sopenharmony_ci	else if ("gl_SubgroupGeMask" == caseDef.varName)
82e5c31af7Sopenharmony_ci	{
83e5c31af7Sopenharmony_ci		bdy << "    if ((i >= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
84e5c31af7Sopenharmony_ci			<< "    {\n"
85e5c31af7Sopenharmony_ci			<< "      tempResult = 0u;\n"
86e5c31af7Sopenharmony_ci			<< "    }\n";
87e5c31af7Sopenharmony_ci	}
88e5c31af7Sopenharmony_ci	else if ("gl_SubgroupGtMask" == caseDef.varName)
89e5c31af7Sopenharmony_ci	{
90e5c31af7Sopenharmony_ci		bdy << "    if ((i > gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
91e5c31af7Sopenharmony_ci			<< "    {\n"
92e5c31af7Sopenharmony_ci			<< "      tempResult = 0u;\n"
93e5c31af7Sopenharmony_ci			<< "    }\n";
94e5c31af7Sopenharmony_ci	}
95e5c31af7Sopenharmony_ci	else if ("gl_SubgroupLeMask" == caseDef.varName)
96e5c31af7Sopenharmony_ci	{
97e5c31af7Sopenharmony_ci		bdy << "    if ((i <= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
98e5c31af7Sopenharmony_ci			<< "    {\n"
99e5c31af7Sopenharmony_ci			<< "      tempResult = 0u;\n"
100e5c31af7Sopenharmony_ci			<< "    }\n";
101e5c31af7Sopenharmony_ci	}
102e5c31af7Sopenharmony_ci	else if ("gl_SubgroupLtMask" == caseDef.varName)
103e5c31af7Sopenharmony_ci	{
104e5c31af7Sopenharmony_ci		bdy << "    if ((i < gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
105e5c31af7Sopenharmony_ci			<< "    {\n"
106e5c31af7Sopenharmony_ci			<< "      tempResult = 0u;\n"
107e5c31af7Sopenharmony_ci			<< "    }\n";
108e5c31af7Sopenharmony_ci	}
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	bdy << "  }\n"
111e5c31af7Sopenharmony_ci		<< "  for (uint i = 0u; i < 32u; i++)\n"
112e5c31af7Sopenharmony_ci		<< "  {\n"
113e5c31af7Sopenharmony_ci		<< "    if ((var.x & bit) > 0u)\n"
114e5c31af7Sopenharmony_ci		<< "    {\n"
115e5c31af7Sopenharmony_ci		<< "      bitCount++;\n"
116e5c31af7Sopenharmony_ci		<< "    }\n"
117e5c31af7Sopenharmony_ci		<< "    if ((var.y & bit) > 0u)\n"
118e5c31af7Sopenharmony_ci		<< "    {\n"
119e5c31af7Sopenharmony_ci		<< "      bitCount++;\n"
120e5c31af7Sopenharmony_ci		<< "    }\n"
121e5c31af7Sopenharmony_ci		<< "    if ((var.z & bit) > 0u)\n"
122e5c31af7Sopenharmony_ci		<< "    {\n"
123e5c31af7Sopenharmony_ci		<< "      bitCount++;\n"
124e5c31af7Sopenharmony_ci		<< "    }\n"
125e5c31af7Sopenharmony_ci		<< "    if ((var.w & bit) > 0u)\n"
126e5c31af7Sopenharmony_ci		<< "    {\n"
127e5c31af7Sopenharmony_ci		<< "      bitCount++;\n"
128e5c31af7Sopenharmony_ci		<< "    }\n"
129e5c31af7Sopenharmony_ci		<< "    bit = bit << 1u;\n"
130e5c31af7Sopenharmony_ci		<< "  }\n"
131e5c31af7Sopenharmony_ci		<< "  if (subgroupBallotBitCount(var) != bitCount)\n"
132e5c31af7Sopenharmony_ci		<< "  {\n"
133e5c31af7Sopenharmony_ci		<< "    tempResult = 0u;\n"
134e5c31af7Sopenharmony_ci		<< "  }\n";
135e5c31af7Sopenharmony_ci	return bdy.str();
136e5c31af7Sopenharmony_ci}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_civoid initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
139e5c31af7Sopenharmony_ci{
140e5c31af7Sopenharmony_ci	subgroups::setFragmentShaderFrameBuffer(programCollection);
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
143e5c31af7Sopenharmony_ci		subgroups::setVertexShaderFrameBuffer(programCollection);
144e5c31af7Sopenharmony_ci
145e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
146e5c31af7Sopenharmony_ci	{
147e5c31af7Sopenharmony_ci		const string bdy = subgroupMask(caseDef);
148e5c31af7Sopenharmony_ci		const string vertexGLSL =
149e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
150e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
151e5c31af7Sopenharmony_ci			"layout(location = 0) out float out_color;\n"
152e5c31af7Sopenharmony_ci			"layout(location = 0) in highp vec4 in_position;\n"
153e5c31af7Sopenharmony_ci			"\n"
154e5c31af7Sopenharmony_ci			"void main (void)\n"
155e5c31af7Sopenharmony_ci			"{\n"
156e5c31af7Sopenharmony_ci			+ bdy +
157e5c31af7Sopenharmony_ci			"  out_color = float(tempResult);\n"
158e5c31af7Sopenharmony_ci			"  gl_Position = in_position;\n"
159e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
160e5c31af7Sopenharmony_ci			"}\n";
161e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertexGLSL);
162e5c31af7Sopenharmony_ci	}
163e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
164e5c31af7Sopenharmony_ci	{
165e5c31af7Sopenharmony_ci		const string bdy = subgroupMask(caseDef);
166e5c31af7Sopenharmony_ci		const string  evaluationSourceGLSL =
167e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
168e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
169e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
170e5c31af7Sopenharmony_ci			"layout(isolines, equal_spacing, ccw ) in;\n"
171e5c31af7Sopenharmony_ci			"layout(location = 0) out float out_color;\n"
172e5c31af7Sopenharmony_ci			"\n"
173e5c31af7Sopenharmony_ci			"void main (void)\n"
174e5c31af7Sopenharmony_ci			"{\n"
175e5c31af7Sopenharmony_ci			+ bdy +
176e5c31af7Sopenharmony_ci			"  out_color = float(tempResult);\n"
177e5c31af7Sopenharmony_ci			"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
178e5c31af7Sopenharmony_ci			"}\n";
179e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
180e5c31af7Sopenharmony_ci		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
181e5c31af7Sopenharmony_ci	}
182e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
183e5c31af7Sopenharmony_ci	{
184e5c31af7Sopenharmony_ci		const string bdy = subgroupMask(caseDef);
185e5c31af7Sopenharmony_ci		const string  controlSourceGLSL =
186e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
187e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
188e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
189e5c31af7Sopenharmony_ci			"layout(vertices = 2) out;\n"
190e5c31af7Sopenharmony_ci			"layout(location = 0) out float out_color[];\n"
191e5c31af7Sopenharmony_ci			"void main (void)\n"
192e5c31af7Sopenharmony_ci			"{\n"
193e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
194e5c31af7Sopenharmony_ci			"  {\n"
195e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
196e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
197e5c31af7Sopenharmony_ci			"  }\n"
198e5c31af7Sopenharmony_ci			+ bdy +
199e5c31af7Sopenharmony_ci			"  out_color[gl_InvocationID] = float(tempResult);\n"
200e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
201e5c31af7Sopenharmony_ci			"}\n";
202e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
203e5c31af7Sopenharmony_ci		subgroups::setTesEvalShaderFrameBuffer(programCollection);
204e5c31af7Sopenharmony_ci	}
205e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
206e5c31af7Sopenharmony_ci	{
207e5c31af7Sopenharmony_ci		const string bdy = subgroupMask(caseDef);
208e5c31af7Sopenharmony_ci		const string geometryGLSL =
209e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
210e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
211e5c31af7Sopenharmony_ci			"layout(points) in;\n"
212e5c31af7Sopenharmony_ci			"layout(points, max_vertices = 1) out;\n"
213e5c31af7Sopenharmony_ci			"layout(location = 0) out float out_color;\n"
214e5c31af7Sopenharmony_ci			"\n"
215e5c31af7Sopenharmony_ci			"void main (void)\n"
216e5c31af7Sopenharmony_ci			"{\n"
217e5c31af7Sopenharmony_ci			+ bdy +
218e5c31af7Sopenharmony_ci			"  out_color = float(tempResult);\n"
219e5c31af7Sopenharmony_ci			"  gl_Position = gl_in[0].gl_Position;\n"
220e5c31af7Sopenharmony_ci			"  EmitVertex();\n"
221e5c31af7Sopenharmony_ci			"  EndPrimitive();\n"
222e5c31af7Sopenharmony_ci			"}\n";
223e5c31af7Sopenharmony_ci		programCollection.add("geometry") << glu::GeometrySource(geometryGLSL);
224e5c31af7Sopenharmony_ci	}
225e5c31af7Sopenharmony_ci	else
226e5c31af7Sopenharmony_ci	{
227e5c31af7Sopenharmony_ci		DE_FATAL("Unsupported shader stage");
228e5c31af7Sopenharmony_ci	}
229e5c31af7Sopenharmony_ci}
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
233e5c31af7Sopenharmony_ci{
234e5c31af7Sopenharmony_ci	const string bdy = subgroupMask(caseDef);
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
237e5c31af7Sopenharmony_ci	{
238e5c31af7Sopenharmony_ci		std::ostringstream src;
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_ci		src << "${VERSION_DECL}\n"
241e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
242e5c31af7Sopenharmony_ci			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
243e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std430) buffer Output\n"
244e5c31af7Sopenharmony_ci			<< "{\n"
245e5c31af7Sopenharmony_ci			<< "  uint result[];\n"
246e5c31af7Sopenharmony_ci			<< "};\n"
247e5c31af7Sopenharmony_ci			<< "\n"
248e5c31af7Sopenharmony_ci			<< "void main (void)\n"
249e5c31af7Sopenharmony_ci			<< "{\n"
250e5c31af7Sopenharmony_ci			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
251e5c31af7Sopenharmony_ci			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
252e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
253e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.x;\n"
254e5c31af7Sopenharmony_ci			<< bdy
255e5c31af7Sopenharmony_ci			<< "  result[offset] = tempResult;\n"
256e5c31af7Sopenharmony_ci			<< "}\n";
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_ci		programCollection.add("comp") << glu::ComputeSource(src.str());
259e5c31af7Sopenharmony_ci	}
260e5c31af7Sopenharmony_ci	else
261e5c31af7Sopenharmony_ci	{
262e5c31af7Sopenharmony_ci		{
263e5c31af7Sopenharmony_ci			const string vertex =
264e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
265e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
266e5c31af7Sopenharmony_ci				"layout(binding = 0, std430) buffer Output0\n"
267e5c31af7Sopenharmony_ci				"{\n"
268e5c31af7Sopenharmony_ci				"  uint result[];\n"
269e5c31af7Sopenharmony_ci				"} b0;\n"
270e5c31af7Sopenharmony_ci				"\n"
271e5c31af7Sopenharmony_ci				"void main (void)\n"
272e5c31af7Sopenharmony_ci				"{\n"
273e5c31af7Sopenharmony_ci				+ bdy +
274e5c31af7Sopenharmony_ci				"  b0.result[gl_VertexID] = tempResult;\n"
275e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
276e5c31af7Sopenharmony_ci				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
277e5c31af7Sopenharmony_ci				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
278e5c31af7Sopenharmony_ci				"  gl_PointSize = 1.0f;\n"
279e5c31af7Sopenharmony_ci				"}\n";
280e5c31af7Sopenharmony_ci			programCollection.add("vert") << glu::VertexSource(vertex);
281e5c31af7Sopenharmony_ci		}
282e5c31af7Sopenharmony_ci
283e5c31af7Sopenharmony_ci		{
284e5c31af7Sopenharmony_ci			const string tesc =
285e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
286e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
287e5c31af7Sopenharmony_ci				"layout(vertices=1) out;\n"
288e5c31af7Sopenharmony_ci				"layout(binding = 1, std430) buffer Output1\n"
289e5c31af7Sopenharmony_ci				"{\n"
290e5c31af7Sopenharmony_ci				"  uint result[];\n"
291e5c31af7Sopenharmony_ci				"} b1;\n"
292e5c31af7Sopenharmony_ci				"\n"
293e5c31af7Sopenharmony_ci				"void main (void)\n"
294e5c31af7Sopenharmony_ci				"{\n"
295e5c31af7Sopenharmony_ci				+ bdy +
296e5c31af7Sopenharmony_ci				"  b1.result[gl_PrimitiveID] = tempResult;\n"
297e5c31af7Sopenharmony_ci				"  if (gl_InvocationID == 0)\n"
298e5c31af7Sopenharmony_ci				"  {\n"
299e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[0] = 1.0f;\n"
300e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[1] = 1.0f;\n"
301e5c31af7Sopenharmony_ci				"  }\n"
302e5c31af7Sopenharmony_ci				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
303e5c31af7Sopenharmony_ci				"}\n";
304e5c31af7Sopenharmony_ci			programCollection.add("tesc") << glu::TessellationControlSource(tesc);
305e5c31af7Sopenharmony_ci		}
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci		{
308e5c31af7Sopenharmony_ci			const string tese =
309e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
310e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
311e5c31af7Sopenharmony_ci				"layout(isolines) in;\n"
312e5c31af7Sopenharmony_ci				"layout(binding = 2, std430) buffer Output2\n"
313e5c31af7Sopenharmony_ci				"{\n"
314e5c31af7Sopenharmony_ci				"  uint result[];\n"
315e5c31af7Sopenharmony_ci				"} b2;\n"
316e5c31af7Sopenharmony_ci				"\n"
317e5c31af7Sopenharmony_ci				"void main (void)\n"
318e5c31af7Sopenharmony_ci				"{\n"
319e5c31af7Sopenharmony_ci				+ bdy +
320e5c31af7Sopenharmony_ci				"  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = tempResult;\n"
321e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
322e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
323e5c31af7Sopenharmony_ci				"}\n";
324e5c31af7Sopenharmony_ci
325e5c31af7Sopenharmony_ci			programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
326e5c31af7Sopenharmony_ci		}
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_ci		{
329e5c31af7Sopenharmony_ci			const string geometry =
330e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
331e5c31af7Sopenharmony_ci				"layout(${TOPOLOGY}) in;\n"
332e5c31af7Sopenharmony_ci				"layout(points, max_vertices = 1) out;\n"
333e5c31af7Sopenharmony_ci				"layout(binding = 3, std430) buffer Output3\n"
334e5c31af7Sopenharmony_ci				"{\n"
335e5c31af7Sopenharmony_ci				"  uint result[];\n"
336e5c31af7Sopenharmony_ci				"} b3;\n"
337e5c31af7Sopenharmony_ci				"\n"
338e5c31af7Sopenharmony_ci				"void main (void)\n"
339e5c31af7Sopenharmony_ci				"{\n"
340e5c31af7Sopenharmony_ci				+ bdy +
341e5c31af7Sopenharmony_ci				"  b3.result[gl_PrimitiveIDIn] = tempResult;\n"
342e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position;\n"
343e5c31af7Sopenharmony_ci				"  EmitVertex();\n"
344e5c31af7Sopenharmony_ci				"  EndPrimitive();\n"
345e5c31af7Sopenharmony_ci				"}\n";
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_ci			subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
348e5c31af7Sopenharmony_ci		}
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci		{
351e5c31af7Sopenharmony_ci			const string fragment =
352e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
353e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
354e5c31af7Sopenharmony_ci				"precision highp int;\n"
355e5c31af7Sopenharmony_ci				"layout(location = 0) out uint result;\n"
356e5c31af7Sopenharmony_ci				"void main (void)\n"
357e5c31af7Sopenharmony_ci				"{\n"
358e5c31af7Sopenharmony_ci				+ bdy +
359e5c31af7Sopenharmony_ci				"  result = tempResult;\n"
360e5c31af7Sopenharmony_ci				"}\n";
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci			programCollection.add("fragment") << glu::FragmentSource(fragment);
363e5c31af7Sopenharmony_ci		}
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci		subgroups::addNoSubgroupShader(programCollection);
366e5c31af7Sopenharmony_ci	}
367e5c31af7Sopenharmony_ci}
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
370e5c31af7Sopenharmony_ci{
371e5c31af7Sopenharmony_ci	DE_UNREF(caseDef);
372e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
373e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
374e5c31af7Sopenharmony_ci}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest(Context& context, const CaseDefinition caseDef)
377e5c31af7Sopenharmony_ci{
378e5c31af7Sopenharmony_ci	if (!areSubgroupOperationsSupportedForStage(
379e5c31af7Sopenharmony_ci				context, caseDef.shaderStage))
380e5c31af7Sopenharmony_ci	{
381e5c31af7Sopenharmony_ci		if (areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
382e5c31af7Sopenharmony_ci		{
383e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
384e5c31af7Sopenharmony_ci					   "Shader stage " + getShaderStageName(caseDef.shaderStage) +
385e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
386e5c31af7Sopenharmony_ci		}
387e5c31af7Sopenharmony_ci		else
388e5c31af7Sopenharmony_ci		{
389e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
390e5c31af7Sopenharmony_ci		}
391e5c31af7Sopenharmony_ci	}
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_BALLOT_BIT))
394e5c31af7Sopenharmony_ci	{
395e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
396e5c31af7Sopenharmony_ci	}
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
399e5c31af7Sopenharmony_ci		return makeVertexFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
400e5c31af7Sopenharmony_ci	else if ((SHADER_STAGE_TESS_EVALUATION_BIT | SHADER_STAGE_TESS_CONTROL_BIT) & caseDef.shaderStage )
401e5c31af7Sopenharmony_ci		return makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_ci	return makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
404e5c31af7Sopenharmony_ci}
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_citcu::TestStatus test(Context& context, const CaseDefinition caseDef)
408e5c31af7Sopenharmony_ci{
409e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_BALLOT_BIT))
410e5c31af7Sopenharmony_ci	{
411e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
412e5c31af7Sopenharmony_ci	}
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
415e5c31af7Sopenharmony_ci	{
416e5c31af7Sopenharmony_ci		if (!areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
417e5c31af7Sopenharmony_ci		{
418e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail(
419e5c31af7Sopenharmony_ci						   "Shader stage " + getShaderStageName(caseDef.shaderStage) +
420e5c31af7Sopenharmony_ci						   " is required to support subgroup operations!");
421e5c31af7Sopenharmony_ci		}
422e5c31af7Sopenharmony_ci		return makeComputeTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkComputeStage);
423e5c31af7Sopenharmony_ci	}
424e5c31af7Sopenharmony_ci	else
425e5c31af7Sopenharmony_ci	{
426e5c31af7Sopenharmony_ci		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci		subgroups::ShaderStageFlags stages = (subgroups::ShaderStageFlags)(caseDef.shaderStage & supportedStages);
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci		if ( SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
431e5c31af7Sopenharmony_ci		{
432e5c31af7Sopenharmony_ci			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
433e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
434e5c31af7Sopenharmony_ci			else
435e5c31af7Sopenharmony_ci				stages = SHADER_STAGE_FRAGMENT_BIT;
436e5c31af7Sopenharmony_ci		}
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci		if ((ShaderStageFlags)0u == stages)
439e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci		return subgroups::allStages(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages, stages);
442e5c31af7Sopenharmony_ci	}
443e5c31af7Sopenharmony_ci}
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsBuiltinMaskVarTests(deqp::Context& testCtx)
446e5c31af7Sopenharmony_ci{
447e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
448e5c31af7Sopenharmony_ci		testCtx, "graphics", "Subgroup builtin mask category	tests: graphics"));
449e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
450e5c31af7Sopenharmony_ci		testCtx, "compute", "Subgroup builtin mask category tests: compute"));
451e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
452e5c31af7Sopenharmony_ci		testCtx, "framebuffer", "Subgroup builtin mask category tests: framebuffer"));
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci	const char* const all_stages_vars[] =
455e5c31af7Sopenharmony_ci	{
456e5c31af7Sopenharmony_ci		"SubgroupEqMask",
457e5c31af7Sopenharmony_ci		"SubgroupGeMask",
458e5c31af7Sopenharmony_ci		"SubgroupGtMask",
459e5c31af7Sopenharmony_ci		"SubgroupLeMask",
460e5c31af7Sopenharmony_ci		"SubgroupLtMask",
461e5c31af7Sopenharmony_ci	};
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	const subgroups::ShaderStageFlags stages[] =
464e5c31af7Sopenharmony_ci	{
465e5c31af7Sopenharmony_ci		SHADER_STAGE_VERTEX_BIT,
466e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_EVALUATION_BIT,
467e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_CONTROL_BIT,
468e5c31af7Sopenharmony_ci		SHADER_STAGE_GEOMETRY_BIT,
469e5c31af7Sopenharmony_ci	};
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ci	for (int a = 0; a < DE_LENGTH_OF_ARRAY(all_stages_vars); ++a)
473e5c31af7Sopenharmony_ci	{
474e5c31af7Sopenharmony_ci		const std::string var = all_stages_vars[a];
475e5c31af7Sopenharmony_ci		const std::string varLower = de::toLower(var);
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ci		{
478e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {"gl_" + var, SHADER_STAGE_ALL_GRAPHICS};
479e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
480e5c31af7Sopenharmony_ci										varLower, "",
481e5c31af7Sopenharmony_ci										supportedCheck, initPrograms, test, caseDef);
482e5c31af7Sopenharmony_ci		}
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci		{
485e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {"gl_" + var, SHADER_STAGE_COMPUTE_BIT};
486e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(),
487e5c31af7Sopenharmony_ci										varLower, "",
488e5c31af7Sopenharmony_ci										supportedCheck, initPrograms, test, caseDef);
489e5c31af7Sopenharmony_ci		}
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci		for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
492e5c31af7Sopenharmony_ci		{
493e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {"gl_" + var, stages[stageIndex]};
494e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
495e5c31af7Sopenharmony_ci						varLower + "_" +
496e5c31af7Sopenharmony_ci						getShaderStageName(caseDef.shaderStage), "",
497e5c31af7Sopenharmony_ci						supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
498e5c31af7Sopenharmony_ci		}
499e5c31af7Sopenharmony_ci	}
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
502e5c31af7Sopenharmony_ci		testCtx, "builtin_mask_var", "Subgroup builtin mask variable tests"));
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
505e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
506e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
507e5c31af7Sopenharmony_ci
508e5c31af7Sopenharmony_ci	return group.release();
509e5c31af7Sopenharmony_ci}
510e5c31af7Sopenharmony_ci} // subgroups
511e5c31af7Sopenharmony_ci} // glc
512