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