1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2018 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 * \file glcLayoutLocationTests.cpp 20 * \brief 21 */ /*-------------------------------------------------------------------*/ 22 #include "glcLayoutLocationTests.hpp" 23 24 #include "tcuRenderTarget.hpp" 25 #include "tcuStringTemplate.hpp" 26 #include "tcuSurface.hpp" 27 #include "tcuTestLog.hpp" 28 #include "tcuTexture.hpp" 29 #include "tcuTextureUtil.hpp" 30 31 #include "deStringUtil.hpp" 32 33 #include "glwDefs.hpp" 34 #include "glwEnums.hpp" 35 #include "glwFunctions.hpp" 36 37 #include "gluDrawUtil.hpp" 38 #include "gluPixelTransfer.hpp" 39 #include "gluShaderProgram.hpp" 40 #include "gluTexture.hpp" 41 #include "gluTextureUtil.hpp" 42 43 using namespace glw; 44 45 namespace glcts 46 { 47 48 static const GLuint WIDTH = 2; 49 static const GLuint HEIGHT = 2; 50 51 // Helper function used to set texture parameters 52 void setTexParameters(const Functions& gl, GLenum target, bool depthTexture) 53 { 54 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 55 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 56 57 if (depthTexture) 58 { 59 gl.texParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 60 gl.texParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LESS); 61 } 62 } 63 64 // Helper function used to create texture data 65 template <typename DATA_TYPE> 66 std::vector<DATA_TYPE> generateData(std::size_t width, std::size_t height, std::size_t components) 67 { 68 DE_ASSERT((components == 1) || (components == 4)); 69 std::size_t size = width * height * components; 70 std::vector<DATA_TYPE> data(size, 0); 71 for (std::size_t i = 0; i < size; i += components) 72 data[i] = static_cast<DATA_TYPE>(255); 73 return data; 74 } 75 76 // Structure used to return id of created object it had to be defined to support 77 // GL_TEXTURE_BUFFER cases which require creation of both texture and buffer 78 struct ResultData 79 { 80 deUint32 textureId; // id of created texture 81 deUint32 bufferId; // used only by GL_TEXTURE_BUFFER 82 83 ResultData(deUint32 tId) : textureId(tId), bufferId(0) 84 { 85 } 86 87 ResultData(deUint32 tId, deUint32 bId) : textureId(tId), bufferId(bId) 88 { 89 } 90 }; 91 92 template <typename DATA_TYPE> 93 ResultData createTexture1D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, 94 GLenum type) 95 { 96 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, 1, components); 97 98 deUint32 id; 99 gl.genTextures(1, &id); 100 gl.bindTexture(GL_TEXTURE_1D, id); 101 gl.texImage1D(GL_TEXTURE_1D, 0, internalFormat, WIDTH, 0, format, type, &data[0]); 102 setTexParameters(gl, GL_TEXTURE_1D, components == 1); 103 return id; 104 } 105 106 template <typename DATA_TYPE> 107 ResultData createTexture2D(const Functions& gl, std::size_t components, GLenum target, GLenum internalFormat, 108 GLenum format, GLenum type) 109 { 110 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); 111 112 deUint32 id; 113 gl.genTextures(1, &id); 114 gl.bindTexture(target, id); 115 gl.texStorage2D(target, 1, internalFormat, WIDTH, HEIGHT); 116 gl.texSubImage2D(target, 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]); 117 setTexParameters(gl, target, components == 1); 118 return id; 119 } 120 121 template <typename DATA_TYPE> 122 ResultData createTexture3D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, 123 GLenum type) 124 { 125 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); 126 127 deUint32 id; 128 gl.genTextures(1, &id); 129 gl.bindTexture(GL_TEXTURE_3D, id); 130 gl.texStorage3D(GL_TEXTURE_3D, 1, internalFormat, WIDTH, HEIGHT, 1); 131 gl.texSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]); 132 setTexParameters(gl, GL_TEXTURE_3D, components == 1); 133 return id; 134 } 135 136 template <typename DATA_TYPE> 137 ResultData createCubeMap(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, GLenum type) 138 { 139 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); 140 141 deUint32 id; 142 gl.genTextures(1, &id); 143 gl.bindTexture(GL_TEXTURE_CUBE_MAP, id); 144 GLenum faces[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 145 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; 146 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalFormat, WIDTH, HEIGHT); 147 for (int i = 0; i < 6; ++i) 148 gl.texSubImage2D(faces[i], 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]); 149 setTexParameters(gl, GL_TEXTURE_CUBE_MAP, components == 1); 150 return id; 151 } 152 153 template <typename DATA_TYPE> 154 ResultData createTexture2DArray(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, 155 GLenum type) 156 { 157 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); 158 159 deUint32 id; 160 gl.genTextures(1, &id); 161 gl.bindTexture(GL_TEXTURE_2D_ARRAY, id); 162 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalFormat, WIDTH, HEIGHT, 1); 163 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]); 164 setTexParameters(gl, GL_TEXTURE_2D_ARRAY, components == 1); 165 return id; 166 } 167 168 template <typename DATA_TYPE> 169 ResultData createTextureBuffer(const Functions& gl, GLenum internalFormat) 170 { 171 std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, 4); 172 173 deUint32 bufferId; 174 gl.genBuffers(1, &bufferId); 175 gl.bindBuffer(GL_TEXTURE_BUFFER, bufferId); 176 gl.bufferData(GL_TEXTURE_BUFFER, WIDTH * HEIGHT * 4 * sizeof(DATA_TYPE), &data[0], GL_STATIC_DRAW); 177 178 deUint32 textureId; 179 gl.genTextures(1, &textureId); 180 gl.bindTexture(GL_TEXTURE_BUFFER, textureId); 181 gl.texBuffer(GL_TEXTURE_BUFFER, internalFormat, bufferId); 182 return ResultData(textureId, bufferId); 183 } 184 185 // create function was implemented for convinience. Specializations of this 186 // template simplify definition of test data by reducting the number of 187 // attributes which were moved to create fn implementation. This aproach 188 // also simplyfies texture creation in the test as create takes just a single 189 // parameter for all test cases. 190 template <GLenum, GLenum> 191 ResultData create(const Functions& gl) 192 { 193 (void)gl; 194 TCU_FAIL("Missing specialization implementation."); 195 } 196 197 template <> 198 ResultData create<GL_TEXTURE_2D, GL_RGBA8>(const Functions& gl) 199 { 200 return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_2D, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 201 } 202 203 template <> 204 ResultData create<GL_TEXTURE_3D, GL_RGBA8>(const Functions& gl) 205 { 206 return createTexture3D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 207 } 208 209 template <> 210 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>(const Functions& gl) 211 { 212 return createCubeMap<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 213 } 214 215 template <> 216 ResultData create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>(const Functions& gl) 217 { 218 return createCubeMap<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); 219 } 220 221 template <> 222 ResultData create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>(const Functions& gl) 223 { 224 return createTexture2D<short>(gl, 1, GL_TEXTURE_2D, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); 225 } 226 227 template <> 228 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>(const Functions& gl) 229 { 230 return createTexture2DArray<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 231 } 232 233 template <> 234 ResultData create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl) 235 { 236 return createTexture2DArray<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); 237 } 238 239 template <> 240 ResultData create<GL_TEXTURE_2D, GL_RGBA32I>(const Functions& gl) 241 { 242 return createTexture2D<int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); 243 } 244 245 template <> 246 ResultData create<GL_TEXTURE_3D, GL_RGBA32I>(const Functions& gl) 247 { 248 return createTexture3D<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); 249 } 250 251 template <> 252 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>(const Functions& gl) 253 { 254 return createCubeMap<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); 255 } 256 257 template <> 258 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>(const Functions& gl) 259 { 260 return createTexture2DArray<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); 261 } 262 263 template <> 264 ResultData create<GL_TEXTURE_2D, GL_RGBA32UI>(const Functions& gl) 265 { 266 return createTexture2D<unsigned int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); 267 } 268 269 template <> 270 ResultData create<GL_TEXTURE_3D, GL_RGBA32UI>(const Functions& gl) 271 { 272 return createTexture3D<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); 273 } 274 275 template <> 276 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>(const Functions& gl) 277 { 278 return createCubeMap<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); 279 } 280 281 template <> 282 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>(const Functions& gl) 283 { 284 return createTexture2DArray<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); 285 } 286 287 template <> 288 ResultData create<GL_TEXTURE_1D, GL_RGBA8>(const Functions& gl) 289 { 290 return createTexture1D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 291 } 292 293 template <> 294 ResultData create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>(const Functions& gl) 295 { 296 return createTexture1D<unsigned char>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); 297 } 298 299 template <> 300 ResultData create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>(const Functions& gl) 301 { 302 return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_1D_ARRAY, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); 303 } 304 305 template <> 306 ResultData create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl) 307 { 308 return createTexture2D<short>(gl, 1, GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, 309 GL_UNSIGNED_SHORT); 310 } 311 312 template <> 313 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32F>(const Functions& gl) 314 { 315 return createTextureBuffer<float>(gl, GL_RGBA32F); 316 } 317 318 template <> 319 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32I>(const Functions& gl) 320 { 321 return createTextureBuffer<int>(gl, GL_RGBA32I); 322 } 323 324 template <> 325 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32UI>(const Functions& gl) 326 { 327 return createTextureBuffer<unsigned int>(gl, GL_RGBA32UI); 328 } 329 330 // Structure used to define all test case data 331 struct SamplerCaseData 332 { 333 typedef ResultData (*CreateFnPtr)(const Functions& gl); 334 335 CreateFnPtr create; // pointer to function that will create texture 336 const char* name; // test case name 337 const char* opaqueType; // sampler or image 338 const char* outAssignment; // operation that determines fragment color 339 const int num_frag_image_uniforms; // the number of required fragment image uniform 340 }; 341 342 class SpecifiedLocationCase : public deqp::TestCase 343 { 344 public: 345 SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data); 346 virtual ~SpecifiedLocationCase(); 347 348 tcu::TestNode::IterateResult iterate(); 349 350 private: 351 ResultData (*m_createFn)(const Functions& gl); 352 std::map<std::string, std::string> m_specializationMap; 353 354 bool m_isImageCase; 355 GLenum m_imageFormat; 356 std::string m_imageFormatQualifier; 357 int m_num_frag_image_uniform; 358 }; 359 360 SpecifiedLocationCase::SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data) 361 : deqp::TestCase(context, data.name, ""), m_createFn(data.create) 362 { 363 std::string type(data.opaqueType); 364 m_specializationMap["OPAQUE_TYPE"] = type; 365 m_specializationMap["OUT_ASSIGNMENT"] = data.outAssignment; 366 367 m_isImageCase = (type.find("sampler") == std::string::npos); 368 if (m_isImageCase) 369 { 370 m_specializationMap["OPAQUE_TYPE_NAME"] = "image"; 371 m_specializationMap["ACCESS"] = "readonly"; 372 373 if (type.find("iimage") != std::string::npos) 374 { 375 m_imageFormatQualifier = "rgba32i"; 376 m_imageFormat = GL_RGBA32I; 377 } 378 else if (type.find("uimage") != std::string::npos) 379 { 380 m_imageFormatQualifier = "rgba32ui"; 381 m_imageFormat = GL_RGBA32UI; 382 } 383 else 384 { 385 m_imageFormatQualifier = "rgba8"; 386 m_imageFormat = GL_RGBA8; 387 } 388 } 389 else 390 { 391 m_specializationMap["OPAQUE_TYPE_NAME"] = "sampler"; 392 m_specializationMap["ACCESS"] = ""; 393 } 394 m_num_frag_image_uniform = data.num_frag_image_uniforms; 395 } 396 397 SpecifiedLocationCase::~SpecifiedLocationCase() 398 { 399 } 400 401 tcu::TestNode::IterateResult SpecifiedLocationCase::iterate(void) 402 { 403 static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 404 static const float positions[] = { -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0 }; 405 406 static const char* vsTemplate = "${VERSION}\n" 407 "precision highp float;\n" 408 "layout(location=0) in highp vec2 inPosition;\n" 409 "layout(location=0) out highp vec2 coords;\n" 410 "void main(void)\n" 411 "{\n" 412 " coords = vec2(max(0.0, inPosition.x), max(0.0, inPosition.y));\n" 413 " gl_Position = vec4(inPosition, 0.0, 1.0);\n" 414 "}\n"; 415 416 static const char* fsTemplate = 417 "${VERSION}\n" 418 "precision highp float;\n" 419 "layout(location=0) in vec2 coords;\n" 420 "layout(location=0) out vec4 fragColor;\n" 421 "layout(${OPAQUE_TYPE_QUALIFIERS}) ${ACCESS} uniform highp ${OPAQUE_TYPE} ${OPAQUE_TYPE_NAME};\n" 422 "void main(void)\n" 423 "{\n" 424 " fragColor = ${OUT_ASSIGNMENT};\n" 425 "}\n"; 426 427 glu::RenderContext& renderContext = m_context.getRenderContext(); 428 glu::ContextType contextType = renderContext.getType(); 429 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType); 430 const Functions& gl = renderContext.getFunctions(); 431 bool contextTypeES = glu::isContextTypeES(contextType); 432 bool contextES32 = glu::contextSupports(contextType, glu::ApiType::es(3, 2)); 433 if (contextTypeES && !contextES32 && !m_context.getContextInfo().isExtensionSupported("GL_ANDROID_extension_pack_es31a")) 434 if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < m_num_frag_image_uniform) 435 throw tcu::NotSupportedError("The number of required fragment image uniform is larger than GL_MAX_FRAGMENT_IMAGE_UNIFORMS"); 436 437 const int expectedLocation = 2; 438 const int definedBinding = 1; 439 440 std::ostringstream layoutSpecification; 441 layoutSpecification << "location=" << expectedLocation; 442 if (m_isImageCase) 443 { 444 if (contextTypeES) 445 layoutSpecification << ", binding=" << definedBinding; 446 layoutSpecification << ", " << m_imageFormatQualifier; 447 } 448 449 m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); 450 m_specializationMap["OPAQUE_TYPE_QUALIFIERS"] = layoutSpecification.str(); 451 452 std::string vs = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap); 453 std::string fs = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap); 454 glu::ShaderProgram program(gl, glu::makeVtxFragSources(vs.c_str(), fs.c_str())); 455 456 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 457 if (!program.isOk()) 458 { 459 m_testCtx.getLog() << program << tcu::TestLog::Message << "Creation of program failed." 460 << tcu::TestLog::EndMessage; 461 return STOP; 462 } 463 464 deUint32 programId = program.getProgram(); 465 int location = gl.getUniformLocation(programId, m_specializationMap["OPAQUE_TYPE_NAME"].c_str()); 466 if (location != expectedLocation) 467 { 468 m_testCtx.getLog() << tcu::TestLog::Message << "Expected uniform to be at location " << expectedLocation 469 << ", not at " << location << "." << tcu::TestLog::EndMessage; 470 return STOP; 471 } 472 473 gl.useProgram(programId); 474 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); 475 476 // Prepare texture/buffer 477 gl.activeTexture(GL_TEXTURE1); 478 ResultData resultData = (*m_createFn)(gl); 479 GLU_EXPECT_NO_ERROR(gl.getError(), "GL object creation failed."); 480 481 if (m_isImageCase) 482 { 483 gl.bindImageTexture(definedBinding, resultData.textureId, 0, GL_TRUE, 0, GL_READ_ONLY, m_imageFormat); 484 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); 485 } 486 487 // in ES image uniforms cannot be updated 488 // through any of the glUniform* commands 489 if (!(contextTypeES && m_isImageCase)) 490 { 491 gl.uniform1i(expectedLocation, definedBinding); 492 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); 493 } 494 495 // Create FBO with RBO 496 deUint32 rboId; 497 deUint32 fboId; 498 gl.genRenderbuffers(1, &rboId); 499 gl.bindRenderbuffer(GL_RENDERBUFFER, rboId); 500 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, WIDTH, HEIGHT); 501 gl.genFramebuffers(1, &fboId); 502 gl.bindFramebuffer(GL_FRAMEBUFFER, fboId); 503 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId); 504 505 // Render 506 gl.viewport(0, 0, WIDTH, HEIGHT); 507 const glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, positions) }; 508 glu::draw(renderContext, programId, DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, 509 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices)); 510 511 // Grab surface 512 tcu::Surface resultFrame(WIDTH, HEIGHT); 513 glu::readPixels(renderContext, 0, 0, resultFrame.getAccess()); 514 515 // Verify color of just first pixel 516 const tcu::RGBA expectedColor(255, 0, 0, 0); 517 tcu::RGBA pixel = resultFrame.getPixel(0, 0); 518 if (pixel != expectedColor) 519 { 520 m_testCtx.getLog() << tcu::TestLog::Message << "Incorrect color was generated, expected: [" 521 << expectedColor.getRed() << ", " << expectedColor.getGreen() << ", " 522 << expectedColor.getBlue() << ", " << expectedColor.getAlpha() << "], got [" 523 << pixel.getRed() << ", " << pixel.getGreen() << ", " << pixel.getBlue() << ", " 524 << pixel.getAlpha() << "]" << tcu::TestLog::EndMessage; 525 } 526 else 527 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 528 529 // Cleanup 530 if (resultData.bufferId) 531 gl.deleteBuffers(1, &resultData.bufferId); 532 gl.deleteFramebuffers(1, &fboId); 533 gl.deleteRenderbuffers(1, &rboId); 534 gl.deleteTextures(1, &resultData.textureId); 535 536 return STOP; 537 } 538 539 class NegativeLocationCase : public deqp::TestCase 540 { 541 public: 542 NegativeLocationCase(deqp::Context& context); 543 virtual ~NegativeLocationCase(); 544 545 tcu::TestNode::IterateResult iterate(); 546 }; 547 548 NegativeLocationCase::NegativeLocationCase(deqp::Context& context) : deqp::TestCase(context, "invalid_cases", "") 549 { 550 } 551 552 NegativeLocationCase::~NegativeLocationCase() 553 { 554 } 555 556 tcu::TestNode::IterateResult NegativeLocationCase::iterate() 557 { 558 glu::RenderContext& renderContext = m_context.getRenderContext(); 559 glu::ContextType contextType = renderContext.getType(); 560 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType); 561 const Functions& gl = renderContext.getFunctions(); 562 563 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 564 565 static const char* csTemplate = "${VERSION}\n" 566 "layout(location=2, binding=0) uniform atomic_uint u_atomic;\n" 567 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 568 "layout(binding=0) buffer Output {\n uint value;\n} sb_out;\n\n" 569 "void main (void) {\n" 570 " sb_out.value = atomicCounterIncrement(u_atomic);\n" 571 "}"; 572 573 std::map<std::string, std::string> specializationMap; 574 specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); 575 std::string cs = tcu::StringTemplate(csTemplate).specialize(specializationMap); 576 577 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 578 579 glu::ProgramSources sourcesCompute; 580 sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(cs); 581 glu::ShaderProgram program(gl, sourcesCompute); 582 if (program.isOk()) 583 { 584 m_testCtx.getLog() << program << tcu::TestLog::Message 585 << "layout(location = N) is not allowed for atomic counters" << tcu::TestLog::EndMessage; 586 return STOP; 587 } 588 589 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 590 return STOP; 591 } 592 593 LayoutLocationTests::LayoutLocationTests(Context& context) : TestCaseGroup(context, "layout_location", "") 594 { 595 } 596 597 LayoutLocationTests::~LayoutLocationTests(void) 598 { 599 } 600 601 void LayoutLocationTests::init(void) 602 { 603 const SamplerCaseData commonArguments[] = 604 { 605 { &create<GL_TEXTURE_2D, GL_RGBA8>, "sampler_2d", "sampler2D", "texture(sampler, coords)", 0 }, 606 { &create<GL_TEXTURE_3D, GL_RGBA8>, "sampler_3d", "sampler3D", "texture(sampler, vec3(coords, 0.0))", 0 }, 607 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "sampler_cube", "samplerCube", "texture(sampler, vec3(coords, 0.0))", 0 }, 608 { &create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>, "sampler_cube_shadow", "samplerCubeShadow", "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0 }, 609 { &create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>, "sampler_2d_shadow", "sampler2DShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, 610 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "sampler_2d_array", "sampler2DArray", "texture(sampler, vec3(coords, 0.0))", 0 }, 611 { &create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_2d_array_shadow", "sampler2DArrayShadow", "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0 }, 612 { &create<GL_TEXTURE_2D, GL_RGBA32I>, "isampler_2d", "isampler2D", "vec4(texture(sampler, coords))/255.0", 0 }, 613 { &create<GL_TEXTURE_3D, GL_RGBA32I>, "isampler_3d", "isampler3D", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 614 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "isampler_cube", "isamplerCube", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 615 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "isampler_2d_array", "isampler2DArray", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 616 { &create<GL_TEXTURE_2D, GL_RGBA32UI>, "usampler_2d", "usampler2D", "vec4(texture(sampler, coords))/255.0", 0 }, 617 { &create<GL_TEXTURE_3D, GL_RGBA32UI>, "usampler_3d", "usampler3D", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 618 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "usampler_cube", "usamplerCube", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 619 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "usampler_2d_array", "usampler2DArray", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, 620 621 { &create<GL_TEXTURE_2D, GL_RGBA8>, "image_2d", "image2D", "imageLoad(image, ivec2(0, 0))", 1 }, 622 { &create<GL_TEXTURE_2D, GL_RGBA32I>, "iimage_2d", "iimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1 }, 623 { &create<GL_TEXTURE_2D, GL_RGBA32UI>, "uimage_2d", "uimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1 }, 624 { &create<GL_TEXTURE_3D, GL_RGBA8>, "image_3d", "image3D", "imageLoad(image, ivec3(0, 0, 0))", 1 }, 625 { &create<GL_TEXTURE_3D, GL_RGBA32I>, "iimage_3d", "iimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 626 { &create<GL_TEXTURE_3D, GL_RGBA32UI>, "uimage_3d", "uimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 627 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "image_cube", "imageCube", "imageLoad(image, ivec3(0, 0, 0))", 1 }, 628 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "iimage_cube", "iimageCube", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 629 { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "uimage_cube", "uimageCube", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 630 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "image_2d_array", "image2DArray", "imageLoad(image, ivec3(0, 0, 0))", 1 }, 631 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "iimage_2d_array", "iimage2DArray", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 632 { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "uimage_2d_array", "uimage2DArray", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, 633 }; 634 635 // Additional array containing entries for core gl 636 const SamplerCaseData coreArguments[] = 637 { 638 { &create<GL_TEXTURE_BUFFER, GL_RGBA32F>, "sampler_buffer", "samplerBuffer", "texelFetch(sampler, 1)", 0 }, 639 { &create<GL_TEXTURE_BUFFER, GL_RGBA32I>, "isampler_buffer", "isamplerBuffer", "vec4(texelFetch(sampler, 1))/255.0", 0 }, 640 { &create<GL_TEXTURE_BUFFER, GL_RGBA32UI>, "usampler_buffer", "usamplerBuffer", "vec4(texelFetch(sampler, 1))/255.0", 0 }, 641 { &create<GL_TEXTURE_1D, GL_RGBA8>, "sampler_1d", "sampler1D", "texture(sampler, coords.x)", 0 }, 642 { &create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>, "sampler_1d_shadow", "sampler1DShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, 643 { &create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>, "sampler_1d_array", "sampler1DArray", "texture(sampler, coords, 0.0)", 0 }, 644 { &create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_1d_array_shadow", "sampler1DArrayShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, 645 }; 646 647 for (int i = 0; i < DE_LENGTH_OF_ARRAY(commonArguments); ++i) 648 addChild(new SpecifiedLocationCase(m_context, commonArguments[i])); 649 650 glu::RenderContext& renderContext = m_context.getRenderContext(); 651 glu::ContextType contextType = renderContext.getType(); 652 if (!glu::isContextTypeES(contextType)) 653 { 654 for (int i = 0; i < DE_LENGTH_OF_ARRAY(coreArguments); ++i) 655 addChild(new SpecifiedLocationCase(m_context, coreArguments[i])); 656 } 657 658 addChild(new NegativeLocationCase(m_context)); 659 } 660 661 } // glcts 662