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 "glcSubgroupsBallotOtherTests.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_cinamespace
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_cienum OpType
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci	OPTYPE_INVERSE_BALLOT = 0,
44e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_BIT_EXTRACT,
45e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_BIT_COUNT,
46e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT,
47e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT,
48e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_FIND_LSB,
49e5c31af7Sopenharmony_ci	OPTYPE_BALLOT_FIND_MSB,
50e5c31af7Sopenharmony_ci	OPTYPE_LAST
51e5c31af7Sopenharmony_ci};
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages(std::vector<const void*> datas,
54e5c31af7Sopenharmony_ci									  deUint32 width, deUint32)
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_ci	return glc::subgroups::check(datas, width, 0xf);
57e5c31af7Sopenharmony_ci}
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cistatic bool checkComputeStage(std::vector<const void*> datas,
60e5c31af7Sopenharmony_ci						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
61e5c31af7Sopenharmony_ci						 deUint32)
62e5c31af7Sopenharmony_ci{
63e5c31af7Sopenharmony_ci	return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 0xf);
64e5c31af7Sopenharmony_ci}
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_cistd::string getOpTypeName(int opType)
67e5c31af7Sopenharmony_ci{
68e5c31af7Sopenharmony_ci	switch (opType)
69e5c31af7Sopenharmony_ci	{
70e5c31af7Sopenharmony_ci		default:
71e5c31af7Sopenharmony_ci			DE_FATAL("Unsupported op type");
72e5c31af7Sopenharmony_ci			return "";
73e5c31af7Sopenharmony_ci		case OPTYPE_INVERSE_BALLOT:
74e5c31af7Sopenharmony_ci			return "subgroupInverseBallot";
75e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_BIT_EXTRACT:
76e5c31af7Sopenharmony_ci			return "subgroupBallotBitExtract";
77e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_BIT_COUNT:
78e5c31af7Sopenharmony_ci			return "subgroupBallotBitCount";
79e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT:
80e5c31af7Sopenharmony_ci			return "subgroupBallotInclusiveBitCount";
81e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT:
82e5c31af7Sopenharmony_ci			return "subgroupBallotExclusiveBitCount";
83e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_FIND_LSB:
84e5c31af7Sopenharmony_ci			return "subgroupBallotFindLSB";
85e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_FIND_MSB:
86e5c31af7Sopenharmony_ci			return "subgroupBallotFindMSB";
87e5c31af7Sopenharmony_ci	}
88e5c31af7Sopenharmony_ci}
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_cistruct CaseDefinition
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	int					opType;
93e5c31af7Sopenharmony_ci	ShaderStageFlags	shaderStage;
94e5c31af7Sopenharmony_ci};
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_cistd::string getBodySource(CaseDefinition caseDef)
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_ci	std::ostringstream bdy;
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci	bdy << "  uvec4 allOnes = uvec4(0xFFFFFFFF);\n"
101e5c31af7Sopenharmony_ci		<< "  uvec4 allZeros = uvec4(0);\n"
102e5c31af7Sopenharmony_ci		<< "  uint tempResult = 0u;\n"
103e5c31af7Sopenharmony_ci		<< "#define MAKE_HIGH_BALLOT_RESULT(i) uvec4("
104e5c31af7Sopenharmony_ci		<< "i >= 32u ? 0u : (0xFFFFFFFFu << i), "
105e5c31af7Sopenharmony_ci		<< "i >= 64u ? 0u : (0xFFFFFFFFu << ((i < 32u) ? 0u : (i - 32u))), "
106e5c31af7Sopenharmony_ci		<< "i >= 96u ? 0u : (0xFFFFFFFFu << ((i < 64u) ? 0u : (i - 64u))), "
107e5c31af7Sopenharmony_ci		<< "i == 128u ? 0u : (0xFFFFFFFFu << ((i < 96u) ? 0u : (i - 96u))))\n"
108e5c31af7Sopenharmony_ci		<< "#define MAKE_SINGLE_BIT_BALLOT_RESULT(i) uvec4("
109e5c31af7Sopenharmony_ci		<< "i >= 32u ? 0u : 0x1u << i, "
110e5c31af7Sopenharmony_ci		<< "i < 32u || i >= 64u ? 0u : 0x1u << (i - 32u), "
111e5c31af7Sopenharmony_ci		<< "i < 64u || i >= 96u ? 0u : 0x1u << (i - 64u), "
112e5c31af7Sopenharmony_ci		<< "i < 96u ? 0u : 0x1u << (i - 96u))\n";
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci	switch (caseDef.opType)
115e5c31af7Sopenharmony_ci	{
116e5c31af7Sopenharmony_ci		default:
117e5c31af7Sopenharmony_ci			DE_FATAL("Unknown op type!");
118e5c31af7Sopenharmony_ci			break;
119e5c31af7Sopenharmony_ci		case OPTYPE_INVERSE_BALLOT:
120e5c31af7Sopenharmony_ci			bdy << "  tempResult |= subgroupInverseBallot(allOnes) ? 0x1u : 0u;\n"
121e5c31af7Sopenharmony_ci				<< "  tempResult |= subgroupInverseBallot(allZeros) ? 0u : 0x2u;\n"
122e5c31af7Sopenharmony_ci				<< "  tempResult |= subgroupInverseBallot(subgroupBallot(true)) ? 0x4u : 0u;\n"
123e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n";
124e5c31af7Sopenharmony_ci			break;
125e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_BIT_EXTRACT:
126e5c31af7Sopenharmony_ci			bdy << "  tempResult |= subgroupBallotBitExtract(allOnes, gl_SubgroupInvocationID) ? 0x1u : 0u;\n"
127e5c31af7Sopenharmony_ci				<< "  tempResult |= subgroupBallotBitExtract(allZeros, gl_SubgroupInvocationID) ? 0u : 0x2u;\n"
128e5c31af7Sopenharmony_ci				<< "  tempResult |= subgroupBallotBitExtract(subgroupBallot(true), gl_SubgroupInvocationID) ? 0x4u : 0u;\n"
129e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n"
130e5c31af7Sopenharmony_ci				<< "  for (uint i = 0u; i < gl_SubgroupSize; i++)\n"
131e5c31af7Sopenharmony_ci				<< "  {\n"
132e5c31af7Sopenharmony_ci				<< "    if (!subgroupBallotBitExtract(allOnes, gl_SubgroupInvocationID))\n"
133e5c31af7Sopenharmony_ci				<< "    {\n"
134e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
135e5c31af7Sopenharmony_ci				<< "    }\n"
136e5c31af7Sopenharmony_ci				<< "  }\n";
137e5c31af7Sopenharmony_ci			break;
138e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_BIT_COUNT:
139e5c31af7Sopenharmony_ci			bdy << "  tempResult |= gl_SubgroupSize == subgroupBallotBitCount(allOnes) ? 0x1u : 0u;\n"
140e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u == subgroupBallotBitCount(allZeros) ? 0x2u : 0u;\n"
141e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u < subgroupBallotBitCount(subgroupBallot(true)) ? 0x4u : 0u;\n"
142e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u == subgroupBallotBitCount(MAKE_HIGH_BALLOT_RESULT(gl_SubgroupSize)) ? 0x8u : 0u;\n";
143e5c31af7Sopenharmony_ci			break;
144e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT:
145e5c31af7Sopenharmony_ci			bdy << "  uint inclusiveOffset = gl_SubgroupInvocationID + 1u;\n"
146e5c31af7Sopenharmony_ci				<< "  tempResult |= inclusiveOffset == subgroupBallotInclusiveBitCount(allOnes) ? 0x1u : 0u;\n"
147e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u == subgroupBallotInclusiveBitCount(allZeros) ? 0x2u : 0u;\n"
148e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u < subgroupBallotInclusiveBitCount(subgroupBallot(true)) ? 0x4u : 0u;\n"
149e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n"
150e5c31af7Sopenharmony_ci				<< "  uvec4 inclusiveUndef = MAKE_HIGH_BALLOT_RESULT(inclusiveOffset);\n"
151e5c31af7Sopenharmony_ci				<< "  bool undefTerritory = false;\n"
152e5c31af7Sopenharmony_ci				<< "  for (uint i = 0u; i <= 128u; i++)\n"
153e5c31af7Sopenharmony_ci				<< "  {\n"
154e5c31af7Sopenharmony_ci				<< "    uvec4 iUndef = MAKE_HIGH_BALLOT_RESULT(i);\n"
155e5c31af7Sopenharmony_ci				<< "    if (iUndef == inclusiveUndef)"
156e5c31af7Sopenharmony_ci				<< "    {\n"
157e5c31af7Sopenharmony_ci				<< "      undefTerritory = true;\n"
158e5c31af7Sopenharmony_ci				<< "    }\n"
159e5c31af7Sopenharmony_ci				<< "    uint inclusiveBitCount = subgroupBallotInclusiveBitCount(iUndef);\n"
160e5c31af7Sopenharmony_ci				<< "    if (undefTerritory && (0u != inclusiveBitCount))\n"
161e5c31af7Sopenharmony_ci				<< "    {\n"
162e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
163e5c31af7Sopenharmony_ci				<< "    }\n"
164e5c31af7Sopenharmony_ci				<< "    else if (!undefTerritory && (0u == inclusiveBitCount))\n"
165e5c31af7Sopenharmony_ci				<< "    {\n"
166e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
167e5c31af7Sopenharmony_ci				<< "    }\n"
168e5c31af7Sopenharmony_ci				<< "  }\n";
169e5c31af7Sopenharmony_ci			break;
170e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT:
171e5c31af7Sopenharmony_ci			bdy << "  uint exclusiveOffset = gl_SubgroupInvocationID;\n"
172e5c31af7Sopenharmony_ci				<< "  tempResult |= exclusiveOffset == subgroupBallotExclusiveBitCount(allOnes) ? 0x1u : 0u;\n"
173e5c31af7Sopenharmony_ci				<< "  tempResult |= 0u == subgroupBallotExclusiveBitCount(allZeros) ? 0x2u : 0u;\n"
174e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x4u;\n"
175e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n"
176e5c31af7Sopenharmony_ci				<< "  uvec4 exclusiveUndef = MAKE_HIGH_BALLOT_RESULT(exclusiveOffset);\n"
177e5c31af7Sopenharmony_ci				<< "  bool undefTerritory = false;\n"
178e5c31af7Sopenharmony_ci				<< "  for (uint i = 0u; i <= 128u; i++)\n"
179e5c31af7Sopenharmony_ci				<< "  {\n"
180e5c31af7Sopenharmony_ci				<< "    uvec4 iUndef = MAKE_HIGH_BALLOT_RESULT(i);\n"
181e5c31af7Sopenharmony_ci				<< "    if (iUndef == exclusiveUndef)"
182e5c31af7Sopenharmony_ci				<< "    {\n"
183e5c31af7Sopenharmony_ci				<< "      undefTerritory = true;\n"
184e5c31af7Sopenharmony_ci				<< "    }\n"
185e5c31af7Sopenharmony_ci				<< "    uint exclusiveBitCount = subgroupBallotExclusiveBitCount(iUndef);\n"
186e5c31af7Sopenharmony_ci				<< "    if (undefTerritory && (0u != exclusiveBitCount))\n"
187e5c31af7Sopenharmony_ci				<< "    {\n"
188e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x4u;\n"
189e5c31af7Sopenharmony_ci				<< "    }\n"
190e5c31af7Sopenharmony_ci				<< "    else if (!undefTerritory && (0u == exclusiveBitCount))\n"
191e5c31af7Sopenharmony_ci				<< "    {\n"
192e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
193e5c31af7Sopenharmony_ci				<< "    }\n"
194e5c31af7Sopenharmony_ci				<< "  }\n";
195e5c31af7Sopenharmony_ci			break;
196e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_FIND_LSB:
197e5c31af7Sopenharmony_ci			bdy << "  tempResult |= 0u == subgroupBallotFindLSB(allOnes) ? 0x1u : 0u;\n"
198e5c31af7Sopenharmony_ci				<< "  if (subgroupElect())\n"
199e5c31af7Sopenharmony_ci				<< "  {\n"
200e5c31af7Sopenharmony_ci				<< "    tempResult |= 0x2u;\n"
201e5c31af7Sopenharmony_ci				<< "  }\n"
202e5c31af7Sopenharmony_ci				<< "  else\n"
203e5c31af7Sopenharmony_ci				<< "  {\n"
204e5c31af7Sopenharmony_ci				<< "    tempResult |= 0u < subgroupBallotFindLSB(subgroupBallot(true)) ? 0x2u : 0u;\n"
205e5c31af7Sopenharmony_ci				<< "  }\n"
206e5c31af7Sopenharmony_ci				<< "  tempResult |= gl_SubgroupSize > subgroupBallotFindLSB(subgroupBallot(true)) ? 0x4u : 0u;\n"
207e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n"
208e5c31af7Sopenharmony_ci				<< "  for (uint i = 0u; i < gl_SubgroupSize; i++)\n"
209e5c31af7Sopenharmony_ci				<< "  {\n"
210e5c31af7Sopenharmony_ci				<< "    if (i != subgroupBallotFindLSB(MAKE_HIGH_BALLOT_RESULT(i)))\n"
211e5c31af7Sopenharmony_ci				<< "    {\n"
212e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
213e5c31af7Sopenharmony_ci				<< "    }\n"
214e5c31af7Sopenharmony_ci				<< "  }\n";
215e5c31af7Sopenharmony_ci			break;
216e5c31af7Sopenharmony_ci		case OPTYPE_BALLOT_FIND_MSB:
217e5c31af7Sopenharmony_ci			bdy << "  tempResult |= (gl_SubgroupSize - 1u) == subgroupBallotFindMSB(allOnes) ? 0x1u : 0u;\n"
218e5c31af7Sopenharmony_ci				<< "  if (subgroupElect())\n"
219e5c31af7Sopenharmony_ci				<< "  {\n"
220e5c31af7Sopenharmony_ci				<< "    tempResult |= 0x2u;\n"
221e5c31af7Sopenharmony_ci				<< "  }\n"
222e5c31af7Sopenharmony_ci				<< "  else\n"
223e5c31af7Sopenharmony_ci				<< "  {\n"
224e5c31af7Sopenharmony_ci				<< "    tempResult |= 0u < subgroupBallotFindMSB(subgroupBallot(true)) ? 0x2u : 0u;\n"
225e5c31af7Sopenharmony_ci				<< "  }\n"
226e5c31af7Sopenharmony_ci				<< "  tempResult |= gl_SubgroupSize > subgroupBallotFindMSB(subgroupBallot(true)) ? 0x4u : 0u;\n"
227e5c31af7Sopenharmony_ci				<< "  tempResult |= 0x8u;\n"
228e5c31af7Sopenharmony_ci				<< "  for (uint i = 0u; i < gl_SubgroupSize; i++)\n"
229e5c31af7Sopenharmony_ci				<< "  {\n"
230e5c31af7Sopenharmony_ci				<< "    if (i != subgroupBallotFindMSB(MAKE_SINGLE_BIT_BALLOT_RESULT(i)))\n"
231e5c31af7Sopenharmony_ci				<< "    {\n"
232e5c31af7Sopenharmony_ci				<< "      tempResult &= ~0x8u;\n"
233e5c31af7Sopenharmony_ci				<< "    }\n"
234e5c31af7Sopenharmony_ci				<< "  }\n";
235e5c31af7Sopenharmony_ci			break;
236e5c31af7Sopenharmony_ci	}
237e5c31af7Sopenharmony_ci   return bdy.str();
238e5c31af7Sopenharmony_ci}
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_civoid initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
241e5c31af7Sopenharmony_ci{
242e5c31af7Sopenharmony_ci	subgroups::setFragmentShaderFrameBuffer(programCollection);
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
245e5c31af7Sopenharmony_ci		subgroups::setVertexShaderFrameBuffer(programCollection);
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci	std::string bdyStr = getBodySource(caseDef);
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
250e5c31af7Sopenharmony_ci	{
251e5c31af7Sopenharmony_ci		std::ostringstream				vertex;
252e5c31af7Sopenharmony_ci		vertex << "${VERSION_DECL}\n"
253e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
254e5c31af7Sopenharmony_ci			<< "layout(location = 0) in highp vec4 in_position;\n"
255e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
256e5c31af7Sopenharmony_ci			<< "\n"
257e5c31af7Sopenharmony_ci			<< "void main (void)\n"
258e5c31af7Sopenharmony_ci			<< "{\n"
259e5c31af7Sopenharmony_ci			<< bdyStr
260e5c31af7Sopenharmony_ci			<< "  out_color = float(tempResult);\n"
261e5c31af7Sopenharmony_ci			<< "  gl_Position = in_position;\n"
262e5c31af7Sopenharmony_ci			<< "  gl_PointSize = 1.0f;\n"
263e5c31af7Sopenharmony_ci			<< "}\n";
264e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertex.str());
265e5c31af7Sopenharmony_ci	}
266e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
267e5c31af7Sopenharmony_ci	{
268e5c31af7Sopenharmony_ci		std::ostringstream geometry;
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci		geometry << "${VERSION_DECL}\n"
271e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
272e5c31af7Sopenharmony_ci			<< "layout(points) in;\n"
273e5c31af7Sopenharmony_ci			<< "layout(points, max_vertices = 1) out;\n"
274e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
275e5c31af7Sopenharmony_ci			<< "void main (void)\n"
276e5c31af7Sopenharmony_ci			<< "{\n"
277e5c31af7Sopenharmony_ci			<< bdyStr
278e5c31af7Sopenharmony_ci			<< "  out_color = float(tempResult);\n"
279e5c31af7Sopenharmony_ci			<< "  gl_Position = gl_in[0].gl_Position;\n"
280e5c31af7Sopenharmony_ci			<< "  EmitVertex();\n"
281e5c31af7Sopenharmony_ci			<< "  EndPrimitive();\n"
282e5c31af7Sopenharmony_ci			<< "}\n";
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci		programCollection.add("geometry") << glu::GeometrySource(geometry.str());
285e5c31af7Sopenharmony_ci	}
286e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
287e5c31af7Sopenharmony_ci	{
288e5c31af7Sopenharmony_ci		std::ostringstream controlSource;
289e5c31af7Sopenharmony_ci
290e5c31af7Sopenharmony_ci		controlSource << "${VERSION_DECL}\n"
291e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
292e5c31af7Sopenharmony_ci			<< "layout(vertices = 2) out;\n"
293e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color[];\n"
294e5c31af7Sopenharmony_ci			<< "\n"
295e5c31af7Sopenharmony_ci			<< "void main (void)\n"
296e5c31af7Sopenharmony_ci			<< "{\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			<< bdyStr
303e5c31af7Sopenharmony_ci			<< "  out_color[gl_InvocationID ] = float(tempResult);\n"
304e5c31af7Sopenharmony_ci			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
305e5c31af7Sopenharmony_ci			<< "}\n";
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
308e5c31af7Sopenharmony_ci		subgroups::setTesEvalShaderFrameBuffer(programCollection);
309e5c31af7Sopenharmony_ci	}
310e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
311e5c31af7Sopenharmony_ci	{
312e5c31af7Sopenharmony_ci		std::ostringstream evaluationSource;
313e5c31af7Sopenharmony_ci		evaluationSource << "${VERSION_DECL}\n"
314e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
315e5c31af7Sopenharmony_ci			<< "layout(isolines, equal_spacing, ccw ) in;\n"
316e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
317e5c31af7Sopenharmony_ci			<< "void main (void)\n"
318e5c31af7Sopenharmony_ci			<< "{\n"
319e5c31af7Sopenharmony_ci			<< bdyStr
320e5c31af7Sopenharmony_ci			<< "  out_color  = float(tempResult);\n"
321e5c31af7Sopenharmony_ci			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
322e5c31af7Sopenharmony_ci			<< "}\n";
323e5c31af7Sopenharmony_ci
324e5c31af7Sopenharmony_ci		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
325e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.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	std::string bdyStr = getBodySource(caseDef);
336e5c31af7Sopenharmony_ci
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_ballot: enable\n"
343e5c31af7Sopenharmony_ci			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
344e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std430) buffer Buffer0\n"
345e5c31af7Sopenharmony_ci			<< "{\n"
346e5c31af7Sopenharmony_ci			<< "  uint result[];\n"
347e5c31af7Sopenharmony_ci			<< "};\n"
348e5c31af7Sopenharmony_ci			<< "\n"
349e5c31af7Sopenharmony_ci			<< "void main (void)\n"
350e5c31af7Sopenharmony_ci			<< "{\n"
351e5c31af7Sopenharmony_ci			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
352e5c31af7Sopenharmony_ci			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
353e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
354e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.x;\n"
355e5c31af7Sopenharmony_ci			<< bdyStr
356e5c31af7Sopenharmony_ci			<< "  result[offset] = tempResult;\n"
357e5c31af7Sopenharmony_ci			<< "}\n";
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_ci		programCollection.add("comp") << glu::ComputeSource(src.str());
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci	else
362e5c31af7Sopenharmony_ci	{
363e5c31af7Sopenharmony_ci		const string vertex =
364e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
365e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
366e5c31af7Sopenharmony_ci			"layout(binding = 0, std430) buffer Buffer0\n"
367e5c31af7Sopenharmony_ci			"{\n"
368e5c31af7Sopenharmony_ci			"  uint result[];\n"
369e5c31af7Sopenharmony_ci			"} b0;\n"
370e5c31af7Sopenharmony_ci			"\n"
371e5c31af7Sopenharmony_ci			"void main (void)\n"
372e5c31af7Sopenharmony_ci			"{\n"
373e5c31af7Sopenharmony_ci			+ bdyStr +
374e5c31af7Sopenharmony_ci			"  b0.result[gl_VertexID] = tempResult;\n"
375e5c31af7Sopenharmony_ci			"  float pixelSize = 2.0f/1024.0f;\n"
376e5c31af7Sopenharmony_ci			"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
377e5c31af7Sopenharmony_ci			"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
378e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
379e5c31af7Sopenharmony_ci			"}\n";
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci		const string tesc =
382e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
383e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
384e5c31af7Sopenharmony_ci			"layout(vertices=1) out;\n"
385e5c31af7Sopenharmony_ci			"layout(binding = 1, std430) buffer Buffer1\n"
386e5c31af7Sopenharmony_ci			"{\n"
387e5c31af7Sopenharmony_ci			"  uint result[];\n"
388e5c31af7Sopenharmony_ci			"} b1;\n"
389e5c31af7Sopenharmony_ci			"\n"
390e5c31af7Sopenharmony_ci			"void main (void)\n"
391e5c31af7Sopenharmony_ci			"{\n"
392e5c31af7Sopenharmony_ci			+ bdyStr +
393e5c31af7Sopenharmony_ci			"  b1.result[gl_PrimitiveID] = tempResult;\n"
394e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
395e5c31af7Sopenharmony_ci			"  {\n"
396e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
397e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
398e5c31af7Sopenharmony_ci			"  }\n"
399e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
400e5c31af7Sopenharmony_ci			"}\n";
401e5c31af7Sopenharmony_ci
402e5c31af7Sopenharmony_ci		const string tese =
403e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
404e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
405e5c31af7Sopenharmony_ci			"layout(isolines) in;\n"
406e5c31af7Sopenharmony_ci			"layout(binding = 2, std430) buffer Buffer2\n"
407e5c31af7Sopenharmony_ci			"{\n"
408e5c31af7Sopenharmony_ci			"  uint result[];\n"
409e5c31af7Sopenharmony_ci			"} b2;\n"
410e5c31af7Sopenharmony_ci			"\n"
411e5c31af7Sopenharmony_ci			"void main (void)\n"
412e5c31af7Sopenharmony_ci			"{\n"
413e5c31af7Sopenharmony_ci			+ bdyStr +
414e5c31af7Sopenharmony_ci			"  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = tempResult;\n"
415e5c31af7Sopenharmony_ci			"  float pixelSize = 2.0f/1024.0f;\n"
416e5c31af7Sopenharmony_ci			"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
417e5c31af7Sopenharmony_ci			"}\n";
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci		const string geometry =
420e5c31af7Sopenharmony_ci			// version string added by addGeometryShadersFromTemplate
421e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
422e5c31af7Sopenharmony_ci			"layout(${TOPOLOGY}) in;\n"
423e5c31af7Sopenharmony_ci			"layout(points, max_vertices = 1) out;\n"
424e5c31af7Sopenharmony_ci			"layout(binding = 3, std430) buffer Buffer3\n"
425e5c31af7Sopenharmony_ci			"{\n"
426e5c31af7Sopenharmony_ci			"  uint result[];\n"
427e5c31af7Sopenharmony_ci			"} b3;\n"
428e5c31af7Sopenharmony_ci			"\n"
429e5c31af7Sopenharmony_ci			"void main (void)\n"
430e5c31af7Sopenharmony_ci			"{\n"
431e5c31af7Sopenharmony_ci			+ bdyStr +
432e5c31af7Sopenharmony_ci			"  b3.result[gl_PrimitiveIDIn] = tempResult;\n"
433e5c31af7Sopenharmony_ci			"  gl_Position = gl_in[0].gl_Position;\n"
434e5c31af7Sopenharmony_ci			"  EmitVertex();\n"
435e5c31af7Sopenharmony_ci			"  EndPrimitive();\n"
436e5c31af7Sopenharmony_ci			"}\n";
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci		const string fragment =
439e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
440e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
441e5c31af7Sopenharmony_ci			"precision highp int;\n"
442e5c31af7Sopenharmony_ci			"layout(location = 0) out uint result;\n"
443e5c31af7Sopenharmony_ci			"void main (void)\n"
444e5c31af7Sopenharmony_ci			"{\n"
445e5c31af7Sopenharmony_ci			+ bdyStr +
446e5c31af7Sopenharmony_ci			"  result = tempResult;\n"
447e5c31af7Sopenharmony_ci			"}\n";
448e5c31af7Sopenharmony_ci
449e5c31af7Sopenharmony_ci		subgroups::addNoSubgroupShader(programCollection);
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertex);
452e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(tesc);
453e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
454e5c31af7Sopenharmony_ci		subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
455e5c31af7Sopenharmony_ci		programCollection.add("fragment") << glu::FragmentSource(fragment);
456e5c31af7Sopenharmony_ci	}
457e5c31af7Sopenharmony_ci}
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
460e5c31af7Sopenharmony_ci{
461e5c31af7Sopenharmony_ci	DE_UNREF(caseDef);
462e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
463e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_BALLOT_BIT))
466e5c31af7Sopenharmony_ci	{
467e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
468e5c31af7Sopenharmony_ci	}
469e5c31af7Sopenharmony_ci}
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
472e5c31af7Sopenharmony_ci{
473e5c31af7Sopenharmony_ci	if (!subgroups::areSubgroupOperationsSupportedForStage(
474e5c31af7Sopenharmony_ci			context, caseDef.shaderStage))
475e5c31af7Sopenharmony_ci	{
476e5c31af7Sopenharmony_ci		if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
477e5c31af7Sopenharmony_ci		{
478e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
479e5c31af7Sopenharmony_ci					   "Shader stage " +
480e5c31af7Sopenharmony_ci					   subgroups::getShaderStageName(caseDef.shaderStage) +
481e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
482e5c31af7Sopenharmony_ci		}
483e5c31af7Sopenharmony_ci		else
484e5c31af7Sopenharmony_ci		{
485e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
486e5c31af7Sopenharmony_ci		}
487e5c31af7Sopenharmony_ci	}
488e5c31af7Sopenharmony_ci
489e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
490e5c31af7Sopenharmony_ci		return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
491e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
492e5c31af7Sopenharmony_ci		return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
493e5c31af7Sopenharmony_ci	else if ((SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT) & caseDef.shaderStage)
494e5c31af7Sopenharmony_ci		return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
495e5c31af7Sopenharmony_ci	else
496e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unhandled shader stage");
497e5c31af7Sopenharmony_ci}
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_citcu::TestStatus test (Context& context, const CaseDefinition caseDef)
500e5c31af7Sopenharmony_ci{
501e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
502e5c31af7Sopenharmony_ci	{
503e5c31af7Sopenharmony_ci		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
504e5c31af7Sopenharmony_ci		{
505e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
506e5c31af7Sopenharmony_ci					   "Shader stage " +
507e5c31af7Sopenharmony_ci				subgroups::getShaderStageName(caseDef.shaderStage) +
508e5c31af7Sopenharmony_ci				" is required to support subgroup operations!");
509e5c31af7Sopenharmony_ci		}
510e5c31af7Sopenharmony_ci		return subgroups::makeComputeTest(context, FORMAT_R32_UINT, DE_NULL, 0, checkComputeStage);
511e5c31af7Sopenharmony_ci	}
512e5c31af7Sopenharmony_ci	else
513e5c31af7Sopenharmony_ci	{
514e5c31af7Sopenharmony_ci		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci		ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci		if ( SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
519e5c31af7Sopenharmony_ci		{
520e5c31af7Sopenharmony_ci			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
521e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
522e5c31af7Sopenharmony_ci			else
523e5c31af7Sopenharmony_ci				stages = SHADER_STAGE_FRAGMENT_BIT;
524e5c31af7Sopenharmony_ci		}
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci		if ((ShaderStageFlags)0u == stages)
527e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci		return subgroups::allStages(context, FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages, stages);
530e5c31af7Sopenharmony_ci	}
531e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
532e5c31af7Sopenharmony_ci}
533e5c31af7Sopenharmony_ci}
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsBallotOtherTests(deqp::Context& testCtx)
536e5c31af7Sopenharmony_ci{
537e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
538e5c31af7Sopenharmony_ci		testCtx, "graphics", "Subgroup ballot other category tests: graphics"));
539e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
540e5c31af7Sopenharmony_ci		testCtx, "compute", "Subgroup ballot other category tests: compute"));
541e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
542e5c31af7Sopenharmony_ci		testCtx, "framebuffer", "Subgroup ballot other category tests: framebuffer"));
543e5c31af7Sopenharmony_ci
544e5c31af7Sopenharmony_ci	const ShaderStageFlags stages[] =
545e5c31af7Sopenharmony_ci	{
546e5c31af7Sopenharmony_ci		SHADER_STAGE_VERTEX_BIT,
547e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_EVALUATION_BIT,
548e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_CONTROL_BIT,
549e5c31af7Sopenharmony_ci		SHADER_STAGE_GEOMETRY_BIT,
550e5c31af7Sopenharmony_ci	};
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
553e5c31af7Sopenharmony_ci	{
554e5c31af7Sopenharmony_ci		const string	op		= de::toLower(getOpTypeName(opTypeIndex));
555e5c31af7Sopenharmony_ci		{
556e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT};
557e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), op, "", supportedCheck, initPrograms, test, caseDef);
558e5c31af7Sopenharmony_ci		}
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci		{
561e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS};
562e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), op, "", supportedCheck, initPrograms, test, caseDef);
563e5c31af7Sopenharmony_ci		}
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci		for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
566e5c31af7Sopenharmony_ci		{
567e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex]};
568e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), op + "_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
569e5c31af7Sopenharmony_ci		}
570e5c31af7Sopenharmony_ci	}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
573e5c31af7Sopenharmony_ci		testCtx, "ballot_other", "Subgroup ballot other category tests"));
574e5c31af7Sopenharmony_ci
575e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
576e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
577e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci	return group.release();
580e5c31af7Sopenharmony_ci}
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ci} // subgroups
583e5c31af7Sopenharmony_ci} // glc
584