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 "glcSubgroupsClusteredTests.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_CLUSTERED_ADD = 0,
44e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_MUL,
45e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_MIN,
46e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_MAX,
47e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_AND,
48e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_OR,
49e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_XOR,
50e5c31af7Sopenharmony_ci	OPTYPE_CLUSTERED_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, 1);
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, 1);
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_CLUSTERED_ADD:
74e5c31af7Sopenharmony_ci			return "subgroupClusteredAdd";
75e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MUL:
76e5c31af7Sopenharmony_ci			return "subgroupClusteredMul";
77e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MIN:
78e5c31af7Sopenharmony_ci			return "subgroupClusteredMin";
79e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MAX:
80e5c31af7Sopenharmony_ci			return "subgroupClusteredMax";
81e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_AND:
82e5c31af7Sopenharmony_ci			return "subgroupClusteredAnd";
83e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_OR:
84e5c31af7Sopenharmony_ci			return "subgroupClusteredOr";
85e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_XOR:
86e5c31af7Sopenharmony_ci			return "subgroupClusteredXor";
87e5c31af7Sopenharmony_ci	}
88e5c31af7Sopenharmony_ci}
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_cistd::string getOpTypeOperation(int opType, Format format, std::string lhs, std::string rhs)
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	switch (opType)
93e5c31af7Sopenharmony_ci	{
94e5c31af7Sopenharmony_ci		default:
95e5c31af7Sopenharmony_ci			DE_FATAL("Unsupported op type");
96e5c31af7Sopenharmony_ci			return "";
97e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_ADD:
98e5c31af7Sopenharmony_ci			return lhs + " + " + rhs;
99e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MUL:
100e5c31af7Sopenharmony_ci			return lhs + " * " + rhs;
101e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MIN:
102e5c31af7Sopenharmony_ci			switch (format)
103e5c31af7Sopenharmony_ci			{
104e5c31af7Sopenharmony_ci				default:
105e5c31af7Sopenharmony_ci					return "min(" + lhs + ", " + rhs + ")";
106e5c31af7Sopenharmony_ci				case FORMAT_R32_SFLOAT:
107e5c31af7Sopenharmony_ci				case FORMAT_R64_SFLOAT:
108e5c31af7Sopenharmony_ci					return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : min(" + lhs + ", " + rhs + ")))";
109e5c31af7Sopenharmony_ci				case FORMAT_R32G32_SFLOAT:
110e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_SFLOAT:
111e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_SFLOAT:
112e5c31af7Sopenharmony_ci				case FORMAT_R64G64_SFLOAT:
113e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64_SFLOAT:
114e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64A64_SFLOAT:
115e5c31af7Sopenharmony_ci					return "mix(mix(min(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))";
116e5c31af7Sopenharmony_ci			}
117e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MAX:
118e5c31af7Sopenharmony_ci			switch (format)
119e5c31af7Sopenharmony_ci			{
120e5c31af7Sopenharmony_ci				default:
121e5c31af7Sopenharmony_ci					return "max(" + lhs + ", " + rhs + ")";
122e5c31af7Sopenharmony_ci				case FORMAT_R32_SFLOAT:
123e5c31af7Sopenharmony_ci				case FORMAT_R64_SFLOAT:
124e5c31af7Sopenharmony_ci					return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : max(" + lhs + ", " + rhs + ")))";
125e5c31af7Sopenharmony_ci				case FORMAT_R32G32_SFLOAT:
126e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_SFLOAT:
127e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_SFLOAT:
128e5c31af7Sopenharmony_ci				case FORMAT_R64G64_SFLOAT:
129e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64_SFLOAT:
130e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64A64_SFLOAT:
131e5c31af7Sopenharmony_ci					return "mix(mix(max(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))";
132e5c31af7Sopenharmony_ci			}
133e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_AND:
134e5c31af7Sopenharmony_ci			switch (format)
135e5c31af7Sopenharmony_ci			{
136e5c31af7Sopenharmony_ci				default:
137e5c31af7Sopenharmony_ci					return lhs + " & " + rhs;
138e5c31af7Sopenharmony_ci				case FORMAT_R32_BOOL:
139e5c31af7Sopenharmony_ci					return lhs + " && " + rhs;
140e5c31af7Sopenharmony_ci				case FORMAT_R32G32_BOOL:
141e5c31af7Sopenharmony_ci					return "bvec2(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y)";
142e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_BOOL:
143e5c31af7Sopenharmony_ci					return "bvec3(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z)";
144e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_BOOL:
145e5c31af7Sopenharmony_ci					return "bvec4(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z, " + lhs + ".w && " + rhs + ".w)";
146e5c31af7Sopenharmony_ci			}
147e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_OR:
148e5c31af7Sopenharmony_ci			switch (format)
149e5c31af7Sopenharmony_ci			{
150e5c31af7Sopenharmony_ci				default:
151e5c31af7Sopenharmony_ci					return lhs + " | " + rhs;
152e5c31af7Sopenharmony_ci				case FORMAT_R32_BOOL:
153e5c31af7Sopenharmony_ci					return lhs + " || " + rhs;
154e5c31af7Sopenharmony_ci				case FORMAT_R32G32_BOOL:
155e5c31af7Sopenharmony_ci					return "bvec2(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y)";
156e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_BOOL:
157e5c31af7Sopenharmony_ci					return "bvec3(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z)";
158e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_BOOL:
159e5c31af7Sopenharmony_ci					return "bvec4(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z, " + lhs + ".w || " + rhs + ".w)";
160e5c31af7Sopenharmony_ci			}
161e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_XOR:
162e5c31af7Sopenharmony_ci			switch (format)
163e5c31af7Sopenharmony_ci			{
164e5c31af7Sopenharmony_ci				default:
165e5c31af7Sopenharmony_ci					return lhs + " ^ " + rhs;
166e5c31af7Sopenharmony_ci				case FORMAT_R32_BOOL:
167e5c31af7Sopenharmony_ci					return lhs + " ^^ " + rhs;
168e5c31af7Sopenharmony_ci				case FORMAT_R32G32_BOOL:
169e5c31af7Sopenharmony_ci					return "bvec2(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y)";
170e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_BOOL:
171e5c31af7Sopenharmony_ci					return "bvec3(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z)";
172e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_BOOL:
173e5c31af7Sopenharmony_ci					return "bvec4(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z, " + lhs + ".w ^^ " + rhs + ".w)";
174e5c31af7Sopenharmony_ci			}
175e5c31af7Sopenharmony_ci	}
176e5c31af7Sopenharmony_ci}
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_cistd::string getIdentity(int opType, Format format)
179e5c31af7Sopenharmony_ci{
180e5c31af7Sopenharmony_ci	bool isFloat = false;
181e5c31af7Sopenharmony_ci	bool isInt = false;
182e5c31af7Sopenharmony_ci	bool isUnsigned = false;
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	switch (format)
185e5c31af7Sopenharmony_ci	{
186e5c31af7Sopenharmony_ci		default:
187e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled format!");
188e5c31af7Sopenharmony_ci			break;
189e5c31af7Sopenharmony_ci		case FORMAT_R32_SINT:
190e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SINT:
191e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SINT:
192e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SINT:
193e5c31af7Sopenharmony_ci			isInt = true;
194e5c31af7Sopenharmony_ci			break;
195e5c31af7Sopenharmony_ci		case FORMAT_R32_UINT:
196e5c31af7Sopenharmony_ci		case FORMAT_R32G32_UINT:
197e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_UINT:
198e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_UINT:
199e5c31af7Sopenharmony_ci			isUnsigned = true;
200e5c31af7Sopenharmony_ci			break;
201e5c31af7Sopenharmony_ci		case FORMAT_R32_SFLOAT:
202e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SFLOAT:
203e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SFLOAT:
204e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SFLOAT:
205e5c31af7Sopenharmony_ci		case FORMAT_R64_SFLOAT:
206e5c31af7Sopenharmony_ci		case FORMAT_R64G64_SFLOAT:
207e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64_SFLOAT:
208e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64A64_SFLOAT:
209e5c31af7Sopenharmony_ci			isFloat = true;
210e5c31af7Sopenharmony_ci			break;
211e5c31af7Sopenharmony_ci		case FORMAT_R32_BOOL:
212e5c31af7Sopenharmony_ci		case FORMAT_R32G32_BOOL:
213e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_BOOL:
214e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_BOOL:
215e5c31af7Sopenharmony_ci			break; // bool types are not anything
216e5c31af7Sopenharmony_ci	}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci	switch (opType)
219e5c31af7Sopenharmony_ci	{
220e5c31af7Sopenharmony_ci		default:
221e5c31af7Sopenharmony_ci			DE_FATAL("Unsupported op type");
222e5c31af7Sopenharmony_ci			return "";
223e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_ADD:
224e5c31af7Sopenharmony_ci			return subgroups::getFormatNameForGLSL(format) + "(0)";
225e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MUL:
226e5c31af7Sopenharmony_ci			return subgroups::getFormatNameForGLSL(format) + "(1)";
227e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MIN:
228e5c31af7Sopenharmony_ci			if (isFloat)
229e5c31af7Sopenharmony_ci			{
230e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0x7f800000))";
231e5c31af7Sopenharmony_ci			}
232e5c31af7Sopenharmony_ci			else if (isInt)
233e5c31af7Sopenharmony_ci			{
234e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(0x7fffffff)";
235e5c31af7Sopenharmony_ci			}
236e5c31af7Sopenharmony_ci			else if (isUnsigned)
237e5c31af7Sopenharmony_ci			{
238e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(0xffffffffu)";
239e5c31af7Sopenharmony_ci			}
240e5c31af7Sopenharmony_ci			else
241e5c31af7Sopenharmony_ci			{
242e5c31af7Sopenharmony_ci				DE_FATAL("Unhandled case");
243e5c31af7Sopenharmony_ci				return "";
244e5c31af7Sopenharmony_ci			}
245e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_MAX:
246e5c31af7Sopenharmony_ci			if (isFloat)
247e5c31af7Sopenharmony_ci			{
248e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0xff800000))";
249e5c31af7Sopenharmony_ci			}
250e5c31af7Sopenharmony_ci			else if (isInt)
251e5c31af7Sopenharmony_ci			{
252e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(0x80000000)";
253e5c31af7Sopenharmony_ci			}
254e5c31af7Sopenharmony_ci			else if (isUnsigned)
255e5c31af7Sopenharmony_ci			{
256e5c31af7Sopenharmony_ci				return subgroups::getFormatNameForGLSL(format) + "(0u)";
257e5c31af7Sopenharmony_ci			}
258e5c31af7Sopenharmony_ci			else
259e5c31af7Sopenharmony_ci			{
260e5c31af7Sopenharmony_ci				DE_FATAL("Unhandled case");
261e5c31af7Sopenharmony_ci				return "";
262e5c31af7Sopenharmony_ci			}
263e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_AND:
264e5c31af7Sopenharmony_ci			return subgroups::getFormatNameForGLSL(format) + "(~0)";
265e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_OR:
266e5c31af7Sopenharmony_ci			return subgroups::getFormatNameForGLSL(format) + "(0)";
267e5c31af7Sopenharmony_ci		case OPTYPE_CLUSTERED_XOR:
268e5c31af7Sopenharmony_ci			return subgroups::getFormatNameForGLSL(format) + "(0)";
269e5c31af7Sopenharmony_ci	}
270e5c31af7Sopenharmony_ci}
271e5c31af7Sopenharmony_ci
272e5c31af7Sopenharmony_cistd::string getCompare(int opType, Format format, std::string lhs, std::string rhs)
273e5c31af7Sopenharmony_ci{
274e5c31af7Sopenharmony_ci	std::string formatName = subgroups::getFormatNameForGLSL(format);
275e5c31af7Sopenharmony_ci	switch (format)
276e5c31af7Sopenharmony_ci	{
277e5c31af7Sopenharmony_ci		default:
278e5c31af7Sopenharmony_ci			return "all(equal(" + lhs + ", " + rhs + "))";
279e5c31af7Sopenharmony_ci		case FORMAT_R32_BOOL:
280e5c31af7Sopenharmony_ci		case FORMAT_R32_UINT:
281e5c31af7Sopenharmony_ci		case FORMAT_R32_SINT:
282e5c31af7Sopenharmony_ci			return "(" + lhs + " == " + rhs + ")";
283e5c31af7Sopenharmony_ci		case FORMAT_R32_SFLOAT:
284e5c31af7Sopenharmony_ci		case FORMAT_R64_SFLOAT:
285e5c31af7Sopenharmony_ci			switch (opType)
286e5c31af7Sopenharmony_ci			{
287e5c31af7Sopenharmony_ci				default:
288e5c31af7Sopenharmony_ci					return "(abs(" + lhs + " - " + rhs + ") < 0.00001)";
289e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_MIN:
290e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_MAX:
291e5c31af7Sopenharmony_ci					return "(" + lhs + " == " + rhs + ")";
292e5c31af7Sopenharmony_ci			}
293e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SFLOAT:
294e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SFLOAT:
295e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SFLOAT:
296e5c31af7Sopenharmony_ci		case FORMAT_R64G64_SFLOAT:
297e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64_SFLOAT:
298e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64A64_SFLOAT:
299e5c31af7Sopenharmony_ci			switch (opType)
300e5c31af7Sopenharmony_ci			{
301e5c31af7Sopenharmony_ci				default:
302e5c31af7Sopenharmony_ci					return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.00001)))";
303e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_MIN:
304e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_MAX:
305e5c31af7Sopenharmony_ci					return "all(equal(" + lhs + ", " + rhs + "))";
306e5c31af7Sopenharmony_ci			}
307e5c31af7Sopenharmony_ci	}
308e5c31af7Sopenharmony_ci}
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_cistruct CaseDefinition
311e5c31af7Sopenharmony_ci{
312e5c31af7Sopenharmony_ci	int					opType;
313e5c31af7Sopenharmony_ci	ShaderStageFlags	shaderStage;
314e5c31af7Sopenharmony_ci	Format				format;
315e5c31af7Sopenharmony_ci};
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_cistd::string getBodySource(CaseDefinition caseDef)
318e5c31af7Sopenharmony_ci{
319e5c31af7Sopenharmony_ci	std::ostringstream bdy;
320e5c31af7Sopenharmony_ci	bdy << "  bool tempResult = true;\n";
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_ci	for (deUint32 i = 1; i <= subgroups::maxSupportedSubgroupSize(); i *= 2)
323e5c31af7Sopenharmony_ci	{
324e5c31af7Sopenharmony_ci		bdy	<< "  {\n"
325e5c31af7Sopenharmony_ci			<< "    const uint clusterSize = " << i << "u;\n"
326e5c31af7Sopenharmony_ci			<< "    if (clusterSize <= gl_SubgroupSize)\n"
327e5c31af7Sopenharmony_ci			<< "    {\n"
328e5c31af7Sopenharmony_ci			<< "      " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
329e5c31af7Sopenharmony_ci			<< getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID], clusterSize);\n"
330e5c31af7Sopenharmony_ci			<< "      for (uint clusterOffset = 0u; clusterOffset < gl_SubgroupSize; clusterOffset += clusterSize)\n"
331e5c31af7Sopenharmony_ci			<< "      {\n"
332e5c31af7Sopenharmony_ci			<< "        " << subgroups::getFormatNameForGLSL(caseDef.format) << " ref = "
333e5c31af7Sopenharmony_ci			<< getIdentity(caseDef.opType, caseDef.format) << ";\n"
334e5c31af7Sopenharmony_ci			<< "        for (uint index = clusterOffset; index < (clusterOffset + clusterSize); index++)\n"
335e5c31af7Sopenharmony_ci			<< "        {\n"
336e5c31af7Sopenharmony_ci			<< "          if (subgroupBallotBitExtract(mask, index))\n"
337e5c31af7Sopenharmony_ci			<< "          {\n"
338e5c31af7Sopenharmony_ci			<< "            ref = " << getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") << ";\n"
339e5c31af7Sopenharmony_ci			<< "          }\n"
340e5c31af7Sopenharmony_ci			<< "        }\n"
341e5c31af7Sopenharmony_ci			<< "        if ((clusterOffset <= gl_SubgroupInvocationID) && (gl_SubgroupInvocationID < (clusterOffset + clusterSize)))\n"
342e5c31af7Sopenharmony_ci			<< "        {\n"
343e5c31af7Sopenharmony_ci			<< "          if (!" << getCompare(caseDef.opType, caseDef.format, "ref", "op") << ")\n"
344e5c31af7Sopenharmony_ci			<< "          {\n"
345e5c31af7Sopenharmony_ci			<< "            tempResult = false;\n"
346e5c31af7Sopenharmony_ci			<< "          }\n"
347e5c31af7Sopenharmony_ci			<< "        }\n"
348e5c31af7Sopenharmony_ci			<< "      }\n"
349e5c31af7Sopenharmony_ci			<< "    }\n"
350e5c31af7Sopenharmony_ci			<< "  }\n";
351e5c31af7Sopenharmony_ci	}
352e5c31af7Sopenharmony_ci	return bdy.str();
353e5c31af7Sopenharmony_ci}
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
356e5c31af7Sopenharmony_ci{
357e5c31af7Sopenharmony_ci	subgroups::setFragmentShaderFrameBuffer(programCollection);
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
360e5c31af7Sopenharmony_ci		subgroups::setVertexShaderFrameBuffer(programCollection);
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci	std::string bdy = getBodySource(caseDef);
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
365e5c31af7Sopenharmony_ci	{
366e5c31af7Sopenharmony_ci		std::ostringstream				vertexSrc;
367e5c31af7Sopenharmony_ci		vertexSrc << "${VERSION_DECL}\n"
368e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_clustered: enable\n"
369e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
370e5c31af7Sopenharmony_ci			<< "layout(location = 0) in highp vec4 in_position;\n"
371e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
372e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer0\n"
373e5c31af7Sopenharmony_ci			<< "{\n"
374e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
375e5c31af7Sopenharmony_ci			<< "};\n"
376e5c31af7Sopenharmony_ci			<< "\n"
377e5c31af7Sopenharmony_ci			<< "void main (void)\n"
378e5c31af7Sopenharmony_ci			<< "{\n"
379e5c31af7Sopenharmony_ci			<< "  uvec4 mask = subgroupBallot(true);\n"
380e5c31af7Sopenharmony_ci			<< bdy
381e5c31af7Sopenharmony_ci			<< "  out_color = float(tempResult ? 1 : 0);\n"
382e5c31af7Sopenharmony_ci			<< "  gl_Position = in_position;\n"
383e5c31af7Sopenharmony_ci			<< "  gl_PointSize = 1.0f;\n"
384e5c31af7Sopenharmony_ci			<< "}\n";
385e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
386e5c31af7Sopenharmony_ci	}
387e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
388e5c31af7Sopenharmony_ci	{
389e5c31af7Sopenharmony_ci		std::ostringstream geometry;
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci		geometry  << "${VERSION_DECL}\n"
392e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_clustered: enable\n"
393e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
394e5c31af7Sopenharmony_ci			<< "layout(points) in;\n"
395e5c31af7Sopenharmony_ci			<< "layout(points, max_vertices = 1) out;\n"
396e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
397e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer0\n"
398e5c31af7Sopenharmony_ci			<< "{\n"
399e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
400e5c31af7Sopenharmony_ci			<< "};\n"
401e5c31af7Sopenharmony_ci			<< "\n"
402e5c31af7Sopenharmony_ci			<< "void main (void)\n"
403e5c31af7Sopenharmony_ci			<< "{\n"
404e5c31af7Sopenharmony_ci			<< "  uvec4 mask = subgroupBallot(true);\n"
405e5c31af7Sopenharmony_ci			<< bdy
406e5c31af7Sopenharmony_ci			<< "  out_color = tempResult ? 1.0 : 0.0;\n"
407e5c31af7Sopenharmony_ci			<< "  gl_Position = gl_in[0].gl_Position;\n"
408e5c31af7Sopenharmony_ci			<< "  EmitVertex();\n"
409e5c31af7Sopenharmony_ci			<< "  EndPrimitive();\n"
410e5c31af7Sopenharmony_ci			<< "}\n";
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_ci		programCollection.add("geometry") << glu::GeometrySource(geometry.str());
413e5c31af7Sopenharmony_ci	}
414e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
415e5c31af7Sopenharmony_ci	{
416e5c31af7Sopenharmony_ci		std::ostringstream controlSource;
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ci		controlSource << "${VERSION_DECL}\n"
419e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_clustered: enable\n"
420e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
421e5c31af7Sopenharmony_ci			<< "layout(vertices = 2) out;\n"
422e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color[];\n"
423e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer0\n"
424e5c31af7Sopenharmony_ci			<< "{\n"
425e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
426e5c31af7Sopenharmony_ci			<< "};\n"
427e5c31af7Sopenharmony_ci			<< "\n"
428e5c31af7Sopenharmony_ci			<< "void main (void)\n"
429e5c31af7Sopenharmony_ci			<< "{\n"
430e5c31af7Sopenharmony_ci			<< "  if (gl_InvocationID == 0)\n"
431e5c31af7Sopenharmony_ci			<<"  {\n"
432e5c31af7Sopenharmony_ci			<< "    gl_TessLevelOuter[0] = 1.0f;\n"
433e5c31af7Sopenharmony_ci			<< "    gl_TessLevelOuter[1] = 1.0f;\n"
434e5c31af7Sopenharmony_ci			<< "  }\n"
435e5c31af7Sopenharmony_ci			<< "  uvec4 mask = subgroupBallot(true);\n"
436e5c31af7Sopenharmony_ci			<< bdy
437e5c31af7Sopenharmony_ci			<< "  out_color[gl_InvocationID] = tempResult ? 1.0 : 0.0;\n"
438e5c31af7Sopenharmony_ci			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
439e5c31af7Sopenharmony_ci			<< "}\n";
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
442e5c31af7Sopenharmony_ci		subgroups::setTesEvalShaderFrameBuffer(programCollection);
443e5c31af7Sopenharmony_ci	}
444e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
445e5c31af7Sopenharmony_ci	{
446e5c31af7Sopenharmony_ci		std::ostringstream evaluationSource;
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ci		evaluationSource << "${VERSION_DECL}\n"
449e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_clustered: enable\n"
450e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
451e5c31af7Sopenharmony_ci			<< "layout(isolines, equal_spacing, ccw ) in;\n"
452e5c31af7Sopenharmony_ci			<< "layout(location = 0) out float out_color;\n"
453e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std140) uniform Buffer0\n"
454e5c31af7Sopenharmony_ci			<< "{\n"
455e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
456e5c31af7Sopenharmony_ci			<< "};\n"
457e5c31af7Sopenharmony_ci			<< "\n"
458e5c31af7Sopenharmony_ci			<< "void main (void)\n"
459e5c31af7Sopenharmony_ci			<< "{\n"
460e5c31af7Sopenharmony_ci			<< "  uvec4 mask = subgroupBallot(true);\n"
461e5c31af7Sopenharmony_ci			<< bdy
462e5c31af7Sopenharmony_ci			<< "  out_color = tempResult ? 1.0 : 0.0;\n"
463e5c31af7Sopenharmony_ci			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
464e5c31af7Sopenharmony_ci			<< "}\n";
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
467e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
468e5c31af7Sopenharmony_ci	}
469e5c31af7Sopenharmony_ci	else
470e5c31af7Sopenharmony_ci	{
471e5c31af7Sopenharmony_ci		DE_FATAL("Unsupported shader stage");
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci}
474e5c31af7Sopenharmony_ci
475e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
476e5c31af7Sopenharmony_ci{
477e5c31af7Sopenharmony_ci	std::string bdy = getBodySource(caseDef);
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
480e5c31af7Sopenharmony_ci	{
481e5c31af7Sopenharmony_ci		std::ostringstream src;
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci		src << "${VERSION_DECL}\n"
484e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_clustered: enable\n"
485e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
486e5c31af7Sopenharmony_ci			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
487e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std430) buffer Buffer0\n"
488e5c31af7Sopenharmony_ci			<< "{\n"
489e5c31af7Sopenharmony_ci			<< "  uint result[];\n"
490e5c31af7Sopenharmony_ci			<< "};\n"
491e5c31af7Sopenharmony_ci			<< "layout(binding = 1, std430) buffer Buffer1\n"
492e5c31af7Sopenharmony_ci			<< "{\n"
493e5c31af7Sopenharmony_ci			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
494e5c31af7Sopenharmony_ci			<< "};\n"
495e5c31af7Sopenharmony_ci			<< "\n"
496e5c31af7Sopenharmony_ci			<< "void main (void)\n"
497e5c31af7Sopenharmony_ci			<< "{\n"
498e5c31af7Sopenharmony_ci			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
499e5c31af7Sopenharmony_ci			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
500e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
501e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.x;\n"
502e5c31af7Sopenharmony_ci			<< "  uvec4 mask = subgroupBallot(true);\n"
503e5c31af7Sopenharmony_ci			<< bdy
504e5c31af7Sopenharmony_ci			<< "  result[offset] = tempResult ? 1u : 0u;\n"
505e5c31af7Sopenharmony_ci			<< "}\n";
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_ci		programCollection.add("comp") << glu::ComputeSource(src.str());
508e5c31af7Sopenharmony_ci	}
509e5c31af7Sopenharmony_ci	else
510e5c31af7Sopenharmony_ci	{
511e5c31af7Sopenharmony_ci		{
512e5c31af7Sopenharmony_ci			const string vertex =
513e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
514e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_clustered: enable\n"
515e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
516e5c31af7Sopenharmony_ci				"layout(binding = 0, std430) buffer Buffer0\n"
517e5c31af7Sopenharmony_ci				"{\n"
518e5c31af7Sopenharmony_ci				"  uint result[];\n"
519e5c31af7Sopenharmony_ci				"} b0;\n"
520e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
521e5c31af7Sopenharmony_ci				"{\n"
522e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
523e5c31af7Sopenharmony_ci				"};\n"
524e5c31af7Sopenharmony_ci				"\n"
525e5c31af7Sopenharmony_ci				"void main (void)\n"
526e5c31af7Sopenharmony_ci				"{\n"
527e5c31af7Sopenharmony_ci				"  uvec4 mask = subgroupBallot(true);\n"
528e5c31af7Sopenharmony_ci				+ bdy +
529e5c31af7Sopenharmony_ci				"  b0.result[gl_VertexID] = tempResult ? 1u : 0u;\n"
530e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
531e5c31af7Sopenharmony_ci				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
532e5c31af7Sopenharmony_ci				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
533e5c31af7Sopenharmony_ci				"}\n";
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci			programCollection.add("vert") << glu::VertexSource(vertex);
536e5c31af7Sopenharmony_ci		}
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci		{
539e5c31af7Sopenharmony_ci			const string tesc =
540e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
541e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_clustered: enable\n"
542e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
543e5c31af7Sopenharmony_ci			"layout(vertices=1) out;\n"
544e5c31af7Sopenharmony_ci			"layout(binding = 1, std430) buffer Buffer1\n"
545e5c31af7Sopenharmony_ci			"{\n"
546e5c31af7Sopenharmony_ci			"  uint result[];\n"
547e5c31af7Sopenharmony_ci			"} b1;\n"
548e5c31af7Sopenharmony_ci			"layout(binding = 4, std430) readonly buffer Buffer4\n"
549e5c31af7Sopenharmony_ci			"{\n"
550e5c31af7Sopenharmony_ci			"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
551e5c31af7Sopenharmony_ci			"};\n"
552e5c31af7Sopenharmony_ci			"\n"
553e5c31af7Sopenharmony_ci			"void main (void)\n"
554e5c31af7Sopenharmony_ci			"{\n"
555e5c31af7Sopenharmony_ci			"  uvec4 mask = subgroupBallot(true);\n"
556e5c31af7Sopenharmony_ci			+ bdy +
557e5c31af7Sopenharmony_ci			"  b1.result[gl_PrimitiveID] = tempResult ? 1u : 0u;\n"
558e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
559e5c31af7Sopenharmony_ci			"  {\n"
560e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
561e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
562e5c31af7Sopenharmony_ci			"  }\n"
563e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
564e5c31af7Sopenharmony_ci			"}\n";
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_ci			programCollection.add("tesc") << glu::TessellationControlSource(tesc);
567e5c31af7Sopenharmony_ci		}
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci		{
570e5c31af7Sopenharmony_ci			const string tese =
571e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
572e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_clustered: enable\n"
573e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
574e5c31af7Sopenharmony_ci				"layout(isolines) in;\n"
575e5c31af7Sopenharmony_ci				"layout(binding = 2, std430) buffer Buffer2\n"
576e5c31af7Sopenharmony_ci				"{\n"
577e5c31af7Sopenharmony_ci				"  uint result[];\n"
578e5c31af7Sopenharmony_ci				"} b2;\n"
579e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
580e5c31af7Sopenharmony_ci				"{\n"
581e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
582e5c31af7Sopenharmony_ci				"};\n"
583e5c31af7Sopenharmony_ci				"\n"
584e5c31af7Sopenharmony_ci				"void main (void)\n"
585e5c31af7Sopenharmony_ci				"{\n"
586e5c31af7Sopenharmony_ci				"  uvec4 mask = subgroupBallot(true);\n"
587e5c31af7Sopenharmony_ci				+ bdy +
588e5c31af7Sopenharmony_ci				"  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = tempResult ? 1u : 0u;\n"
589e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
590e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
591e5c31af7Sopenharmony_ci				"}\n";
592e5c31af7Sopenharmony_ci			programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
593e5c31af7Sopenharmony_ci		}
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci		{
596e5c31af7Sopenharmony_ci			const string geometry =
597e5c31af7Sopenharmony_ci				// version string added by addGeometryShadersFromTemplate
598e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_clustered: enable\n"
599e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
600e5c31af7Sopenharmony_ci				"layout(${TOPOLOGY}) in;\n"
601e5c31af7Sopenharmony_ci				"layout(points, max_vertices = 1) out;\n"
602e5c31af7Sopenharmony_ci				"layout(binding = 3, std430) buffer Buffer3\n"
603e5c31af7Sopenharmony_ci				"{\n"
604e5c31af7Sopenharmony_ci				"  uint result[];\n"
605e5c31af7Sopenharmony_ci				"} b3;\n"
606e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
607e5c31af7Sopenharmony_ci				"{\n"
608e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
609e5c31af7Sopenharmony_ci				"};\n"
610e5c31af7Sopenharmony_ci				"\n"
611e5c31af7Sopenharmony_ci				"void main (void)\n"
612e5c31af7Sopenharmony_ci				"{\n"
613e5c31af7Sopenharmony_ci				"  uvec4 mask = subgroupBallot(true);\n"
614e5c31af7Sopenharmony_ci				+ bdy +
615e5c31af7Sopenharmony_ci				"  b3.result[gl_PrimitiveIDIn] = tempResult ? 1u : 0u;\n"
616e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position;\n"
617e5c31af7Sopenharmony_ci				"  EmitVertex();\n"
618e5c31af7Sopenharmony_ci				"  EndPrimitive();\n"
619e5c31af7Sopenharmony_ci				"}\n";
620e5c31af7Sopenharmony_ci			subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
621e5c31af7Sopenharmony_ci		}
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci		{
624e5c31af7Sopenharmony_ci			const string fragment =
625e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
626e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_clustered: enable\n"
627e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
628e5c31af7Sopenharmony_ci				"precision highp int;\n"
629e5c31af7Sopenharmony_ci				"precision highp float;\n"
630e5c31af7Sopenharmony_ci				"layout(location = 0) out uint result;\n"
631e5c31af7Sopenharmony_ci				"layout(binding = 4, std430) readonly buffer Buffer4\n"
632e5c31af7Sopenharmony_ci				"{\n"
633e5c31af7Sopenharmony_ci				"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
634e5c31af7Sopenharmony_ci				"};\n"
635e5c31af7Sopenharmony_ci				"void main (void)\n"
636e5c31af7Sopenharmony_ci				"{\n"
637e5c31af7Sopenharmony_ci				"  uvec4 mask = subgroupBallot(true);\n"
638e5c31af7Sopenharmony_ci				+ bdy +
639e5c31af7Sopenharmony_ci				"  result = tempResult ? 1u : 0u;\n"
640e5c31af7Sopenharmony_ci				"}\n";
641e5c31af7Sopenharmony_ci			programCollection.add("fragment") << glu::FragmentSource(fragment);
642e5c31af7Sopenharmony_ci		}
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci		subgroups::addNoSubgroupShader(programCollection);
645e5c31af7Sopenharmony_ci	}
646e5c31af7Sopenharmony_ci}
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
649e5c31af7Sopenharmony_ci{
650e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
651e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
652e5c31af7Sopenharmony_ci
653e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_CLUSTERED_BIT))
654e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup clustered operations");
655e5c31af7Sopenharmony_ci
656e5c31af7Sopenharmony_ci	if (subgroups::isDoubleFormat(caseDef.format) &&
657e5c31af7Sopenharmony_ci			!subgroups::isDoubleSupportedForDevice(context))
658e5c31af7Sopenharmony_ci	{
659e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
660e5c31af7Sopenharmony_ci	}
661e5c31af7Sopenharmony_ci}
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
664e5c31af7Sopenharmony_ci{
665e5c31af7Sopenharmony_ci	if (!subgroups::areSubgroupOperationsSupportedForStage(
666e5c31af7Sopenharmony_ci				context, caseDef.shaderStage))
667e5c31af7Sopenharmony_ci	{
668e5c31af7Sopenharmony_ci		if (subgroups::areSubgroupOperationsRequiredForStage(
669e5c31af7Sopenharmony_ci					caseDef.shaderStage))
670e5c31af7Sopenharmony_ci		{
671e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
672e5c31af7Sopenharmony_ci					   "Shader stage " +
673e5c31af7Sopenharmony_ci					   subgroups::getShaderStageName(caseDef.shaderStage) +
674e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
675e5c31af7Sopenharmony_ci		}
676e5c31af7Sopenharmony_ci		else
677e5c31af7Sopenharmony_ci		{
678e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
679e5c31af7Sopenharmony_ci		}
680e5c31af7Sopenharmony_ci	}
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci	subgroups::SSBOData inputData;
683e5c31af7Sopenharmony_ci	inputData.format = caseDef.format;
684e5c31af7Sopenharmony_ci	inputData.layout = subgroups::SSBOData::LayoutStd140;
685e5c31af7Sopenharmony_ci	inputData.numElements = subgroups::maxSupportedSubgroupSize();
686e5c31af7Sopenharmony_ci	inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
687e5c31af7Sopenharmony_ci	inputData.binding = 0u;
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
690e5c31af7Sopenharmony_ci		return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
691e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
692e5c31af7Sopenharmony_ci		return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
693e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
694e5c31af7Sopenharmony_ci		return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
695e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
696e5c31af7Sopenharmony_ci		return subgroups::makeTessellationEvaluationFrameBufferTest(context,  FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
697e5c31af7Sopenharmony_ci	else
698e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unhandled shader stage");
699e5c31af7Sopenharmony_ci}
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_citcu::TestStatus test(Context& context, const CaseDefinition caseDef)
702e5c31af7Sopenharmony_ci{
703e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
704e5c31af7Sopenharmony_ci	{
705e5c31af7Sopenharmony_ci		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
706e5c31af7Sopenharmony_ci		{
707e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail(
708e5c31af7Sopenharmony_ci						   "Shader stage " +
709e5c31af7Sopenharmony_ci						   subgroups::getShaderStageName(caseDef.shaderStage) +
710e5c31af7Sopenharmony_ci						   " is required to support subgroup operations!");
711e5c31af7Sopenharmony_ci		}
712e5c31af7Sopenharmony_ci		subgroups::SSBOData inputData;
713e5c31af7Sopenharmony_ci		inputData.format = caseDef.format;
714e5c31af7Sopenharmony_ci		inputData.layout = subgroups::SSBOData::LayoutStd430;
715e5c31af7Sopenharmony_ci		inputData.numElements = subgroups::maxSupportedSubgroupSize();
716e5c31af7Sopenharmony_ci		inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
717e5c31af7Sopenharmony_ci		inputData.binding = 1u;
718e5c31af7Sopenharmony_ci
719e5c31af7Sopenharmony_ci		return subgroups::makeComputeTest(context, FORMAT_R32_UINT, &inputData, 1, checkComputeStage);
720e5c31af7Sopenharmony_ci	}
721e5c31af7Sopenharmony_ci	else
722e5c31af7Sopenharmony_ci	{
723e5c31af7Sopenharmony_ci		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
724e5c31af7Sopenharmony_ci
725e5c31af7Sopenharmony_ci		ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
726e5c31af7Sopenharmony_ci
727e5c31af7Sopenharmony_ci		if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
728e5c31af7Sopenharmony_ci		{
729e5c31af7Sopenharmony_ci			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
730e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
731e5c31af7Sopenharmony_ci			else
732e5c31af7Sopenharmony_ci				stages = SHADER_STAGE_FRAGMENT_BIT;
733e5c31af7Sopenharmony_ci		}
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci		if ((ShaderStageFlags)0u == stages)
736e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci		subgroups::SSBOData inputData;
739e5c31af7Sopenharmony_ci		inputData.format			= caseDef.format;
740e5c31af7Sopenharmony_ci		inputData.layout			= subgroups::SSBOData::LayoutStd430;
741e5c31af7Sopenharmony_ci		inputData.numElements		= subgroups::maxSupportedSubgroupSize();
742e5c31af7Sopenharmony_ci		inputData.initializeType	= subgroups::SSBOData::InitializeNonZero;
743e5c31af7Sopenharmony_ci		inputData.binding			= 4u;
744e5c31af7Sopenharmony_ci		inputData.stages			= stages;
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci		return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
747e5c31af7Sopenharmony_ci	}
748e5c31af7Sopenharmony_ci}
749e5c31af7Sopenharmony_ci}
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsClusteredTests(deqp::Context& testCtx)
752e5c31af7Sopenharmony_ci{
753e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
754e5c31af7Sopenharmony_ci		testCtx, "graphics", "Subgroup clustered category tests: graphics"));
755e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
756e5c31af7Sopenharmony_ci		testCtx, "compute", "Subgroup clustered category tests: compute"));
757e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
758e5c31af7Sopenharmony_ci		testCtx, "framebuffer", "Subgroup clustered category tests: framebuffer"));
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ci	const ShaderStageFlags stages[] =
761e5c31af7Sopenharmony_ci	{
762e5c31af7Sopenharmony_ci		SHADER_STAGE_VERTEX_BIT,
763e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_EVALUATION_BIT,
764e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_CONTROL_BIT,
765e5c31af7Sopenharmony_ci		SHADER_STAGE_GEOMETRY_BIT
766e5c31af7Sopenharmony_ci	};
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci	const Format formats[] =
769e5c31af7Sopenharmony_ci	{
770e5c31af7Sopenharmony_ci		FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
771e5c31af7Sopenharmony_ci		FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
772e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
773e5c31af7Sopenharmony_ci		FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
774e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
775e5c31af7Sopenharmony_ci		FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
776e5c31af7Sopenharmony_ci		FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
777e5c31af7Sopenharmony_ci		FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
778e5c31af7Sopenharmony_ci		FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
779e5c31af7Sopenharmony_ci	};
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci	for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
782e5c31af7Sopenharmony_ci	{
783e5c31af7Sopenharmony_ci		const Format format = formats[formatIndex];
784e5c31af7Sopenharmony_ci
785e5c31af7Sopenharmony_ci		for (int opTypeIndex = 0; opTypeIndex < OPTYPE_CLUSTERED_LAST; ++opTypeIndex)
786e5c31af7Sopenharmony_ci		{
787e5c31af7Sopenharmony_ci			bool isBool = false;
788e5c31af7Sopenharmony_ci			bool isFloat = false;
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_ci			switch (format)
791e5c31af7Sopenharmony_ci			{
792e5c31af7Sopenharmony_ci				default:
793e5c31af7Sopenharmony_ci					break;
794e5c31af7Sopenharmony_ci				case FORMAT_R32_SFLOAT:
795e5c31af7Sopenharmony_ci				case FORMAT_R32G32_SFLOAT:
796e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_SFLOAT:
797e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_SFLOAT:
798e5c31af7Sopenharmony_ci				case FORMAT_R64_SFLOAT:
799e5c31af7Sopenharmony_ci				case FORMAT_R64G64_SFLOAT:
800e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64_SFLOAT:
801e5c31af7Sopenharmony_ci				case FORMAT_R64G64B64A64_SFLOAT:
802e5c31af7Sopenharmony_ci					isFloat = true;
803e5c31af7Sopenharmony_ci					break;
804e5c31af7Sopenharmony_ci				case FORMAT_R32_BOOL:
805e5c31af7Sopenharmony_ci				case FORMAT_R32G32_BOOL:
806e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32_BOOL:
807e5c31af7Sopenharmony_ci				case FORMAT_R32G32B32A32_BOOL:
808e5c31af7Sopenharmony_ci					isBool = true;
809e5c31af7Sopenharmony_ci					break;
810e5c31af7Sopenharmony_ci			}
811e5c31af7Sopenharmony_ci
812e5c31af7Sopenharmony_ci			bool isBitwiseOp = false;
813e5c31af7Sopenharmony_ci
814e5c31af7Sopenharmony_ci			switch (opTypeIndex)
815e5c31af7Sopenharmony_ci			{
816e5c31af7Sopenharmony_ci				default:
817e5c31af7Sopenharmony_ci					break;
818e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_AND:
819e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_OR:
820e5c31af7Sopenharmony_ci				case OPTYPE_CLUSTERED_XOR:
821e5c31af7Sopenharmony_ci					isBitwiseOp = true;
822e5c31af7Sopenharmony_ci					break;
823e5c31af7Sopenharmony_ci			}
824e5c31af7Sopenharmony_ci
825e5c31af7Sopenharmony_ci			if (isFloat && isBitwiseOp)
826e5c31af7Sopenharmony_ci			{
827e5c31af7Sopenharmony_ci				// Skip float with bitwise category.
828e5c31af7Sopenharmony_ci				continue;
829e5c31af7Sopenharmony_ci			}
830e5c31af7Sopenharmony_ci
831e5c31af7Sopenharmony_ci			if (isBool && !isBitwiseOp)
832e5c31af7Sopenharmony_ci			{
833e5c31af7Sopenharmony_ci				// Skip bool when its not the bitwise category.
834e5c31af7Sopenharmony_ci				continue;
835e5c31af7Sopenharmony_ci			}
836e5c31af7Sopenharmony_ci
837e5c31af7Sopenharmony_ci			const std::string name = de::toLower(getOpTypeName(opTypeIndex))
838e5c31af7Sopenharmony_ci				+"_" + subgroups::getFormatNameForGLSL(format);
839e5c31af7Sopenharmony_ci
840e5c31af7Sopenharmony_ci			{
841e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
842e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
843e5c31af7Sopenharmony_ci			}
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci			{
846e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
847e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), name,
848e5c31af7Sopenharmony_ci										"", supportedCheck, initPrograms, test, caseDef);
849e5c31af7Sopenharmony_ci			}
850e5c31af7Sopenharmony_ci
851e5c31af7Sopenharmony_ci			for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
852e5c31af7Sopenharmony_ci			{
853e5c31af7Sopenharmony_ci				const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
854e5c31af7Sopenharmony_ci				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), name +"_" + getShaderStageName(caseDef.shaderStage), "",
855e5c31af7Sopenharmony_ci											supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
856e5c31af7Sopenharmony_ci			}
857e5c31af7Sopenharmony_ci		}
858e5c31af7Sopenharmony_ci	}
859e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
860e5c31af7Sopenharmony_ci		testCtx, "clustered", "Subgroup clustered category tests"));
861e5c31af7Sopenharmony_ci
862e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
863e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
864e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	return group.release();
867e5c31af7Sopenharmony_ci}
868e5c31af7Sopenharmony_ci
869e5c31af7Sopenharmony_ci} // subgroups
870e5c31af7Sopenharmony_ci} // glc
871