Home | History | Annotate | Download | only in gl
      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 
     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_LAST; ++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 
    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_LAST; ++shaderType)
    189 	{
    190 		delete[] m_shaderChunks[shaderType];
    191 	}
    192 }
    193 
    194 const char* const* ShaderBallotBaseTestCase::ShaderPipeline::getShaderParts(glu::ShaderType shaderType) const
    195 {
    196 	return m_shaderChunks[shaderType];
    197 }
    198 
    199 unsigned int ShaderBallotBaseTestCase::ShaderPipeline::getShaderPartsCount(glu::ShaderType shaderType) const
    200 {
    201 	return m_shaders[shaderType].size();
    202 }
    203 
    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 
    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 
    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 
    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 
    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 
    368 ShaderBallotBaseTestCase::~ShaderBallotBaseTestCase()
    369 {
    370 	for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
    371 	{
    372 		delete *iter;
    373 	}
    374 }
    375 
    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 
    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 
    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 */
    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_LAST; ++i)
    476 	{
    477 		m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet));
    478 	}
    479 }
    480 
    481 /** Initializes the test
    482 */
    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 */
    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 */
    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_LAST; ++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 */
    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 */
    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 */
    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_LAST; ++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 */
    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 */
    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 */
    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_LAST; ++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 */
    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 */
    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 **/
    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 **/
    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