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 "glcSubgroupsBuiltinVarTests.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_cibool checkVertexPipelineStagesSubgroupSize(std::vector<const void*> datas,
41e5c31af7Sopenharmony_ci		deUint32 width, deUint32 subgroupSize)
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci	const deUint32* data =
44e5c31af7Sopenharmony_ci		reinterpret_cast<const deUint32*>(datas[0]);
45e5c31af7Sopenharmony_ci	for (deUint32 x = 0; x < width; ++x)
46e5c31af7Sopenharmony_ci	{
47e5c31af7Sopenharmony_ci		deUint32 val = data[x * 4];
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ci		if (subgroupSize != val)
50e5c31af7Sopenharmony_ci			return false;
51e5c31af7Sopenharmony_ci	}
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ci	return true;
54e5c31af7Sopenharmony_ci}
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_cibool checkVertexPipelineStagesSubgroupInvocationID(std::vector<const void*> datas,
57e5c31af7Sopenharmony_ci		deUint32 width, deUint32 subgroupSize)
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci	const deUint32* data =
60e5c31af7Sopenharmony_ci		reinterpret_cast<const deUint32*>(datas[0]);
61e5c31af7Sopenharmony_ci	vector<deUint32> subgroupInvocationHits(subgroupSize, 0);
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci	for (deUint32 x = 0; x < width; ++x)
64e5c31af7Sopenharmony_ci	{
65e5c31af7Sopenharmony_ci		deUint32 subgroupInvocationID = data[(x * 4) + 1];
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci		if (subgroupInvocationID >= subgroupSize)
68e5c31af7Sopenharmony_ci			return false;
69e5c31af7Sopenharmony_ci		subgroupInvocationHits[subgroupInvocationID]++;
70e5c31af7Sopenharmony_ci	}
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci	const deUint32 totalSize = width;
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci	deUint32 totalInvocationsRun = 0;
75e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < subgroupSize; ++i)
76e5c31af7Sopenharmony_ci	{
77e5c31af7Sopenharmony_ci		totalInvocationsRun += subgroupInvocationHits[i];
78e5c31af7Sopenharmony_ci	}
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ci	if (totalInvocationsRun != totalSize)
81e5c31af7Sopenharmony_ci		return false;
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	return true;
84e5c31af7Sopenharmony_ci}
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_cistatic bool checkComputeSubgroupSize(std::vector<const void*> datas,
87e5c31af7Sopenharmony_ci									 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
88e5c31af7Sopenharmony_ci									 deUint32 subgroupSize)
89e5c31af7Sopenharmony_ci{
90e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
93e5c31af7Sopenharmony_ci	{
94e5c31af7Sopenharmony_ci		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
95e5c31af7Sopenharmony_ci		{
96e5c31af7Sopenharmony_ci			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
97e5c31af7Sopenharmony_ci			{
98e5c31af7Sopenharmony_ci				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
99e5c31af7Sopenharmony_ci				{
100e5c31af7Sopenharmony_ci					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
101e5c31af7Sopenharmony_ci					{
102e5c31af7Sopenharmony_ci						for (deUint32 lZ = 0; lZ < localSize[2];
103e5c31af7Sopenharmony_ci								++lZ)
104e5c31af7Sopenharmony_ci						{
105e5c31af7Sopenharmony_ci							const deUint32 globalInvocationX =
106e5c31af7Sopenharmony_ci								nX * localSize[0] + lX;
107e5c31af7Sopenharmony_ci							const deUint32 globalInvocationY =
108e5c31af7Sopenharmony_ci								nY * localSize[1] + lY;
109e5c31af7Sopenharmony_ci							const deUint32 globalInvocationZ =
110e5c31af7Sopenharmony_ci								nZ * localSize[2] + lZ;
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci							const deUint32 globalSizeX =
113e5c31af7Sopenharmony_ci								numWorkgroups[0] * localSize[0];
114e5c31af7Sopenharmony_ci							const deUint32 globalSizeY =
115e5c31af7Sopenharmony_ci								numWorkgroups[1] * localSize[1];
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci							const deUint32 offset =
118e5c31af7Sopenharmony_ci								globalSizeX *
119e5c31af7Sopenharmony_ci								((globalSizeY *
120e5c31af7Sopenharmony_ci								  globalInvocationZ) +
121e5c31af7Sopenharmony_ci								 globalInvocationY) +
122e5c31af7Sopenharmony_ci								globalInvocationX;
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci							if (subgroupSize != data[offset * 4])
125e5c31af7Sopenharmony_ci								return false;
126e5c31af7Sopenharmony_ci						}
127e5c31af7Sopenharmony_ci					}
128e5c31af7Sopenharmony_ci				}
129e5c31af7Sopenharmony_ci			}
130e5c31af7Sopenharmony_ci		}
131e5c31af7Sopenharmony_ci	}
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci	return true;
134e5c31af7Sopenharmony_ci}
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_cistatic bool checkComputeSubgroupInvocationID(std::vector<const void*> datas,
137e5c31af7Sopenharmony_ci		const deUint32 numWorkgroups[3], const deUint32 localSize[3],
138e5c31af7Sopenharmony_ci		deUint32 subgroupSize)
139e5c31af7Sopenharmony_ci{
140e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
143e5c31af7Sopenharmony_ci	{
144e5c31af7Sopenharmony_ci		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
145e5c31af7Sopenharmony_ci		{
146e5c31af7Sopenharmony_ci			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
147e5c31af7Sopenharmony_ci			{
148e5c31af7Sopenharmony_ci				const deUint32 totalLocalSize =
149e5c31af7Sopenharmony_ci					localSize[0] * localSize[1] * localSize[2];
150e5c31af7Sopenharmony_ci				vector<deUint32> subgroupInvocationHits(subgroupSize, 0);
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
153e5c31af7Sopenharmony_ci				{
154e5c31af7Sopenharmony_ci					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
155e5c31af7Sopenharmony_ci					{
156e5c31af7Sopenharmony_ci						for (deUint32 lZ = 0; lZ < localSize[2];
157e5c31af7Sopenharmony_ci								++lZ)
158e5c31af7Sopenharmony_ci						{
159e5c31af7Sopenharmony_ci							const deUint32 globalInvocationX =
160e5c31af7Sopenharmony_ci								nX * localSize[0] + lX;
161e5c31af7Sopenharmony_ci							const deUint32 globalInvocationY =
162e5c31af7Sopenharmony_ci								nY * localSize[1] + lY;
163e5c31af7Sopenharmony_ci							const deUint32 globalInvocationZ =
164e5c31af7Sopenharmony_ci								nZ * localSize[2] + lZ;
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci							const deUint32 globalSizeX =
167e5c31af7Sopenharmony_ci								numWorkgroups[0] * localSize[0];
168e5c31af7Sopenharmony_ci							const deUint32 globalSizeY =
169e5c31af7Sopenharmony_ci								numWorkgroups[1] * localSize[1];
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ci							const deUint32 offset =
172e5c31af7Sopenharmony_ci								globalSizeX *
173e5c31af7Sopenharmony_ci								((globalSizeY *
174e5c31af7Sopenharmony_ci								  globalInvocationZ) +
175e5c31af7Sopenharmony_ci								 globalInvocationY) +
176e5c31af7Sopenharmony_ci								globalInvocationX;
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci							deUint32 subgroupInvocationID = data[(offset * 4) + 1];
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci							if (subgroupInvocationID >= subgroupSize)
181e5c31af7Sopenharmony_ci								return false;
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ci							subgroupInvocationHits[subgroupInvocationID]++;
184e5c31af7Sopenharmony_ci						}
185e5c31af7Sopenharmony_ci					}
186e5c31af7Sopenharmony_ci				}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci				deUint32 totalInvocationsRun = 0;
189e5c31af7Sopenharmony_ci				for (deUint32 i = 0; i < subgroupSize; ++i)
190e5c31af7Sopenharmony_ci				{
191e5c31af7Sopenharmony_ci					totalInvocationsRun += subgroupInvocationHits[i];
192e5c31af7Sopenharmony_ci				}
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci				if (totalInvocationsRun != totalLocalSize)
195e5c31af7Sopenharmony_ci					return false;
196e5c31af7Sopenharmony_ci			}
197e5c31af7Sopenharmony_ci		}
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	return true;
201e5c31af7Sopenharmony_ci}
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_cistatic bool checkComputeNumSubgroups	(std::vector<const void*>	datas,
204e5c31af7Sopenharmony_ci										const deUint32				numWorkgroups[3],
205e5c31af7Sopenharmony_ci										const deUint32				localSize[3],
206e5c31af7Sopenharmony_ci										deUint32)
207e5c31af7Sopenharmony_ci{
208e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
211e5c31af7Sopenharmony_ci	{
212e5c31af7Sopenharmony_ci		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
213e5c31af7Sopenharmony_ci		{
214e5c31af7Sopenharmony_ci			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
215e5c31af7Sopenharmony_ci			{
216e5c31af7Sopenharmony_ci				const deUint32 totalLocalSize =
217e5c31af7Sopenharmony_ci					localSize[0] * localSize[1] * localSize[2];
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
220e5c31af7Sopenharmony_ci				{
221e5c31af7Sopenharmony_ci					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
222e5c31af7Sopenharmony_ci					{
223e5c31af7Sopenharmony_ci						for (deUint32 lZ = 0; lZ < localSize[2];
224e5c31af7Sopenharmony_ci								++lZ)
225e5c31af7Sopenharmony_ci						{
226e5c31af7Sopenharmony_ci							const deUint32 globalInvocationX =
227e5c31af7Sopenharmony_ci								nX * localSize[0] + lX;
228e5c31af7Sopenharmony_ci							const deUint32 globalInvocationY =
229e5c31af7Sopenharmony_ci								nY * localSize[1] + lY;
230e5c31af7Sopenharmony_ci							const deUint32 globalInvocationZ =
231e5c31af7Sopenharmony_ci								nZ * localSize[2] + lZ;
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci							const deUint32 globalSizeX =
234e5c31af7Sopenharmony_ci								numWorkgroups[0] * localSize[0];
235e5c31af7Sopenharmony_ci							const deUint32 globalSizeY =
236e5c31af7Sopenharmony_ci								numWorkgroups[1] * localSize[1];
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci							const deUint32 offset =
239e5c31af7Sopenharmony_ci								globalSizeX *
240e5c31af7Sopenharmony_ci								((globalSizeY *
241e5c31af7Sopenharmony_ci								  globalInvocationZ) +
242e5c31af7Sopenharmony_ci								 globalInvocationY) +
243e5c31af7Sopenharmony_ci								globalInvocationX;
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci							deUint32 numSubgroups = data[(offset * 4) + 2];
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci							if (numSubgroups > totalLocalSize)
248e5c31af7Sopenharmony_ci								return false;
249e5c31af7Sopenharmony_ci						}
250e5c31af7Sopenharmony_ci					}
251e5c31af7Sopenharmony_ci				}
252e5c31af7Sopenharmony_ci			}
253e5c31af7Sopenharmony_ci		}
254e5c31af7Sopenharmony_ci	}
255e5c31af7Sopenharmony_ci
256e5c31af7Sopenharmony_ci	return true;
257e5c31af7Sopenharmony_ci}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_cistatic bool checkComputeSubgroupID	(std::vector<const void*>	datas,
260e5c31af7Sopenharmony_ci									const deUint32				numWorkgroups[3],
261e5c31af7Sopenharmony_ci									const deUint32				localSize[3],
262e5c31af7Sopenharmony_ci									deUint32)
263e5c31af7Sopenharmony_ci{
264e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci	for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
267e5c31af7Sopenharmony_ci	{
268e5c31af7Sopenharmony_ci		for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
269e5c31af7Sopenharmony_ci		{
270e5c31af7Sopenharmony_ci			for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
271e5c31af7Sopenharmony_ci			{
272e5c31af7Sopenharmony_ci				for (deUint32 lX = 0; lX < localSize[0]; ++lX)
273e5c31af7Sopenharmony_ci				{
274e5c31af7Sopenharmony_ci					for (deUint32 lY = 0; lY < localSize[1]; ++lY)
275e5c31af7Sopenharmony_ci					{
276e5c31af7Sopenharmony_ci						for (deUint32 lZ = 0; lZ < localSize[2];
277e5c31af7Sopenharmony_ci								++lZ)
278e5c31af7Sopenharmony_ci						{
279e5c31af7Sopenharmony_ci							const deUint32 globalInvocationX =
280e5c31af7Sopenharmony_ci								nX * localSize[0] + lX;
281e5c31af7Sopenharmony_ci							const deUint32 globalInvocationY =
282e5c31af7Sopenharmony_ci								nY * localSize[1] + lY;
283e5c31af7Sopenharmony_ci							const deUint32 globalInvocationZ =
284e5c31af7Sopenharmony_ci								nZ * localSize[2] + lZ;
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ci							const deUint32 globalSizeX =
287e5c31af7Sopenharmony_ci								numWorkgroups[0] * localSize[0];
288e5c31af7Sopenharmony_ci							const deUint32 globalSizeY =
289e5c31af7Sopenharmony_ci								numWorkgroups[1] * localSize[1];
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci							const deUint32 offset =
292e5c31af7Sopenharmony_ci								globalSizeX *
293e5c31af7Sopenharmony_ci								((globalSizeY *
294e5c31af7Sopenharmony_ci								  globalInvocationZ) +
295e5c31af7Sopenharmony_ci								 globalInvocationY) +
296e5c31af7Sopenharmony_ci								globalInvocationX;
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci							deUint32 numSubgroups = data[(offset * 4) + 2];
299e5c31af7Sopenharmony_ci							deUint32 subgroupID = data[(offset * 4) + 3];
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci							if (subgroupID >= numSubgroups)
302e5c31af7Sopenharmony_ci								return false;
303e5c31af7Sopenharmony_ci						}
304e5c31af7Sopenharmony_ci					}
305e5c31af7Sopenharmony_ci				}
306e5c31af7Sopenharmony_ci			}
307e5c31af7Sopenharmony_ci		}
308e5c31af7Sopenharmony_ci	}
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci	return true;
311e5c31af7Sopenharmony_ci}
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_cinamespace
314e5c31af7Sopenharmony_ci{
315e5c31af7Sopenharmony_cistruct CaseDefinition
316e5c31af7Sopenharmony_ci{
317e5c31af7Sopenharmony_ci	std::string varName;
318e5c31af7Sopenharmony_ci	ShaderStageFlags shaderStage;
319e5c31af7Sopenharmony_ci};
320e5c31af7Sopenharmony_ci}
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	{
325e5c31af7Sopenharmony_ci		const string fragmentGLSL =
326e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
327e5c31af7Sopenharmony_ci			"precision highp int;\n"
328e5c31af7Sopenharmony_ci			"layout(location = 0) in highp vec4 in_color;\n"
329e5c31af7Sopenharmony_ci			"layout(location = 0) out uvec4 out_color;\n"
330e5c31af7Sopenharmony_ci			"void main()\n"
331e5c31af7Sopenharmony_ci			"{\n"
332e5c31af7Sopenharmony_ci			"	out_color = uvec4(in_color);\n"
333e5c31af7Sopenharmony_ci			"}\n";
334e5c31af7Sopenharmony_ci		programCollection.add("fragment") << glu::FragmentSource(fragmentGLSL);
335e5c31af7Sopenharmony_ci	}
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
338e5c31af7Sopenharmony_ci		subgroups::setVertexShaderFrameBuffer(programCollection);
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
341e5c31af7Sopenharmony_ci	{
342e5c31af7Sopenharmony_ci		const string vertexGLSL =
343e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
344e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_basic: enable\n"
345e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color;\n"
346e5c31af7Sopenharmony_ci			"layout(location = 0) in highp vec4 in_position;\n"
347e5c31af7Sopenharmony_ci			"\n"
348e5c31af7Sopenharmony_ci			"void main (void)\n"
349e5c31af7Sopenharmony_ci			"{\n"
350e5c31af7Sopenharmony_ci			"  out_color = vec4(gl_SubgroupSize, gl_SubgroupInvocationID, 1.0f, 1.0f);\n"
351e5c31af7Sopenharmony_ci			"  gl_Position = in_position;\n"
352e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
353e5c31af7Sopenharmony_ci			"}\n";
354e5c31af7Sopenharmony_ci		programCollection.add("vert") << glu::VertexSource(vertexGLSL);
355e5c31af7Sopenharmony_ci	}
356e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
357e5c31af7Sopenharmony_ci	{
358e5c31af7Sopenharmony_ci		const string controlSourceGLSL =
359e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
360e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
361e5c31af7Sopenharmony_ci			"layout(vertices = 2) out;\n"
362e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color[];\n"
363e5c31af7Sopenharmony_ci			"void main (void)\n"
364e5c31af7Sopenharmony_ci			"{\n"
365e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
366e5c31af7Sopenharmony_ci			"  {\n"
367e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
368e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
369e5c31af7Sopenharmony_ci			"  }\n"
370e5c31af7Sopenharmony_ci			"  out_color[gl_InvocationID] = vec4(0.0f);\n"
371e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
372e5c31af7Sopenharmony_ci			"}\n";
373e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		const string evaluationSourceGLSL =
376e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
377e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_basic: enable\n"
378e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
379e5c31af7Sopenharmony_ci			"layout(isolines, equal_spacing, ccw ) in;\n"
380e5c31af7Sopenharmony_ci			"layout(location = 0) in vec4 in_color[];\n"
381e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color;\n"
382e5c31af7Sopenharmony_ci			"\n"
383e5c31af7Sopenharmony_ci			"void main (void)\n"
384e5c31af7Sopenharmony_ci			"{\n"
385e5c31af7Sopenharmony_ci			"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
386e5c31af7Sopenharmony_ci			"  out_color = vec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0.0f, 0.0f);\n"
387e5c31af7Sopenharmony_ci			"}\n";
388e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
389e5c31af7Sopenharmony_ci	}
390e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
391e5c31af7Sopenharmony_ci	{
392e5c31af7Sopenharmony_ci		const string controlSourceGLSL =
393e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
394e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
395e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_basic: enable\n"
396e5c31af7Sopenharmony_ci			"layout(vertices = 2) out;\n"
397e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color[];\n"
398e5c31af7Sopenharmony_ci			"void main (void)\n"
399e5c31af7Sopenharmony_ci			"{\n"
400e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
401e5c31af7Sopenharmony_ci			"  {\n"
402e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
403e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
404e5c31af7Sopenharmony_ci			"  }\n"
405e5c31af7Sopenharmony_ci			"  out_color[gl_InvocationID] = vec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
406e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
407e5c31af7Sopenharmony_ci			"}\n";
408e5c31af7Sopenharmony_ci		programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci		const string  evaluationSourceGLSL =
411e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
412e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_basic: enable\n"
413e5c31af7Sopenharmony_ci			"${TESS_EXTENSION}\n"
414e5c31af7Sopenharmony_ci			"layout(isolines, equal_spacing, ccw ) in;\n"
415e5c31af7Sopenharmony_ci			"layout(location = 0) in vec4 in_color[];\n"
416e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color;\n"
417e5c31af7Sopenharmony_ci			"\n"
418e5c31af7Sopenharmony_ci			"void main (void)\n"
419e5c31af7Sopenharmony_ci			"{\n"
420e5c31af7Sopenharmony_ci			"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
421e5c31af7Sopenharmony_ci			"  out_color = in_color[0];\n"
422e5c31af7Sopenharmony_ci			"}\n";
423e5c31af7Sopenharmony_ci		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
424e5c31af7Sopenharmony_ci	}
425e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
426e5c31af7Sopenharmony_ci	{
427e5c31af7Sopenharmony_ci		const string geometryGLSL =
428e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
429e5c31af7Sopenharmony_ci			"#extension GL_KHR_shader_subgroup_basic: enable\n"
430e5c31af7Sopenharmony_ci			"layout(points) in;\n"
431e5c31af7Sopenharmony_ci			"layout(points, max_vertices = 1) out;\n"
432e5c31af7Sopenharmony_ci			"layout(location = 0) out vec4 out_color;\n"
433e5c31af7Sopenharmony_ci			"void main (void)\n"
434e5c31af7Sopenharmony_ci			"{\n"
435e5c31af7Sopenharmony_ci			"  out_color = vec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
436e5c31af7Sopenharmony_ci			"  gl_Position = gl_in[0].gl_Position;\n"
437e5c31af7Sopenharmony_ci			"  EmitVertex();\n"
438e5c31af7Sopenharmony_ci			"  EndPrimitive();\n"
439e5c31af7Sopenharmony_ci			"}\n";
440e5c31af7Sopenharmony_ci		programCollection.add("geometry") << glu::GeometrySource(geometryGLSL);
441e5c31af7Sopenharmony_ci	}
442e5c31af7Sopenharmony_ci	else
443e5c31af7Sopenharmony_ci	{
444e5c31af7Sopenharmony_ci		DE_FATAL("Unsupported shader stage");
445e5c31af7Sopenharmony_ci	}
446e5c31af7Sopenharmony_ci}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
449e5c31af7Sopenharmony_ci{
450e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
451e5c31af7Sopenharmony_ci	{
452e5c31af7Sopenharmony_ci		std::ostringstream src;
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci		src << "${VERSION_DECL}\n"
455e5c31af7Sopenharmony_ci			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
456e5c31af7Sopenharmony_ci			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
457e5c31af7Sopenharmony_ci			<< "layout(binding = 0, std430) buffer Output\n"
458e5c31af7Sopenharmony_ci			<< "{\n"
459e5c31af7Sopenharmony_ci			<< "  uvec4 result[];\n"
460e5c31af7Sopenharmony_ci			<< "};\n"
461e5c31af7Sopenharmony_ci			<< "\n"
462e5c31af7Sopenharmony_ci			<< "void main (void)\n"
463e5c31af7Sopenharmony_ci			<< "{\n"
464e5c31af7Sopenharmony_ci			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
465e5c31af7Sopenharmony_ci			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
466e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
467e5c31af7Sopenharmony_ci			"gl_GlobalInvocationID.x;\n"
468e5c31af7Sopenharmony_ci			<< "  result[offset] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, gl_NumSubgroups, gl_SubgroupID);\n"
469e5c31af7Sopenharmony_ci			<< "}\n";
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci		programCollection.add("comp") << glu::ComputeSource(src.str());
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci	else
474e5c31af7Sopenharmony_ci	{
475e5c31af7Sopenharmony_ci		{
476e5c31af7Sopenharmony_ci			const string vertexGLSL =
477e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
478e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_basic: enable\n"
479e5c31af7Sopenharmony_ci				"layout(binding = 0, std430) buffer Output0\n"
480e5c31af7Sopenharmony_ci				"{\n"
481e5c31af7Sopenharmony_ci				"  uvec4 result[];\n"
482e5c31af7Sopenharmony_ci				"} b0;\n"
483e5c31af7Sopenharmony_ci				"\n"
484e5c31af7Sopenharmony_ci				"void main (void)\n"
485e5c31af7Sopenharmony_ci				"{\n"
486e5c31af7Sopenharmony_ci				"  b0.result[gl_VertexID] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
487e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
488e5c31af7Sopenharmony_ci				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
489e5c31af7Sopenharmony_ci				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
490e5c31af7Sopenharmony_ci				"  gl_PointSize = 1.0f;\n"
491e5c31af7Sopenharmony_ci				"}\n";
492e5c31af7Sopenharmony_ci			programCollection.add("vert") << glu::VertexSource(vertexGLSL);
493e5c31af7Sopenharmony_ci		}
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ci		{
496e5c31af7Sopenharmony_ci			const string tescGLSL =
497e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
498e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_basic: enable\n"
499e5c31af7Sopenharmony_ci				"layout(vertices=1) out;\n"
500e5c31af7Sopenharmony_ci				"layout(binding = 1, std430) buffer Output1\n"
501e5c31af7Sopenharmony_ci				"{\n"
502e5c31af7Sopenharmony_ci				"  uvec4 result[];\n"
503e5c31af7Sopenharmony_ci				"} b1;\n"
504e5c31af7Sopenharmony_ci				"\n"
505e5c31af7Sopenharmony_ci				"void main (void)\n"
506e5c31af7Sopenharmony_ci				"{\n"
507e5c31af7Sopenharmony_ci				"  b1.result[gl_PrimitiveID] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
508e5c31af7Sopenharmony_ci				"  if (gl_InvocationID == 0)\n"
509e5c31af7Sopenharmony_ci				"  {\n"
510e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[0] = 1.0f;\n"
511e5c31af7Sopenharmony_ci				"    gl_TessLevelOuter[1] = 1.0f;\n"
512e5c31af7Sopenharmony_ci				"  }\n"
513e5c31af7Sopenharmony_ci				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
514e5c31af7Sopenharmony_ci				"}\n";
515e5c31af7Sopenharmony_ci			programCollection.add("tesc") << glu::TessellationControlSource(tescGLSL);
516e5c31af7Sopenharmony_ci		}
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci		{
519e5c31af7Sopenharmony_ci			const string teseGLSL =
520e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
521e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_basic: enable\n"
522e5c31af7Sopenharmony_ci				"layout(isolines) in;\n"
523e5c31af7Sopenharmony_ci				"layout(binding = 2, std430) buffer Output2\n"
524e5c31af7Sopenharmony_ci				"{\n"
525e5c31af7Sopenharmony_ci				"  uvec4 result[];\n"
526e5c31af7Sopenharmony_ci				"} b2;\n"
527e5c31af7Sopenharmony_ci				"\n"
528e5c31af7Sopenharmony_ci				"void main (void)\n"
529e5c31af7Sopenharmony_ci				"{\n"
530e5c31af7Sopenharmony_ci				"  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
531e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
532e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
533e5c31af7Sopenharmony_ci				"}\n";
534e5c31af7Sopenharmony_ci			programCollection.add("tese") << glu::TessellationEvaluationSource(teseGLSL);
535e5c31af7Sopenharmony_ci		}
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci		{
538e5c31af7Sopenharmony_ci			const string geometryGLSL =
539e5c31af7Sopenharmony_ci				// version string is added by addGeometryShadersFromTemplate
540e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_basic: enable\n"
541e5c31af7Sopenharmony_ci				"layout(${TOPOLOGY}) in;\n"
542e5c31af7Sopenharmony_ci				"layout(points, max_vertices = 1) out;\n"
543e5c31af7Sopenharmony_ci				"layout(binding = 3, std430) buffer Output3\n"
544e5c31af7Sopenharmony_ci				"{\n"
545e5c31af7Sopenharmony_ci				"  uvec4 result[];\n"
546e5c31af7Sopenharmony_ci				"} b3;\n"
547e5c31af7Sopenharmony_ci				"\n"
548e5c31af7Sopenharmony_ci				"void main (void)\n"
549e5c31af7Sopenharmony_ci				"{\n"
550e5c31af7Sopenharmony_ci				"  b3.result[gl_PrimitiveIDIn] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
551e5c31af7Sopenharmony_ci				"  gl_Position = gl_in[0].gl_Position;\n"
552e5c31af7Sopenharmony_ci				"  EmitVertex();\n"
553e5c31af7Sopenharmony_ci				"  EndPrimitive();\n"
554e5c31af7Sopenharmony_ci				"}\n";
555e5c31af7Sopenharmony_ci			addGeometryShadersFromTemplate(geometryGLSL, programCollection);
556e5c31af7Sopenharmony_ci		}
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci		{
559e5c31af7Sopenharmony_ci			const string fragmentGLSL =
560e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
561e5c31af7Sopenharmony_ci				"#extension GL_KHR_shader_subgroup_basic: enable\n"
562e5c31af7Sopenharmony_ci				"precision highp int;\n"
563e5c31af7Sopenharmony_ci				"layout(location = 0) out uvec4 data;\n"
564e5c31af7Sopenharmony_ci				"void main (void)\n"
565e5c31af7Sopenharmony_ci				"{\n"
566e5c31af7Sopenharmony_ci				"  data = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, 0, 0);\n"
567e5c31af7Sopenharmony_ci				"}\n";
568e5c31af7Sopenharmony_ci			programCollection.add("fragment") << glu::FragmentSource(fragmentGLSL);
569e5c31af7Sopenharmony_ci		}
570e5c31af7Sopenharmony_ci
571e5c31af7Sopenharmony_ci		subgroups::addNoSubgroupShader(programCollection);
572e5c31af7Sopenharmony_ci	}
573e5c31af7Sopenharmony_ci}
574e5c31af7Sopenharmony_ci
575e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef)
576e5c31af7Sopenharmony_ci{
577e5c31af7Sopenharmony_ci	DE_UNREF(caseDef);
578e5c31af7Sopenharmony_ci	if (!subgroups::isSubgroupSupported(context))
579e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
580e5c31af7Sopenharmony_ci}
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
583e5c31af7Sopenharmony_ci{
584e5c31af7Sopenharmony_ci	if (!areSubgroupOperationsSupportedForStage(
585e5c31af7Sopenharmony_ci				context, caseDef.shaderStage))
586e5c31af7Sopenharmony_ci	{
587e5c31af7Sopenharmony_ci		if (areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
588e5c31af7Sopenharmony_ci		{
589e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
590e5c31af7Sopenharmony_ci					   "Shader stage " + getShaderStageName(caseDef.shaderStage) +
591e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
592e5c31af7Sopenharmony_ci		}
593e5c31af7Sopenharmony_ci		else
594e5c31af7Sopenharmony_ci		{
595e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
596e5c31af7Sopenharmony_ci		}
597e5c31af7Sopenharmony_ci	}
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
600e5c31af7Sopenharmony_ci	{
601e5c31af7Sopenharmony_ci		if ("gl_SubgroupSize" == caseDef.varName)
602e5c31af7Sopenharmony_ci		{
603e5c31af7Sopenharmony_ci			return makeVertexFrameBufferTest(
604e5c31af7Sopenharmony_ci					   context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
605e5c31af7Sopenharmony_ci		}
606e5c31af7Sopenharmony_ci		else if ("gl_SubgroupInvocationID" == caseDef.varName)
607e5c31af7Sopenharmony_ci		{
608e5c31af7Sopenharmony_ci			return makeVertexFrameBufferTest(
609e5c31af7Sopenharmony_ci					   context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
610e5c31af7Sopenharmony_ci		}
611e5c31af7Sopenharmony_ci		else
612e5c31af7Sopenharmony_ci		{
613e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
614e5c31af7Sopenharmony_ci					   caseDef.varName + " failed (unhandled error checking case " +
615e5c31af7Sopenharmony_ci					   caseDef.varName + ")!");
616e5c31af7Sopenharmony_ci		}
617e5c31af7Sopenharmony_ci	}
618e5c31af7Sopenharmony_ci	else if ((SHADER_STAGE_TESS_EVALUATION_BIT | SHADER_STAGE_TESS_CONTROL_BIT) & caseDef.shaderStage )
619e5c31af7Sopenharmony_ci	{
620e5c31af7Sopenharmony_ci		if ("gl_SubgroupSize" == caseDef.varName)
621e5c31af7Sopenharmony_ci		{
622e5c31af7Sopenharmony_ci			return makeTessellationEvaluationFrameBufferTest(
623e5c31af7Sopenharmony_ci					context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
624e5c31af7Sopenharmony_ci		}
625e5c31af7Sopenharmony_ci		else if ("gl_SubgroupInvocationID" == caseDef.varName)
626e5c31af7Sopenharmony_ci		{
627e5c31af7Sopenharmony_ci			return makeTessellationEvaluationFrameBufferTest(
628e5c31af7Sopenharmony_ci					context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
629e5c31af7Sopenharmony_ci		}
630e5c31af7Sopenharmony_ci		else
631e5c31af7Sopenharmony_ci		{
632e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
633e5c31af7Sopenharmony_ci					caseDef.varName + " failed (unhandled error checking case " +
634e5c31af7Sopenharmony_ci					caseDef.varName + ")!");
635e5c31af7Sopenharmony_ci		}
636e5c31af7Sopenharmony_ci	}
637e5c31af7Sopenharmony_ci	else if (SHADER_STAGE_GEOMETRY_BIT & caseDef.shaderStage )
638e5c31af7Sopenharmony_ci	{
639e5c31af7Sopenharmony_ci		if ("gl_SubgroupSize" == caseDef.varName)
640e5c31af7Sopenharmony_ci		{
641e5c31af7Sopenharmony_ci			return makeGeometryFrameBufferTest(
642e5c31af7Sopenharmony_ci					context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize);
643e5c31af7Sopenharmony_ci		}
644e5c31af7Sopenharmony_ci		else if ("gl_SubgroupInvocationID" == caseDef.varName)
645e5c31af7Sopenharmony_ci		{
646e5c31af7Sopenharmony_ci			return makeGeometryFrameBufferTest(
647e5c31af7Sopenharmony_ci					context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID);
648e5c31af7Sopenharmony_ci		}
649e5c31af7Sopenharmony_ci		else
650e5c31af7Sopenharmony_ci		{
651e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
652e5c31af7Sopenharmony_ci					caseDef.varName + " failed (unhandled error checking case " +
653e5c31af7Sopenharmony_ci					caseDef.varName + ")!");
654e5c31af7Sopenharmony_ci		}
655e5c31af7Sopenharmony_ci	}
656e5c31af7Sopenharmony_ci	else
657e5c31af7Sopenharmony_ci	{
658e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Unhandled shader stage");
659e5c31af7Sopenharmony_ci	}
660e5c31af7Sopenharmony_ci}
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_citcu::TestStatus test(Context& context, const CaseDefinition caseDef)
664e5c31af7Sopenharmony_ci{
665e5c31af7Sopenharmony_ci	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
666e5c31af7Sopenharmony_ci	{
667e5c31af7Sopenharmony_ci		if (!areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
668e5c31af7Sopenharmony_ci		{
669e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
670e5c31af7Sopenharmony_ci					   "Shader stage " + getShaderStageName(caseDef.shaderStage) +
671e5c31af7Sopenharmony_ci					   " is required to support subgroup operations!");
672e5c31af7Sopenharmony_ci		}
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci		if ("gl_SubgroupSize" == caseDef.varName)
675e5c31af7Sopenharmony_ci		{
676e5c31af7Sopenharmony_ci			return makeComputeTest(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupSize);
677e5c31af7Sopenharmony_ci		}
678e5c31af7Sopenharmony_ci		else if ("gl_SubgroupInvocationID" == caseDef.varName)
679e5c31af7Sopenharmony_ci		{
680e5c31af7Sopenharmony_ci			return makeComputeTest(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupInvocationID);
681e5c31af7Sopenharmony_ci		}
682e5c31af7Sopenharmony_ci		else if ("gl_NumSubgroups" == caseDef.varName)
683e5c31af7Sopenharmony_ci		{
684e5c31af7Sopenharmony_ci			return makeComputeTest(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeNumSubgroups);
685e5c31af7Sopenharmony_ci		}
686e5c31af7Sopenharmony_ci		else if ("gl_SubgroupID" == caseDef.varName)
687e5c31af7Sopenharmony_ci		{
688e5c31af7Sopenharmony_ci			return makeComputeTest(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkComputeSubgroupID);
689e5c31af7Sopenharmony_ci		}
690e5c31af7Sopenharmony_ci		else
691e5c31af7Sopenharmony_ci		{
692e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
693e5c31af7Sopenharmony_ci					caseDef.varName + " failed (unhandled error checking case " +
694e5c31af7Sopenharmony_ci					caseDef.varName + ")!");
695e5c31af7Sopenharmony_ci		}
696e5c31af7Sopenharmony_ci	}
697e5c31af7Sopenharmony_ci	else
698e5c31af7Sopenharmony_ci	{
699e5c31af7Sopenharmony_ci		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci		subgroups::ShaderStageFlags stages = (subgroups::ShaderStageFlags)(caseDef.shaderStage & supportedStages);
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ci		if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
704e5c31af7Sopenharmony_ci		{
705e5c31af7Sopenharmony_ci			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
706e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
707e5c31af7Sopenharmony_ci			else
708e5c31af7Sopenharmony_ci				stages = SHADER_STAGE_FRAGMENT_BIT;
709e5c31af7Sopenharmony_ci		}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci		if ((ShaderStageFlags)0u == stages)
712e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_ci		if ("gl_SubgroupSize" == caseDef.varName)
715e5c31af7Sopenharmony_ci		{
716e5c31af7Sopenharmony_ci			return subgroups::allStages(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupSize, stages);
717e5c31af7Sopenharmony_ci		}
718e5c31af7Sopenharmony_ci		else if ("gl_SubgroupInvocationID" == caseDef.varName)
719e5c31af7Sopenharmony_ci		{
720e5c31af7Sopenharmony_ci			return subgroups::allStages(context, FORMAT_R32G32B32A32_UINT, DE_NULL, 0, checkVertexPipelineStagesSubgroupInvocationID, stages);
721e5c31af7Sopenharmony_ci		}
722e5c31af7Sopenharmony_ci		else
723e5c31af7Sopenharmony_ci		{
724e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(
725e5c31af7Sopenharmony_ci					   caseDef.varName + " failed (unhandled error checking case " +
726e5c31af7Sopenharmony_ci					   caseDef.varName + ")!");
727e5c31af7Sopenharmony_ci		}
728e5c31af7Sopenharmony_ci	}
729e5c31af7Sopenharmony_ci}
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsBuiltinVarTests(deqp::Context& testCtx)
732e5c31af7Sopenharmony_ci{
733e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
734e5c31af7Sopenharmony_ci		testCtx, "graphics", "Subgroup builtin variable tests: graphics"));
735e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
736e5c31af7Sopenharmony_ci		testCtx, "compute", "Subgroup builtin variable tests: compute"));
737e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
738e5c31af7Sopenharmony_ci		testCtx, "framebuffer", "Subgroup builtin variable tests: framebuffer"));
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci	const char* const all_stages_vars[] =
741e5c31af7Sopenharmony_ci	{
742e5c31af7Sopenharmony_ci		"SubgroupSize",
743e5c31af7Sopenharmony_ci		"SubgroupInvocationID"
744e5c31af7Sopenharmony_ci	};
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci	const char* const compute_only_vars[] =
747e5c31af7Sopenharmony_ci	{
748e5c31af7Sopenharmony_ci		"NumSubgroups",
749e5c31af7Sopenharmony_ci		"SubgroupID"
750e5c31af7Sopenharmony_ci	};
751e5c31af7Sopenharmony_ci
752e5c31af7Sopenharmony_ci	const ShaderStageFlags stages[] =
753e5c31af7Sopenharmony_ci	{
754e5c31af7Sopenharmony_ci		SHADER_STAGE_VERTEX_BIT,
755e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_EVALUATION_BIT,
756e5c31af7Sopenharmony_ci		SHADER_STAGE_TESS_CONTROL_BIT,
757e5c31af7Sopenharmony_ci		SHADER_STAGE_GEOMETRY_BIT,
758e5c31af7Sopenharmony_ci	};
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ci	for (int a = 0; a < DE_LENGTH_OF_ARRAY(all_stages_vars); ++a)
761e5c31af7Sopenharmony_ci	{
762e5c31af7Sopenharmony_ci		const std::string var = all_stages_vars[a];
763e5c31af7Sopenharmony_ci		const std::string varLower = de::toLower(var);
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci		{
766e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = { "gl_" + var, SHADER_STAGE_ALL_GRAPHICS};
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
769e5c31af7Sopenharmony_ci										varLower, "",
770e5c31af7Sopenharmony_ci										supportedCheck, initPrograms, test, caseDef);
771e5c31af7Sopenharmony_ci		}
772e5c31af7Sopenharmony_ci
773e5c31af7Sopenharmony_ci		{
774e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {"gl_" + var, SHADER_STAGE_COMPUTE_BIT};
775e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(),
776e5c31af7Sopenharmony_ci						varLower + "_" + getShaderStageName(caseDef.shaderStage), "",
777e5c31af7Sopenharmony_ci						supportedCheck, initPrograms, test, caseDef);
778e5c31af7Sopenharmony_ci		}
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci		for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
781e5c31af7Sopenharmony_ci		{
782e5c31af7Sopenharmony_ci			const CaseDefinition caseDef = {"gl_" + var, stages[stageIndex]};
783e5c31af7Sopenharmony_ci			SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
784e5c31af7Sopenharmony_ci						varLower + "_" + getShaderStageName(caseDef.shaderStage), "",
785e5c31af7Sopenharmony_ci						supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
786e5c31af7Sopenharmony_ci		}
787e5c31af7Sopenharmony_ci	}
788e5c31af7Sopenharmony_ci
789e5c31af7Sopenharmony_ci	for (int a = 0; a < DE_LENGTH_OF_ARRAY(compute_only_vars); ++a)
790e5c31af7Sopenharmony_ci	{
791e5c31af7Sopenharmony_ci		const std::string var = compute_only_vars[a];
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_ci		const CaseDefinition caseDef = {"gl_" + var, SHADER_STAGE_COMPUTE_BIT};
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci		SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), de::toLower(var), "",
796e5c31af7Sopenharmony_ci									supportedCheck, initPrograms, test, caseDef);
797e5c31af7Sopenharmony_ci	}
798e5c31af7Sopenharmony_ci
799e5c31af7Sopenharmony_ci	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
800e5c31af7Sopenharmony_ci		testCtx, "builtin_var", "Subgroup builtin variable tests"));
801e5c31af7Sopenharmony_ci
802e5c31af7Sopenharmony_ci	group->addChild(graphicGroup.release());
803e5c31af7Sopenharmony_ci	group->addChild(computeGroup.release());
804e5c31af7Sopenharmony_ci	group->addChild(framebufferGroup.release());
805e5c31af7Sopenharmony_ci
806e5c31af7Sopenharmony_ci	return group.release();
807e5c31af7Sopenharmony_ci}
808e5c31af7Sopenharmony_ci
809e5c31af7Sopenharmony_ci} // subgroups
810e5c31af7Sopenharmony_ci} // glc
811