• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2017 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file  gl4cShaderBallotTests.cpp
21 * \brief Conformance tests for the ARB_shader_ballot functionality.
22 */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cShaderBallotTests.hpp"
25 
26 #include "glcContext.hpp"
27 #include "gluContextInfo.hpp"
28 #include "gluDefs.hpp"
29 #include "gluDrawUtil.hpp"
30 #include "gluObjectWrapper.hpp"
31 #include "gluProgramInterfaceQuery.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuRenderTarget.hpp"
36 
37 namespace gl4cts
38 {
39 
ShaderPipeline(glu::ShaderType testedShader,const std::string & contentSnippet,std::map<std::string,std::string> specMap)40 ShaderBallotBaseTestCase::ShaderPipeline::ShaderPipeline(glu::ShaderType	testedShader,
41 														 const std::string& contentSnippet,
42 														 std::map<std::string, std::string> specMap)
43 	: m_programRender(NULL), m_programCompute(NULL), m_testedShader(testedShader), m_specializationMap(specMap)
44 {
45 	std::string testedHeadPart = "#extension GL_ARB_shader_ballot : enable\n"
46 								 "#extension GL_ARB_gpu_shader_int64 : enable\n";
47 
48 	std::string testedContentPart = contentSnippet;
49 
50 	// vertex shader parts
51 
52 	m_shaders[glu::SHADERTYPE_VERTEX].push_back("#version 450 core\n");
53 	m_shaders[glu::SHADERTYPE_VERTEX].push_back(m_testedShader == glu::SHADERTYPE_VERTEX ? testedHeadPart : "");
54 	m_shaders[glu::SHADERTYPE_VERTEX].push_back("in highp vec2 inPosition;\n"
55 												"in highp vec4 inColor;\n"
56 												"out highp vec3 vsPosition;\n"
57 												"out highp vec4 vsColor;\n"
58 												"void main()\n"
59 												"{\n"
60 												"	gl_Position = vec4(inPosition, 0.0, 1.0);\n"
61 												"	vsPosition = vec3(inPosition, 0.0);\n"
62 												"	vec4 outColor = vec4(0.0); \n");
63 	m_shaders[glu::SHADERTYPE_VERTEX].push_back(m_testedShader == glu::SHADERTYPE_VERTEX ? testedContentPart :
64 																						   "	outColor = inColor;\n");
65 	m_shaders[glu::SHADERTYPE_VERTEX].push_back("	vsColor = outColor;\n"
66 												"}\n");
67 
68 	// fragment shader parts
69 
70 	m_shaders[glu::SHADERTYPE_FRAGMENT].push_back("#version 450 core\n");
71 	m_shaders[glu::SHADERTYPE_FRAGMENT].push_back(m_testedShader == glu::SHADERTYPE_FRAGMENT ? testedHeadPart : "");
72 	m_shaders[glu::SHADERTYPE_FRAGMENT].push_back("in highp vec4 gsColor;\n"
73 												  "out highp vec4 fsColor;\n"
74 												  "void main()\n"
75 												  "{\n"
76 												  "	vec4 outColor = vec4(0.0); \n");
77 	m_shaders[glu::SHADERTYPE_FRAGMENT].push_back(
78 		m_testedShader == glu::SHADERTYPE_FRAGMENT ? testedContentPart : "	outColor = gsColor;\n");
79 	m_shaders[glu::SHADERTYPE_FRAGMENT].push_back("	fsColor = outColor;\n"
80 												  "}\n");
81 
82 	// tessellation control shader parts
83 
84 	m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back("#version 450 core\n");
85 	m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(
86 		m_testedShader == glu::SHADERTYPE_TESSELLATION_CONTROL ? testedHeadPart : "");
87 	m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(
88 		"layout(vertices = 3) out;\n"
89 		"in highp vec4 vsColor[];\n"
90 		"in highp vec3 vsPosition[];\n"
91 		"out highp vec3 tcsPosition[];\n"
92 		"out highp vec4 tcsColor[];\n"
93 		"void main()\n"
94 		"{\n"
95 		"	tcsPosition[gl_InvocationID] = vsPosition[gl_InvocationID];\n"
96 		"	vec4 outColor = vec4(0.0);\n");
97 	m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(m_testedShader == glu::SHADERTYPE_TESSELLATION_CONTROL ?
98 																  testedContentPart :
99 																  "	outColor = vsColor[gl_InvocationID];\n");
100 	m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back("	tcsColor[gl_InvocationID] = outColor;\n"
101 															  "	gl_TessLevelInner[0] = 3;\n"
102 															  "	gl_TessLevelOuter[0] = 3;\n"
103 															  "	gl_TessLevelOuter[1] = 3;\n"
104 															  "	gl_TessLevelOuter[2] = 3;\n"
105 															  "}\n");
106 
107 	// tessellation evaluation shader parts
108 
109 	m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("#version 450 core\n");
110 	m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(
111 		m_testedShader == glu::SHADERTYPE_TESSELLATION_EVALUATION ? testedHeadPart : "");
112 	m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("layout(triangles, equal_spacing, cw) in;\n"
113 																 "in highp vec3 tcsPosition[];\n"
114 																 "in highp vec4 tcsColor[];\n"
115 																 "out highp vec4 tesColor;\n"
116 																 "void main()\n"
117 																 "{\n"
118 																 "	vec3 p0 = gl_TessCoord.x * tcsPosition[0];\n"
119 																 "	vec3 p1 = gl_TessCoord.y * tcsPosition[1];\n"
120 																 "	vec3 p2 = gl_TessCoord.z * tcsPosition[2];\n"
121 																 "	vec4 outColor = vec4(0.0);\n");
122 	m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(
123 		m_testedShader == glu::SHADERTYPE_TESSELLATION_EVALUATION ? testedContentPart : "	outColor = tcsColor[0];\n");
124 	m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("	tesColor = outColor;\n"
125 																 "	gl_Position = vec4(normalize(p0 + p1 + p2), 1.0);\n"
126 																 "}\n");
127 
128 	// geometry shader parts
129 
130 	m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("#version 450 core\n");
131 	m_shaders[glu::SHADERTYPE_GEOMETRY].push_back(m_testedShader == glu::SHADERTYPE_GEOMETRY ? testedHeadPart : "");
132 	m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("layout(triangles) in;\n"
133 												  "layout(triangle_strip, max_vertices = 3) out;\n"
134 												  "in highp vec4 tesColor[];\n"
135 												  "out highp vec4 gsColor;\n"
136 												  "void main()\n"
137 												  "{\n"
138 												  "	for (int i = 0; i<3; i++)\n"
139 												  "	{\n"
140 												  "		gl_Position = gl_in[i].gl_Position;\n"
141 												  "		vec4 outColor = vec4(0.0);\n");
142 	m_shaders[glu::SHADERTYPE_GEOMETRY].push_back(
143 		m_testedShader == glu::SHADERTYPE_GEOMETRY ? testedContentPart : "		outColor = tesColor[i];\n");
144 	m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("		gsColor = outColor;\n"
145 												  "		EmitVertex();\n"
146 												  "	}\n"
147 												  "	EndPrimitive();\n"
148 												  "}\n");
149 
150 	// compute shader parts
151 
152 	m_shaders[glu::SHADERTYPE_COMPUTE].push_back("#version 450 core\n");
153 	m_shaders[glu::SHADERTYPE_COMPUTE].push_back(m_testedShader == glu::SHADERTYPE_COMPUTE ? testedHeadPart : "");
154 	m_shaders[glu::SHADERTYPE_COMPUTE].push_back(
155 		"layout(rgba32f, binding = 1) writeonly uniform highp image2D destImage;\n"
156 		"layout (local_size_x = 16, local_size_y = 16) in;\n"
157 		"void main (void)\n"
158 		"{\n"
159 		"vec4 outColor = vec4(0.0);\n");
160 	m_shaders[glu::SHADERTYPE_COMPUTE].push_back(m_testedShader == glu::SHADERTYPE_COMPUTE ? testedContentPart : "");
161 	m_shaders[glu::SHADERTYPE_COMPUTE].push_back("imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
162 												 "}\n");
163 
164 	// create shader chunks
165 
166 	for (unsigned int shaderType = 0; shaderType <= glu::SHADERTYPE_COMPUTE; ++shaderType)
167 	{
168 		m_shaderChunks[shaderType] = new char*[m_shaders[shaderType].size()];
169 		for (unsigned int i = 0; i < m_shaders[i].size(); ++i)
170 		{
171 			m_shaderChunks[shaderType][i] = (char*)m_shaders[shaderType][i].data();
172 		}
173 	}
174 }
175 
~ShaderPipeline()176 ShaderBallotBaseTestCase::ShaderPipeline::~ShaderPipeline()
177 {
178 	if (m_programRender)
179 	{
180 		delete m_programRender;
181 	}
182 
183 	if (m_programCompute)
184 	{
185 		delete m_programCompute;
186 	}
187 
188 	for (unsigned int shaderType = 0; shaderType <= glu::SHADERTYPE_COMPUTE; ++shaderType)
189 	{
190 		delete[] m_shaderChunks[shaderType];
191 	}
192 }
193 
getShaderParts(glu::ShaderType shaderType) const194 const char* const* ShaderBallotBaseTestCase::ShaderPipeline::getShaderParts(glu::ShaderType shaderType) const
195 {
196 	return m_shaderChunks[shaderType];
197 }
198 
getShaderPartsCount(glu::ShaderType shaderType) const199 unsigned int ShaderBallotBaseTestCase::ShaderPipeline::getShaderPartsCount(glu::ShaderType shaderType) const
200 {
201 	return static_cast<unsigned int>(m_shaders[shaderType].size());
202 }
203 
renderQuad(deqp::Context & context)204 void ShaderBallotBaseTestCase::ShaderPipeline::renderQuad(deqp::Context& context)
205 {
206 	const glw::Functions& gl = context.getRenderContext().getFunctions();
207 
208 	deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
209 
210 	float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
211 
212 	glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, position) };
213 
214 	this->use(context);
215 
216 	glu::PrimitiveList primitiveList = glu::pr::Patches(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices);
217 
218 	glu::draw(context.getRenderContext(), m_programRender->getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
219 			  primitiveList);
220 
221 	GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
222 }
223 
executeComputeShader(deqp::Context & context)224 void ShaderBallotBaseTestCase::ShaderPipeline::executeComputeShader(deqp::Context& context)
225 {
226 	const glw::Functions& gl = context.getRenderContext().getFunctions();
227 
228 	const glu::Texture outputTexture(context.getRenderContext());
229 
230 	gl.useProgram(m_programCompute->getProgram());
231 
232 	// output image
233 	gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
234 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 16, 16);
235 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
237 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading image data failed");
238 
239 	// bind image
240 	gl.bindImageTexture(1, *outputTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
241 	GLU_EXPECT_NO_ERROR(gl.getError(), "Image setup failed");
242 
243 	// dispatch compute
244 	gl.dispatchCompute(1, 1, 1);
245 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()");
246 
247 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
248 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier()");
249 
250 	// render output texture
251 
252 	std::string vs = "#version 450 core\n"
253 					 "in highp vec2 position;\n"
254 					 "in vec2 inTexcoord;\n"
255 					 "out vec2 texcoord;\n"
256 					 "void main()\n"
257 					 "{\n"
258 					 "	texcoord = inTexcoord;\n"
259 					 "	gl_Position = vec4(position, 0.0, 1.0);\n"
260 					 "}\n";
261 
262 	std::string fs = "#version 450 core\n"
263 					 "uniform sampler2D sampler;\n"
264 					 "in vec2 texcoord;\n"
265 					 "out vec4 color;\n"
266 					 "void main()\n"
267 					 "{\n"
268 					 "	color = texture(sampler, texcoord);\n"
269 					 "}\n";
270 
271 	glu::ProgramSources sources;
272 	sources.sources[glu::SHADERTYPE_VERTEX].push_back(vs);
273 	sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fs);
274 	glu::ShaderProgram renderShader(context.getRenderContext(), sources);
275 
276 	if (!m_programRender->isOk())
277 	{
278 		TCU_FAIL("Shader compilation failed");
279 	}
280 
281 	gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
282 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
283 
284 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
286 
287 	gl.useProgram(renderShader.getProgram());
288 
289 	gl.uniform1i(gl.getUniformLocation(renderShader.getProgram(), "sampler"), 0);
290 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");
291 
292 	deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
293 
294 	float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
295 
296 	float const texCoord[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
297 
298 	glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("position", 2, 4, 0, position),
299 											   glu::va::Float("inTexcoord", 2, 4, 0, texCoord) };
300 
301 	glu::draw(context.getRenderContext(), renderShader.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
302 			  glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
303 
304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
305 }
306 
use(deqp::Context & context)307 void ShaderBallotBaseTestCase::ShaderPipeline::use(deqp::Context& context)
308 {
309 	const glw::Functions& gl = context.getRenderContext().getFunctions();
310 	gl.useProgram(m_programRender->getProgram());
311 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");
312 }
313 
test(deqp::Context & context)314 void ShaderBallotBaseTestCase::ShaderPipeline::test(deqp::Context& context)
315 {
316 	if (m_testedShader == glu::SHADERTYPE_COMPUTE)
317 	{
318 		executeComputeShader(context);
319 	}
320 	else
321 	{
322 		renderQuad(context);
323 	}
324 }
325 
createShaderPrograms(ShaderPipeline & pipeline)326 void ShaderBallotBaseTestCase::createShaderPrograms(ShaderPipeline& pipeline)
327 {
328 	glu::ProgramSources sourcesRender;
329 
330 	for (unsigned int i = 0; i < glu::SHADERTYPE_COMPUTE; ++i)
331 	{
332 		glu::ShaderType shaderType = (glu::ShaderType)i;
333 
334 		std::map<std::string, std::string>::const_iterator mapIter;
335 		for (mapIter = pipeline.getSpecializationMap().begin(); mapIter != pipeline.getSpecializationMap().end();
336 			 mapIter++)
337 			m_specializationMap[mapIter->first] = mapIter->second;
338 
339 		std::string shader =
340 			specializeShader(pipeline.getShaderPartsCount(shaderType), pipeline.getShaderParts(shaderType));
341 		sourcesRender.sources[i].push_back(shader);
342 	}
343 
344 	glu::ShaderProgram* programRender = new glu::ShaderProgram(m_context.getRenderContext(), sourcesRender);
345 
346 	if (!programRender->isOk())
347 	{
348 		TCU_FAIL("Shader compilation failed");
349 	}
350 
351 	glu::ProgramSources sourcesCompute;
352 
353 	m_specializationMap.insert(pipeline.getSpecializationMap().begin(), pipeline.getSpecializationMap().end());
354 	std::string shaderCompute = specializeShader(pipeline.getShaderPartsCount(glu::SHADERTYPE_COMPUTE),
355 												 pipeline.getShaderParts(glu::SHADERTYPE_COMPUTE));
356 	sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(shaderCompute);
357 
358 	glu::ShaderProgram* programCompute = new glu::ShaderProgram(m_context.getRenderContext(), sourcesCompute);
359 
360 	if (!programCompute->isOk())
361 	{
362 		TCU_FAIL("Shader compilation failed");
363 	}
364 
365 	pipeline.setShaderPrograms(programRender, programCompute);
366 }
367 
~ShaderBallotBaseTestCase()368 ShaderBallotBaseTestCase::~ShaderBallotBaseTestCase()
369 {
370 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
371 	{
372 		delete *iter;
373 	}
374 }
375 
validateScreenPixels(deqp::Context & context,tcu::Vec4 desiredColor,tcu::Vec4 ignoredColor)376 bool ShaderBallotBaseTestCase::validateScreenPixels(deqp::Context& context, tcu::Vec4 desiredColor,
377 													tcu::Vec4 ignoredColor)
378 {
379 	const glw::Functions&   gl			 = context.getRenderContext().getFunctions();
380 	const tcu::RenderTarget renderTarget = context.getRenderContext().getRenderTarget();
381 	tcu::IVec2				size(renderTarget.getWidth(), renderTarget.getHeight());
382 
383 	glw::GLfloat* pixels = new glw::GLfloat[size.x() * size.y() * 4];
384 
385 	// clear buffer
386 	for (int x = 0; x < size.x(); ++x)
387 	{
388 		for (int y = 0; y < size.y(); ++y)
389 		{
390 			int mappedPixelPosition = y * size.x() + x;
391 
392 			pixels[mappedPixelPosition * 4 + 0] = -1.0f;
393 			pixels[mappedPixelPosition * 4 + 1] = -1.0f;
394 			pixels[mappedPixelPosition * 4 + 2] = -1.0f;
395 			pixels[mappedPixelPosition * 4 + 3] = -1.0f;
396 		}
397 	}
398 
399 	// read pixels
400 	gl.readPixels(0, 0, size.x(), size.y(), GL_RGBA, GL_FLOAT, pixels);
401 
402 	// validate pixels
403 	bool rendered = false;
404 	for (int x = 0; x < size.x(); ++x)
405 	{
406 		for (int y = 0; y < size.y(); ++y)
407 		{
408 			int mappedPixelPosition = y * size.x() + x;
409 
410 			tcu::Vec4 color(pixels[mappedPixelPosition * 4 + 0], pixels[mappedPixelPosition * 4 + 1],
411 							pixels[mappedPixelPosition * 4 + 2], pixels[mappedPixelPosition * 4 + 3]);
412 
413 			if (!ShaderBallotBaseTestCase::validateColor(color, ignoredColor))
414 			{
415 				rendered = true;
416 				if (!ShaderBallotBaseTestCase::validateColor(color, desiredColor))
417 				{
418 					return false;
419 				}
420 			}
421 		}
422 	}
423 
424 	delete[] pixels;
425 
426 	return rendered;
427 }
428 
validateScreenPixelsSameColor(deqp::Context & context,tcu::Vec4 ignoredColor)429 bool ShaderBallotBaseTestCase::validateScreenPixelsSameColor(deqp::Context& context, tcu::Vec4 ignoredColor)
430 {
431 	const glw::Functions&   gl			 = context.getRenderContext().getFunctions();
432 	const tcu::RenderTarget renderTarget = context.getRenderContext().getRenderTarget();
433 	tcu::IVec2				size(renderTarget.getWidth(), renderTarget.getHeight());
434 
435 	glw::GLfloat* centerPixel = new glw::GLfloat[4];
436 	centerPixel[0]			  = -1.0f;
437 	centerPixel[1]			  = -1.0f;
438 	centerPixel[2]			  = -1.0f;
439 	centerPixel[3]			  = -1.0f;
440 
441 	// read pixel
442 	gl.readPixels(size.x() / 2, size.y() / 2, 1, 1, GL_RGBA, GL_FLOAT, centerPixel);
443 
444 	tcu::Vec4 desiredColor(centerPixel[0], centerPixel[1], centerPixel[2], centerPixel[3]);
445 
446 	delete[] centerPixel;
447 
448 	// validation
449 	return ShaderBallotBaseTestCase::validateScreenPixels(context, desiredColor, ignoredColor);
450 }
451 
validateColor(tcu::Vec4 testedColor,tcu::Vec4 desiredColor)452 bool ShaderBallotBaseTestCase::validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor)
453 {
454 	const float epsilon = 0.008f;
455 	return de::abs(testedColor.x() - desiredColor.x()) < epsilon &&
456 		   de::abs(testedColor.y() - desiredColor.y()) < epsilon &&
457 		   de::abs(testedColor.z() - desiredColor.z()) < epsilon &&
458 		   de::abs(testedColor.w() - desiredColor.w()) < epsilon;
459 }
460 
461 /** Constructor.
462 *
463 *  @param context Rendering context
464 */
ShaderBallotAvailabilityTestCase(deqp::Context & context)465 ShaderBallotAvailabilityTestCase::ShaderBallotAvailabilityTestCase(deqp::Context& context)
466 	: ShaderBallotBaseTestCase(context, "ShaderBallotAvailability",
467 							   "Implements verification of availability for new build-in features")
468 {
469 	std::string colorShaderSnippet =
470 		"	float red = gl_SubGroupSizeARB / 64.0f;\n"
471 		"	float green = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
472 		"	float blue = float(ballotARB(true) % 256) / 256.0f;\n"
473 		"	outColor = readInvocationARB(vec4(red, green, blue, 1.0f), gl_SubGroupInvocationARB);\n";
474 
475 	for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
476 	{
477 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet));
478 	}
479 }
480 
481 /** Initializes the test
482 */
init()483 void ShaderBallotAvailabilityTestCase::init()
484 {
485 }
486 
487 /** Executes test iteration.
488 *
489 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
490 */
iterate()491 tcu::TestNode::IterateResult ShaderBallotAvailabilityTestCase::iterate()
492 {
493 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
494 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
495 	{
496 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
497 		return STOP;
498 	}
499 
500 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
501 	{
502 		createShaderPrograms(**iter);
503 	}
504 
505 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
506 
507 	for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
508 		 ++pipelineIter)
509 	{
510 		gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
511 		gl.clear(GL_COLOR_BUFFER_BIT);
512 
513 		(*pipelineIter)->test(m_context);
514 
515 		gl.flush();
516 	}
517 
518 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
519 	return STOP;
520 }
521 
522 /** Constructor.
523 *
524 *  @param context Rendering context
525 */
ShaderBallotBitmasksTestCase(deqp::Context & context)526 ShaderBallotBitmasksTestCase::ShaderBallotBitmasksTestCase(deqp::Context& context)
527 	: ShaderBallotBaseTestCase(context, "ShaderBallotBitmasks",
528 							   "Implements verification of values of gl_SubGroup*MaskARB variables")
529 {
530 	m_maskVars["gl_SubGroupEqMaskARB"] = "==";
531 	m_maskVars["gl_SubGroupGeMaskARB"] = ">=";
532 	m_maskVars["gl_SubGroupGtMaskARB"] = ">";
533 	m_maskVars["gl_SubGroupLeMaskARB"] = "<=";
534 	m_maskVars["gl_SubGroupLtMaskARB"] = "<";
535 
536 	std::string colorShaderSnippet = "	uint64_t mask = 0;\n"
537 									 "	for(uint i = 0; i < gl_SubGroupSizeARB; ++i)\n"
538 									 "	{\n"
539 									 "		if(i ${MASK_OPERATOR} gl_SubGroupInvocationARB)\n"
540 									 "			mask = mask | (1ul << i);\n"
541 									 "	}\n"
542 									 "	float color = (${MASK_VAR} ^ mask) == 0ul ? 1.0 : 0.0;\n"
543 									 "	outColor = vec4(color, color, color, 1.0);\n";
544 
545 	for (MaskVarIter maskIter = m_maskVars.begin(); maskIter != m_maskVars.end(); maskIter++)
546 	{
547 		for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
548 		{
549 			std::map<std::string, std::string> specMap;
550 			specMap["MASK_VAR"]		 = maskIter->first;
551 			specMap["MASK_OPERATOR"] = maskIter->second;
552 			m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet, specMap));
553 		}
554 	}
555 }
556 
557 /** Initializes the test
558 */
init()559 void ShaderBallotBitmasksTestCase::init()
560 {
561 }
562 
563 /** Executes test iteration.
564 *
565 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
566 */
iterate()567 tcu::TestNode::IterateResult ShaderBallotBitmasksTestCase::iterate()
568 {
569 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
570 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
571 	{
572 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
573 		return STOP;
574 	}
575 
576 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
577 	{
578 		createShaderPrograms(**iter);
579 	}
580 
581 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
582 
583 	for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
584 		 ++pipelineIter)
585 	{
586 		gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
587 		gl.clear(GL_COLOR_BUFFER_BIT);
588 
589 		(*pipelineIter)->test(m_context);
590 
591 		gl.flush();
592 
593 		bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
594 			m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
595 		TCU_CHECK_MSG(validationResult, "Bitmask value is not correct");
596 	}
597 
598 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
599 	return STOP;
600 }
601 
602 /** Constructor.
603 *
604 *  @param context Rendering context
605 */
ShaderBallotFunctionBallotTestCase(deqp::Context & context)606 ShaderBallotFunctionBallotTestCase::ShaderBallotFunctionBallotTestCase(deqp::Context& context)
607 	: ShaderBallotBaseTestCase(context, "ShaderBallotFunctionBallot",
608 							   "Implements verification of ballotARB calls and returned results")
609 {
610 	std::string ballotFalseSnippet = "	uint64_t result = ballotARB(false);\n"
611 									 "	float color = result == 0ul ? 1.0 : 0.0;\n"
612 									 "	outColor = vec4(color, color, color, 1.0);\n";
613 
614 	std::string ballotTrueSnippet = "	uint64_t result = ballotARB(true);\n"
615 									"	float color = result != 0ul ? 1.0 : 0.0;\n"
616 									"	uint64_t invocationBit = 1ul << gl_SubGroupInvocationARB;\n"
617 									"	color *= float(invocationBit & result);\n"
618 									"	outColor = vec4(color, color, color, 1.0);\n";
619 
620 	std::string ballotMixedSnippet = "	bool param = (gl_SubGroupInvocationARB % 2) == 0ul;\n"
621 									 "	uint64_t result = ballotARB(param);\n"
622 									 "	float color = (param && result != 0ul) || !param ? 1.0 : 0.0;\n"
623 									 "	outColor = vec4(color, color, color, 1.0);\n";
624 
625 	for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
626 	{
627 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotFalseSnippet));
628 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotTrueSnippet));
629 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotMixedSnippet));
630 	}
631 }
632 
633 /** Initializes the test
634 */
init()635 void ShaderBallotFunctionBallotTestCase::init()
636 {
637 }
638 
639 /** Executes test iteration.
640 *
641 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
642 */
iterate()643 tcu::TestNode::IterateResult ShaderBallotFunctionBallotTestCase::iterate()
644 {
645 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
646 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
647 	{
648 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
649 		return STOP;
650 	}
651 
652 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
653 	{
654 		createShaderPrograms(**iter);
655 	}
656 
657 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
658 
659 	for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
660 		 ++pipelineIter)
661 	{
662 		gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
663 		gl.clear(GL_COLOR_BUFFER_BIT);
664 
665 		(*pipelineIter)->test(m_context);
666 
667 		gl.flush();
668 
669 		bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
670 			m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
671 		TCU_CHECK_MSG(validationResult, "Value returned from ballotARB function is not correct");
672 	}
673 
674 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
675 	return STOP;
676 }
677 
678 /** Constructor.
679 *
680 *  @param context Rendering context
681 */
ShaderBallotFunctionReadTestCase(deqp::Context & context)682 ShaderBallotFunctionReadTestCase::ShaderBallotFunctionReadTestCase(deqp::Context& context)
683 	: ShaderBallotBaseTestCase(context, "ShaderBallotFunctionRead",
684 							   "Implements verification of readInvocationARB and readFirstInvocationARB function calls")
685 {
686 	std::string readFirstInvSnippet = "float color = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
687 									  "outColor = readFirstInvocationARB(vec4(color, color, color, 1.0f));\n";
688 
689 	std::string readInvSnippet = "float color = 1.0 - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
690 								 "uvec2 parts = unpackUint2x32(ballotARB(true));\n"
691 								 "uint invocation;\n"
692 								 "if (parts.x != 0) {\n"
693 								 "    invocation = findLSB(parts.x);\n"
694 								 "} else {\n"
695 								 "    invocation = findLSB(parts.y) + 32;\n"
696 								 "}\n"
697 								 "outColor = readInvocationARB(vec4(color, color, color, 1.0f), invocation);\n";
698 
699 	for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
700 	{
701 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readFirstInvSnippet));
702 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readInvSnippet));
703 	}
704 }
705 
706 /** Initializes the test
707 */
init()708 void ShaderBallotFunctionReadTestCase::init()
709 {
710 }
711 
712 /** Executes test iteration.
713 *
714 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
715 */
iterate()716 tcu::TestNode::IterateResult ShaderBallotFunctionReadTestCase::iterate()
717 {
718 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
719 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
720 	{
721 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
722 		return STOP;
723 	}
724 
725 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
726 	{
727 		createShaderPrograms(**iter);
728 	}
729 
730 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
731 	const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget();
732 
733 	gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
734 	gl.viewport(renderTarget.getWidth() / 2 - 1, renderTarget.getHeight() / 2 - 1, 2, 2);
735 
736 	for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
737 		 ++pipelineIter)
738 	{
739 		gl.clear(GL_COLOR_BUFFER_BIT);
740 
741 		(*pipelineIter)->test(m_context);
742 
743 		gl.flush();
744 
745 		bool validationResult =
746 			ShaderBallotBaseTestCase::validateScreenPixelsSameColor(m_context, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
747 		TCU_CHECK_MSG(validationResult, "Read functions result is not correct");
748 	}
749 
750 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
751 	return STOP;
752 }
753 
754 /** Constructor.
755 *
756 *  @param context Rendering context.
757 **/
ShaderBallotTests(deqp::Context & context)758 ShaderBallotTests::ShaderBallotTests(deqp::Context& context)
759 	: TestCaseGroup(context, "shader_ballot_tests", "Verify conformance of CTS_ARB_shader_ballot implementation")
760 {
761 }
762 
763 /** Initializes the shader_ballot test group.
764 *
765 **/
init(void)766 void ShaderBallotTests::init(void)
767 {
768 	addChild(new ShaderBallotAvailabilityTestCase(m_context));
769 	addChild(new ShaderBallotBitmasksTestCase(m_context));
770 	addChild(new ShaderBallotFunctionBallotTestCase(m_context));
771 	addChild(new ShaderBallotFunctionReadTestCase(m_context));
772 }
773 } /* glcts namespace */
774