1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 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 gl4cShaderAtomicCounterOpsTests.cpp 21 * \brief Conformance tests for the ARB_shader_atomic_counter_ops functionality. 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "gl4cShaderAtomicCounterOpsTests.hpp" 25 #include "gluContextInfo.hpp" 26 #include "gluDefs.hpp" 27 #include "gluDrawUtil.hpp" 28 #include "gluObjectWrapper.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "glwEnums.hpp" 31 #include "glwFunctions.hpp" 32 #include "tcuRenderTarget.hpp" 33 34 #include <algorithm> 35 #include <sstream> 36 #include <string> 37 38 using namespace glw; 39 40 namespace gl4cts 41 { 42 43 ShaderAtomicCounterOpsTestBase::ShaderPipeline::ShaderPipeline(glu::ShaderType testedShader, AtomicOperation* newOp, 44 bool contextGL46) 45 : m_program(NULL), m_programCompute(NULL), m_testedShader(testedShader), m_atomicOp(newOp) 46 { 47 m_shaders[glu::SHADERTYPE_VERTEX] = "<version>\n" 48 "<head>" 49 "in highp vec2 inPosition;\n" 50 "out highp vec3 vsPosition;\n" 51 "out highp vec4 vsColor;\n" 52 "void main()\n" 53 "{\n" 54 " gl_Position = vec4(inPosition, 0.0, 1.0);\n" 55 " vsPosition = vec3(inPosition, 0.0);\n" 56 " vec4 outColor = vec4(1.0);\n" 57 "<atomic_operation>" 58 " vsColor = outColor;\n" 59 "}\n"; 60 61 m_shaders[glu::SHADERTYPE_FRAGMENT] = "<version>\n" 62 "<head>" 63 "in highp vec4 gsColor;\n" 64 "out highp vec4 fsColor;\n" 65 "void main()\n" 66 "{\n" 67 " vec4 outColor = gsColor; \n" 68 "<atomic_operation>" 69 " fsColor = outColor;\n" 70 "}\n"; 71 72 m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL] = "<version>\n" 73 "<head>" 74 "layout(vertices = 3) out;\n" 75 "in highp vec4 vsColor[];\n" 76 "in highp vec3 vsPosition[];\n" 77 "out highp vec3 tcsPosition[];\n" 78 "out highp vec4 tcsColor[];\n" 79 "void main()\n" 80 "{\n" 81 " tcsPosition[gl_InvocationID] = vsPosition[gl_InvocationID];\n" 82 " vec4 outColor = vsColor[gl_InvocationID];\n" 83 "<atomic_operation>" 84 " tcsColor[gl_InvocationID] = outColor;\n" 85 " gl_TessLevelInner[0] = 3;\n" 86 " gl_TessLevelOuter[0] = 3;\n" 87 " gl_TessLevelOuter[1] = 3;\n" 88 " gl_TessLevelOuter[2] = 3;\n" 89 "}\n"; 90 91 m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION] = "<version>\n" 92 "<head>" 93 "layout(triangles, equal_spacing, cw) in;\n" 94 "in highp vec3 tcsPosition[];\n" 95 "in highp vec4 tcsColor[];\n" 96 "out highp vec4 tesColor;\n" 97 "void main()\n" 98 "{\n" 99 " vec3 p0 = gl_TessCoord.x * tcsPosition[0];\n" 100 " vec3 p1 = gl_TessCoord.y * tcsPosition[1];\n" 101 " vec3 p2 = gl_TessCoord.z * tcsPosition[2];\n" 102 " vec4 outColor = tcsColor[0];\n" 103 "<atomic_operation>" 104 " tesColor = outColor;\n" 105 " gl_Position = vec4(normalize(p0 + p1 + p2), 1.0);\n" 106 "}\n"; 107 108 m_shaders[glu::SHADERTYPE_GEOMETRY] = "<version>\n" 109 "<head>" 110 "layout(triangles) in;\n" 111 "layout(triangle_strip, max_vertices = 3) out;\n" 112 "in highp vec4 tesColor[];\n" 113 "out highp vec4 gsColor;\n" 114 "void main()\n" 115 "{\n" 116 " for (int i = 0; i<3; i++)\n" 117 " {\n" 118 " gl_Position = gl_in[i].gl_Position;\n" 119 " vec4 outColor = tesColor[i];\n" 120 "<atomic_operation>" 121 " gsColor = outColor;\n" 122 " EmitVertex();\n" 123 " }\n" 124 " EndPrimitive();\n" 125 "}\n"; 126 127 m_shaders[glu::SHADERTYPE_COMPUTE] = "<version>\n" 128 "<head>" 129 "layout(rgba32f, binding = 2) writeonly uniform highp image2D destImage;\n" 130 "layout (local_size_x = 16, local_size_y = 16) in;\n" 131 "void main (void)\n" 132 "{\n" 133 " vec4 outColor = vec4(1.0);\n" 134 "<atomic_operation>" 135 " imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n" 136 "}\n"; 137 138 // prepare shaders 139 140 std::string postfix(contextGL46 ? "" : "ARB"); 141 std::stringstream atomicOperationStream; 142 atomicOperationStream << "uint returned = " << m_atomicOp->getFunction() + postfix + "(counter, "; 143 if (m_atomicOp->getCompareValue() != 0) 144 { 145 atomicOperationStream << m_atomicOp->getCompareValue(); 146 atomicOperationStream << "u, "; 147 } 148 atomicOperationStream << m_atomicOp->getParamValue(); 149 atomicOperationStream << "u);\n"; 150 atomicOperationStream << "uint after = atomicCounter(counter);\n"; 151 152 if (m_atomicOp->shouldTestReturnValue()) 153 { 154 atomicOperationStream << "if(after == returned) outColor = vec4(0.0f);\n"; 155 } 156 157 atomicOperationStream << "atomicCounterIncrement(calls);\n"; 158 159 std::string versionString; 160 std::string headString; 161 if (contextGL46) 162 { 163 versionString = "#version 460 core"; 164 headString = "layout (binding=0) uniform atomic_uint counter;\n" 165 "layout (binding=1) uniform atomic_uint calls;\n"; 166 } 167 else 168 { 169 versionString = "#version 450 core"; 170 headString = "#extension GL_ARB_shader_atomic_counters: enable\n" 171 "#extension GL_ARB_shader_atomic_counter_ops: enable\n" 172 "layout (binding=0) uniform atomic_uint counter;\n" 173 "layout (binding=1) uniform atomic_uint calls;\n"; 174 } 175 176 for (unsigned int i = 0; i < glu::SHADERTYPE_LAST; ++i) 177 { 178 prepareShader(m_shaders[i], "<version>", versionString); 179 prepareShader(m_shaders[i], "<head>", i == testedShader ? headString : ""); 180 prepareShader(m_shaders[i], "<atomic_operation>", i == testedShader ? atomicOperationStream.str() : ""); 181 } 182 } 183 184 ShaderAtomicCounterOpsTestBase::ShaderPipeline::~ShaderPipeline() 185 { 186 if (m_program) 187 { 188 delete m_program; 189 } 190 191 if (m_programCompute) 192 { 193 delete m_programCompute; 194 } 195 } 196 197 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::prepareShader(std::string& shader, const std::string& tag, 198 const std::string& value) 199 { 200 size_t tagPos = shader.find(tag); 201 202 if (tagPos != std::string::npos) 203 shader.replace(tagPos, tag.length(), value); 204 } 205 206 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::create(deqp::Context& context) 207 { 208 glu::ProgramSources sources; 209 for (unsigned int i = 0; i < glu::SHADERTYPE_COMPUTE; ++i) 210 { 211 if (!m_shaders[i].empty()) 212 { 213 sources.sources[i].push_back(m_shaders[i]); 214 } 215 } 216 m_program = new glu::ShaderProgram(context.getRenderContext(), sources); 217 218 if (!m_program->isOk()) 219 { 220 TCU_FAIL("Shader compilation failed"); 221 } 222 223 glu::ProgramSources sourcesCompute; 224 sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(m_shaders[glu::SHADERTYPE_COMPUTE]); 225 m_programCompute = new glu::ShaderProgram(context.getRenderContext(), sourcesCompute); 226 227 if (!m_programCompute->isOk()) 228 { 229 TCU_FAIL("Shader compilation failed"); 230 } 231 } 232 233 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::use(deqp::Context& context) 234 { 235 const glw::Functions& gl = context.getRenderContext().getFunctions(); 236 gl.useProgram(m_program->getProgram()); 237 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed"); 238 } 239 240 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::test(deqp::Context& context) 241 { 242 const glw::Functions& gl = context.getRenderContext().getFunctions(); 243 244 gl.clearColor(0.5f, 0.5f, 0.5f, 1.0f); 245 gl.clear(GL_COLOR_BUFFER_BIT); 246 247 if (m_testedShader == glu::SHADERTYPE_COMPUTE) 248 { 249 executeComputeShader(context); 250 } 251 else 252 { 253 renderQuad(context); 254 } 255 256 gl.flush(); 257 } 258 259 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::renderQuad(deqp::Context& context) 260 { 261 const glw::Functions& gl = context.getRenderContext().getFunctions(); 262 263 deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 264 265 float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; 266 267 glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, position) }; 268 269 this->use(context); 270 271 glu::PrimitiveList primitiveList = glu::pr::Patches(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices); 272 273 glu::draw(context.getRenderContext(), this->getShaderProgram()->getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), 274 vertexArrays, primitiveList); 275 276 GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error"); 277 278 gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 279 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() error"); 280 } 281 282 void ShaderAtomicCounterOpsTestBase::ShaderPipeline::executeComputeShader(deqp::Context& context) 283 { 284 const glw::Functions& gl = context.getRenderContext().getFunctions(); 285 286 const glu::Texture outputTexture(context.getRenderContext()); 287 288 gl.useProgram(m_programCompute->getProgram()); 289 290 // output image 291 gl.bindTexture(GL_TEXTURE_2D, *outputTexture); 292 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 16, 16); 293 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 294 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 295 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading image data failed"); 296 297 // bind image 298 gl.bindImageTexture(2, *outputTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 299 GLU_EXPECT_NO_ERROR(gl.getError(), "Image setup failed"); 300 301 // dispatch compute 302 gl.dispatchCompute(1, 1, 1); 303 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() error"); 304 gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 305 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() error"); 306 307 // render output texture 308 309 std::string vs = "#version 450 core\n" 310 "in highp vec2 position;\n" 311 "in vec2 inTexcoord;\n" 312 "out vec2 texcoord;\n" 313 "void main()\n" 314 "{\n" 315 " texcoord = inTexcoord;\n" 316 " gl_Position = vec4(position, 0.0, 1.0);\n" 317 "}\n"; 318 319 std::string fs = "#version 450 core\n" 320 "uniform sampler2D sampler;\n" 321 "in vec2 texcoord;\n" 322 "out vec4 color;\n" 323 "void main()\n" 324 "{\n" 325 " color = texture(sampler, texcoord);\n" 326 "}\n"; 327 328 glu::ProgramSources sources; 329 sources.sources[glu::SHADERTYPE_VERTEX].push_back(vs); 330 sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fs); 331 glu::ShaderProgram renderShader(context.getRenderContext(), sources); 332 333 if (!m_program->isOk()) 334 { 335 TCU_FAIL("Shader compilation failed"); 336 } 337 338 gl.bindTexture(GL_TEXTURE_2D, *outputTexture); 339 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 340 341 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 342 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 343 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri failed"); 344 345 gl.useProgram(renderShader.getProgram()); 346 GLU_EXPECT_NO_ERROR(gl.getError(), "useProgram failed"); 347 348 gl.uniform1i(gl.getUniformLocation(renderShader.getProgram(), "sampler"), 0); 349 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed"); 350 351 deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 352 353 float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; 354 355 float const texCoord[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; 356 357 glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("position", 2, 4, 0, position), 358 glu::va::Float("inTexcoord", 2, 4, 0, texCoord) }; 359 360 glu::draw(context.getRenderContext(), renderShader.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, 361 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices)); 362 363 GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error"); 364 } 365 366 void ShaderAtomicCounterOpsTestBase::fillAtomicCounterBuffer(AtomicOperation* atomicOp) 367 { 368 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 369 370 GLuint* dataPtr; 371 372 // fill values buffer 373 374 GLuint inputValue = atomicOp->getInputValue(); 375 376 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer); 377 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 378 379 dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), 380 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT); 381 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed."); 382 383 *dataPtr = inputValue; 384 385 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 386 GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed."); 387 388 // fill calls buffer 389 390 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer); 391 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 392 393 dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), 394 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT); 395 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed."); 396 397 *dataPtr = 0; 398 399 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 400 GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed."); 401 } 402 403 bool ShaderAtomicCounterOpsTestBase::checkAtomicCounterBuffer(AtomicOperation* atomicOp) 404 { 405 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 406 407 GLuint* dataPtr; 408 409 // get value 410 411 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer); 412 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 413 414 dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT); 415 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed."); 416 417 GLuint finalValue = *dataPtr; 418 419 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 420 GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed."); 421 422 // get calls 423 424 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer); 425 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 426 427 dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT); 428 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed."); 429 430 GLuint numberOfCalls = *dataPtr; 431 432 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 433 GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed."); 434 435 // validate 436 437 GLuint expectedValue = atomicOp->getResult(numberOfCalls); 438 439 return finalValue == expectedValue; 440 } 441 442 void ShaderAtomicCounterOpsTestBase::bindBuffers() 443 { 444 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 445 446 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_atomicCounterBuffer); 447 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferBase() call failed."); 448 449 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 1, m_atomicCounterCallsBuffer); 450 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferBase() call failed."); 451 } 452 453 bool ShaderAtomicCounterOpsTestBase::validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor) 454 { 455 const float epsilon = 1.1f / 31.0f; // Accommodate framebuffers with 5-bit channels. 456 return de::abs(testedColor.x() - desiredColor.x()) < epsilon && 457 de::abs(testedColor.y() - desiredColor.y()) < epsilon && 458 de::abs(testedColor.z() - desiredColor.z()) < epsilon; 459 } 460 461 bool ShaderAtomicCounterOpsTestBase::validateScreenPixels(tcu::Vec4 desiredColor, tcu::Vec4 ignoredColor) 462 { 463 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 464 const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget(); 465 tcu::IVec2 size(renderTarget.getWidth(), renderTarget.getHeight()); 466 467 glw::GLfloat* pixels = new glw::GLfloat[size.x() * size.y() * 4]; 468 469 // clear buffer 470 for (int x = 0; x < size.x(); ++x) 471 { 472 for (int y = 0; y < size.y(); ++y) 473 { 474 int mappedPixelPosition = y * size.x() + x; 475 476 pixels[mappedPixelPosition * 4 + 0] = -1.0f; 477 pixels[mappedPixelPosition * 4 + 1] = -1.0f; 478 pixels[mappedPixelPosition * 4 + 2] = -1.0f; 479 pixels[mappedPixelPosition * 4 + 3] = -1.0f; 480 } 481 } 482 483 // read pixels 484 gl.readPixels(0, 0, size.x(), size.y(), GL_RGBA, GL_FLOAT, pixels); 485 486 // validate pixels 487 bool rendered = false; 488 for (int x = 0; x < size.x(); ++x) 489 { 490 for (int y = 0; y < size.y(); ++y) 491 { 492 int mappedPixelPosition = y * size.x() + x; 493 494 tcu::Vec4 color(pixels[mappedPixelPosition * 4 + 0], pixels[mappedPixelPosition * 4 + 1], 495 pixels[mappedPixelPosition * 4 + 2], pixels[mappedPixelPosition * 4 + 3]); 496 497 if (!validateColor(color, ignoredColor)) 498 { 499 rendered = true; 500 if (!validateColor(color, desiredColor)) 501 { 502 delete[] pixels; 503 return false; 504 } 505 } 506 } 507 } 508 509 delete[] pixels; 510 511 return rendered; 512 } 513 514 ShaderAtomicCounterOpsTestBase::ShaderAtomicCounterOpsTestBase(deqp::Context& context, const char* name, 515 const char* description) 516 : TestCase(context, name, description), m_atomicCounterBuffer(0), m_atomicCounterCallsBuffer(0) 517 { 518 glu::ContextType contextType = m_context.getRenderContext().getType(); 519 m_contextSupportsGL46 = glu::contextSupports(contextType, glu::ApiType::core(4, 6)); 520 } 521 522 void ShaderAtomicCounterOpsTestBase::init() 523 { 524 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 525 526 // generate atomic counter buffer 527 528 gl.genBuffers(1, &m_atomicCounterBuffer); 529 GLU_EXPECT_NO_ERROR(gl.getError(), "genBuffers() call failed."); 530 531 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer); 532 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 533 534 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); 535 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData() call failed."); 536 537 // generate atomic counter calls buffer 538 539 gl.genBuffers(1, &m_atomicCounterCallsBuffer); 540 GLU_EXPECT_NO_ERROR(gl.getError(), "genBuffers() call failed."); 541 542 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer); 543 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed."); 544 545 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); 546 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData() call failed."); 547 548 // setup tested atomic operations 549 550 setOperations(); 551 552 // setup shaders 553 554 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter) 555 { 556 iter->create(m_context); 557 } 558 } 559 560 void ShaderAtomicCounterOpsTestBase::deinit() 561 { 562 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 563 564 // delete atomic counter buffer 565 566 gl.deleteBuffers(1, &m_atomicCounterBuffer); 567 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteBuffers() call failed."); 568 569 // delete atomic counter calls buffer 570 571 gl.deleteBuffers(1, &m_atomicCounterCallsBuffer); 572 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteBuffers() call failed."); 573 574 // delete operations 575 576 for (AtomicOperationIter iter = m_operations.begin(); iter != m_operations.end(); ++iter) 577 { 578 delete *iter; 579 } 580 } 581 582 tcu::TestNode::IterateResult ShaderAtomicCounterOpsTestBase::iterate() 583 { 584 if (!m_contextSupportsGL46) 585 { 586 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters") || 587 !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counter_ops")) 588 { 589 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 590 return STOP; 591 } 592 } 593 594 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter) 595 { 596 fillAtomicCounterBuffer(iter->getAtomicOperation()); 597 bindBuffers(); 598 iter->test(m_context); 599 600 bool operationValueValid = checkAtomicCounterBuffer(iter->getAtomicOperation()); 601 std::string operationFailMsg = "Result of atomic operation was different than expected (" + 602 iter->getAtomicOperation()->getFunction() + ")."; 603 TCU_CHECK_MSG(operationValueValid, operationFailMsg.c_str()); 604 605 bool returnValueValid = validateScreenPixels(tcu::Vec4(1.0f), tcu::Vec4(0.5f)); 606 std::string returnFailMsg = "Result of atomic operation return value was different than expected (" + 607 iter->getAtomicOperation()->getFunction() + ")."; 608 TCU_CHECK_MSG(returnValueValid, returnFailMsg.c_str()); 609 } 610 611 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 612 return STOP; 613 } 614 615 /** Constructor. 616 * 617 * @param context Rendering context 618 */ 619 ShaderAtomicCounterOpsAdditionSubstractionTestCase::ShaderAtomicCounterOpsAdditionSubstractionTestCase( 620 deqp::Context& context) 621 : ShaderAtomicCounterOpsTestBase( 622 context, "ShaderAtomicCounterOpsAdditionSubstractionTestCase", 623 "Implements verification of new built-in addition and substraction atomic counter operations") 624 { 625 } 626 627 void ShaderAtomicCounterOpsAdditionSubstractionTestCase::setOperations() 628 { 629 glw::GLuint input = 12; 630 glw::GLuint param = 4; 631 632 addOperation(new AtomicOperationAdd(input, param)); 633 addOperation(new AtomicOperationSubtract(input, param)); 634 } 635 636 /** Constructor. 637 * 638 * @param context Rendering context 639 */ 640 ShaderAtomicCounterOpsMinMaxTestCase::ShaderAtomicCounterOpsMinMaxTestCase(deqp::Context& context) 641 : ShaderAtomicCounterOpsTestBase( 642 context, "ShaderAtomicCounterOpsMinMaxTestCase", 643 "Implements verification of new built-in minimum and maximum atomic counter operations") 644 { 645 } 646 647 void ShaderAtomicCounterOpsMinMaxTestCase::setOperations() 648 { 649 glw::GLuint input = 12; 650 glw::GLuint params[] = { 4, 16 }; 651 652 addOperation(new AtomicOperationMin(input, params[0])); 653 addOperation(new AtomicOperationMin(input, params[1])); 654 addOperation(new AtomicOperationMax(input, params[0])); 655 addOperation(new AtomicOperationMax(input, params[1])); 656 } 657 658 /** Constructor. 659 * 660 * @param context Rendering context 661 */ 662 ShaderAtomicCounterOpsBitwiseTestCase::ShaderAtomicCounterOpsBitwiseTestCase(deqp::Context& context) 663 : ShaderAtomicCounterOpsTestBase(context, "ShaderAtomicCounterOpsBitwiseTestCase", 664 "Implements verification of new built-in bitwise atomic counter operations") 665 { 666 } 667 668 void ShaderAtomicCounterOpsBitwiseTestCase::setOperations() 669 { 670 glw::GLuint input = 0x2ED; // 0b1011101101; 671 glw::GLuint param = 0x3A9; // 0b1110101001; 672 673 addOperation(new AtomicOperationAnd(input, param)); 674 addOperation(new AtomicOperationOr(input, param)); 675 addOperation(new AtomicOperationXor(input, param)); 676 } 677 678 /** Constructor. 679 * 680 * @param context Rendering context 681 */ 682 ShaderAtomicCounterOpsExchangeTestCase::ShaderAtomicCounterOpsExchangeTestCase(deqp::Context& context) 683 : ShaderAtomicCounterOpsTestBase( 684 context, "ShaderAtomicCounterOpsExchangeTestCase", 685 "Implements verification of new built-in exchange and swap atomic counter operations") 686 { 687 } 688 689 void ShaderAtomicCounterOpsExchangeTestCase::setOperations() 690 { 691 glw::GLuint input = 5; 692 glw::GLuint param = 10; 693 glw::GLuint compare[] = { 5, 20 }; 694 695 addOperation(new AtomicOperationExchange(input, param)); 696 addOperation(new AtomicOperationCompSwap(input, param, compare[0])); 697 addOperation(new AtomicOperationCompSwap(input, param, compare[1])); 698 } 699 700 /** Constructor. 701 * 702 * @param context Rendering context. 703 */ 704 ShaderAtomicCounterOps::ShaderAtomicCounterOps(deqp::Context& context) 705 : TestCaseGroup(context, "shader_atomic_counter_ops_tests", 706 "Verify conformance of CTS_ARB_shader_atomic_counter_ops implementation") 707 { 708 } 709 710 /** Initializes the test group contents. */ 711 void ShaderAtomicCounterOps::init() 712 { 713 addChild(new ShaderAtomicCounterOpsAdditionSubstractionTestCase(m_context)); 714 addChild(new ShaderAtomicCounterOpsMinMaxTestCase(m_context)); 715 addChild(new ShaderAtomicCounterOpsBitwiseTestCase(m_context)); 716 addChild(new ShaderAtomicCounterOpsExchangeTestCase(m_context)); 717 } 718 } /* gl4cts namespace */ 719