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 Utils
24e5c31af7Sopenharmony_ci */ /*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "glcSubgroupsTestsUtils.hpp"
27e5c31af7Sopenharmony_ci#include "deRandom.hpp"
28e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
29e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
30e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
31e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ciusing namespace deqp;
34e5c31af7Sopenharmony_ciusing namespace std;
35e5c31af7Sopenharmony_ciusing namespace glc;
36e5c31af7Sopenharmony_ciusing namespace glw;
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_cinamespace
39e5c31af7Sopenharmony_ci{
40e5c31af7Sopenharmony_ci// debug callback function
41e5c31af7Sopenharmony_ci// To use:
42e5c31af7Sopenharmony_ci//	  gl.enable(GL_DEBUG_OUTPUT);
43e5c31af7Sopenharmony_ci//	  gl.debugMessageCallback(debugCallback, &context);
44e5c31af7Sopenharmony_ci//
45e5c31af7Sopenharmony_civoid debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
46e5c31af7Sopenharmony_ci					GLsizei length, const char * message, const void * userParam)
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci	glc::Context *context = (glc::Context *)userParam;
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context->getDeqpContext().getTestContext().getLog();
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ci	log << tcu::TestLog::Message
53e5c31af7Sopenharmony_ci		<< "DEBUG: source = " << source << ", type= " << type << ", id = " << id << ", severity = " << severity
54e5c31af7Sopenharmony_ci		<< ", length = " << length << "\n"
55e5c31af7Sopenharmony_ci		<< "DEBUG: `" << message << "`"
56e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci}
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci// getFormatReadInfo
61e5c31af7Sopenharmony_ci// returns the stride in bytes
62e5c31af7Sopenharmony_cideUint32 getFormatReadInfo(const subgroups::Format format, GLenum &readFormat, GLenum &readType)
63e5c31af7Sopenharmony_ci{
64e5c31af7Sopenharmony_ci	using namespace subgroups;
65e5c31af7Sopenharmony_ci	switch (format)
66e5c31af7Sopenharmony_ci	{
67e5c31af7Sopenharmony_ci		default:
68e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled format!");
69e5c31af7Sopenharmony_ci			// fall-through
70e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SFLOAT:
71e5c31af7Sopenharmony_ci			readFormat = GL_RGBA;
72e5c31af7Sopenharmony_ci			readType = GL_FLOAT;
73e5c31af7Sopenharmony_ci			return 4u;
74e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SFLOAT:
75e5c31af7Sopenharmony_ci			readFormat = GL_RG;
76e5c31af7Sopenharmony_ci			readType = GL_FLOAT;
77e5c31af7Sopenharmony_ci			return 2u;
78e5c31af7Sopenharmony_ci		case FORMAT_R32_UINT:
79e5c31af7Sopenharmony_ci			readFormat = GL_RED_INTEGER;
80e5c31af7Sopenharmony_ci			readType = GL_UNSIGNED_INT;
81e5c31af7Sopenharmony_ci			return 1u;
82e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_UINT:
83e5c31af7Sopenharmony_ci			readFormat = GL_RGBA_INTEGER;
84e5c31af7Sopenharmony_ci			readType = GL_UNSIGNED_INT;
85e5c31af7Sopenharmony_ci			return 4u;
86e5c31af7Sopenharmony_ci	}
87e5c31af7Sopenharmony_ci}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_cideUint32 getMaxWidth ()
90e5c31af7Sopenharmony_ci{
91e5c31af7Sopenharmony_ci	return 1024u;
92e5c31af7Sopenharmony_ci}
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_cideUint32 getNextWidth (const deUint32 width)
95e5c31af7Sopenharmony_ci{
96e5c31af7Sopenharmony_ci	if (width < 128)
97e5c31af7Sopenharmony_ci	{
98e5c31af7Sopenharmony_ci		// This ensures we test every value up to 128 (the max subgroup size).
99e5c31af7Sopenharmony_ci		return width + 1;
100e5c31af7Sopenharmony_ci	}
101e5c31af7Sopenharmony_ci	else
102e5c31af7Sopenharmony_ci	{
103e5c31af7Sopenharmony_ci		// And once we hit 128 we increment to only power of 2's to reduce testing time.
104e5c31af7Sopenharmony_ci		return width * 2;
105e5c31af7Sopenharmony_ci	}
106e5c31af7Sopenharmony_ci}
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_cideUint32 getFormatSizeInBytes(const subgroups::Format format)
109e5c31af7Sopenharmony_ci{
110e5c31af7Sopenharmony_ci	using namespace subgroups;
111e5c31af7Sopenharmony_ci	switch (format)
112e5c31af7Sopenharmony_ci	{
113e5c31af7Sopenharmony_ci		default:
114e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled format!");
115e5c31af7Sopenharmony_ci			return 0;
116e5c31af7Sopenharmony_ci		case FORMAT_R32_SINT:
117e5c31af7Sopenharmony_ci		case FORMAT_R32_UINT:
118e5c31af7Sopenharmony_ci			return sizeof(deInt32);
119e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SINT:
120e5c31af7Sopenharmony_ci		case FORMAT_R32G32_UINT:
121e5c31af7Sopenharmony_ci			return static_cast<deUint32>(sizeof(deInt32) * 2);
122e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SINT:
123e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_UINT:
124e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SINT:
125e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_UINT:
126e5c31af7Sopenharmony_ci			return static_cast<deUint32>(sizeof(deInt32) * 4);
127e5c31af7Sopenharmony_ci		case FORMAT_R32_SFLOAT:
128e5c31af7Sopenharmony_ci			return 4;
129e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SFLOAT:
130e5c31af7Sopenharmony_ci			return 8;
131e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SFLOAT:
132e5c31af7Sopenharmony_ci			return 16;
133e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SFLOAT:
134e5c31af7Sopenharmony_ci			return 16;
135e5c31af7Sopenharmony_ci		case FORMAT_R64_SFLOAT:
136e5c31af7Sopenharmony_ci			return 8;
137e5c31af7Sopenharmony_ci		case FORMAT_R64G64_SFLOAT:
138e5c31af7Sopenharmony_ci			return 16;
139e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64_SFLOAT:
140e5c31af7Sopenharmony_ci			return 32;
141e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64A64_SFLOAT:
142e5c31af7Sopenharmony_ci			return 32;
143e5c31af7Sopenharmony_ci		// The below formats are used to represent bool and bvec* types. These
144e5c31af7Sopenharmony_ci		// types are passed to the shader as int and ivec* types, before the
145e5c31af7Sopenharmony_ci		// calculations are done as booleans. We need a distinct type here so
146e5c31af7Sopenharmony_ci		// that the shader generators can switch on it and generate the correct
147e5c31af7Sopenharmony_ci		// shader source for testing.
148e5c31af7Sopenharmony_ci		case FORMAT_R32_BOOL:
149e5c31af7Sopenharmony_ci			return sizeof(deInt32);
150e5c31af7Sopenharmony_ci		case FORMAT_R32G32_BOOL:
151e5c31af7Sopenharmony_ci			return static_cast<deUint32>(sizeof(deInt32) * 2);
152e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_BOOL:
153e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_BOOL:
154e5c31af7Sopenharmony_ci			return static_cast<deUint32>(sizeof(deInt32) * 4);
155e5c31af7Sopenharmony_ci	}
156e5c31af7Sopenharmony_ci}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_cideUint32 getElementSizeInBytes(
159e5c31af7Sopenharmony_ci	const subgroups::Format format,
160e5c31af7Sopenharmony_ci	const subgroups::SSBOData::InputDataLayoutType layout)
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	deUint32 bytes = getFormatSizeInBytes(format);
163e5c31af7Sopenharmony_ci	if (layout == subgroups::SSBOData::LayoutStd140)
164e5c31af7Sopenharmony_ci		return bytes < 16 ? 16 : bytes;
165e5c31af7Sopenharmony_ci	else
166e5c31af7Sopenharmony_ci		return bytes;
167e5c31af7Sopenharmony_ci}
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_cide::MovePtr<glu::ShaderProgram> makeGraphicsPipeline(glc::Context&				context,
171e5c31af7Sopenharmony_ci									  const subgroups::ShaderStageFlags			stages,
172e5c31af7Sopenharmony_ci									  const GlslSource *						vshader,
173e5c31af7Sopenharmony_ci									  const GlslSource *						fshader,
174e5c31af7Sopenharmony_ci									  const GlslSource *						gshader,
175e5c31af7Sopenharmony_ci									  const GlslSource *						tcshader,
176e5c31af7Sopenharmony_ci									  const GlslSource *						teshader)
177e5c31af7Sopenharmony_ci{
178e5c31af7Sopenharmony_ci	tcu::TestLog&	log			= context.getDeqpContext().getTestContext().getLog();
179e5c31af7Sopenharmony_ci	const bool		doShaderLog	= log.isShaderLoggingEnabled();
180e5c31af7Sopenharmony_ci	DE_UNREF(stages);			// only used for asserts
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci	map<string, string> templateArgs;
183e5c31af7Sopenharmony_ci	string				versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
184e5c31af7Sopenharmony_ci	string				tessExtension =
185e5c31af7Sopenharmony_ci		 context.getDeqpContext().getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ?
186e5c31af7Sopenharmony_ci						   "#extension GL_EXT_tessellation_shader : require" :
187e5c31af7Sopenharmony_ci						   "";
188e5c31af7Sopenharmony_ci	templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
189e5c31af7Sopenharmony_ci	templateArgs.insert(pair<string, string>("TESS_EXTENSION", tessExtension));
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ci	string vertSource, tescSource, teseSource, geomSource, fragSource;
192e5c31af7Sopenharmony_ci	if (vshader)
193e5c31af7Sopenharmony_ci	{
194e5c31af7Sopenharmony_ci		DE_ASSERT(stages & subgroups::SHADER_STAGE_VERTEX_BIT);
195e5c31af7Sopenharmony_ci		tcu::StringTemplate shaderTemplate(vshader->sources[glu::SHADERTYPE_VERTEX][0]);
196e5c31af7Sopenharmony_ci		string shaderSource(shaderTemplate.specialize(templateArgs));
197e5c31af7Sopenharmony_ci		if (doShaderLog)
198e5c31af7Sopenharmony_ci		{
199e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "vertex shader:\n"
200e5c31af7Sopenharmony_ci				<< shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
201e5c31af7Sopenharmony_ci		}
202e5c31af7Sopenharmony_ci		vertSource = shaderSource;
203e5c31af7Sopenharmony_ci	}
204e5c31af7Sopenharmony_ci	if (tcshader)
205e5c31af7Sopenharmony_ci	{
206e5c31af7Sopenharmony_ci		DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_CONTROL_BIT);
207e5c31af7Sopenharmony_ci		tcu::StringTemplate shaderTemplate(tcshader->sources[glu::SHADERTYPE_TESSELLATION_CONTROL][0]);
208e5c31af7Sopenharmony_ci		string shaderSource(shaderTemplate.specialize(templateArgs));
209e5c31af7Sopenharmony_ci		if (doShaderLog)
210e5c31af7Sopenharmony_ci		{
211e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "tess control shader:\n"
212e5c31af7Sopenharmony_ci				<< shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
213e5c31af7Sopenharmony_ci		}
214e5c31af7Sopenharmony_ci		tescSource = shaderSource;
215e5c31af7Sopenharmony_ci	}
216e5c31af7Sopenharmony_ci	if (teshader)
217e5c31af7Sopenharmony_ci	{
218e5c31af7Sopenharmony_ci		DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_EVALUATION_BIT);
219e5c31af7Sopenharmony_ci		tcu::StringTemplate shaderTemplate(teshader->sources[glu::SHADERTYPE_TESSELLATION_EVALUATION][0]);
220e5c31af7Sopenharmony_ci		string shaderSource(shaderTemplate.specialize(templateArgs));
221e5c31af7Sopenharmony_ci		if (doShaderLog)
222e5c31af7Sopenharmony_ci		{
223e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "tess eval shader:\n"
224e5c31af7Sopenharmony_ci				<< shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
225e5c31af7Sopenharmony_ci		}
226e5c31af7Sopenharmony_ci		teseSource = shaderSource;
227e5c31af7Sopenharmony_ci	}
228e5c31af7Sopenharmony_ci	if (gshader)
229e5c31af7Sopenharmony_ci	{
230e5c31af7Sopenharmony_ci		DE_ASSERT(stages & subgroups::SHADER_STAGE_GEOMETRY_BIT);
231e5c31af7Sopenharmony_ci		tcu::StringTemplate shaderTemplate(gshader->sources[glu::SHADERTYPE_GEOMETRY][0]);
232e5c31af7Sopenharmony_ci		string shaderSource(shaderTemplate.specialize(templateArgs));
233e5c31af7Sopenharmony_ci		if (doShaderLog)
234e5c31af7Sopenharmony_ci		{
235e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "geometry shader:\n"
236e5c31af7Sopenharmony_ci				<< shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
237e5c31af7Sopenharmony_ci		}
238e5c31af7Sopenharmony_ci		geomSource = shaderSource;
239e5c31af7Sopenharmony_ci	}
240e5c31af7Sopenharmony_ci	if (fshader)
241e5c31af7Sopenharmony_ci	{
242e5c31af7Sopenharmony_ci		DE_ASSERT(stages & subgroups::SHADER_STAGE_FRAGMENT_BIT);
243e5c31af7Sopenharmony_ci		tcu::StringTemplate shaderTemplate(fshader->sources[glu::SHADERTYPE_FRAGMENT][0]);
244e5c31af7Sopenharmony_ci		string shaderSource(shaderTemplate.specialize(templateArgs));
245e5c31af7Sopenharmony_ci		if (doShaderLog)
246e5c31af7Sopenharmony_ci		{
247e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "fragment shader:\n"
248e5c31af7Sopenharmony_ci				<< shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
249e5c31af7Sopenharmony_ci		}
250e5c31af7Sopenharmony_ci		fragSource = shaderSource;
251e5c31af7Sopenharmony_ci	}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	glu::ShaderProgram *program = DE_NULL;
254e5c31af7Sopenharmony_ci	if(context.getShaderType() == SHADER_TYPE_GLSL)
255e5c31af7Sopenharmony_ci	{
256e5c31af7Sopenharmony_ci		glu::ProgramSources sources;
257e5c31af7Sopenharmony_ci		if (vshader)
258e5c31af7Sopenharmony_ci			sources << glu::VertexSource(vertSource);
259e5c31af7Sopenharmony_ci		if (tcshader)
260e5c31af7Sopenharmony_ci			sources << glu::TessellationControlSource(tescSource);
261e5c31af7Sopenharmony_ci		if (teshader)
262e5c31af7Sopenharmony_ci			sources << glu::TessellationEvaluationSource(teseSource);
263e5c31af7Sopenharmony_ci		if (gshader)
264e5c31af7Sopenharmony_ci			sources << glu::GeometrySource(geomSource);
265e5c31af7Sopenharmony_ci		if (fshader)
266e5c31af7Sopenharmony_ci			sources << glu::FragmentSource(fragSource);
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci		program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
269e5c31af7Sopenharmony_ci	} else {
270e5c31af7Sopenharmony_ci		DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
271e5c31af7Sopenharmony_ci
272e5c31af7Sopenharmony_ci		glu::ProgramBinaries binaries;
273e5c31af7Sopenharmony_ci		if (vshader)
274e5c31af7Sopenharmony_ci			binaries << spirvUtils::makeSpirV(log, glu::VertexSource(vertSource), spirvUtils::SPIRV_VERSION_1_3);
275e5c31af7Sopenharmony_ci		if (tcshader)
276e5c31af7Sopenharmony_ci			binaries << spirvUtils::makeSpirV(log, glu::TessellationControlSource(tescSource), spirvUtils::SPIRV_VERSION_1_3);
277e5c31af7Sopenharmony_ci		if (teshader)
278e5c31af7Sopenharmony_ci			binaries << spirvUtils::makeSpirV(log, glu::TessellationEvaluationSource(teseSource), spirvUtils::SPIRV_VERSION_1_3);
279e5c31af7Sopenharmony_ci		if (gshader)
280e5c31af7Sopenharmony_ci			binaries << spirvUtils::makeSpirV(log, glu::GeometrySource(geomSource), spirvUtils::SPIRV_VERSION_1_3);
281e5c31af7Sopenharmony_ci		if (fshader)
282e5c31af7Sopenharmony_ci			binaries << spirvUtils::makeSpirV(log, glu::FragmentSource(fragSource), spirvUtils::SPIRV_VERSION_1_3);
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci		program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
285e5c31af7Sopenharmony_ci	}
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci	if (!program->isOk())
288e5c31af7Sopenharmony_ci	{
289e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << "Shader build failed.\n"
290e5c31af7Sopenharmony_ci			<< "Vertex: " << (vshader ? program->getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog : "n/a") << "\n"
291e5c31af7Sopenharmony_ci			<< "Tess Cont: " << (tcshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).infoLog : "n/a") << "\n"
292e5c31af7Sopenharmony_ci			<< "Tess Eval: " << (teshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION).infoLog : "n/a") << "\n"
293e5c31af7Sopenharmony_ci			<< "Geometry: " << (gshader ? program->getShaderInfo(glu::SHADERTYPE_GEOMETRY).infoLog : "n/a") << "\n"
294e5c31af7Sopenharmony_ci			<< "Fragment: " << (fshader ? program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog : "n/a") << "\n"
295e5c31af7Sopenharmony_ci			<< "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
296e5c31af7Sopenharmony_ci	}
297e5c31af7Sopenharmony_ci	return de::MovePtr<glu::ShaderProgram>(program);
298e5c31af7Sopenharmony_ci}
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_cide::MovePtr<glu::ShaderProgram> makeComputePipeline(glc::Context& context, const GlslSource &glslTemplate,
301e5c31af7Sopenharmony_ci									 deUint32 localSizeX, deUint32 localSizeY, deUint32 localSizeZ)
302e5c31af7Sopenharmony_ci{
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci	tcu::TestLog&	log			= context.getDeqpContext().getTestContext().getLog();
305e5c31af7Sopenharmony_ci	const bool		doShaderLog	= log.isShaderLoggingEnabled();
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci	tcu::StringTemplate computeTemplate(glslTemplate.sources[glu::SHADERTYPE_COMPUTE][0]);
308e5c31af7Sopenharmony_ci
309e5c31af7Sopenharmony_ci	map<string, string>		templateArgs;
310e5c31af7Sopenharmony_ci	{
311e5c31af7Sopenharmony_ci		stringstream localSize;
312e5c31af7Sopenharmony_ci		localSize << "local_size_x = " << localSizeX;
313e5c31af7Sopenharmony_ci		templateArgs.insert(pair<string, string>("LOCAL_SIZE_X", localSize.str()));
314e5c31af7Sopenharmony_ci	}
315e5c31af7Sopenharmony_ci	{
316e5c31af7Sopenharmony_ci		stringstream localSize;
317e5c31af7Sopenharmony_ci		localSize << "local_size_y = " << localSizeY;
318e5c31af7Sopenharmony_ci		templateArgs.insert(pair<string, string>("LOCAL_SIZE_Y", localSize.str()));
319e5c31af7Sopenharmony_ci	}
320e5c31af7Sopenharmony_ci	{
321e5c31af7Sopenharmony_ci		stringstream localSize;
322e5c31af7Sopenharmony_ci		localSize << "local_size_z = " << localSizeZ;
323e5c31af7Sopenharmony_ci		templateArgs.insert(pair<string, string>("LOCAL_SIZE_Z", localSize.str()));
324e5c31af7Sopenharmony_ci	}
325e5c31af7Sopenharmony_ci	string versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
326e5c31af7Sopenharmony_ci	templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_ci	glu::ComputeSource cshader(glu::ComputeSource(computeTemplate.specialize(templateArgs)));
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	if (doShaderLog)
331e5c31af7Sopenharmony_ci	{
332e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << "compute shader specialized source:\n"
333e5c31af7Sopenharmony_ci			<< cshader.source << "\n:end:" << tcu::TestLog::EndMessage;
334e5c31af7Sopenharmony_ci	}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	glu::ShaderProgram *program = DE_NULL;
337e5c31af7Sopenharmony_ci	if(context.getShaderType() == SHADER_TYPE_GLSL)
338e5c31af7Sopenharmony_ci	{
339e5c31af7Sopenharmony_ci		glu::ProgramSources sources;
340e5c31af7Sopenharmony_ci		sources << cshader;
341e5c31af7Sopenharmony_ci		program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
342e5c31af7Sopenharmony_ci	} else {
343e5c31af7Sopenharmony_ci		DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci		glu::ProgramBinaries binaries;
346e5c31af7Sopenharmony_ci		binaries << spirvUtils::makeSpirV(log, cshader, spirvUtils::SPIRV_VERSION_1_3);
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_ci		program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
349e5c31af7Sopenharmony_ci	}
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_ci	if (!program->isOk())
352e5c31af7Sopenharmony_ci	{
353e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << "Shader build failed.\n"
354e5c31af7Sopenharmony_ci			<< "Compute: " << program->getShaderInfo(glu::SHADERTYPE_COMPUTE).infoLog << "\n"
355e5c31af7Sopenharmony_ci			<< "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
356e5c31af7Sopenharmony_ci	}
357e5c31af7Sopenharmony_ci	return de::MovePtr<glu::ShaderProgram>(program);
358e5c31af7Sopenharmony_ci}
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_cistruct Buffer;
361e5c31af7Sopenharmony_cistruct Image;
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_cistruct BufferOrImage
364e5c31af7Sopenharmony_ci{
365e5c31af7Sopenharmony_ci	bool isImage() const
366e5c31af7Sopenharmony_ci	{
367e5c31af7Sopenharmony_ci		return m_isImage;
368e5c31af7Sopenharmony_ci	}
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci	Buffer* getAsBuffer()
371e5c31af7Sopenharmony_ci	{
372e5c31af7Sopenharmony_ci		if (m_isImage) DE_FATAL("Trying to get a buffer as an image!");
373e5c31af7Sopenharmony_ci		return reinterpret_cast<Buffer* >(this);
374e5c31af7Sopenharmony_ci	}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci	Image* getAsImage()
377e5c31af7Sopenharmony_ci	{
378e5c31af7Sopenharmony_ci		if (!m_isImage) DE_FATAL("Trying to get an image as a buffer!");
379e5c31af7Sopenharmony_ci		return reinterpret_cast<Image*>(this);
380e5c31af7Sopenharmony_ci	}
381e5c31af7Sopenharmony_ci
382e5c31af7Sopenharmony_ci	virtual subgroups::DescriptorType getType() const
383e5c31af7Sopenharmony_ci	{
384e5c31af7Sopenharmony_ci		if (m_isImage)
385e5c31af7Sopenharmony_ci		{
386e5c31af7Sopenharmony_ci			return subgroups::DESCRIPTOR_TYPE_STORAGE_IMAGE;
387e5c31af7Sopenharmony_ci		}
388e5c31af7Sopenharmony_ci		else
389e5c31af7Sopenharmony_ci		{
390e5c31af7Sopenharmony_ci			return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
391e5c31af7Sopenharmony_ci		}
392e5c31af7Sopenharmony_ci	}
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	GLuint getId()
395e5c31af7Sopenharmony_ci	{
396e5c31af7Sopenharmony_ci		return m_objectId;
397e5c31af7Sopenharmony_ci	}
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_ci	virtual ~BufferOrImage() {}
400e5c31af7Sopenharmony_ci
401e5c31af7Sopenharmony_ciprotected:
402e5c31af7Sopenharmony_ci	explicit BufferOrImage(glc::Context& context, bool image)
403e5c31af7Sopenharmony_ci		: m_gl(context.getDeqpContext().getRenderContext().getFunctions())
404e5c31af7Sopenharmony_ci		, m_isImage(image)
405e5c31af7Sopenharmony_ci		, m_objectId(0) {}
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_ci	const glw::Functions &	m_gl;
408e5c31af7Sopenharmony_ci	bool					m_isImage;
409e5c31af7Sopenharmony_ci	GLuint					m_objectId;
410e5c31af7Sopenharmony_ci};
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_cistruct Buffer : public BufferOrImage
413e5c31af7Sopenharmony_ci{
414e5c31af7Sopenharmony_ci	explicit Buffer(
415e5c31af7Sopenharmony_ci		glc::Context& context, deUint64 sizeInBytes, GLenum target = GL_SHADER_STORAGE_BUFFER)
416e5c31af7Sopenharmony_ci		: BufferOrImage		(context, false)
417e5c31af7Sopenharmony_ci		, m_sizeInBytes		(sizeInBytes)
418e5c31af7Sopenharmony_ci		, m_target			(target)
419e5c31af7Sopenharmony_ci	{
420e5c31af7Sopenharmony_ci		m_gl.genBuffers(1, &m_objectId);
421e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "genBuffers");
422e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, m_objectId);
423e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer");
424e5c31af7Sopenharmony_ci		m_gl.bufferData(m_target, m_sizeInBytes, NULL, GL_DYNAMIC_DRAW);
425e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "bufferData");
426e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, 0);
427e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer(0)");
428e5c31af7Sopenharmony_ci	}
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci	virtual ~Buffer()
431e5c31af7Sopenharmony_ci	{
432e5c31af7Sopenharmony_ci		if (m_objectId != 0)
433e5c31af7Sopenharmony_ci		{
434e5c31af7Sopenharmony_ci			m_gl.deleteBuffers(1, &m_objectId);
435e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers");
436e5c31af7Sopenharmony_ci		}
437e5c31af7Sopenharmony_ci	}
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ci	virtual subgroups::DescriptorType getType() const
440e5c31af7Sopenharmony_ci	{
441e5c31af7Sopenharmony_ci		if (GL_UNIFORM_BUFFER == m_target)
442e5c31af7Sopenharmony_ci		{
443e5c31af7Sopenharmony_ci			return subgroups::DESCRIPTOR_TYPE_UNIFORM_BUFFER;
444e5c31af7Sopenharmony_ci		}
445e5c31af7Sopenharmony_ci		return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
446e5c31af7Sopenharmony_ci	}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ci	glw::GLvoid* mapBufferPtr() {
449e5c31af7Sopenharmony_ci		glw::GLvoid *ptr;
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, m_objectId);
452e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci		ptr = m_gl.mapBufferRange(m_target, 0, m_sizeInBytes, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
455e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer");
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, 0);
458e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci		return ptr;
461e5c31af7Sopenharmony_ci	}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	void unmapBufferPtr() {
464e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, m_objectId);
465e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_ci		m_gl.unmapBuffer(m_target);
468e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer");
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ci		m_gl.bindBuffer(m_target, 0);
471e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci	deUint64 getSize() const {
475e5c31af7Sopenharmony_ci		return m_sizeInBytes;
476e5c31af7Sopenharmony_ci	}
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_ciprivate:
479e5c31af7Sopenharmony_ci	deUint64					m_sizeInBytes;
480e5c31af7Sopenharmony_ci	const GLenum				m_target;
481e5c31af7Sopenharmony_ci};
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_cistruct Image : public BufferOrImage
484e5c31af7Sopenharmony_ci{
485e5c31af7Sopenharmony_ci	explicit Image(glc::Context& context, deUint32 width, deUint32 height,
486e5c31af7Sopenharmony_ci				   subgroups::Format format)
487e5c31af7Sopenharmony_ci		: BufferOrImage(context, true)
488e5c31af7Sopenharmony_ci	{
489e5c31af7Sopenharmony_ci		m_gl.genTextures(1, &m_objectId);
490e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures");
491e5c31af7Sopenharmony_ci		m_gl.bindTexture(GL_TEXTURE_2D, m_objectId);
492e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture");
493e5c31af7Sopenharmony_ci		m_gl.texStorage2D(GL_TEXTURE_2D, 1, format, width, height);
494e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D");
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ci		m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
497e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexParameteri");
498e5c31af7Sopenharmony_ci		m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
499e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexParameteri");
500e5c31af7Sopenharmony_ci	}
501e5c31af7Sopenharmony_ci
502e5c31af7Sopenharmony_ci	virtual ~Image()
503e5c31af7Sopenharmony_ci	{
504e5c31af7Sopenharmony_ci		if (m_objectId != 0)
505e5c31af7Sopenharmony_ci		{
506e5c31af7Sopenharmony_ci			m_gl.deleteTextures(1, &m_objectId);
507e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteTextures");
508e5c31af7Sopenharmony_ci		}
509e5c31af7Sopenharmony_ci	}
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ciprivate:
512e5c31af7Sopenharmony_ci};
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_cistruct Vao
515e5c31af7Sopenharmony_ci{
516e5c31af7Sopenharmony_ci	explicit Vao(glc::Context& context)
517e5c31af7Sopenharmony_ci		: m_gl(context.getDeqpContext().getRenderContext().getFunctions())
518e5c31af7Sopenharmony_ci		, m_objectId(0)
519e5c31af7Sopenharmony_ci	{
520e5c31af7Sopenharmony_ci		m_gl.genVertexArrays(1, &m_objectId);
521e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays");
522e5c31af7Sopenharmony_ci		m_gl.bindVertexArray(m_objectId);
523e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray");
524e5c31af7Sopenharmony_ci	}
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci	~Vao()
527e5c31af7Sopenharmony_ci	{
528e5c31af7Sopenharmony_ci		if (m_objectId != 0)
529e5c31af7Sopenharmony_ci		{
530e5c31af7Sopenharmony_ci			m_gl.deleteVertexArrays(1, &m_objectId);
531e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteVertexArrays");
532e5c31af7Sopenharmony_ci		}
533e5c31af7Sopenharmony_ci	}
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ciprivate:
536e5c31af7Sopenharmony_ci	const glw::Functions &	m_gl;
537e5c31af7Sopenharmony_ci	GLuint					m_objectId;
538e5c31af7Sopenharmony_ci};
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_cistruct Fbo
541e5c31af7Sopenharmony_ci{
542e5c31af7Sopenharmony_ci	explicit Fbo(glc::Context& context)
543e5c31af7Sopenharmony_ci		: m_gl(context.getDeqpContext().getRenderContext().getFunctions())
544e5c31af7Sopenharmony_ci		, m_objectId(0)
545e5c31af7Sopenharmony_ci	{
546e5c31af7Sopenharmony_ci		m_gl.genFramebuffers(1, &m_objectId);
547e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers");
548e5c31af7Sopenharmony_ci		m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_objectId);
549e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer");
550e5c31af7Sopenharmony_ci	}
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	~Fbo()
553e5c31af7Sopenharmony_ci	{
554e5c31af7Sopenharmony_ci		if (m_objectId != 0)
555e5c31af7Sopenharmony_ci		{
556e5c31af7Sopenharmony_ci			m_gl.deleteFramebuffers(1, &m_objectId);
557e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "deleteFramebuffers");
558e5c31af7Sopenharmony_ci		}
559e5c31af7Sopenharmony_ci	}
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ci	void bind2D(Image &img)
562e5c31af7Sopenharmony_ci	{
563e5c31af7Sopenharmony_ci		m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img.getId(), 0);
564e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferTexture2D");
565e5c31af7Sopenharmony_ci	}
566e5c31af7Sopenharmony_ci
567e5c31af7Sopenharmony_ciprivate:
568e5c31af7Sopenharmony_ci	const glw::Functions &	m_gl;
569e5c31af7Sopenharmony_ci	GLuint					m_objectId;
570e5c31af7Sopenharmony_ci
571e5c31af7Sopenharmony_ci};
572e5c31af7Sopenharmony_ci}
573e5c31af7Sopenharmony_ci
574e5c31af7Sopenharmony_cistd::string glc::subgroups::getSharedMemoryBallotHelper()
575e5c31af7Sopenharmony_ci{
576e5c31af7Sopenharmony_ci	return	"shared uvec4 superSecretComputeShaderHelper[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
577e5c31af7Sopenharmony_ci			"uvec4 sharedMemoryBallot(bool vote)\n"
578e5c31af7Sopenharmony_ci			"{\n"
579e5c31af7Sopenharmony_ci			"  uint groupOffset = gl_SubgroupID;\n"
580e5c31af7Sopenharmony_ci			"  // One invocation in the group 0's the whole group's data\n"
581e5c31af7Sopenharmony_ci			"  if (subgroupElect())\n"
582e5c31af7Sopenharmony_ci			"  {\n"
583e5c31af7Sopenharmony_ci			"    superSecretComputeShaderHelper[groupOffset] = uvec4(0);\n"
584e5c31af7Sopenharmony_ci			"  }\n"
585e5c31af7Sopenharmony_ci			"  subgroupMemoryBarrierShared();\n"
586e5c31af7Sopenharmony_ci			"  if (vote)\n"
587e5c31af7Sopenharmony_ci			"  {\n"
588e5c31af7Sopenharmony_ci			"    highp uint invocationId = gl_SubgroupInvocationID % 32u;\n"
589e5c31af7Sopenharmony_ci			"    highp uint bitToSet = 1u << invocationId;\n"
590e5c31af7Sopenharmony_ci			"    switch (gl_SubgroupInvocationID / 32u)\n"
591e5c31af7Sopenharmony_ci			"    {\n"
592e5c31af7Sopenharmony_ci			"    case 0u: atomicOr(superSecretComputeShaderHelper[groupOffset].x, bitToSet); break;\n"
593e5c31af7Sopenharmony_ci			"    case 1u: atomicOr(superSecretComputeShaderHelper[groupOffset].y, bitToSet); break;\n"
594e5c31af7Sopenharmony_ci			"    case 2u: atomicOr(superSecretComputeShaderHelper[groupOffset].z, bitToSet); break;\n"
595e5c31af7Sopenharmony_ci			"    case 3u: atomicOr(superSecretComputeShaderHelper[groupOffset].w, bitToSet); break;\n"
596e5c31af7Sopenharmony_ci			"    }\n"
597e5c31af7Sopenharmony_ci			"  }\n"
598e5c31af7Sopenharmony_ci			"  subgroupMemoryBarrierShared();\n"
599e5c31af7Sopenharmony_ci			"  return superSecretComputeShaderHelper[groupOffset];\n"
600e5c31af7Sopenharmony_ci			"}\n";
601e5c31af7Sopenharmony_ci}
602e5c31af7Sopenharmony_ci
603e5c31af7Sopenharmony_cideUint32 glc::subgroups::getSubgroupSize(Context& context)
604e5c31af7Sopenharmony_ci{
605e5c31af7Sopenharmony_ci	int subgroupSize = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SIZE_KHR);
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci	return subgroupSize;
608e5c31af7Sopenharmony_ci}
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_cideUint32 glc::subgroups::maxSupportedSubgroupSize() {
611e5c31af7Sopenharmony_ci	return 128u;
612e5c31af7Sopenharmony_ci}
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_cistd::string glc::subgroups::getShaderStageName(ShaderStageFlags stage)
615e5c31af7Sopenharmony_ci{
616e5c31af7Sopenharmony_ci	DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
617e5c31af7Sopenharmony_ci	switch (stage)
618e5c31af7Sopenharmony_ci	{
619e5c31af7Sopenharmony_ci		default:
620e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled stage!");
621e5c31af7Sopenharmony_ci			return "";
622e5c31af7Sopenharmony_ci		case SHADER_STAGE_COMPUTE_BIT:
623e5c31af7Sopenharmony_ci			return "compute";
624e5c31af7Sopenharmony_ci		case SHADER_STAGE_FRAGMENT_BIT:
625e5c31af7Sopenharmony_ci			return "fragment";
626e5c31af7Sopenharmony_ci		case SHADER_STAGE_VERTEX_BIT:
627e5c31af7Sopenharmony_ci			return "vertex";
628e5c31af7Sopenharmony_ci		case SHADER_STAGE_GEOMETRY_BIT:
629e5c31af7Sopenharmony_ci			return "geometry";
630e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_CONTROL_BIT:
631e5c31af7Sopenharmony_ci			return "tess_control";
632e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_EVALUATION_BIT:
633e5c31af7Sopenharmony_ci			return "tess_eval";
634e5c31af7Sopenharmony_ci	}
635e5c31af7Sopenharmony_ci}
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_cistd::string glc::subgroups::getSubgroupFeatureName(SubgroupFeatureFlags bit)
638e5c31af7Sopenharmony_ci{
639e5c31af7Sopenharmony_ci	DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
640e5c31af7Sopenharmony_ci	switch (bit)
641e5c31af7Sopenharmony_ci	{
642e5c31af7Sopenharmony_ci		default:
643e5c31af7Sopenharmony_ci			DE_FATAL("Unknown subgroup feature category!");
644e5c31af7Sopenharmony_ci			return "";
645e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_BASIC_BIT:
646e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_BASIC_BIT_KHR";
647e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_VOTE_BIT:
648e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_VOTE_BIT_KHR";
649e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_ARITHMETIC_BIT:
650e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR";
651e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_BALLOT_BIT:
652e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR";
653e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_SHUFFLE_BIT:
654e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR";
655e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
656e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR";
657e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_CLUSTERED_BIT:
658e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR";
659e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_QUAD_BIT:
660e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_QUAD_BIT_KHR";
661e5c31af7Sopenharmony_ci		case SUBGROUP_FEATURE_PARTITIONED_BIT_NV:
662e5c31af7Sopenharmony_ci			return "GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV";
663e5c31af7Sopenharmony_ci	}
664e5c31af7Sopenharmony_ci}
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_civoid glc::subgroups::addNoSubgroupShader (SourceCollections& programCollection)
667e5c31af7Sopenharmony_ci{
668e5c31af7Sopenharmony_ci	{
669e5c31af7Sopenharmony_ci		const std::string vertNoSubgroupGLSL =
670e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
671e5c31af7Sopenharmony_ci			"void main (void)\n"
672e5c31af7Sopenharmony_ci			"{\n"
673e5c31af7Sopenharmony_ci			"  float pixelSize = 2.0f/1024.0f;\n"
674e5c31af7Sopenharmony_ci			"   float pixelPosition = pixelSize/2.0f - 1.0f;\n"
675e5c31af7Sopenharmony_ci			"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
676e5c31af7Sopenharmony_ci			"  gl_PointSize = 1.0f;\n"
677e5c31af7Sopenharmony_ci			"}\n";
678e5c31af7Sopenharmony_ci		programCollection.add("vert_noSubgroup") << glu::VertexSource(vertNoSubgroupGLSL);
679e5c31af7Sopenharmony_ci	}
680e5c31af7Sopenharmony_ci
681e5c31af7Sopenharmony_ci	{
682e5c31af7Sopenharmony_ci		const std::string tescNoSubgroupGLSL =
683e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
684e5c31af7Sopenharmony_ci			"layout(vertices=1) out;\n"
685e5c31af7Sopenharmony_ci			"\n"
686e5c31af7Sopenharmony_ci			"void main (void)\n"
687e5c31af7Sopenharmony_ci			"{\n"
688e5c31af7Sopenharmony_ci			"  if (gl_InvocationID == 0)\n"
689e5c31af7Sopenharmony_ci			"  {\n"
690e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[0] = 1.0f;\n"
691e5c31af7Sopenharmony_ci			"    gl_TessLevelOuter[1] = 1.0f;\n"
692e5c31af7Sopenharmony_ci			"  }\n"
693e5c31af7Sopenharmony_ci			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
694e5c31af7Sopenharmony_ci			"}\n";
695e5c31af7Sopenharmony_ci		programCollection.add("tesc_noSubgroup") << glu::TessellationControlSource(tescNoSubgroupGLSL);
696e5c31af7Sopenharmony_ci	}
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci	{
699e5c31af7Sopenharmony_ci		const std::string teseNoSubgroupGLSL =
700e5c31af7Sopenharmony_ci			"${VERSION_DECL}\n"
701e5c31af7Sopenharmony_ci			"layout(isolines) in;\n"
702e5c31af7Sopenharmony_ci			"\n"
703e5c31af7Sopenharmony_ci			"void main (void)\n"
704e5c31af7Sopenharmony_ci			"{\n"
705e5c31af7Sopenharmony_ci			"  float pixelSize = 2.0f/1024.0f;\n"
706e5c31af7Sopenharmony_ci			"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
707e5c31af7Sopenharmony_ci			"}\n";
708e5c31af7Sopenharmony_ci		programCollection.add("tese_noSubgroup") << glu::TessellationEvaluationSource(teseNoSubgroupGLSL);
709e5c31af7Sopenharmony_ci	}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci}
712e5c31af7Sopenharmony_ci
713e5c31af7Sopenharmony_cistd::string glc::subgroups::getVertShaderForStage(const ShaderStageFlags stage)
714e5c31af7Sopenharmony_ci{
715e5c31af7Sopenharmony_ci	DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
716e5c31af7Sopenharmony_ci	switch (stage)
717e5c31af7Sopenharmony_ci	{
718e5c31af7Sopenharmony_ci		default:
719e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled stage!");
720e5c31af7Sopenharmony_ci			return "";
721e5c31af7Sopenharmony_ci		case SHADER_STAGE_FRAGMENT_BIT:
722e5c31af7Sopenharmony_ci			return
723e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
724e5c31af7Sopenharmony_ci				"void main (void)\n"
725e5c31af7Sopenharmony_ci				"{\n"
726e5c31af7Sopenharmony_ci				"  float pixelSize = 2.0f/1024.0f;\n"
727e5c31af7Sopenharmony_ci				"   float pixelPosition = pixelSize/2.0f - 1.0f;\n"
728e5c31af7Sopenharmony_ci				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
729e5c31af7Sopenharmony_ci				"}\n";
730e5c31af7Sopenharmony_ci		case SHADER_STAGE_GEOMETRY_BIT:
731e5c31af7Sopenharmony_ci			return
732e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
733e5c31af7Sopenharmony_ci				"void main (void)\n"
734e5c31af7Sopenharmony_ci				"{\n"
735e5c31af7Sopenharmony_ci				"}\n";
736e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_CONTROL_BIT:
737e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_EVALUATION_BIT:
738e5c31af7Sopenharmony_ci			return
739e5c31af7Sopenharmony_ci				"${VERSION_DECL}\n"
740e5c31af7Sopenharmony_ci				"void main (void)\n"
741e5c31af7Sopenharmony_ci				"{\n"
742e5c31af7Sopenharmony_ci				"}\n";
743e5c31af7Sopenharmony_ci	}
744e5c31af7Sopenharmony_ci}
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_cibool glc::subgroups::isSubgroupSupported(Context& context)
747e5c31af7Sopenharmony_ci{
748e5c31af7Sopenharmony_ci	return context.getDeqpContext().getContextInfo().isExtensionSupported("GL_KHR_shader_subgroup");
749e5c31af7Sopenharmony_ci}
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_cibool glc::subgroups::areSubgroupOperationsSupportedForStage(
752e5c31af7Sopenharmony_ci	Context& context, const ShaderStageFlags stage)
753e5c31af7Sopenharmony_ci{
754e5c31af7Sopenharmony_ci	DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
755e5c31af7Sopenharmony_ci	int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	return (stage & supportedStages) ? true : false;
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_cibool glc::subgroups::areSubgroupOperationsRequiredForStage(
761e5c31af7Sopenharmony_ci	const ShaderStageFlags stage)
762e5c31af7Sopenharmony_ci{
763e5c31af7Sopenharmony_ci	DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
764e5c31af7Sopenharmony_ci	switch (stage)
765e5c31af7Sopenharmony_ci	{
766e5c31af7Sopenharmony_ci		default:
767e5c31af7Sopenharmony_ci			return false;
768e5c31af7Sopenharmony_ci		case SHADER_STAGE_COMPUTE_BIT:
769e5c31af7Sopenharmony_ci			return true;
770e5c31af7Sopenharmony_ci	}
771e5c31af7Sopenharmony_ci}
772e5c31af7Sopenharmony_ci
773e5c31af7Sopenharmony_cibool glc::subgroups::isSubgroupFeatureSupportedForDevice(
774e5c31af7Sopenharmony_ci	Context& context,
775e5c31af7Sopenharmony_ci	const SubgroupFeatureFlags bit)
776e5c31af7Sopenharmony_ci{
777e5c31af7Sopenharmony_ci	DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
778e5c31af7Sopenharmony_ci
779e5c31af7Sopenharmony_ci	int supportedOperations = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_FEATURES_KHR);
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci	return (bit & supportedOperations) ? true : false;
782e5c31af7Sopenharmony_ci}
783e5c31af7Sopenharmony_ci
784e5c31af7Sopenharmony_cibool glc::subgroups::isFragmentSSBOSupportedForDevice(Context& context)
785e5c31af7Sopenharmony_ci{
786e5c31af7Sopenharmony_ci	int numFragmentSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
787e5c31af7Sopenharmony_ci
788e5c31af7Sopenharmony_ci	return (numFragmentSSBOs > 0) ? true : false;
789e5c31af7Sopenharmony_ci}
790e5c31af7Sopenharmony_ci
791e5c31af7Sopenharmony_cibool glc::subgroups::isVertexSSBOSupportedForDevice(Context& context)
792e5c31af7Sopenharmony_ci{
793e5c31af7Sopenharmony_ci	int numVertexSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci	return (numVertexSSBOs > 0) ? true : false;
796e5c31af7Sopenharmony_ci}
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_cibool glc::subgroups::isImageSupportedForStageOnDevice(Context& context, const ShaderStageFlags stage)
799e5c31af7Sopenharmony_ci{
800e5c31af7Sopenharmony_ci	glw::GLint stageQuery;
801e5c31af7Sopenharmony_ci	DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
802e5c31af7Sopenharmony_ci
803e5c31af7Sopenharmony_ci	// image uniforms are optional in VTG stages
804e5c31af7Sopenharmony_ci	switch (stage)
805e5c31af7Sopenharmony_ci	{
806e5c31af7Sopenharmony_ci		case SHADER_STAGE_FRAGMENT_BIT:
807e5c31af7Sopenharmony_ci		case SHADER_STAGE_COMPUTE_BIT:
808e5c31af7Sopenharmony_ci		default:
809e5c31af7Sopenharmony_ci			return true;
810e5c31af7Sopenharmony_ci		case SHADER_STAGE_VERTEX_BIT:
811e5c31af7Sopenharmony_ci			stageQuery = GL_MAX_VERTEX_IMAGE_UNIFORMS;
812e5c31af7Sopenharmony_ci			break;
813e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_CONTROL_BIT:
814e5c31af7Sopenharmony_ci			stageQuery = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
815e5c31af7Sopenharmony_ci			break;
816e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_EVALUATION_BIT:
817e5c31af7Sopenharmony_ci			stageQuery = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
818e5c31af7Sopenharmony_ci			break;
819e5c31af7Sopenharmony_ci		case SHADER_STAGE_GEOMETRY_BIT:
820e5c31af7Sopenharmony_ci			stageQuery = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
821e5c31af7Sopenharmony_ci			break;
822e5c31af7Sopenharmony_ci	}
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci	int numImages = context.getDeqpContext().getContextInfo().getInt(stageQuery);
825e5c31af7Sopenharmony_ci
826e5c31af7Sopenharmony_ci	return (numImages > 0) ? true : false;
827e5c31af7Sopenharmony_ci}
828e5c31af7Sopenharmony_ci
829e5c31af7Sopenharmony_cibool glc::subgroups::isDoubleSupportedForDevice(Context& context)
830e5c31af7Sopenharmony_ci{
831e5c31af7Sopenharmony_ci	glu::ContextType contextType = context.getDeqpContext().getRenderContext().getType();
832e5c31af7Sopenharmony_ci	return (glu::contextSupports(contextType, glu::ApiType::core(4, 0)) ||
833e5c31af7Sopenharmony_ci			context.getDeqpContext().getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"));
834e5c31af7Sopenharmony_ci}
835e5c31af7Sopenharmony_ci
836e5c31af7Sopenharmony_cibool glc::subgroups::isDoubleFormat(Format format)
837e5c31af7Sopenharmony_ci{
838e5c31af7Sopenharmony_ci	switch (format)
839e5c31af7Sopenharmony_ci	{
840e5c31af7Sopenharmony_ci		default:
841e5c31af7Sopenharmony_ci			return false;
842e5c31af7Sopenharmony_ci		case FORMAT_R64_SFLOAT:
843e5c31af7Sopenharmony_ci		case FORMAT_R64G64_SFLOAT:
844e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64_SFLOAT:
845e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64A64_SFLOAT:
846e5c31af7Sopenharmony_ci			return true;
847e5c31af7Sopenharmony_ci	}
848e5c31af7Sopenharmony_ci}
849e5c31af7Sopenharmony_ci
850e5c31af7Sopenharmony_cistd::string glc::subgroups::getFormatNameForGLSL (Format format)
851e5c31af7Sopenharmony_ci{
852e5c31af7Sopenharmony_ci	switch (format)
853e5c31af7Sopenharmony_ci	{
854e5c31af7Sopenharmony_ci		default:
855e5c31af7Sopenharmony_ci			DE_FATAL("Unhandled format!");
856e5c31af7Sopenharmony_ci			return "";
857e5c31af7Sopenharmony_ci		case FORMAT_R32_SINT:
858e5c31af7Sopenharmony_ci			return "int";
859e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SINT:
860e5c31af7Sopenharmony_ci			return "ivec2";
861e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SINT:
862e5c31af7Sopenharmony_ci			return "ivec3";
863e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SINT:
864e5c31af7Sopenharmony_ci			return "ivec4";
865e5c31af7Sopenharmony_ci		case FORMAT_R32_UINT:
866e5c31af7Sopenharmony_ci			return "uint";
867e5c31af7Sopenharmony_ci		case FORMAT_R32G32_UINT:
868e5c31af7Sopenharmony_ci			return "uvec2";
869e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_UINT:
870e5c31af7Sopenharmony_ci			return "uvec3";
871e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_UINT:
872e5c31af7Sopenharmony_ci			return "uvec4";
873e5c31af7Sopenharmony_ci		case FORMAT_R32_SFLOAT:
874e5c31af7Sopenharmony_ci			return "float";
875e5c31af7Sopenharmony_ci		case FORMAT_R32G32_SFLOAT:
876e5c31af7Sopenharmony_ci			return "vec2";
877e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_SFLOAT:
878e5c31af7Sopenharmony_ci			return "vec3";
879e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_SFLOAT:
880e5c31af7Sopenharmony_ci			return "vec4";
881e5c31af7Sopenharmony_ci		case FORMAT_R64_SFLOAT:
882e5c31af7Sopenharmony_ci			return "double";
883e5c31af7Sopenharmony_ci		case FORMAT_R64G64_SFLOAT:
884e5c31af7Sopenharmony_ci			return "dvec2";
885e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64_SFLOAT:
886e5c31af7Sopenharmony_ci			return "dvec3";
887e5c31af7Sopenharmony_ci		case FORMAT_R64G64B64A64_SFLOAT:
888e5c31af7Sopenharmony_ci			return "dvec4";
889e5c31af7Sopenharmony_ci		case FORMAT_R32_BOOL:
890e5c31af7Sopenharmony_ci			return "bool";
891e5c31af7Sopenharmony_ci		case FORMAT_R32G32_BOOL:
892e5c31af7Sopenharmony_ci			return "bvec2";
893e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32_BOOL:
894e5c31af7Sopenharmony_ci			return "bvec3";
895e5c31af7Sopenharmony_ci		case FORMAT_R32G32B32A32_BOOL:
896e5c31af7Sopenharmony_ci			return "bvec4";
897e5c31af7Sopenharmony_ci	}
898e5c31af7Sopenharmony_ci}
899e5c31af7Sopenharmony_ci
900e5c31af7Sopenharmony_civoid glc::subgroups::setVertexShaderFrameBuffer (SourceCollections& programCollection)
901e5c31af7Sopenharmony_ci{
902e5c31af7Sopenharmony_ci	programCollection.add("vert") << glu::VertexSource(
903e5c31af7Sopenharmony_ci		"${VERSION_DECL}\n"
904e5c31af7Sopenharmony_ci		"layout(location = 0) in highp vec4 in_position;\n"
905e5c31af7Sopenharmony_ci		"void main (void)\n"
906e5c31af7Sopenharmony_ci		"{\n"
907e5c31af7Sopenharmony_ci		"  gl_Position = in_position;\n"
908e5c31af7Sopenharmony_ci		"}\n");
909e5c31af7Sopenharmony_ci}
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_civoid glc::subgroups::setFragmentShaderFrameBuffer (SourceCollections& programCollection)
912e5c31af7Sopenharmony_ci{
913e5c31af7Sopenharmony_ci	programCollection.add("fragment") << glu::FragmentSource(
914e5c31af7Sopenharmony_ci		"${VERSION_DECL}\n"
915e5c31af7Sopenharmony_ci		"precision highp int;\n"
916e5c31af7Sopenharmony_ci		"layout(location = 0) in highp float in_color;\n"
917e5c31af7Sopenharmony_ci		"layout(location = 0) out uint out_color;\n"
918e5c31af7Sopenharmony_ci		"void main()\n"
919e5c31af7Sopenharmony_ci		"{\n"
920e5c31af7Sopenharmony_ci		"	out_color = uint(in_color);\n"
921e5c31af7Sopenharmony_ci		"}\n");
922e5c31af7Sopenharmony_ci}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_civoid glc::subgroups::setTesCtrlShaderFrameBuffer (SourceCollections& programCollection)
925e5c31af7Sopenharmony_ci{
926e5c31af7Sopenharmony_ci	programCollection.add("tesc") << glu::TessellationControlSource(
927e5c31af7Sopenharmony_ci		"${VERSION_DECL}\n"
928e5c31af7Sopenharmony_ci		"#extension GL_KHR_shader_subgroup_basic: enable\n"
929e5c31af7Sopenharmony_ci		"${TESS_EXTENSION}\n"
930e5c31af7Sopenharmony_ci		"layout(vertices = 2) out;\n"
931e5c31af7Sopenharmony_ci		"void main (void)\n"
932e5c31af7Sopenharmony_ci		"{\n"
933e5c31af7Sopenharmony_ci		"  if (gl_InvocationID == 0)\n"
934e5c31af7Sopenharmony_ci		"  {\n"
935e5c31af7Sopenharmony_ci		"    gl_TessLevelOuter[0] = 1.0f;\n"
936e5c31af7Sopenharmony_ci		"    gl_TessLevelOuter[1] = 1.0f;\n"
937e5c31af7Sopenharmony_ci		"  }\n"
938e5c31af7Sopenharmony_ci		"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
939e5c31af7Sopenharmony_ci		"}\n");
940e5c31af7Sopenharmony_ci}
941e5c31af7Sopenharmony_ci
942e5c31af7Sopenharmony_civoid glc::subgroups::setTesEvalShaderFrameBuffer (SourceCollections& programCollection)
943e5c31af7Sopenharmony_ci{
944e5c31af7Sopenharmony_ci	programCollection.add("tese") << glu::TessellationEvaluationSource(
945e5c31af7Sopenharmony_ci		"${VERSION_DECL}\n"
946e5c31af7Sopenharmony_ci		"#extension GL_KHR_shader_subgroup_ballot: enable\n"
947e5c31af7Sopenharmony_ci		"${TESS_EXTENSION}\n"
948e5c31af7Sopenharmony_ci		"layout(isolines, equal_spacing, ccw ) in;\n"
949e5c31af7Sopenharmony_ci		"layout(location = 0) in float in_color[];\n"
950e5c31af7Sopenharmony_ci		"layout(location = 0) out float out_color;\n"
951e5c31af7Sopenharmony_ci		"\n"
952e5c31af7Sopenharmony_ci		"void main (void)\n"
953e5c31af7Sopenharmony_ci		"{\n"
954e5c31af7Sopenharmony_ci		"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
955e5c31af7Sopenharmony_ci		"  out_color = in_color[0];\n"
956e5c31af7Sopenharmony_ci		"}\n");
957e5c31af7Sopenharmony_ci}
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_civoid glc::subgroups::addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection)
960e5c31af7Sopenharmony_ci{
961e5c31af7Sopenharmony_ci	tcu::StringTemplate geometryTemplate(glslTemplate);
962e5c31af7Sopenharmony_ci
963e5c31af7Sopenharmony_ci	map<string, string>		linesParams;
964e5c31af7Sopenharmony_ci	linesParams.insert(pair<string, string>("TOPOLOGY", "lines"));
965e5c31af7Sopenharmony_ci
966e5c31af7Sopenharmony_ci	map<string, string>		pointsParams;
967e5c31af7Sopenharmony_ci	pointsParams.insert(pair<string, string>("TOPOLOGY", "points"));
968e5c31af7Sopenharmony_ci
969e5c31af7Sopenharmony_ci	collection.add("geometry_lines")	<< glu::GeometrySource("${VERSION_DECL}\n" + geometryTemplate.specialize(linesParams));
970e5c31af7Sopenharmony_ci	collection.add("geometry_points")	<< glu::GeometrySource("${VERSION_DECL}\n" + geometryTemplate.specialize(pointsParams));
971e5c31af7Sopenharmony_ci}
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_civoid initializeMemory(deqp::Context& context, glw::GLvoid *hostPtr, subgroups::SSBOData& data)
974e5c31af7Sopenharmony_ci{
975e5c31af7Sopenharmony_ci	using namespace subgroups;
976e5c31af7Sopenharmony_ci	const Format format = data.format;
977e5c31af7Sopenharmony_ci	const deUint64 size = data.numElements *
978e5c31af7Sopenharmony_ci		(data.isImage ? getFormatSizeInBytes(format) : getElementSizeInBytes(format, data.layout));
979e5c31af7Sopenharmony_ci	if (subgroups::SSBOData::InitializeNonZero == data.initializeType)
980e5c31af7Sopenharmony_ci	{
981e5c31af7Sopenharmony_ci		de::Random rnd(context.getTestContext().getCommandLine().getBaseSeed());
982e5c31af7Sopenharmony_ci		switch (format)
983e5c31af7Sopenharmony_ci		{
984e5c31af7Sopenharmony_ci			default:
985e5c31af7Sopenharmony_ci				DE_FATAL("Illegal buffer format");
986e5c31af7Sopenharmony_ci				break;
987e5c31af7Sopenharmony_ci			case FORMAT_R32_BOOL:
988e5c31af7Sopenharmony_ci			case FORMAT_R32G32_BOOL:
989e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32_BOOL:
990e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32A32_BOOL:
991e5c31af7Sopenharmony_ci			{
992e5c31af7Sopenharmony_ci				deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ci				for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
995e5c31af7Sopenharmony_ci				{
996e5c31af7Sopenharmony_ci					deUint32 r = rnd.getUint32();
997e5c31af7Sopenharmony_ci					ptr[k] = (r & 1) ? r : 0;
998e5c31af7Sopenharmony_ci				}
999e5c31af7Sopenharmony_ci			}
1000e5c31af7Sopenharmony_ci			break;
1001e5c31af7Sopenharmony_ci			case FORMAT_R32_SINT:
1002e5c31af7Sopenharmony_ci			case FORMAT_R32G32_SINT:
1003e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32_SINT:
1004e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32A32_SINT:
1005e5c31af7Sopenharmony_ci			case FORMAT_R32_UINT:
1006e5c31af7Sopenharmony_ci			case FORMAT_R32G32_UINT:
1007e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32_UINT:
1008e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32A32_UINT:
1009e5c31af7Sopenharmony_ci			{
1010e5c31af7Sopenharmony_ci				deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
1011e5c31af7Sopenharmony_ci
1012e5c31af7Sopenharmony_ci				for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
1013e5c31af7Sopenharmony_ci				{
1014e5c31af7Sopenharmony_ci					ptr[k] = rnd.getUint32();
1015e5c31af7Sopenharmony_ci				}
1016e5c31af7Sopenharmony_ci			}
1017e5c31af7Sopenharmony_ci			break;
1018e5c31af7Sopenharmony_ci			case FORMAT_R32_SFLOAT:
1019e5c31af7Sopenharmony_ci			case FORMAT_R32G32_SFLOAT:
1020e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32_SFLOAT:
1021e5c31af7Sopenharmony_ci			case FORMAT_R32G32B32A32_SFLOAT:
1022e5c31af7Sopenharmony_ci			{
1023e5c31af7Sopenharmony_ci				float* ptr = reinterpret_cast<float*>(hostPtr);
1024e5c31af7Sopenharmony_ci
1025e5c31af7Sopenharmony_ci				for (deUint64 k = 0; k < (size / sizeof(float)); k++)
1026e5c31af7Sopenharmony_ci				{
1027e5c31af7Sopenharmony_ci					ptr[k] = rnd.getFloat();
1028e5c31af7Sopenharmony_ci				}
1029e5c31af7Sopenharmony_ci			}
1030e5c31af7Sopenharmony_ci			break;
1031e5c31af7Sopenharmony_ci			case FORMAT_R64_SFLOAT:
1032e5c31af7Sopenharmony_ci			case FORMAT_R64G64_SFLOAT:
1033e5c31af7Sopenharmony_ci			case FORMAT_R64G64B64_SFLOAT:
1034e5c31af7Sopenharmony_ci			case FORMAT_R64G64B64A64_SFLOAT:
1035e5c31af7Sopenharmony_ci			{
1036e5c31af7Sopenharmony_ci				double* ptr = reinterpret_cast<double*>(hostPtr);
1037e5c31af7Sopenharmony_ci
1038e5c31af7Sopenharmony_ci				for (deUint64 k = 0; k < (size / sizeof(double)); k++)
1039e5c31af7Sopenharmony_ci				{
1040e5c31af7Sopenharmony_ci					ptr[k] = rnd.getDouble();
1041e5c31af7Sopenharmony_ci				}
1042e5c31af7Sopenharmony_ci			}
1043e5c31af7Sopenharmony_ci			break;
1044e5c31af7Sopenharmony_ci		}
1045e5c31af7Sopenharmony_ci	}
1046e5c31af7Sopenharmony_ci	else if (subgroups::SSBOData::InitializeZero == data.initializeType)
1047e5c31af7Sopenharmony_ci	{
1048e5c31af7Sopenharmony_ci		deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
1049e5c31af7Sopenharmony_ci
1050e5c31af7Sopenharmony_ci		for (deUint64 k = 0; k < size / 4; k++)
1051e5c31af7Sopenharmony_ci		{
1052e5c31af7Sopenharmony_ci			ptr[k] = 0;
1053e5c31af7Sopenharmony_ci		}
1054e5c31af7Sopenharmony_ci	}
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ci	if (subgroups::SSBOData::InitializeNone != data.initializeType)
1057e5c31af7Sopenharmony_ci	{
1058e5c31af7Sopenharmony_ci		// nothing to do for GL
1059e5c31af7Sopenharmony_ci	}
1060e5c31af7Sopenharmony_ci}
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_cideUint32 getResultBinding (const glc::subgroups::ShaderStageFlags shaderStage)
1063e5c31af7Sopenharmony_ci{
1064e5c31af7Sopenharmony_ci	using namespace glc::subgroups;
1065e5c31af7Sopenharmony_ci	switch(shaderStage)
1066e5c31af7Sopenharmony_ci	{
1067e5c31af7Sopenharmony_ci		case SHADER_STAGE_VERTEX_BIT:
1068e5c31af7Sopenharmony_ci			return 0u;
1069e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_CONTROL_BIT:
1070e5c31af7Sopenharmony_ci			return 1u;
1071e5c31af7Sopenharmony_ci		case SHADER_STAGE_TESS_EVALUATION_BIT:
1072e5c31af7Sopenharmony_ci			return 2u;
1073e5c31af7Sopenharmony_ci		case SHADER_STAGE_GEOMETRY_BIT:
1074e5c31af7Sopenharmony_ci			return 3u;
1075e5c31af7Sopenharmony_ci		default:
1076e5c31af7Sopenharmony_ci			DE_ASSERT(0);
1077e5c31af7Sopenharmony_ci			return -1;
1078e5c31af7Sopenharmony_ci	}
1079e5c31af7Sopenharmony_ci	DE_ASSERT(0);
1080e5c31af7Sopenharmony_ci	return -1;
1081e5c31af7Sopenharmony_ci}
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::makeTessellationEvaluationFrameBufferTest(
1084e5c31af7Sopenharmony_ci	Context& context, Format format, SSBOData* extraData,
1085e5c31af7Sopenharmony_ci	deUint32 extraDataCount,
1086e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1087e5c31af7Sopenharmony_ci	const ShaderStageFlags shaderStage)
1088e5c31af7Sopenharmony_ci{
1089e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context.getDeqpContext().getTestContext().getLog();
1090e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_ci	const deUint32							maxWidth				= getMaxWidth();
1093e5c31af7Sopenharmony_ci	vector<de::SharedPtr<BufferOrImage> >	inputBuffers			(extraDataCount);
1094e5c31af7Sopenharmony_ci
1095e5c31af7Sopenharmony_ci	const GlslSource& vshader = context.getSourceCollection().get("vert");
1096e5c31af7Sopenharmony_ci	const GlslSource& tcshader = context.getSourceCollection().get("tesc");
1097e5c31af7Sopenharmony_ci	const GlslSource& teshader = context.getSourceCollection().get("tese");
1098e5c31af7Sopenharmony_ci	const GlslSource& fshader = context.getSourceCollection().get("fragment");
1099e5c31af7Sopenharmony_ci
1100e5c31af7Sopenharmony_ci	for (deUint32 i = 0u; i < extraDataCount; i++)
1101e5c31af7Sopenharmony_ci	{
1102e5c31af7Sopenharmony_ci		if (extraData[i].isImage)
1103e5c31af7Sopenharmony_ci		{
1104e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1105e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
1106e5c31af7Sopenharmony_ci			DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1107e5c31af7Sopenharmony_ci		}
1108e5c31af7Sopenharmony_ci		else
1109e5c31af7Sopenharmony_ci		{
1110e5c31af7Sopenharmony_ci			deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1111e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1112e5c31af7Sopenharmony_ci
1113e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1114e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1115e5c31af7Sopenharmony_ci			inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1116e5c31af7Sopenharmony_ci		}
1117e5c31af7Sopenharmony_ci	}
1118e5c31af7Sopenharmony_ci
1119e5c31af7Sopenharmony_ci	for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1120e5c31af7Sopenharmony_ci	{
1121e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1122e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1123e5c31af7Sopenharmony_ci			<< "stage = " << shaderStage << " , binding = " << extraData[ndx].binding << "\n"
1124e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1125e5c31af7Sopenharmony_ci
1126e5c31af7Sopenharmony_ci		if (inputBuffers[ndx]->isImage())
1127e5c31af7Sopenharmony_ci		{
1128e5c31af7Sopenharmony_ci			gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1129e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1130e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1131e5c31af7Sopenharmony_ci		} else
1132e5c31af7Sopenharmony_ci		{
1133e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1134e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1135e5c31af7Sopenharmony_ci		}
1136e5c31af7Sopenharmony_ci	}
1137e5c31af7Sopenharmony_ci
1138e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> pipeline(
1139e5c31af7Sopenharmony_ci			makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT),
1140e5c31af7Sopenharmony_ci								 &vshader, &fshader, DE_NULL, &tcshader, &teshader));
1141e5c31af7Sopenharmony_ci	if (!pipeline->isOk())
1142e5c31af7Sopenharmony_ci	{
1143e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("tese graphics program build failed");
1144e5c31af7Sopenharmony_ci	}
1145e5c31af7Sopenharmony_ci
1146e5c31af7Sopenharmony_ci	const deUint32							subgroupSize			= getSubgroupSize(context);
1147e5c31af7Sopenharmony_ci	const deUint64							vertexBufferSize		= 2ull * maxWidth * sizeof(tcu::Vec4);
1148e5c31af7Sopenharmony_ci	Buffer									vertexBuffer			(context, vertexBufferSize, GL_ARRAY_BUFFER);
1149e5c31af7Sopenharmony_ci	unsigned								totalIterations			= 0u;
1150e5c31af7Sopenharmony_ci	unsigned								failedIterations		= 0u;
1151e5c31af7Sopenharmony_ci	Image									discardableImage		(context, maxWidth, 1u, format);
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_ci	{
1154e5c31af7Sopenharmony_ci		glw::GLvoid *			bufferPtr			= vertexBuffer.mapBufferPtr();
1155e5c31af7Sopenharmony_ci		std::vector<tcu::Vec4>	data				(2u * maxWidth, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
1156e5c31af7Sopenharmony_ci		const float				pixelSize			= 2.0f / static_cast<float>(maxWidth);
1157e5c31af7Sopenharmony_ci		float					leftHandPosition	= -1.0f;
1158e5c31af7Sopenharmony_ci
1159e5c31af7Sopenharmony_ci		for(deUint32 ndx = 0u; ndx < data.size(); ndx+=2u)
1160e5c31af7Sopenharmony_ci		{
1161e5c31af7Sopenharmony_ci			data[ndx][0] = leftHandPosition;
1162e5c31af7Sopenharmony_ci			leftHandPosition += pixelSize;
1163e5c31af7Sopenharmony_ci			data[ndx+1][0] = leftHandPosition;
1164e5c31af7Sopenharmony_ci		}
1165e5c31af7Sopenharmony_ci
1166e5c31af7Sopenharmony_ci		deMemcpy(bufferPtr, &data[0], data.size() * sizeof(tcu::Vec4));
1167e5c31af7Sopenharmony_ci		vertexBuffer.unmapBufferPtr();
1168e5c31af7Sopenharmony_ci	}
1169e5c31af7Sopenharmony_ci
1170e5c31af7Sopenharmony_ci	Vao vao(context);
1171e5c31af7Sopenharmony_ci	Fbo fbo(context);
1172e5c31af7Sopenharmony_ci	fbo.bind2D(discardableImage);
1173e5c31af7Sopenharmony_ci
1174e5c31af7Sopenharmony_ci	gl.viewport(0, 0, maxWidth, 1u);
1175e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1176e5c31af7Sopenharmony_ci
1177e5c31af7Sopenharmony_ci	const deUint64				imageResultSize		= getFormatSizeInBytes(format) * maxWidth;
1178e5c31af7Sopenharmony_ci	vector<glw::GLubyte>		imageBufferResult(imageResultSize);
1179e5c31af7Sopenharmony_ci	const deUint64				vertexBufferOffset	= 0u;
1180e5c31af7Sopenharmony_ci
1181e5c31af7Sopenharmony_ci	for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1182e5c31af7Sopenharmony_ci	{
1183e5c31af7Sopenharmony_ci		totalIterations++;
1184e5c31af7Sopenharmony_ci
1185e5c31af7Sopenharmony_ci		{
1186e5c31af7Sopenharmony_ci			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1187e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1188e5c31af7Sopenharmony_ci			gl.clear(GL_COLOR_BUFFER_BIT);
1189e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1190e5c31af7Sopenharmony_ci
1191e5c31af7Sopenharmony_ci			gl.useProgram(pipeline->getProgram());
1192e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1193e5c31af7Sopenharmony_ci
1194e5c31af7Sopenharmony_ci			gl.enableVertexAttribArray(0);
1195e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1196e5c31af7Sopenharmony_ci
1197e5c31af7Sopenharmony_ci			gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1198e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1199e5c31af7Sopenharmony_ci
1200e5c31af7Sopenharmony_ci			gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1201e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1202e5c31af7Sopenharmony_ci
1203e5c31af7Sopenharmony_ci			gl.patchParameteri(GL_PATCH_VERTICES, 2u);
1204e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1205e5c31af7Sopenharmony_ci
1206e5c31af7Sopenharmony_ci			gl.drawArrays(GL_PATCHES, 0, 2 * width);
1207e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1208e5c31af7Sopenharmony_ci
1209e5c31af7Sopenharmony_ci			gl.disableVertexAttribArray(0);
1210e5c31af7Sopenharmony_ci
1211e5c31af7Sopenharmony_ci			GLenum readFormat;
1212e5c31af7Sopenharmony_ci			GLenum readType;
1213e5c31af7Sopenharmony_ci			getFormatReadInfo(format, readFormat, readType);
1214e5c31af7Sopenharmony_ci
1215e5c31af7Sopenharmony_ci			gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1216e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1217e5c31af7Sopenharmony_ci		}
1218e5c31af7Sopenharmony_ci
1219e5c31af7Sopenharmony_ci		{
1220e5c31af7Sopenharmony_ci			std::vector<const void*> datas;
1221e5c31af7Sopenharmony_ci			datas.push_back(&imageBufferResult[0]);
1222e5c31af7Sopenharmony_ci			if (!checkResult(datas, width/2u, subgroupSize))
1223e5c31af7Sopenharmony_ci				failedIterations++;
1224e5c31af7Sopenharmony_ci		}
1225e5c31af7Sopenharmony_ci	}
1226e5c31af7Sopenharmony_ci
1227e5c31af7Sopenharmony_ci	if (0 < failedIterations)
1228e5c31af7Sopenharmony_ci	{
1229e5c31af7Sopenharmony_ci		log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1230e5c31af7Sopenharmony_ci				<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
1231e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed!");
1232e5c31af7Sopenharmony_ci	} else
1233e5c31af7Sopenharmony_ci	{
1234e5c31af7Sopenharmony_ci		log	<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1235e5c31af7Sopenharmony_ci				<<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1236e5c31af7Sopenharmony_ci	}
1237e5c31af7Sopenharmony_ci
1238e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
1239e5c31af7Sopenharmony_ci}
1240e5c31af7Sopenharmony_ci
1241e5c31af7Sopenharmony_cibool glc::subgroups::check(std::vector<const void*> datas,
1242e5c31af7Sopenharmony_ci	deUint32 width, deUint32 ref)
1243e5c31af7Sopenharmony_ci{
1244e5c31af7Sopenharmony_ci	const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
1245e5c31af7Sopenharmony_ci
1246e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < width; ++n)
1247e5c31af7Sopenharmony_ci	{
1248e5c31af7Sopenharmony_ci		if (data[n] != ref)
1249e5c31af7Sopenharmony_ci		{
1250e5c31af7Sopenharmony_ci			return false;
1251e5c31af7Sopenharmony_ci		}
1252e5c31af7Sopenharmony_ci	}
1253e5c31af7Sopenharmony_ci
1254e5c31af7Sopenharmony_ci	return true;
1255e5c31af7Sopenharmony_ci}
1256e5c31af7Sopenharmony_ci
1257e5c31af7Sopenharmony_cibool glc::subgroups::checkCompute(std::vector<const void*> datas,
1258e5c31af7Sopenharmony_ci	const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1259e5c31af7Sopenharmony_ci	deUint32 ref)
1260e5c31af7Sopenharmony_ci{
1261e5c31af7Sopenharmony_ci	const deUint32 globalSizeX = numWorkgroups[0] * localSize[0];
1262e5c31af7Sopenharmony_ci	const deUint32 globalSizeY = numWorkgroups[1] * localSize[1];
1263e5c31af7Sopenharmony_ci	const deUint32 globalSizeZ = numWorkgroups[2] * localSize[2];
1264e5c31af7Sopenharmony_ci
1265e5c31af7Sopenharmony_ci	return check(datas, globalSizeX * globalSizeY * globalSizeZ, ref);
1266e5c31af7Sopenharmony_ci}
1267e5c31af7Sopenharmony_ci
1268e5c31af7Sopenharmony_ci
1269e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::makeGeometryFrameBufferTest(
1270e5c31af7Sopenharmony_ci	Context& context, Format format, SSBOData* extraData,
1271e5c31af7Sopenharmony_ci	deUint32 extraDataCount,
1272e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1273e5c31af7Sopenharmony_ci{
1274e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context.getDeqpContext().getTestContext().getLog();
1275e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1276e5c31af7Sopenharmony_ci
1277e5c31af7Sopenharmony_ci	const deUint32							maxWidth				= getMaxWidth();
1278e5c31af7Sopenharmony_ci	vector<de::SharedPtr<BufferOrImage> >	inputBuffers			(extraDataCount);
1279e5c31af7Sopenharmony_ci
1280e5c31af7Sopenharmony_ci	const GlslSource& vshader = context.getSourceCollection().get("vert");
1281e5c31af7Sopenharmony_ci	const GlslSource& gshader = context.getSourceCollection().get("geometry");
1282e5c31af7Sopenharmony_ci	const GlslSource& fshader = context.getSourceCollection().get("fragment");
1283e5c31af7Sopenharmony_ci
1284e5c31af7Sopenharmony_ci	for (deUint32 i = 0u; i < extraDataCount; i++)
1285e5c31af7Sopenharmony_ci	{
1286e5c31af7Sopenharmony_ci		if (extraData[i].isImage)
1287e5c31af7Sopenharmony_ci		{
1288e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1289e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
1290e5c31af7Sopenharmony_ci			DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1291e5c31af7Sopenharmony_ci		}
1292e5c31af7Sopenharmony_ci		else
1293e5c31af7Sopenharmony_ci		{
1294e5c31af7Sopenharmony_ci			deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1295e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1296e5c31af7Sopenharmony_ci
1297e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1298e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1299e5c31af7Sopenharmony_ci			inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1300e5c31af7Sopenharmony_ci		}
1301e5c31af7Sopenharmony_ci	}
1302e5c31af7Sopenharmony_ci
1303e5c31af7Sopenharmony_ci	for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1304e5c31af7Sopenharmony_ci	{
1305e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1306e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1307e5c31af7Sopenharmony_ci			<< "GEOMETRY, binding = " << extraData[ndx].binding << "\n"
1308e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1309e5c31af7Sopenharmony_ci
1310e5c31af7Sopenharmony_ci		if (inputBuffers[ndx]->isImage())
1311e5c31af7Sopenharmony_ci		{
1312e5c31af7Sopenharmony_ci			gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1313e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1314e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1315e5c31af7Sopenharmony_ci		} else
1316e5c31af7Sopenharmony_ci		{
1317e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1318e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1319e5c31af7Sopenharmony_ci		}
1320e5c31af7Sopenharmony_ci	}
1321e5c31af7Sopenharmony_ci
1322e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> pipeline(
1323e5c31af7Sopenharmony_ci			makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT),
1324e5c31af7Sopenharmony_ci								 &vshader, &fshader, &gshader, DE_NULL, DE_NULL));
1325e5c31af7Sopenharmony_ci	if (!pipeline->isOk())
1326e5c31af7Sopenharmony_ci	{
1327e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("geom graphics program build failed");
1328e5c31af7Sopenharmony_ci	}
1329e5c31af7Sopenharmony_ci
1330e5c31af7Sopenharmony_ci	const deUint32							subgroupSize			= getSubgroupSize(context);
1331e5c31af7Sopenharmony_ci	const deUint64							vertexBufferSize		= maxWidth * sizeof(tcu::Vec4);
1332e5c31af7Sopenharmony_ci	Buffer									vertexBuffer			(context, vertexBufferSize, GL_ARRAY_BUFFER);
1333e5c31af7Sopenharmony_ci	unsigned								totalIterations			= 0u;
1334e5c31af7Sopenharmony_ci	unsigned								failedIterations		= 0u;
1335e5c31af7Sopenharmony_ci	Image									discardableImage		(context, maxWidth, 1u, format);
1336e5c31af7Sopenharmony_ci
1337e5c31af7Sopenharmony_ci	{
1338e5c31af7Sopenharmony_ci		glw::GLvoid *			bufferPtr			= vertexBuffer.mapBufferPtr();
1339e5c31af7Sopenharmony_ci		std::vector<tcu::Vec4>	data				(maxWidth, tcu::Vec4(1.0f, 0.5f, 1.0f, 1.0f));
1340e5c31af7Sopenharmony_ci		const float				pixelSize			= 2.0f / static_cast<float>(maxWidth);
1341e5c31af7Sopenharmony_ci		float					leftHandPosition	= -1.0f;
1342e5c31af7Sopenharmony_ci
1343e5c31af7Sopenharmony_ci		for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1344e5c31af7Sopenharmony_ci		{
1345e5c31af7Sopenharmony_ci			data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1346e5c31af7Sopenharmony_ci			leftHandPosition += pixelSize;
1347e5c31af7Sopenharmony_ci		}
1348e5c31af7Sopenharmony_ci
1349e5c31af7Sopenharmony_ci		deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1350e5c31af7Sopenharmony_ci		vertexBuffer.unmapBufferPtr();
1351e5c31af7Sopenharmony_ci	}
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_ci	Vao vao(context);
1354e5c31af7Sopenharmony_ci	Fbo fbo(context);
1355e5c31af7Sopenharmony_ci	fbo.bind2D(discardableImage);
1356e5c31af7Sopenharmony_ci
1357e5c31af7Sopenharmony_ci	gl.viewport(0, 0, maxWidth, 1u);
1358e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1359e5c31af7Sopenharmony_ci
1360e5c31af7Sopenharmony_ci	const deUint64				imageResultSize		= getFormatSizeInBytes(format) * maxWidth;
1361e5c31af7Sopenharmony_ci	vector<glw::GLubyte>		imageBufferResult(imageResultSize);
1362e5c31af7Sopenharmony_ci	const deUint64				vertexBufferOffset	= 0u;
1363e5c31af7Sopenharmony_ci
1364e5c31af7Sopenharmony_ci	for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1365e5c31af7Sopenharmony_ci	{
1366e5c31af7Sopenharmony_ci		totalIterations++;
1367e5c31af7Sopenharmony_ci
1368e5c31af7Sopenharmony_ci		for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1369e5c31af7Sopenharmony_ci		{
1370e5c31af7Sopenharmony_ci			if (inputBuffers[ndx]->isImage())
1371e5c31af7Sopenharmony_ci			{
1372e5c31af7Sopenharmony_ci				DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1373e5c31af7Sopenharmony_ci			} else
1374e5c31af7Sopenharmony_ci			{
1375e5c31af7Sopenharmony_ci				glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1376e5c31af7Sopenharmony_ci				initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1377e5c31af7Sopenharmony_ci				inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1378e5c31af7Sopenharmony_ci			}
1379e5c31af7Sopenharmony_ci		}
1380e5c31af7Sopenharmony_ci
1381e5c31af7Sopenharmony_ci		{
1382e5c31af7Sopenharmony_ci			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1383e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1384e5c31af7Sopenharmony_ci			gl.clear(GL_COLOR_BUFFER_BIT);
1385e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1386e5c31af7Sopenharmony_ci
1387e5c31af7Sopenharmony_ci			gl.useProgram(pipeline->getProgram());
1388e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1389e5c31af7Sopenharmony_ci
1390e5c31af7Sopenharmony_ci			gl.enableVertexAttribArray(0);
1391e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1392e5c31af7Sopenharmony_ci
1393e5c31af7Sopenharmony_ci			gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1394e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1395e5c31af7Sopenharmony_ci
1396e5c31af7Sopenharmony_ci			gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1397e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1398e5c31af7Sopenharmony_ci
1399e5c31af7Sopenharmony_ci			gl.drawArrays(GL_POINTS, 0, width);
1400e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1401e5c31af7Sopenharmony_ci
1402e5c31af7Sopenharmony_ci			gl.disableVertexAttribArray(0);
1403e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1404e5c31af7Sopenharmony_ci
1405e5c31af7Sopenharmony_ci			GLenum readFormat;
1406e5c31af7Sopenharmony_ci			GLenum readType;
1407e5c31af7Sopenharmony_ci			getFormatReadInfo(format, readFormat, readType);
1408e5c31af7Sopenharmony_ci
1409e5c31af7Sopenharmony_ci			gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1410e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1411e5c31af7Sopenharmony_ci		}
1412e5c31af7Sopenharmony_ci
1413e5c31af7Sopenharmony_ci		{
1414e5c31af7Sopenharmony_ci			std::vector<const void*> datas;
1415e5c31af7Sopenharmony_ci			datas.push_back(&imageBufferResult[0]);
1416e5c31af7Sopenharmony_ci			if (!checkResult(datas, width, subgroupSize))
1417e5c31af7Sopenharmony_ci				failedIterations++;
1418e5c31af7Sopenharmony_ci		}
1419e5c31af7Sopenharmony_ci	}
1420e5c31af7Sopenharmony_ci
1421e5c31af7Sopenharmony_ci	if (0 < failedIterations)
1422e5c31af7Sopenharmony_ci	{
1423e5c31af7Sopenharmony_ci		log	<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1424e5c31af7Sopenharmony_ci				<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
1425e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed!");
1426e5c31af7Sopenharmony_ci	} else
1427e5c31af7Sopenharmony_ci	{
1428e5c31af7Sopenharmony_ci		log	<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1429e5c31af7Sopenharmony_ci				<<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1430e5c31af7Sopenharmony_ci	}
1431e5c31af7Sopenharmony_ci
1432e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
1433e5c31af7Sopenharmony_ci}
1434e5c31af7Sopenharmony_ci
1435e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::allStages(
1436e5c31af7Sopenharmony_ci	Context& context, Format format, SSBOData* extraDatas,
1437e5c31af7Sopenharmony_ci	deUint32 extraDatasCount,
1438e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1439e5c31af7Sopenharmony_ci	const ShaderStageFlags shaderStageTested)
1440e5c31af7Sopenharmony_ci{
1441e5c31af7Sopenharmony_ci	const deUint32					maxWidth			= getMaxWidth();
1442e5c31af7Sopenharmony_ci	vector<ShaderStageFlags>		stagesVector;
1443e5c31af7Sopenharmony_ci	ShaderStageFlags				shaderStageRequired	= (ShaderStageFlags)0ull;
1444e5c31af7Sopenharmony_ci	tcu::TestLog&					log					= context.getDeqpContext().getTestContext().getLog();
1445e5c31af7Sopenharmony_ci	const glw::Functions&			gl					= context.getDeqpContext().getRenderContext().getFunctions();
1446e5c31af7Sopenharmony_ci
1447e5c31af7Sopenharmony_ci	if (shaderStageTested & SHADER_STAGE_VERTEX_BIT)
1448e5c31af7Sopenharmony_ci	{
1449e5c31af7Sopenharmony_ci		stagesVector.push_back(SHADER_STAGE_VERTEX_BIT);
1450e5c31af7Sopenharmony_ci	}
1451e5c31af7Sopenharmony_ci	if (shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT)
1452e5c31af7Sopenharmony_ci	{
1453e5c31af7Sopenharmony_ci		stagesVector.push_back(SHADER_STAGE_TESS_CONTROL_BIT);
1454e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_EVALUATION_BIT));
1455e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1456e5c31af7Sopenharmony_ci	}
1457e5c31af7Sopenharmony_ci	if (shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT)
1458e5c31af7Sopenharmony_ci	{
1459e5c31af7Sopenharmony_ci		stagesVector.push_back(SHADER_STAGE_TESS_EVALUATION_BIT);
1460e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1461e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_CONTROL_BIT));
1462e5c31af7Sopenharmony_ci	}
1463e5c31af7Sopenharmony_ci	if (shaderStageTested & SHADER_STAGE_GEOMETRY_BIT)
1464e5c31af7Sopenharmony_ci	{
1465e5c31af7Sopenharmony_ci		stagesVector.push_back(SHADER_STAGE_GEOMETRY_BIT);
1466e5c31af7Sopenharmony_ci		const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1467e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1468e5c31af7Sopenharmony_ci	}
1469e5c31af7Sopenharmony_ci	if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1470e5c31af7Sopenharmony_ci	{
1471e5c31af7Sopenharmony_ci		const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1472e5c31af7Sopenharmony_ci		shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1473e5c31af7Sopenharmony_ci	}
1474e5c31af7Sopenharmony_ci
1475e5c31af7Sopenharmony_ci	const deUint32	stagesCount	= static_cast<deUint32>(stagesVector.size());
1476e5c31af7Sopenharmony_ci	const string	vert		= (shaderStageRequired & SHADER_STAGE_VERTEX_BIT)			? "vert_noSubgroup"		: "vert";
1477e5c31af7Sopenharmony_ci	const string	tesc		= (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)		? "tesc_noSubgroup"		: "tesc";
1478e5c31af7Sopenharmony_ci	const string	tese		= (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)	? "tese_noSubgroup"		: "tese";
1479e5c31af7Sopenharmony_ci
1480e5c31af7Sopenharmony_ci	shaderStageRequired = (ShaderStageFlags)(shaderStageTested | shaderStageRequired);
1481e5c31af7Sopenharmony_ci
1482e5c31af7Sopenharmony_ci	const GlslSource *vshader = &context.getSourceCollection().get(vert);
1483e5c31af7Sopenharmony_ci	const GlslSource *fshader = DE_NULL;
1484e5c31af7Sopenharmony_ci	const GlslSource *gshader = DE_NULL;
1485e5c31af7Sopenharmony_ci	const GlslSource *tcshader = DE_NULL;
1486e5c31af7Sopenharmony_ci	const GlslSource *teshader = DE_NULL;
1487e5c31af7Sopenharmony_ci
1488e5c31af7Sopenharmony_ci	if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1489e5c31af7Sopenharmony_ci	{
1490e5c31af7Sopenharmony_ci		tcshader = &context.getSourceCollection().get(tesc);
1491e5c31af7Sopenharmony_ci		teshader = &context.getSourceCollection().get(tese);
1492e5c31af7Sopenharmony_ci	}
1493e5c31af7Sopenharmony_ci	if (shaderStageRequired & SHADER_STAGE_GEOMETRY_BIT)
1494e5c31af7Sopenharmony_ci	{
1495e5c31af7Sopenharmony_ci		if (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)
1496e5c31af7Sopenharmony_ci		{
1497e5c31af7Sopenharmony_ci			// tessellation shaders output line primitives
1498e5c31af7Sopenharmony_ci			gshader = &context.getSourceCollection().get("geometry_lines");
1499e5c31af7Sopenharmony_ci		}
1500e5c31af7Sopenharmony_ci		else
1501e5c31af7Sopenharmony_ci		{
1502e5c31af7Sopenharmony_ci			// otherwise points are processed by geometry shader
1503e5c31af7Sopenharmony_ci			gshader = &context.getSourceCollection().get("geometry_points");
1504e5c31af7Sopenharmony_ci		}
1505e5c31af7Sopenharmony_ci	}
1506e5c31af7Sopenharmony_ci	if (shaderStageRequired & SHADER_STAGE_FRAGMENT_BIT)
1507e5c31af7Sopenharmony_ci	{
1508e5c31af7Sopenharmony_ci		fshader = &context.getSourceCollection().get("fragment");
1509e5c31af7Sopenharmony_ci	}
1510e5c31af7Sopenharmony_ci
1511e5c31af7Sopenharmony_ci	std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(stagesCount + extraDatasCount);
1512e5c31af7Sopenharmony_ci
1513e5c31af7Sopenharmony_ci	// The implicit result SSBO we use to store our outputs from the shader
1514e5c31af7Sopenharmony_ci	for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1515e5c31af7Sopenharmony_ci	{
1516e5c31af7Sopenharmony_ci		const deUint64 shaderSize = (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? maxWidth * 2 : maxWidth;
1517e5c31af7Sopenharmony_ci		const deUint64 size = getElementSizeInBytes(format, SSBOData::LayoutStd430) * shaderSize;
1518e5c31af7Sopenharmony_ci		inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1519e5c31af7Sopenharmony_ci
1520e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1521e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", "
1522e5c31af7Sopenharmony_ci			<< inputBuffers[ndx]->getId() << ", " << size << "), "
1523e5c31af7Sopenharmony_ci			<< "inputstage[" << ndx << "] = " << stagesVector[ndx] << " binding = " << getResultBinding(stagesVector[ndx])
1524e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1525e5c31af7Sopenharmony_ci
1526e5c31af7Sopenharmony_ci		gl.bindBufferBase(inputBuffers[ndx]->getType(), getResultBinding(stagesVector[ndx]), inputBuffers[ndx]->getId());
1527e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(ndx, inputBuffers[ndx])");
1528e5c31af7Sopenharmony_ci	}
1529e5c31af7Sopenharmony_ci
1530e5c31af7Sopenharmony_ci	for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1531e5c31af7Sopenharmony_ci	{
1532e5c31af7Sopenharmony_ci		const deUint32 datasNdx = ndx - stagesCount;
1533e5c31af7Sopenharmony_ci		if (extraDatas[datasNdx].isImage)
1534e5c31af7Sopenharmony_ci		{
1535e5c31af7Sopenharmony_ci			inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraDatas[datasNdx].numElements), 1, extraDatas[datasNdx].format));
1536e5c31af7Sopenharmony_ci
1537e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
1538e5c31af7Sopenharmony_ci			DE_ASSERT(extraDatas[datasNdx].initializeType == subgroups::SSBOData::InitializeNone);
1539e5c31af7Sopenharmony_ci		}
1540e5c31af7Sopenharmony_ci		else
1541e5c31af7Sopenharmony_ci		{
1542e5c31af7Sopenharmony_ci			const deUint64 size = getElementSizeInBytes(extraDatas[datasNdx].format, extraDatas[datasNdx].layout) * extraDatas[datasNdx].numElements;
1543e5c31af7Sopenharmony_ci			inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1544e5c31af7Sopenharmony_ci
1545e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1546e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, extraDatas[datasNdx]);
1547e5c31af7Sopenharmony_ci			inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1548e5c31af7Sopenharmony_ci		}
1549e5c31af7Sopenharmony_ci
1550e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1551e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", "
1552e5c31af7Sopenharmony_ci			<< inputBuffers[ndx]->getId() << ", " << extraDatas[datasNdx].numElements << " els), "
1553e5c31af7Sopenharmony_ci			<< "extrastage[" << datasNdx << "] = " << extraDatas[datasNdx].stages << " binding = " << extraDatas[datasNdx].binding
1554e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1555e5c31af7Sopenharmony_ci
1556e5c31af7Sopenharmony_ci		if (inputBuffers[ndx]->isImage())
1557e5c31af7Sopenharmony_ci		{
1558e5c31af7Sopenharmony_ci			gl.bindImageTexture(extraDatas[datasNdx].binding, inputBuffers[ndx]->getId(),
1559e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_WRITE, extraDatas[datasNdx].format);
1560e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(extraDatas[datasNdx])");
1561e5c31af7Sopenharmony_ci		} else
1562e5c31af7Sopenharmony_ci		{
1563e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[ndx]->getType(), extraDatas[datasNdx].binding, inputBuffers[ndx]->getId());
1564e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(extraDatas[datasNdx])");
1565e5c31af7Sopenharmony_ci		}
1566e5c31af7Sopenharmony_ci	}
1567e5c31af7Sopenharmony_ci
1568e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> pipeline(
1569e5c31af7Sopenharmony_ci			makeGraphicsPipeline(context, shaderStageRequired, vshader, fshader, gshader, tcshader, teshader));
1570e5c31af7Sopenharmony_ci
1571e5c31af7Sopenharmony_ci	if (!pipeline->isOk())
1572e5c31af7Sopenharmony_ci	{
1573e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("allstages graphics program build failed");
1574e5c31af7Sopenharmony_ci	}
1575e5c31af7Sopenharmony_ci
1576e5c31af7Sopenharmony_ci	{
1577e5c31af7Sopenharmony_ci		const deUint32					subgroupSize			= getSubgroupSize(context);
1578e5c31af7Sopenharmony_ci		unsigned						totalIterations			= 0u;
1579e5c31af7Sopenharmony_ci		unsigned						failedIterations		= 0u;
1580e5c31af7Sopenharmony_ci		Image							resultImage				(context, maxWidth, 1, format);
1581e5c31af7Sopenharmony_ci		const deUint64					imageResultSize			= getFormatSizeInBytes(format) * maxWidth;
1582e5c31af7Sopenharmony_ci		vector<glw::GLubyte>			imageBufferResult(imageResultSize);
1583e5c31af7Sopenharmony_ci
1584e5c31af7Sopenharmony_ci		Vao vao(context);
1585e5c31af7Sopenharmony_ci		Fbo fbo(context);
1586e5c31af7Sopenharmony_ci		fbo.bind2D(resultImage);
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_ci		gl.viewport(0, 0, maxWidth, 1u);
1589e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1590e5c31af7Sopenharmony_ci
1591e5c31af7Sopenharmony_ci		for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1592e5c31af7Sopenharmony_ci		{
1593e5c31af7Sopenharmony_ci			for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1594e5c31af7Sopenharmony_ci			{
1595e5c31af7Sopenharmony_ci				// re-init the data
1596e5c31af7Sopenharmony_ci				if (extraDatas[ndx - stagesCount].isImage)
1597e5c31af7Sopenharmony_ci				{
1598e5c31af7Sopenharmony_ci					// haven't implemented init for images yet
1599e5c31af7Sopenharmony_ci					DE_ASSERT(extraDatas[ndx - stagesCount].initializeType == subgroups::SSBOData::InitializeNone);
1600e5c31af7Sopenharmony_ci				} else
1601e5c31af7Sopenharmony_ci				{
1602e5c31af7Sopenharmony_ci					glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1603e5c31af7Sopenharmony_ci					initializeMemory(context.getDeqpContext(), ptr, extraDatas[ndx - stagesCount]);
1604e5c31af7Sopenharmony_ci					inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1605e5c31af7Sopenharmony_ci				}
1606e5c31af7Sopenharmony_ci			}
1607e5c31af7Sopenharmony_ci
1608e5c31af7Sopenharmony_ci			totalIterations++;
1609e5c31af7Sopenharmony_ci
1610e5c31af7Sopenharmony_ci			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1611e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1612e5c31af7Sopenharmony_ci			gl.clear(GL_COLOR_BUFFER_BIT);
1613e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1614e5c31af7Sopenharmony_ci
1615e5c31af7Sopenharmony_ci			gl.useProgram(pipeline->getProgram());
1616e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1617e5c31af7Sopenharmony_ci
1618e5c31af7Sopenharmony_ci			glw::GLenum drawType;
1619e5c31af7Sopenharmony_ci			if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1620e5c31af7Sopenharmony_ci			{
1621e5c31af7Sopenharmony_ci				drawType = GL_PATCHES;
1622e5c31af7Sopenharmony_ci				gl.patchParameteri(GL_PATCH_VERTICES, 1u);
1623e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1624e5c31af7Sopenharmony_ci			} else
1625e5c31af7Sopenharmony_ci			{
1626e5c31af7Sopenharmony_ci				drawType = GL_POINTS;
1627e5c31af7Sopenharmony_ci			}
1628e5c31af7Sopenharmony_ci
1629e5c31af7Sopenharmony_ci			gl.drawArrays(drawType, 0, width);
1630e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1631e5c31af7Sopenharmony_ci
1632e5c31af7Sopenharmony_ci			GLenum readFormat;
1633e5c31af7Sopenharmony_ci			GLenum readType;
1634e5c31af7Sopenharmony_ci			getFormatReadInfo(format, readFormat, readType);
1635e5c31af7Sopenharmony_ci
1636e5c31af7Sopenharmony_ci			gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1637e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1638e5c31af7Sopenharmony_ci
1639e5c31af7Sopenharmony_ci			for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1640e5c31af7Sopenharmony_ci			{
1641e5c31af7Sopenharmony_ci				std::vector<const void*> datas;
1642e5c31af7Sopenharmony_ci				std::vector<Buffer *> buffersToUnmap;
1643e5c31af7Sopenharmony_ci
1644e5c31af7Sopenharmony_ci				if (!inputBuffers[ndx]->isImage())
1645e5c31af7Sopenharmony_ci				{
1646e5c31af7Sopenharmony_ci					glw::GLvoid * resultData = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1647e5c31af7Sopenharmony_ci					buffersToUnmap.push_back(inputBuffers[ndx]->getAsBuffer());
1648e5c31af7Sopenharmony_ci					// we always have our result data first
1649e5c31af7Sopenharmony_ci					datas.push_back(resultData);
1650e5c31af7Sopenharmony_ci				}
1651e5c31af7Sopenharmony_ci
1652e5c31af7Sopenharmony_ci				for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1653e5c31af7Sopenharmony_ci				{
1654e5c31af7Sopenharmony_ci					const deUint32 datasNdx = index - stagesCount;
1655e5c31af7Sopenharmony_ci					if ((stagesVector[ndx] & extraDatas[datasNdx].stages) && (!inputBuffers[index]->isImage()))
1656e5c31af7Sopenharmony_ci					{
1657e5c31af7Sopenharmony_ci						glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1658e5c31af7Sopenharmony_ci						buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1659e5c31af7Sopenharmony_ci						datas.push_back(resultData);
1660e5c31af7Sopenharmony_ci					}
1661e5c31af7Sopenharmony_ci				}
1662e5c31af7Sopenharmony_ci
1663e5c31af7Sopenharmony_ci				if (!checkResult(datas, (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? width * 2 : width , subgroupSize))
1664e5c31af7Sopenharmony_ci					failedIterations++;
1665e5c31af7Sopenharmony_ci
1666e5c31af7Sopenharmony_ci				while( !buffersToUnmap.empty() )
1667e5c31af7Sopenharmony_ci				{
1668e5c31af7Sopenharmony_ci					Buffer * buf = buffersToUnmap.back();
1669e5c31af7Sopenharmony_ci					buf->unmapBufferPtr();
1670e5c31af7Sopenharmony_ci					buffersToUnmap.pop_back();
1671e5c31af7Sopenharmony_ci				}
1672e5c31af7Sopenharmony_ci			}
1673e5c31af7Sopenharmony_ci			if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1674e5c31af7Sopenharmony_ci			{
1675e5c31af7Sopenharmony_ci				std::vector<const void*> datas;
1676e5c31af7Sopenharmony_ci				std::vector<Buffer *> buffersToUnmap;
1677e5c31af7Sopenharmony_ci
1678e5c31af7Sopenharmony_ci				// we always have our result data first
1679e5c31af7Sopenharmony_ci				datas.push_back(&imageBufferResult[0]);
1680e5c31af7Sopenharmony_ci
1681e5c31af7Sopenharmony_ci				for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1682e5c31af7Sopenharmony_ci				{
1683e5c31af7Sopenharmony_ci					const deUint32 datasNdx = index - stagesCount;
1684e5c31af7Sopenharmony_ci					if (SHADER_STAGE_FRAGMENT_BIT & extraDatas[datasNdx].stages && (!inputBuffers[index]->isImage()))
1685e5c31af7Sopenharmony_ci					{
1686e5c31af7Sopenharmony_ci						glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1687e5c31af7Sopenharmony_ci						buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1688e5c31af7Sopenharmony_ci						// we always have our result data first
1689e5c31af7Sopenharmony_ci						datas.push_back(resultData);
1690e5c31af7Sopenharmony_ci					}
1691e5c31af7Sopenharmony_ci				}
1692e5c31af7Sopenharmony_ci
1693e5c31af7Sopenharmony_ci				if (!checkResult(datas, width, subgroupSize))
1694e5c31af7Sopenharmony_ci					failedIterations++;
1695e5c31af7Sopenharmony_ci
1696e5c31af7Sopenharmony_ci				while( !buffersToUnmap.empty() )
1697e5c31af7Sopenharmony_ci				{
1698e5c31af7Sopenharmony_ci					Buffer * buf = buffersToUnmap.back();
1699e5c31af7Sopenharmony_ci					buf->unmapBufferPtr();
1700e5c31af7Sopenharmony_ci					buffersToUnmap.pop_back();
1701e5c31af7Sopenharmony_ci				}
1702e5c31af7Sopenharmony_ci			}
1703e5c31af7Sopenharmony_ci
1704e5c31af7Sopenharmony_ci		}
1705e5c31af7Sopenharmony_ci
1706e5c31af7Sopenharmony_ci		if (0 < failedIterations)
1707e5c31af7Sopenharmony_ci		{
1708e5c31af7Sopenharmony_ci			log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1709e5c31af7Sopenharmony_ci					<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
1710e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("Failed!");
1711e5c31af7Sopenharmony_ci		} else
1712e5c31af7Sopenharmony_ci		{
1713e5c31af7Sopenharmony_ci			log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1714e5c31af7Sopenharmony_ci					<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
1715e5c31af7Sopenharmony_ci		}
1716e5c31af7Sopenharmony_ci	}
1717e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
1718e5c31af7Sopenharmony_ci}
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::makeVertexFrameBufferTest(Context& context, Format format,
1721e5c31af7Sopenharmony_ci	SSBOData* extraData, deUint32 extraDataCount,
1722e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1723e5c31af7Sopenharmony_ci{
1724e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context.getDeqpContext().getTestContext().getLog();
1725e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1726e5c31af7Sopenharmony_ci
1727e5c31af7Sopenharmony_ci	const deUint32							maxWidth				= getMaxWidth();
1728e5c31af7Sopenharmony_ci	vector<de::SharedPtr<BufferOrImage> >	inputBuffers			(extraDataCount);
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_ci	const GlslSource& vshader = context.getSourceCollection().get("vert");
1731e5c31af7Sopenharmony_ci	const GlslSource& fshader = context.getSourceCollection().get("fragment");
1732e5c31af7Sopenharmony_ci
1733e5c31af7Sopenharmony_ci	for (deUint32 i = 0u; i < extraDataCount; i++)
1734e5c31af7Sopenharmony_ci	{
1735e5c31af7Sopenharmony_ci		if (extraData[i].isImage)
1736e5c31af7Sopenharmony_ci		{
1737e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1738e5c31af7Sopenharmony_ci
1739e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
1740e5c31af7Sopenharmony_ci			DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1741e5c31af7Sopenharmony_ci		}
1742e5c31af7Sopenharmony_ci		else
1743e5c31af7Sopenharmony_ci		{
1744e5c31af7Sopenharmony_ci			deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1745e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1746e5c31af7Sopenharmony_ci
1747e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1748e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1749e5c31af7Sopenharmony_ci			inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1750e5c31af7Sopenharmony_ci		}
1751e5c31af7Sopenharmony_ci	}
1752e5c31af7Sopenharmony_ci
1753e5c31af7Sopenharmony_ci	for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1754e5c31af7Sopenharmony_ci	{
1755e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1756e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1757e5c31af7Sopenharmony_ci			<< "VERTEX, binding = " << extraData[ndx].binding << "\n"
1758e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1759e5c31af7Sopenharmony_ci
1760e5c31af7Sopenharmony_ci		if (inputBuffers[ndx]->isImage())
1761e5c31af7Sopenharmony_ci		{
1762e5c31af7Sopenharmony_ci			gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1763e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1764e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1765e5c31af7Sopenharmony_ci		} else
1766e5c31af7Sopenharmony_ci		{
1767e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1768e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1769e5c31af7Sopenharmony_ci		}
1770e5c31af7Sopenharmony_ci	}
1771e5c31af7Sopenharmony_ci
1772e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> pipeline(
1773e5c31af7Sopenharmony_ci			makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1774e5c31af7Sopenharmony_ci								 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1775e5c31af7Sopenharmony_ci
1776e5c31af7Sopenharmony_ci	if (!pipeline->isOk())
1777e5c31af7Sopenharmony_ci	{
1778e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("vert graphics program build failed");
1779e5c31af7Sopenharmony_ci	}
1780e5c31af7Sopenharmony_ci
1781e5c31af7Sopenharmony_ci	const deUint32							subgroupSize			= getSubgroupSize(context);
1782e5c31af7Sopenharmony_ci
1783e5c31af7Sopenharmony_ci	const deUint64							vertexBufferSize		= maxWidth * sizeof(tcu::Vec4);
1784e5c31af7Sopenharmony_ci	Buffer									vertexBuffer			(context, vertexBufferSize, GL_ARRAY_BUFFER);
1785e5c31af7Sopenharmony_ci
1786e5c31af7Sopenharmony_ci	unsigned								totalIterations			= 0u;
1787e5c31af7Sopenharmony_ci	unsigned								failedIterations		= 0u;
1788e5c31af7Sopenharmony_ci
1789e5c31af7Sopenharmony_ci	Image									discardableImage		(context, maxWidth, 1u, format);
1790e5c31af7Sopenharmony_ci
1791e5c31af7Sopenharmony_ci	{
1792e5c31af7Sopenharmony_ci		glw::GLvoid *			bufferPtr			= vertexBuffer.mapBufferPtr();
1793e5c31af7Sopenharmony_ci		std::vector<tcu::Vec4>	data				(maxWidth, tcu::Vec4(1.0f, 0.5f, 1.0f, 1.0f));
1794e5c31af7Sopenharmony_ci		const float				pixelSize			= 2.0f / static_cast<float>(maxWidth);
1795e5c31af7Sopenharmony_ci		float					leftHandPosition	= -1.0f;
1796e5c31af7Sopenharmony_ci
1797e5c31af7Sopenharmony_ci		for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1798e5c31af7Sopenharmony_ci		{
1799e5c31af7Sopenharmony_ci			data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1800e5c31af7Sopenharmony_ci			leftHandPosition += pixelSize;
1801e5c31af7Sopenharmony_ci		}
1802e5c31af7Sopenharmony_ci
1803e5c31af7Sopenharmony_ci		deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1804e5c31af7Sopenharmony_ci		vertexBuffer.unmapBufferPtr();
1805e5c31af7Sopenharmony_ci	}
1806e5c31af7Sopenharmony_ci
1807e5c31af7Sopenharmony_ci	Vao vao(context);
1808e5c31af7Sopenharmony_ci	Fbo fbo(context);
1809e5c31af7Sopenharmony_ci	fbo.bind2D(discardableImage);
1810e5c31af7Sopenharmony_ci
1811e5c31af7Sopenharmony_ci	gl.viewport(0, 0, maxWidth, 1u);
1812e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1813e5c31af7Sopenharmony_ci
1814e5c31af7Sopenharmony_ci	const deUint64				imageResultSize		= getFormatSizeInBytes(format) * maxWidth;
1815e5c31af7Sopenharmony_ci	vector<glw::GLubyte>		imageBufferResult(imageResultSize);
1816e5c31af7Sopenharmony_ci	const deUint64				vertexBufferOffset	= 0u;
1817e5c31af7Sopenharmony_ci
1818e5c31af7Sopenharmony_ci	for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1819e5c31af7Sopenharmony_ci	{
1820e5c31af7Sopenharmony_ci		totalIterations++;
1821e5c31af7Sopenharmony_ci
1822e5c31af7Sopenharmony_ci		for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1823e5c31af7Sopenharmony_ci		{
1824e5c31af7Sopenharmony_ci			if (inputBuffers[ndx]->isImage())
1825e5c31af7Sopenharmony_ci			{
1826e5c31af7Sopenharmony_ci				DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1827e5c31af7Sopenharmony_ci			} else
1828e5c31af7Sopenharmony_ci			{
1829e5c31af7Sopenharmony_ci				glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1830e5c31af7Sopenharmony_ci				initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1831e5c31af7Sopenharmony_ci				inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1832e5c31af7Sopenharmony_ci			}
1833e5c31af7Sopenharmony_ci		}
1834e5c31af7Sopenharmony_ci
1835e5c31af7Sopenharmony_ci		{
1836e5c31af7Sopenharmony_ci			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1837e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1838e5c31af7Sopenharmony_ci			gl.clear(GL_COLOR_BUFFER_BIT);
1839e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1840e5c31af7Sopenharmony_ci
1841e5c31af7Sopenharmony_ci			gl.useProgram(pipeline->getProgram());
1842e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1843e5c31af7Sopenharmony_ci
1844e5c31af7Sopenharmony_ci			gl.enableVertexAttribArray(0);
1845e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1846e5c31af7Sopenharmony_ci
1847e5c31af7Sopenharmony_ci			gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1848e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1849e5c31af7Sopenharmony_ci
1850e5c31af7Sopenharmony_ci			gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1851e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1852e5c31af7Sopenharmony_ci
1853e5c31af7Sopenharmony_ci			gl.drawArrays(GL_POINTS, 0, width);
1854e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1855e5c31af7Sopenharmony_ci
1856e5c31af7Sopenharmony_ci			gl.disableVertexAttribArray(0);
1857e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1858e5c31af7Sopenharmony_ci
1859e5c31af7Sopenharmony_ci			GLenum readFormat;
1860e5c31af7Sopenharmony_ci			GLenum readType;
1861e5c31af7Sopenharmony_ci			getFormatReadInfo(format, readFormat, readType);
1862e5c31af7Sopenharmony_ci
1863e5c31af7Sopenharmony_ci			gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1864e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1865e5c31af7Sopenharmony_ci		}
1866e5c31af7Sopenharmony_ci
1867e5c31af7Sopenharmony_ci		{
1868e5c31af7Sopenharmony_ci			std::vector<const void*> datas;
1869e5c31af7Sopenharmony_ci			datas.push_back(&imageBufferResult[0]);
1870e5c31af7Sopenharmony_ci			if (!checkResult(datas, width, subgroupSize))
1871e5c31af7Sopenharmony_ci				failedIterations++;
1872e5c31af7Sopenharmony_ci		}
1873e5c31af7Sopenharmony_ci	}
1874e5c31af7Sopenharmony_ci
1875e5c31af7Sopenharmony_ci	if (0 < failedIterations)
1876e5c31af7Sopenharmony_ci	{
1877e5c31af7Sopenharmony_ci		log	<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1878e5c31af7Sopenharmony_ci			<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
1879e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed!");
1880e5c31af7Sopenharmony_ci	} else
1881e5c31af7Sopenharmony_ci	{
1882e5c31af7Sopenharmony_ci		log	<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1883e5c31af7Sopenharmony_ci				<<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1884e5c31af7Sopenharmony_ci	}
1885e5c31af7Sopenharmony_ci
1886e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
1887e5c31af7Sopenharmony_ci}
1888e5c31af7Sopenharmony_ci
1889e5c31af7Sopenharmony_ci
1890e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::makeFragmentFrameBufferTest	(Context& context, Format format, SSBOData* extraDatas,
1891e5c31af7Sopenharmony_ci	deUint32 extraDatasCount,
1892e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
1893e5c31af7Sopenharmony_ci						deUint32 height, deUint32 subgroupSize))
1894e5c31af7Sopenharmony_ci{
1895e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context.getDeqpContext().getTestContext().getLog();
1896e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1897e5c31af7Sopenharmony_ci
1898e5c31af7Sopenharmony_ci	const GlslSource& vshader = context.getSourceCollection().get("vert");
1899e5c31af7Sopenharmony_ci	const GlslSource& fshader = context.getSourceCollection().get("fragment");
1900e5c31af7Sopenharmony_ci
1901e5c31af7Sopenharmony_ci	std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
1902e5c31af7Sopenharmony_ci
1903e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < extraDatasCount; i++)
1904e5c31af7Sopenharmony_ci	{
1905e5c31af7Sopenharmony_ci		if (extraDatas[i].isImage)
1906e5c31af7Sopenharmony_ci		{
1907e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1908e5c31af7Sopenharmony_ci										static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1909e5c31af7Sopenharmony_ci
1910e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
1911e5c31af7Sopenharmony_ci			DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1912e5c31af7Sopenharmony_ci		}
1913e5c31af7Sopenharmony_ci		else
1914e5c31af7Sopenharmony_ci		{
1915e5c31af7Sopenharmony_ci			deUint64 size =
1916e5c31af7Sopenharmony_ci				getElementSizeInBytes(extraDatas[i].format, extraDatas[i].layout) * extraDatas[i].numElements;
1917e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1918e5c31af7Sopenharmony_ci
1919e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1920e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1921e5c31af7Sopenharmony_ci			inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1922e5c31af7Sopenharmony_ci		}
1923e5c31af7Sopenharmony_ci	}
1924e5c31af7Sopenharmony_ci
1925e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < extraDatasCount; i++)
1926e5c31af7Sopenharmony_ci	{
1927e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
1928e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << i << "](" << inputBuffers[i]->getType() << ", " << inputBuffers[i]->getId() << " ), "
1929e5c31af7Sopenharmony_ci			<< "FRAGMENT, binding = " << extraDatas[i].binding << "\n"
1930e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1931e5c31af7Sopenharmony_ci
1932e5c31af7Sopenharmony_ci		if (inputBuffers[i]->isImage())
1933e5c31af7Sopenharmony_ci		{
1934e5c31af7Sopenharmony_ci			gl.bindImageTexture(extraDatas[i].binding, inputBuffers[i]->getId(),
1935e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_ONLY, extraDatas[i].format);
1936e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1937e5c31af7Sopenharmony_ci		} else
1938e5c31af7Sopenharmony_ci		{
1939e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[i]->getType(), extraDatas[i].binding, inputBuffers[i]->getId());
1940e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1941e5c31af7Sopenharmony_ci		}
1942e5c31af7Sopenharmony_ci	}
1943e5c31af7Sopenharmony_ci
1944e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> pipeline(
1945e5c31af7Sopenharmony_ci			makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1946e5c31af7Sopenharmony_ci								 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1947e5c31af7Sopenharmony_ci
1948e5c31af7Sopenharmony_ci	if (!pipeline->isOk())
1949e5c31af7Sopenharmony_ci	{
1950e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("frag graphics program build failed");
1951e5c31af7Sopenharmony_ci	}
1952e5c31af7Sopenharmony_ci
1953e5c31af7Sopenharmony_ci	const deUint32 subgroupSize = getSubgroupSize(context);
1954e5c31af7Sopenharmony_ci
1955e5c31af7Sopenharmony_ci	unsigned totalIterations = 0;
1956e5c31af7Sopenharmony_ci	unsigned failedIterations = 0;
1957e5c31af7Sopenharmony_ci
1958e5c31af7Sopenharmony_ci	Vao vao(context);
1959e5c31af7Sopenharmony_ci	Fbo fbo(context);
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_ci	for (deUint32 width = 8; width <= subgroupSize; width *= 2)
1962e5c31af7Sopenharmony_ci	{
1963e5c31af7Sopenharmony_ci		for (deUint32 height = 8; height <= subgroupSize; height *= 2)
1964e5c31af7Sopenharmony_ci		{
1965e5c31af7Sopenharmony_ci			totalIterations++;
1966e5c31af7Sopenharmony_ci
1967e5c31af7Sopenharmony_ci			// re-init the data
1968e5c31af7Sopenharmony_ci			for (deUint32 i = 0; i < extraDatasCount; i++)
1969e5c31af7Sopenharmony_ci			{
1970e5c31af7Sopenharmony_ci				if (inputBuffers[i]->isImage())
1971e5c31af7Sopenharmony_ci				{
1972e5c31af7Sopenharmony_ci					DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1973e5c31af7Sopenharmony_ci				} else
1974e5c31af7Sopenharmony_ci				{
1975e5c31af7Sopenharmony_ci					glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1976e5c31af7Sopenharmony_ci					initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1977e5c31af7Sopenharmony_ci					inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1978e5c31af7Sopenharmony_ci				}
1979e5c31af7Sopenharmony_ci			}
1980e5c31af7Sopenharmony_ci
1981e5c31af7Sopenharmony_ci			deUint64 formatSize = getFormatSizeInBytes(format);
1982e5c31af7Sopenharmony_ci			const deUint64 resultImageSizeInBytes =
1983e5c31af7Sopenharmony_ci				width * height * formatSize;
1984e5c31af7Sopenharmony_ci
1985e5c31af7Sopenharmony_ci			Image resultImage(context, width, height, format);
1986e5c31af7Sopenharmony_ci
1987e5c31af7Sopenharmony_ci			vector<glw::GLubyte>  resultBuffer(resultImageSizeInBytes);
1988e5c31af7Sopenharmony_ci
1989e5c31af7Sopenharmony_ci			fbo.bind2D(resultImage);
1990e5c31af7Sopenharmony_ci
1991e5c31af7Sopenharmony_ci			gl.viewport(0, 0, width, height);
1992e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1993e5c31af7Sopenharmony_ci
1994e5c31af7Sopenharmony_ci			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1995e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1996e5c31af7Sopenharmony_ci			gl.clear(GL_COLOR_BUFFER_BIT);
1997e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1998e5c31af7Sopenharmony_ci
1999e5c31af7Sopenharmony_ci			gl.useProgram(pipeline->getProgram());
2000e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2001e5c31af7Sopenharmony_ci
2002e5c31af7Sopenharmony_ci			gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
2003e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
2004e5c31af7Sopenharmony_ci
2005e5c31af7Sopenharmony_ci			GLenum readFormat;
2006e5c31af7Sopenharmony_ci			GLenum readType;
2007e5c31af7Sopenharmony_ci			getFormatReadInfo(format, readFormat, readType);
2008e5c31af7Sopenharmony_ci
2009e5c31af7Sopenharmony_ci			gl.readPixels(0, 0, width, height, readFormat, readType, (GLvoid*)&resultBuffer[0]);
2010e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2011e5c31af7Sopenharmony_ci
2012e5c31af7Sopenharmony_ci			std::vector<const void*> datas;
2013e5c31af7Sopenharmony_ci			{
2014e5c31af7Sopenharmony_ci				// we always have our result data first
2015e5c31af7Sopenharmony_ci				datas.push_back(&resultBuffer[0]);
2016e5c31af7Sopenharmony_ci			}
2017e5c31af7Sopenharmony_ci
2018e5c31af7Sopenharmony_ci			if (!checkResult(datas, width, height, subgroupSize))
2019e5c31af7Sopenharmony_ci			{
2020e5c31af7Sopenharmony_ci				failedIterations++;
2021e5c31af7Sopenharmony_ci			}
2022e5c31af7Sopenharmony_ci		}
2023e5c31af7Sopenharmony_ci	}
2024e5c31af7Sopenharmony_ci
2025e5c31af7Sopenharmony_ci	if (0 < failedIterations)
2026e5c31af7Sopenharmony_ci	{
2027e5c31af7Sopenharmony_ci		log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2028e5c31af7Sopenharmony_ci				<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
2029e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed!");
2030e5c31af7Sopenharmony_ci	} else
2031e5c31af7Sopenharmony_ci	{
2032e5c31af7Sopenharmony_ci		log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2033e5c31af7Sopenharmony_ci				<<totalIterations << " values passed" << tcu::TestLog::EndMessage;
2034e5c31af7Sopenharmony_ci	}
2035e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
2036e5c31af7Sopenharmony_ci}
2037e5c31af7Sopenharmony_ci
2038e5c31af7Sopenharmony_citcu::TestStatus glc::subgroups::makeComputeTest(
2039e5c31af7Sopenharmony_ci	Context& context, Format format, SSBOData* inputs, deUint32 inputsCount,
2040e5c31af7Sopenharmony_ci	bool (*checkResult)(std::vector<const void*> datas,
2041e5c31af7Sopenharmony_ci						const deUint32 numWorkgroups[3], const deUint32 localSize[3],
2042e5c31af7Sopenharmony_ci						deUint32 subgroupSize))
2043e5c31af7Sopenharmony_ci{
2044e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
2045e5c31af7Sopenharmony_ci	deUint64 elementSize = getFormatSizeInBytes(format);
2046e5c31af7Sopenharmony_ci
2047e5c31af7Sopenharmony_ci	const deUint64 resultBufferSize = maxSupportedSubgroupSize() *
2048e5c31af7Sopenharmony_ci										  maxSupportedSubgroupSize() *
2049e5c31af7Sopenharmony_ci										  maxSupportedSubgroupSize();
2050e5c31af7Sopenharmony_ci	const deUint64 resultBufferSizeInBytes = resultBufferSize * elementSize;
2051e5c31af7Sopenharmony_ci
2052e5c31af7Sopenharmony_ci	Buffer resultBuffer(
2053e5c31af7Sopenharmony_ci		context, resultBufferSizeInBytes);
2054e5c31af7Sopenharmony_ci
2055e5c31af7Sopenharmony_ci	std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(inputsCount);
2056e5c31af7Sopenharmony_ci
2057e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < inputsCount; i++)
2058e5c31af7Sopenharmony_ci	{
2059e5c31af7Sopenharmony_ci		if (inputs[i].isImage)
2060e5c31af7Sopenharmony_ci		{
2061e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
2062e5c31af7Sopenharmony_ci										static_cast<deUint32>(inputs[i].numElements), 1, inputs[i].format));
2063e5c31af7Sopenharmony_ci			// haven't implemented init for images yet
2064e5c31af7Sopenharmony_ci			DE_ASSERT(inputs[i].initializeType == subgroups::SSBOData::InitializeNone);
2065e5c31af7Sopenharmony_ci		}
2066e5c31af7Sopenharmony_ci		else
2067e5c31af7Sopenharmony_ci		{
2068e5c31af7Sopenharmony_ci			deUint64 size =
2069e5c31af7Sopenharmony_ci				getElementSizeInBytes(inputs[i].format, inputs[i].layout) * inputs[i].numElements;
2070e5c31af7Sopenharmony_ci			inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
2071e5c31af7Sopenharmony_ci
2072e5c31af7Sopenharmony_ci			glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2073e5c31af7Sopenharmony_ci			initializeMemory(context.getDeqpContext(), ptr, inputs[i]);
2074e5c31af7Sopenharmony_ci			inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2075e5c31af7Sopenharmony_ci		}
2076e5c31af7Sopenharmony_ci
2077e5c31af7Sopenharmony_ci	}
2078e5c31af7Sopenharmony_ci
2079e5c31af7Sopenharmony_ci	tcu::TestLog& log	= context.getDeqpContext().getTestContext().getLog();
2080e5c31af7Sopenharmony_ci	log << tcu::TestLog::Message
2081e5c31af7Sopenharmony_ci		<< "binding resultbuffer(type=" << resultBuffer.getType()
2082e5c31af7Sopenharmony_ci		<< ", id=" << resultBuffer.getId() << ", binding=0), COMPUTE"
2083e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ci	gl.bindBufferBase(resultBuffer.getType(), 0, resultBuffer.getId());
2086e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(0, resultBuffer)");
2087e5c31af7Sopenharmony_ci
2088e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < inputsCount; i++)
2089e5c31af7Sopenharmony_ci	{
2090e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message
2091e5c31af7Sopenharmony_ci			<< "binding inputBuffers[" << i << "](type=" << inputBuffers[i]->getType()
2092e5c31af7Sopenharmony_ci			<< ", id=" << inputBuffers[i]->getId() << ", binding="
2093e5c31af7Sopenharmony_ci			<< inputs[i].binding << "), 1, COMPUTE"
2094e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
2095e5c31af7Sopenharmony_ci
2096e5c31af7Sopenharmony_ci		if (inputBuffers[i]->isImage())
2097e5c31af7Sopenharmony_ci		{
2098e5c31af7Sopenharmony_ci			gl.bindImageTexture(inputs[i].binding, inputBuffers[i]->getId(),
2099e5c31af7Sopenharmony_ci								0, GL_FALSE, 0, GL_READ_WRITE, inputs[i].format);
2100e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(inputBuffer[i]");
2101e5c31af7Sopenharmony_ci		} else
2102e5c31af7Sopenharmony_ci		{
2103e5c31af7Sopenharmony_ci			gl.bindBufferBase(inputBuffers[i]->getType(), inputs[i].binding, inputBuffers[i]->getId());
2104e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(inputBuffer[i])");
2105e5c31af7Sopenharmony_ci		}
2106e5c31af7Sopenharmony_ci	}
2107e5c31af7Sopenharmony_ci
2108e5c31af7Sopenharmony_ci	const GlslSource &cshader = context.getSourceCollection().get("comp");
2109e5c31af7Sopenharmony_ci
2110e5c31af7Sopenharmony_ci	unsigned totalIterations = 0;
2111e5c31af7Sopenharmony_ci	unsigned failedIterations = 0;
2112e5c31af7Sopenharmony_ci
2113e5c31af7Sopenharmony_ci	const deUint32 subgroupSize = getSubgroupSize(context);
2114e5c31af7Sopenharmony_ci
2115e5c31af7Sopenharmony_ci	const deUint32 numWorkgroups[3] = {4, 2, 2};
2116e5c31af7Sopenharmony_ci
2117e5c31af7Sopenharmony_ci	const deUint32 localSizesToTestCount = 15;
2118e5c31af7Sopenharmony_ci	deUint32 localSizesToTest[localSizesToTestCount][3] =
2119e5c31af7Sopenharmony_ci	{
2120e5c31af7Sopenharmony_ci		{1, 1, 1},
2121e5c31af7Sopenharmony_ci		{32, 4, 1},
2122e5c31af7Sopenharmony_ci		{32, 1, 4},
2123e5c31af7Sopenharmony_ci		{1, 32, 4},
2124e5c31af7Sopenharmony_ci		{1, 4, 32},
2125e5c31af7Sopenharmony_ci		{4, 1, 32},
2126e5c31af7Sopenharmony_ci		{4, 32, 1},
2127e5c31af7Sopenharmony_ci		{subgroupSize, 1, 1},
2128e5c31af7Sopenharmony_ci		{1, subgroupSize, 1},
2129e5c31af7Sopenharmony_ci		{1, 1, subgroupSize},
2130e5c31af7Sopenharmony_ci		{3, 5, 7},
2131e5c31af7Sopenharmony_ci		{128, 1, 1},
2132e5c31af7Sopenharmony_ci		{1, 128, 1},
2133e5c31af7Sopenharmony_ci		{1, 1, 64},
2134e5c31af7Sopenharmony_ci		{1, 1, 1} // Isn't used, just here to make double buffering checks easier
2135e5c31af7Sopenharmony_ci	};
2136e5c31af7Sopenharmony_ci
2137e5c31af7Sopenharmony_ci
2138e5c31af7Sopenharmony_ci	de::MovePtr<glu::ShaderProgram> lastPipeline(
2139e5c31af7Sopenharmony_ci		makeComputePipeline(context, cshader,
2140e5c31af7Sopenharmony_ci							localSizesToTest[0][0], localSizesToTest[0][1], localSizesToTest[0][2]));
2141e5c31af7Sopenharmony_ci
2142e5c31af7Sopenharmony_ci	for (deUint32 index = 0; index < (localSizesToTestCount - 1); index++)
2143e5c31af7Sopenharmony_ci	{
2144e5c31af7Sopenharmony_ci		const deUint32 nextX = localSizesToTest[index + 1][0];
2145e5c31af7Sopenharmony_ci		const deUint32 nextY = localSizesToTest[index + 1][1];
2146e5c31af7Sopenharmony_ci		const deUint32 nextZ = localSizesToTest[index + 1][2];
2147e5c31af7Sopenharmony_ci
2148e5c31af7Sopenharmony_ci		// we are running one test
2149e5c31af7Sopenharmony_ci		totalIterations++;
2150e5c31af7Sopenharmony_ci
2151e5c31af7Sopenharmony_ci		if (!lastPipeline->isOk())
2152e5c31af7Sopenharmony_ci		{
2153e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("compute shaders build failed");
2154e5c31af7Sopenharmony_ci		}
2155e5c31af7Sopenharmony_ci
2156e5c31af7Sopenharmony_ci		gl.useProgram(lastPipeline->getProgram());
2157e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2158e5c31af7Sopenharmony_ci
2159e5c31af7Sopenharmony_ci		gl.dispatchCompute(numWorkgroups[0], numWorkgroups[1], numWorkgroups[2]);
2160e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
2161e5c31af7Sopenharmony_ci
2162e5c31af7Sopenharmony_ci		de::MovePtr<glu::ShaderProgram> nextPipeline(
2163e5c31af7Sopenharmony_ci			makeComputePipeline(context, cshader, nextX, nextY, nextZ));
2164e5c31af7Sopenharmony_ci
2165e5c31af7Sopenharmony_ci		std::vector<const void*> datas;
2166e5c31af7Sopenharmony_ci
2167e5c31af7Sopenharmony_ci		{
2168e5c31af7Sopenharmony_ci			glw::GLvoid * resultData = resultBuffer.mapBufferPtr();
2169e5c31af7Sopenharmony_ci
2170e5c31af7Sopenharmony_ci			// we always have our result data first
2171e5c31af7Sopenharmony_ci			datas.push_back(resultData);
2172e5c31af7Sopenharmony_ci		}
2173e5c31af7Sopenharmony_ci
2174e5c31af7Sopenharmony_ci		for (deUint32 i = 0; i < inputsCount; i++)
2175e5c31af7Sopenharmony_ci		{
2176e5c31af7Sopenharmony_ci			if (!inputBuffers[i]->isImage())
2177e5c31af7Sopenharmony_ci			{
2178e5c31af7Sopenharmony_ci				glw::GLvoid *resultData = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2179e5c31af7Sopenharmony_ci
2180e5c31af7Sopenharmony_ci				// we always have our result data first
2181e5c31af7Sopenharmony_ci				datas.push_back(resultData);
2182e5c31af7Sopenharmony_ci			}
2183e5c31af7Sopenharmony_ci		}
2184e5c31af7Sopenharmony_ci
2185e5c31af7Sopenharmony_ci		if (!checkResult(datas, numWorkgroups, localSizesToTest[index], subgroupSize))
2186e5c31af7Sopenharmony_ci		{
2187e5c31af7Sopenharmony_ci			failedIterations++;
2188e5c31af7Sopenharmony_ci		}
2189e5c31af7Sopenharmony_ci
2190e5c31af7Sopenharmony_ci		resultBuffer.unmapBufferPtr();
2191e5c31af7Sopenharmony_ci		for (deUint32 i = 0; i < inputsCount; i++)
2192e5c31af7Sopenharmony_ci		{
2193e5c31af7Sopenharmony_ci			if (!inputBuffers[i]->isImage())
2194e5c31af7Sopenharmony_ci			{
2195e5c31af7Sopenharmony_ci				inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2196e5c31af7Sopenharmony_ci			}
2197e5c31af7Sopenharmony_ci		}
2198e5c31af7Sopenharmony_ci
2199e5c31af7Sopenharmony_ci		lastPipeline = nextPipeline;
2200e5c31af7Sopenharmony_ci	}
2201e5c31af7Sopenharmony_ci
2202e5c31af7Sopenharmony_ci	if (0 < failedIterations)
2203e5c31af7Sopenharmony_ci	{
2204e5c31af7Sopenharmony_ci		log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2205e5c31af7Sopenharmony_ci				<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
2206e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed!");
2207e5c31af7Sopenharmony_ci	} else
2208e5c31af7Sopenharmony_ci	{
2209e5c31af7Sopenharmony_ci		log		<< tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2210e5c31af7Sopenharmony_ci				<< totalIterations << " values passed" << tcu::TestLog::EndMessage;
2211e5c31af7Sopenharmony_ci	}
2212e5c31af7Sopenharmony_ci
2213e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("OK");
2214e5c31af7Sopenharmony_ci}
2215