1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 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 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "es31cSeparateShaderObjsTests.hpp" 25 #include "deMath.h" 26 #include "deRandom.hpp" 27 #include "deString.h" 28 #include "deStringUtil.hpp" 29 #include "gluDrawUtil.hpp" 30 #include "gluPixelTransfer.hpp" 31 #include "gluShaderProgram.hpp" 32 #include "glw.h" 33 #include "glwEnums.hpp" 34 #include "glwFunctions.hpp" 35 #include "tcuImageCompare.hpp" 36 #include "tcuRenderTarget.hpp" 37 #include "tcuStringTemplate.hpp" 38 #include "tcuSurface.hpp" 39 #include "tcuTestLog.hpp" 40 #include "tcuVector.hpp" 41 42 #include <map> 43 44 /*************************************************************************/ 45 /* Test Plan for shared_shader_objects: 46 * Overview 47 * 48 * This is a conformance test for XXX_separate_shader_objects extension. The 49 * results of the tests are verified by checking the expected GL error, 50 * by checking the expected state with state query functions and by rendering 51 * test images and comparing specified pixels with expected values. Not all of 52 * the methods are applicable for all tests. Additional details such as 53 * expected error codes are included in test descriptions. 54 * 55 *New Tests 56 * 57 *-- Tests for invidual API functions 58 * 59 * 60 * CreateShaderProgramv tests 61 * 62 * Positive tests: 63 * 64 * * Test with valid parameters and verify that program and GL state are set 65 * accordingly to the code sequence defined in the extension spec. 66 * * Test with vertex and fragment shader types. 67 * * Test with few different count/strings parameters (count >= 1) 68 * 69 * Negative tests: 70 * 71 * * Test with invalid type. Expect INVALID_ENUM and zero return value. 72 * * Test with uncompilable / unlinkable source. Expect no errors. Program 73 * should be returned Program info log may contain information about link / 74 * compile failure. 75 * * Test with count < 0. Expect INVALID_VALUE and zero return value. 76 * 77 * 78 * UseProgramStages tests 79 * 80 * Positive tests: 81 * 82 * * Test with a program containing 83 * - vertex stage only 84 * - fragment stage only 85 * - both stages 86 * * Test with null program to reset a stage or stages. Expect no errors. 87 * * Test with a program that doesn't contain code for a stage defined in the 88 * stages bitfield. Expect no errors. 89 * * Test with a new program pipeline object that has not yet been used/bound. 90 * 91 * Negative tests: 92 * 93 * * Test with invalid stages bitfield (with unused bits). Expect INVALID_VALUE GL error. 94 * * Test with deleted/nonexistent pipeline. Expect INVALID_OPERATION GL error. 95 * * Test with program that isn't separable. Expect INVALID_OPERATION GL error. 96 * * Test with program that isn't linked succesfully. Expect INVALID_OPERATION 97 * GL error. 98 * * Test with deleted/nonexistent program. Expect INVALID_OPERATION error. 99 * 100 * 101 * ActiveShaderProgram tests 102 * 103 * Positive tests: 104 * 105 * * Test with a new program pipeline object that has not yet been used/bound. 106 * 107 * Negative tests: 108 * 109 * * Test with deleted/nonexistent program pipeline object. Expect INVALID_OPERATION and no 110 * changes to active program. 111 * * Test with nonexistent/deleted/unsuccesfully linked program. Expect 112 * INVALID_OPERATION GL error and no changes to active program. 113 * 114 * 115 * GenProgramPipelines tests 116 * 117 * Positive tests: 118 * 119 * * Test creating different amounts of program pipeline object names. 120 * Verify with IsProgramPipeline. 121 * 122 * 123 * BindProgramPipeline tests 124 * 125 * Positive tests: 126 * 127 * * Test binding existing program pipeline object. Verify with 128 * PROGRAM_PIPELINE_BINDING 129 * * Test binding zero program pipeline object. Verify 130 * PROGRAM_PIPELINE_BINDING is reset to 0 131 * 132 * Negative tests: 133 * 134 * * Test binding deleted/nonexistent program pipeline object. Expect 135 * INVALID_OPERATION GL error and no changes to bound pipeline. 136 * 137 * 138 * DeleteProgramPipelines tests 139 * 140 * Positive tests: 141 * 142 * * Test deleting zero and unused names. Expect no errors (should be no-op) 143 * * Test deleting different amounts of existing pipeline names. Verify 144 * deletion with IsProgramPipeline. 145 * * Test deleting bound names. Expect pipeline binding revert to zero, verify 146 * with PROGRAM_PIPELINE_BINDING. 147 * 148 * 149 * IsProgramPipeline 150 * 151 * Positive tests: 152 * 153 * * Test with deleted/nonexistent program pipeline names. 154 * * Test with existing program pipeline names. 155 * 156 * 157 * ProgramParameteri / PROGRAM_SEPARABLE tests 158 * 159 * Positive tests: 160 * 161 * * Test setting TRUE and FALSE values for existing, unlinked programs. 162 * Verify with GetProgramParameteri 163 * 164 * Negative tests: 165 * 166 * * Test with nonexistent/deleted program. Expect INVALID_OPERATION GL error 167 * * Test with invalid value. Expect INVALID_VALUE GL error 168 * 169 * 170 * GetProgramPipelineiv tests 171 * 172 * Positive tests: 173 * 174 * * Test with new program pipeline object that has not yet been used/bound 175 * * Test ACTIVE_PROGRAM 176 * * Test VERTEX_SHADER 177 * * Test FRAGMENT_SHADER 178 * * Test VALIDATE_STATUS 179 * * Test INFO_LOG_LENGTH 180 * 181 * Negative tests: 182 * 183 * * Test with deleted/nonexistent pipeline. Expect INVALID_OPERATION GL error 184 * 185 * 186 * ValidateProgramPipeline tests: 187 * 188 * Positive tests: 189 * 190 * * Test with valid program pipeline. Expect VALIDATE_STATUS = TRUE 191 * * Test with invalid program pipeline Expect VALIDATE_STATUS = FALSE 192 * * Test with empty program pipeline (uninitialized, but bound). Expect VALIDATE_STATUS = FALSE. 193 * * Test that initial (unvalidated) VALIDATE_STATUS is FALSE 194 * * Test with a new program pipeline object that has not been used/bound yet 195 * 196 * Negative tests: 197 * 198 * * Test with deleted/nonexistent program pipeline object. Expect 199 * INVALID_OPERATION 200 * 201 * 202 * ProgramUniform* tests 203 * 204 * Positive tests: 205 * 206 * * Test all ProgramUniform* methods with few different parameters combinations 207 * * Setup pipeline with programs A and B. Update uniforms for A and verify 208 * that only A is affected. 209 * * Test with a program with all combinations of 210 * - program is/isn't part of a bound pipeline 211 * - program is/isn't made current with UseProgram 212 * - program is/isn't made active with ActiveShaderProgram 213 * in all cases, only the uniforms of the specified program should be 214 * updated. 215 * 216 * Negative tests: 217 * 218 * * Test with deleted/nonexistent program. Expect INVALID_VALUE GL error. 219 * * Test with unsuccesfully linked program. Expect INVALID_OPERATION GL error. 220 * 221 * 222 * GetProgramPipelineInfoLog tests 223 * 224 * Run ValidateProgramPipeline for valid / invalid program pipeline object 225 * before running the tests. NOTE: The spec doesn't require that the driver 226 * updates the pipeline info log. It may or may not contain information about 227 * validation. 228 * 229 * Positive tests 230 * 231 * * Test with NULL length. 232 * * Test with zero bufSize. Expect no errors 233 * * Test with varying bufSizes (where 0 < bufSize <= INFO_LOG_LENGTH). Except 234 * * length = (bufSize - 1) and zero-terminated string with matching length in 235 * infoLog. 236 * 237 * Negative tests 238 * 239 * * Test with deleted/nonexistent program pipeline object. Expect 240 * GL_INVALID_VALUE error (the error is still missing from the spec) 241 * 242 * 243 *-- Other tests 244 * 245 * 246 * UseProgram vs. BindProgramPipeline tests 247 * 248 * Positive tests: 249 * 250 * * Test that a program made active with UseProgram has precedence over 251 * program pipeline object bound with BindProgramPipeline. 252 * * Test that program(s) in bound program pipeline object will be used if 253 * there is no active program set with UseProgram 254 * * Test that a state without active program or without bound pipeline object 255 * generates no errors. 256 * 257 * 258 * Pipeline setup tests 259 * 260 * Positive tests: 261 * 262 * * Test that missing pipeline stages produces no errors: 263 * - no program set with UseProgramStages for vertex or frargment stages 264 * - no vertex or fragment code in a program set for the stage 265 * 266 * Negative tests: 267 * 268 * * Test that program with both vertex and fragment shaders cannot be attached 269 * just to vertex or fragment stage. Expect DrawArrays/Elements to generate 270 * INVALID_OPERATION and pipeline VALIDATE_STATUS set to FALSE. 271 * - Run with and without validating the pipeline with ValidateProgramPipeline 272 * 273 * 274 * Shader/program management tests 275 * 276 * Positive tests: 277 * 278 * * Test creating separable shader objects both by 279 * - Using the core functions combined with PROGRAM_SEPARABLE flag 280 * - CreateShaderProgram 281 * * Test that separable program can contain and links properly if there are 282 * - vertex stage 283 * - fragment stage 284 * - both stages 285 * * Test that active program isn't deleted immediately (deletion doesn't 286 * affect rendering state) 287 * * Test that program in current pipeline isn't deleted immediately 288 * * Test that attaching/detaching/recompiling a shader in active program or 289 * program in current pipeline doesn't affect the program link status or 290 * rendering state. 291 * * Test that succesfully re-linking active program or program in current 292 * pipeline affects the rendering state. 293 * 294 * Negative tests: 295 * 296 * aren't present. 297 * * Test that unsuccesfully re-linking active program or program in current 298 * pipeline sets LINK_STATUS=FALSE but doesn't affect the rendering state. 299 * * Test that unsuccesfully linked program cannot be made part of a program 300 * pipeline object. 301 * 302 * 303 * Uniform update tests 304 * 305 * Positive cases: 306 * 307 * with UseProgram. 308 * * Test that Uniform* functions update the uniforms of a program made active with 309 * ActiveShader program if no program has been made active with UseProgram. 310 * * Test that ProgramUniform* functions update the uniforms of a specified 311 * program regardless of active program (probably already covered with 312 * "ProgramUniform* tests") 313 * 314 * Negative cases: 315 * 316 * * Test that Uniform* functions set INVALID_OPERATION if there is no active 317 * program set with UseProgram nor ActiveShaderProgram 318 * 319 * 320 * Shader interface matching tests 321 * 322 * Positive tests: 323 * 324 * * Test that partially or completely mismatching shaders do not generate 325 * validation nor other GL errors (just undefined inputs) 326 * * Test that exactly matching shaders work. 327 * * Test that variables with matching layout qualifiers match and are defined 328 * even if the shaders don't match exactly. 329 * - Test with int, uint and float component types 330 * - Test with different vector sizes, where output vector size >= input 331 * vector size 332 * 333 * 334 * End Test Plan */ 335 /*************************************************************************/ 336 337 namespace glcts 338 { 339 340 using tcu::TestLog; 341 using std::string; 342 using std::vector; 343 344 // A fragment shader to allow testing various scalar and vector 345 // uniforms as well as array [2] varieties. To keep the uniforms 346 // active they are compared against constants. 347 static const char* s_unifFragShaderSrc = 348 "precision highp float;\n" 349 "uniform ${SCALAR_TYPE} uVal0;\n" 350 "uniform ${VECTOR_TYPE}2 uVal1;\n" 351 "uniform ${VECTOR_TYPE}3 uVal2;\n" 352 "uniform ${VECTOR_TYPE}4 uVal3;\n" 353 "\n" 354 "uniform ${SCALAR_TYPE} uVal4[2];\n" 355 "uniform ${VECTOR_TYPE}2 uVal5[2];\n" 356 "uniform ${VECTOR_TYPE}3 uVal6[2];\n" 357 "uniform ${VECTOR_TYPE}4 uVal7[2];\n" 358 "\n" 359 "const ${SCALAR_TYPE} kVal0= 1${SFX};\n" 360 "const ${VECTOR_TYPE}2 kVal1 = ${VECTOR_TYPE}2(2${SFX}, 3${SFX});\n" 361 "const ${VECTOR_TYPE}3 kVal2 = ${VECTOR_TYPE}3(4${SFX}, 5${SFX}, 6${SFX});\n" 362 "const ${VECTOR_TYPE}4 kVal3 = ${VECTOR_TYPE}4(7${SFX}, 8${SFX}, 9${SFX}, 10${SFX});\n" 363 "\n" 364 "const ${SCALAR_TYPE} kArr4_0 = 11${SFX};\n" 365 "const ${SCALAR_TYPE} kArr4_1 = 12${SFX};\n" 366 "const ${VECTOR_TYPE}2 kArr5_0 = ${VECTOR_TYPE}2(13${SFX}, 14${SFX});\n" 367 "const ${VECTOR_TYPE}2 kArr5_1 = ${VECTOR_TYPE}2(15${SFX}, 16${SFX});\n" 368 "const ${VECTOR_TYPE}3 kArr6_0 = ${VECTOR_TYPE}3(17${SFX}, 18${SFX}, 19${SFX});\n" 369 "const ${VECTOR_TYPE}3 kArr6_1 = ${VECTOR_TYPE}3(20${SFX}, 21${SFX}, 22${SFX});\n" 370 "const ${VECTOR_TYPE}4 kArr7_0 = ${VECTOR_TYPE}4(23${SFX}, 24${SFX}, 25${SFX}, 26${SFX});\n" 371 "const ${VECTOR_TYPE}4 kArr7_1 = ${VECTOR_TYPE}4(27${SFX}, 28${SFX}, 29${SFX}, 30${SFX});\n" 372 "\n" 373 "layout(location = 0) out mediump vec4 o_color;\n" 374 "\n" 375 "void main() {\n" 376 " if ((uVal0 != kVal0) ||\n" 377 " (uVal1 != kVal1) ||\n" 378 " (uVal2 != kVal2) ||\n" 379 " (uVal3 != kVal3) ||\n" 380 " (uVal4[0] != kArr4_0) || (uVal4[1] != kArr4_1) ||\n" 381 " (uVal5[0] != kArr5_0) || (uVal5[1] != kArr5_1) ||\n" 382 " (uVal6[0] != kArr6_0) || (uVal6[1] != kArr6_1) ||\n" 383 " (uVal7[0] != kArr7_0) || (uVal7[1] != kArr7_1)) {\n" 384 " o_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 385 " } else {\n" 386 " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 387 " }\n" 388 "}\n"; 389 390 // A fragment shader to test uniforms of square matrices 391 static const char* s_unifFragSquareMatShaderSrc = "precision highp float;\n" 392 "uniform mat2 uValM2[2];\n" 393 "uniform mat3 uValM3[2];\n" 394 "uniform mat4 uValM4[2];\n" 395 "\n" 396 "const mat2 kMat2_0 = mat2(91.0, 92.0, 93.0, 94.0);\n" 397 "const mat2 kMat2_1 = mat2(95.0, 96.0, 97.0, 98.0);\n" 398 "const mat3 kMat3_0 = mat3(vec3( 99.0, 100.0, 101.0),\n" 399 " vec3(102.0, 103.0, 104.0),\n" 400 " vec3(105.0, 106.0, 107.0));\n" 401 "const mat3 kMat3_1 = mat3(vec3(108.0, 109.0, 110.0),\n" 402 " vec3(111.0, 112.0, 113.0),\n" 403 " vec3(114.0, 115.0, 116.0));\n" 404 "const mat4 kMat4_0 = mat4(vec4(117.0, 118.0, 119.0, 120.0),\n" 405 " vec4(121.0, 122.0, 123.0, 124.0),\n" 406 " vec4(125.0, 126.0, 127.0, 128.0),\n" 407 " vec4(129.0, 130.0, 131.0, 132.0));\n" 408 "const mat4 kMat4_1 = mat4(vec4(133.0, 134.0, 135.0, 136.0),\n" 409 " vec4(137.0, 138.0, 139.0, 140.0),\n" 410 " vec4(141.0, 142.0, 143.0, 144.0),\n" 411 " vec4(145.0, 146.0, 147.0, 148.0));\n" 412 "\n" 413 "layout(location = 0) out mediump vec4 o_color;\n" 414 "\n" 415 "void main() {\n" 416 " if ((uValM2[0] != kMat2_0) || (uValM2[1] != kMat2_1) ||\n" 417 " (uValM3[0] != kMat3_0) || (uValM3[1] != kMat3_1) ||\n" 418 " (uValM4[0] != kMat4_0) || (uValM4[1] != kMat4_1)) {\n" 419 " o_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 420 " } else {\n" 421 " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 422 " }\n" 423 "}\n"; 424 425 // A fragment shader to test uniforms of square matrices 426 static const char* s_unifFragNonSquareMatShaderSrc = 427 "precision highp float;\n" 428 "uniform mat2x3 uValM2x3[2];\n" 429 "uniform mat3x2 uValM3x2[2];\n" 430 "uniform mat2x4 uValM2x4[2];\n" 431 "uniform mat4x2 uValM4x2[2];\n" 432 "uniform mat3x4 uValM3x4[2];\n" 433 "uniform mat4x3 uValM4x3[2];\n" 434 "\n" 435 "const mat2x3 kMat2x3_0 = mat2x3(vec2(149.0, 150.0),\n" 436 " vec2(151.0, 152.0),\n" 437 " vec2(153.0, 154.0));\n" 438 "const mat2x3 kMat2x3_1 = mat2x3(vec2(155.0, 156.0),\n" 439 " vec2(157.0, 158.0),\n" 440 " vec2(159.0, 160.0));\n" 441 "const mat3x2 kMat3x2_0 = mat3x2(vec3(161.0, 162.0, 163.0),\n" 442 " vec3(164.0, 165.0, 166.0));\n" 443 "const mat3x2 kMat3x2_1 = mat3x2(vec3(167.0, 168.0, 169.0),\n" 444 " vec3(170.0, 171.0, 172.0));\n" 445 "const mat2x4 kMat2x4_0 = mat2x4(vec2(173.0, 174.0),\n" 446 " vec2(175.0, 176.0),\n" 447 " vec2(177.0, 178.0),\n" 448 " vec2(179.0, 180.0));\n" 449 "const mat2x4 kMat2x4_1 = mat2x4(vec2(181.0, 182.0),\n" 450 " vec2(183.0, 184.0),\n" 451 " vec2(185.0, 186.0),\n" 452 " vec2(187.0, 188.0));\n" 453 "const mat4x2 kMat4x2_0 = mat4x2(vec4(189.0, 190.0, 191.0, 192.0),\n" 454 " vec4(193.0, 194.0, 195.0, 196.0));\n" 455 "const mat4x2 kMat4x2_1 = mat4x2(vec4(197.0, 198.0, 199.0, 200.0),\n" 456 " vec4(201.0, 202.0, 203.0, 204.0));\n" 457 "const mat3x4 kMat3x4_0 = mat3x4(vec3(205.0, 206.0, 207.0),\n" 458 " vec3(208.0, 209.0, 210.0),\n" 459 " vec3(211.0, 212.0, 213.0),\n" 460 " vec3(214.0, 215.0, 216.0));\n" 461 "const mat3x4 kMat3x4_1 = mat3x4(vec3(217.0, 218.0, 219.0),\n" 462 " vec3(220.0, 221.0, 222.0),\n" 463 " vec3(223.0, 224.0, 225.0),\n" 464 " vec3(226.0, 227.0, 228.0));\n" 465 "const mat4x3 kMat4x3_0 = mat4x3(vec4(229.0, 230.0, 231.0, 232.0),\n" 466 " vec4(233.0, 234.0, 235.0, 236.0),\n" 467 " vec4(237.0, 238.0, 239.0, 240.0));\n" 468 "const mat4x3 kMat4x3_1 = mat4x3(vec4(241.0, 242.0, 243.0, 244.0),\n" 469 " vec4(245.0, 246.0, 247.0, 248.0),\n" 470 " vec4(249.0, 250.0, 251.0, 252.0));\n" 471 "\n" 472 "layout(location = 0) out mediump vec4 o_color;\n" 473 "\n" 474 "void main() {\n" 475 " if ((uValM2x3[0] != kMat2x3_0) || (uValM2x3[1] != kMat2x3_1) ||\n" 476 " (uValM3x2[0] != kMat3x2_0) || (uValM3x2[1] != kMat3x2_1) ||\n" 477 " (uValM2x4[0] != kMat2x4_0) || (uValM2x4[1] != kMat2x4_1) ||\n" 478 " (uValM4x2[0] != kMat4x2_0) || (uValM4x2[1] != kMat4x2_1) ||\n" 479 " (uValM3x4[0] != kMat3x4_0) || (uValM3x4[1] != kMat3x4_1) ||\n" 480 " (uValM4x3[0] != kMat4x3_0) || (uValM4x3[1] != kMat4x3_1)) {\n" 481 " o_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 482 " } else {\n" 483 " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 484 " }\n" 485 "}\n"; 486 487 static std::string generateBasicVertexSrc(glu::GLSLVersion glslVersion) 488 { 489 std::stringstream str; 490 491 str << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 492 str << "in highp vec4 a_position;\n"; 493 if (glslVersion >= glu::GLSL_VERSION_410) 494 { 495 str << "out gl_PerVertex {\n" 496 " vec4 gl_Position;\n" 497 "};\n"; 498 } 499 str << "void main (void)\n" 500 "{\n" 501 " gl_Position = a_position;\n" 502 "}\n"; 503 504 return str.str(); 505 } 506 507 static std::string generateBasicFragmentSrc(glu::GLSLVersion glslVersion) 508 { 509 std::stringstream str; 510 511 str << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 512 str << "uniform highp vec4 u_color;\n" 513 "layout(location = 0) out mediump vec4 o_color;\n" 514 "void main (void)\n" 515 "{\n" 516 " o_color = u_color;\n" 517 "}\n"; 518 519 return str.str(); 520 } 521 522 // Testcase for glCreateShaderProgramv 523 class CreateShadProgCase : public TestCase 524 { 525 public: 526 CreateShadProgCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion) 527 : TestCase(context, name, description), m_glslVersion(glslVersion) 528 { 529 } 530 531 ~CreateShadProgCase(void) 532 { 533 } 534 535 // Check program validity created with CreateShaderProgram 536 bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedSep = GL_TRUE, int expectedLink = GL_TRUE) 537 { 538 int separable = GL_FALSE; 539 int linked = GL_FALSE; 540 if (program != 0) 541 { 542 gl.getProgramiv(program, GL_PROGRAM_SEPARABLE, &separable); 543 gl.getProgramiv(program, GL_LINK_STATUS, &linked); 544 } 545 546 return (program != 0) && (separable == expectedSep) && (linked == expectedLink); 547 } 548 549 IterateResult iterate(void) 550 { 551 TestLog& log = m_testCtx.getLog(); 552 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 553 int i; 554 const char* srcStrings[10]; 555 glw::GLuint program; 556 glw::GLenum err; 557 558 // CreateShaderProgramv verification 559 log << TestLog::Message << "Begin:CreateShadProgCase iterate" << TestLog::EndMessage; 560 561 // vertex shader 562 i = 0; 563 srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion); 564 srcStrings[i++] = "\n"; 565 if (m_glslVersion >= glu::GLSL_VERSION_410) 566 { 567 srcStrings[i++] = "out gl_PerVertex {\n" 568 " vec4 gl_Position;\n" 569 "};\n"; 570 } 571 srcStrings[i++] = "in vec4 a_position;\n"; 572 srcStrings[i++] = "void main ()\n"; 573 srcStrings[i++] = "{\n"; 574 srcStrings[i++] = " gl_Position = a_position;\n"; 575 srcStrings[i++] = "}\n"; 576 577 program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings); 578 if (!checkCSProg(gl, program)) 579 { 580 TCU_FAIL("CreateShaderProgramv failed for vertex shader"); 581 } 582 583 gl.deleteProgram(program); 584 585 // Half as many strings 586 i = 0; 587 srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion); 588 srcStrings[i++] = "\n"; 589 if (m_glslVersion >= glu::GLSL_VERSION_410) 590 { 591 srcStrings[i++] = "out gl_PerVertex {\n" 592 " vec4 gl_Position;\n" 593 "};\n"; 594 } 595 srcStrings[i++] = "in vec4 a_position;\n" 596 "void main ()\n"; 597 srcStrings[i++] = "{\n" 598 " gl_Position = a_position;\n"; 599 srcStrings[i++] = "}\n"; 600 601 program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings); 602 if (!checkCSProg(gl, program)) 603 { 604 TCU_FAIL("CreateShaderProgramv failed for vertex shader"); 605 } 606 607 gl.deleteProgram(program); 608 609 // Fragment shader 610 i = 0; 611 srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion); 612 srcStrings[i++] = "\nin highp vec4 u_color;\n"; 613 srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n"; 614 srcStrings[i++] = "void main ()\n"; 615 srcStrings[i++] = "{\n"; 616 srcStrings[i++] = " o_color = u_color;\n"; 617 srcStrings[i++] = "}\n"; 618 619 program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings); 620 if (!checkCSProg(gl, program)) 621 { 622 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 623 } 624 625 gl.deleteProgram(program); 626 627 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed"); 628 629 // Negative Cases 630 631 // invalid type 632 program = gl.createShaderProgramv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, i, srcStrings); 633 err = gl.getError(); 634 if ((program != 0) || (err != GL_INVALID_ENUM)) 635 { 636 TCU_FAIL("CreateShaderProgramv failed"); 637 } 638 639 // Negative count 640 program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, -1, srcStrings); 641 err = gl.getError(); 642 if ((program != 0) || (err != GL_INVALID_VALUE)) 643 { 644 TCU_FAIL("CreateShaderProgramv failed"); 645 } 646 647 // source compile error 648 i = 0; 649 srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion); 650 srcStrings[i++] = "\nin highp vec4 u_color;\n"; 651 srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n"; 652 srcStrings[i++] = "void main ()\n"; 653 srcStrings[i++] = "{\n"; 654 srcStrings[i++] = " o_color = u_color;\n"; 655 656 program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings); 657 // expect valid program and false for link status 658 if (!checkCSProg(gl, program, GL_FALSE, GL_FALSE)) 659 { 660 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 661 } 662 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed"); 663 gl.deleteProgram(program); 664 665 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 666 return STOP; 667 } 668 669 private: 670 glu::GLSLVersion m_glslVersion; 671 }; 672 673 // Testcase for glUseProgamStages 674 class UseProgStagesCase : public TestCase 675 { 676 public: 677 UseProgStagesCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion) 678 : TestCase(context, name, description), m_glslVersion(glslVersion) 679 { 680 } 681 682 ~UseProgStagesCase(void) 683 { 684 } 685 686 IterateResult iterate(void) 687 { 688 TestLog& log = m_testCtx.getLog(); 689 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 690 glw::GLenum err; 691 glw::GLuint pipeline; 692 glw::GLuint progIdV, progIdF; 693 glw::GLuint programVtx, programFrag; 694 const char* shaderSrc[1]; 695 std::string vtx; 696 std::string frag; 697 glw::GLint linkStatus; 698 699 vtx = generateBasicVertexSrc(m_glslVersion); 700 frag = generateBasicFragmentSrc(m_glslVersion); 701 702 // UseProgramStages verification 703 log << TestLog::Message << "Begin:UseProgStagesCase iterate" << TestLog::EndMessage; 704 705 gl.genProgramPipelines(1, &pipeline); 706 gl.bindProgramPipeline(pipeline); 707 708 // Use Vertex Shader 709 shaderSrc[0] = vtx.c_str(); 710 programVtx = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, shaderSrc); 711 712 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx); 713 gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV); 714 gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF); 715 if ((programVtx == 0) || (progIdV != programVtx) || (progIdF != 0)) 716 { 717 TCU_FAIL("UseProgramStages failed"); 718 } 719 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 720 721 // Use Fragment Shader 722 shaderSrc[0] = frag.c_str(); 723 programFrag = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc); 724 725 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag); 726 gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF); 727 if ((programFrag == 0) || (progIdF != programFrag) || (progIdF == progIdV)) 728 { 729 TCU_FAIL("UseProgramStages failed"); 730 } 731 732 // Reset stages 733 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0); 734 gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV); 735 gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF); 736 if ((progIdV != 0) || (progIdF != 0)) 737 { 738 TCU_FAIL("UseProgramStages failed"); 739 } 740 741 // One program for both. 742 glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str())); 743 744 // Make separable and relink 745 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 746 gl.linkProgram(progVF.getProgram()); 747 gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus); 748 if (linkStatus != 1) 749 { 750 TCU_FAIL("UseProgramStages failed"); 751 } 752 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 753 754 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram()); 755 gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV); 756 gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF); 757 if ((progIdV != progVF.getProgram()) || (progIdV != progIdF)) 758 { 759 TCU_FAIL("UseProgramStages failed"); 760 } 761 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 762 763 // Use a fragment program with vertex bit 764 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0); 765 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programFrag); 766 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 767 768 // Unbound pipeline 769 gl.bindProgramPipeline(0); 770 gl.deleteProgramPipelines(1, &pipeline); 771 pipeline = 0; 772 gl.genProgramPipelines(1, &pipeline); 773 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx); 774 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag); 775 gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV); 776 gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF); 777 if ((progIdV != programVtx) || (progIdF != programFrag)) 778 { 779 TCU_FAIL("UseProgramStages failed"); 780 } 781 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 782 783 // Negative Cases 784 785 // Invalid stages 786 gl.useProgramStages(pipeline, GL_ALL_SHADER_BITS ^ (GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT), programVtx); 787 err = gl.getError(); 788 if (err != GL_INVALID_VALUE) 789 { 790 TCU_FAIL("UseProgramStages failed"); 791 } 792 793 // Program that is not separable 794 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE); 795 gl.linkProgram(progVF.getProgram()); 796 gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus); 797 if (linkStatus != 1) 798 { 799 TCU_FAIL("UseProgramStages failed"); 800 } 801 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed"); 802 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram()); 803 err = gl.getError(); 804 if (err != GL_INVALID_OPERATION) 805 { 806 TCU_FAIL("UseProgramStages failed"); 807 } 808 809 // Program that is not successfully linked 810 // remove the main keyword 811 std::string fragNoMain = frag; 812 unsigned int pos = (unsigned int)fragNoMain.find("main"); 813 fragNoMain.replace(pos, 4, "niaM"); 814 glu::ShaderProgram progNoLink(m_context.getRenderContext(), 815 glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str())); 816 817 gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 818 gl.linkProgram(progNoLink.getProgram()); 819 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progNoLink.getProgram()); 820 err = gl.getError(); 821 if (err != GL_INVALID_OPERATION) 822 { 823 TCU_FAIL("UseProgramStages failed"); 824 } 825 826 // Invalid pipeline 827 gl.useProgramStages(pipeline + 1000, GL_VERTEX_SHADER_BIT, programVtx); 828 err = gl.getError(); 829 if (err != GL_INVALID_OPERATION) 830 { 831 TCU_FAIL("UseProgramStages failed"); 832 } 833 834 // Invalid pipeline 835 gl.deleteProgramPipelines(1, &pipeline); 836 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx); 837 err = gl.getError(); 838 if (err != GL_INVALID_OPERATION) 839 { 840 TCU_FAIL("UseProgramStages failed"); 841 } 842 843 gl.deleteProgram(programVtx); 844 gl.deleteProgram(programFrag); 845 846 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 847 return STOP; 848 } 849 850 private: 851 glu::GLSLVersion m_glslVersion; 852 }; 853 854 // Testcase for pipeline api 855 class PipelineApiCase : public TestCase 856 { 857 public: 858 PipelineApiCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion) 859 : TestCase(context, name, description), m_glslVersion(glslVersion) 860 { 861 } 862 863 ~PipelineApiCase(void) 864 { 865 } 866 867 // Validate glGetProgramPipelineInfoLog 868 void checkProgInfoLog(const glw::Functions& gl, GLuint pipeline) 869 { 870 glw::GLint value; 871 glw::GLsizei bufSize; 872 glw::GLsizei length; 873 glw::GLenum err; 874 875 gl.getProgramPipelineiv(pipeline, GL_INFO_LOG_LENGTH, &value); 876 std::vector<char> infoLogBuf(value + 1); 877 878 bufSize = 0; 879 gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]); 880 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineInfoLog failed"); 881 882 bufSize = value / 2; // read half the log 883 gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]); 884 if ((bufSize != 0) && (bufSize != length + 1)) 885 { 886 TCU_FAIL("GetProgramPipelineInfoLog failed"); 887 } 888 bufSize = value; 889 gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]); 890 if ((bufSize != 0) && (bufSize != length + 1)) 891 { 892 TCU_FAIL("GetProgramPipelineInfoLog failed"); 893 } 894 895 // Negative case for GetProgramPipelineInfoLog 896 897 gl.getProgramPipelineInfoLog(pipeline + 101, bufSize, &length, &infoLogBuf[0]); 898 err = gl.getError(); 899 if (err != GL_INVALID_VALUE) 900 { 901 TCU_FAIL("GetProgramPipelineInfoLog failed"); 902 } 903 } 904 905 IterateResult iterate(void) 906 { 907 TestLog& log = m_testCtx.getLog(); 908 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 909 glw::GLenum err; 910 const int maxpipelines = 10; 911 glw::GLuint pipelines[maxpipelines]; 912 std::string vtx; 913 std::string frag; 914 glw::GLint linkStatus; 915 glw::GLuint value; 916 917 vtx = generateBasicVertexSrc(m_glslVersion); 918 frag = generateBasicFragmentSrc(m_glslVersion); 919 920 // Pipeline API verification 921 log << TestLog::Message << "Begin:PipelineApiCase iterate" << TestLog::EndMessage; 922 923 glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str())); 924 925 // Make separable and relink 926 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 927 gl.linkProgram(progVF.getProgram()); 928 gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus); 929 if (linkStatus != 1) 930 { 931 TCU_FAIL("LinkProgram failed"); 932 } 933 934 gl.genProgramPipelines(1, pipelines); 935 936 // ActiveShaderProgram 937 gl.activeShaderProgram(pipelines[0], progVF.getProgram()); 938 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveShaderProgram failed"); 939 940 // Negative cases for ActiveShaderProgram 941 942 // Nonexistent program 943 gl.activeShaderProgram(pipelines[0], progVF.getProgram() + 100); 944 err = gl.getError(); 945 if (err != GL_INVALID_VALUE) 946 { 947 TCU_FAIL("ActiveShaderProgram failed"); 948 } 949 gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value); 950 if (value != progVF.getProgram()) 951 { 952 TCU_FAIL("ActiveShaderProgram failed"); 953 } 954 955 // Deleted pipeline 956 gl.deleteProgramPipelines(1, pipelines); 957 gl.activeShaderProgram(pipelines[0], progVF.getProgram()); 958 err = gl.getError(); 959 if (err != GL_INVALID_OPERATION) 960 { 961 TCU_FAIL("ActiveShaderProgram failed"); 962 } 963 964 // GenProgramPipeline 965 966 gl.genProgramPipelines(2, &pipelines[0]); 967 gl.genProgramPipelines(3, &pipelines[2]); 968 gl.genProgramPipelines(5, &pipelines[5]); 969 970 for (int i = 0; i < maxpipelines; i++) 971 { 972 gl.bindProgramPipeline(pipelines[i]); // has to be bound to be recognized 973 if (!gl.isProgramPipeline(pipelines[i])) 974 { 975 TCU_FAIL("GenProgramPipelines failed"); 976 } 977 } 978 gl.deleteProgramPipelines(maxpipelines, pipelines); 979 980 // BindProgramPipeline 981 982 gl.genProgramPipelines(2, pipelines); 983 gl.bindProgramPipeline(pipelines[0]); 984 gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value); 985 if (value != pipelines[0]) 986 { 987 TCU_FAIL("BindProgramPipeline failed"); 988 } 989 gl.bindProgramPipeline(pipelines[1]); 990 gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value); 991 if (value != pipelines[1]) 992 { 993 TCU_FAIL("BindProgramPipeline failed"); 994 } 995 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline failed"); 996 997 // Negative Case for BindProgramPipeline 998 999 gl.bindProgramPipeline(pipelines[2]); // deleted pipeline 1000 gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value); 1001 err = gl.getError(); 1002 if ((err != GL_INVALID_OPERATION) || (value != pipelines[1])) 1003 { 1004 TCU_FAIL("BindProgramPipeline failed"); 1005 } 1006 1007 // DeleteProgramPipelines 1008 1009 gl.genProgramPipelines(8, &pipelines[2]); // back to 10 total 1010 gl.deleteProgramPipelines(2, &pipelines[8]); 1011 gl.deleteProgramPipelines(3, &pipelines[5]); 1012 pipelines[9] = 0; 1013 gl.deleteProgramPipelines(maxpipelines, pipelines); // 5 good, 4 deleted, 1 zero 1014 gl.deleteProgramPipelines(0, pipelines); 1015 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines failed"); 1016 for (int i = 0; i < maxpipelines; i++) 1017 { 1018 if (gl.isProgramPipeline(pipelines[i])) 1019 { 1020 TCU_FAIL("DeleteProgramPipelines failed"); 1021 } 1022 } 1023 gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value); 1024 if (value != 0) 1025 { 1026 TCU_FAIL("DeleteProgramPipelines failed"); 1027 } 1028 1029 // IsProgramPipeline 1030 1031 pipelines[1] = 0x1000; 1032 pipelines[2] += 100; 1033 for (int i = 0; i < 3; i++) 1034 { 1035 // 1 deleted and 2 bogus values 1036 if (gl.isProgramPipeline(pipelines[i])) 1037 { 1038 TCU_FAIL("IsProgramPipeline failed"); 1039 } 1040 } 1041 gl.genProgramPipelines(1, pipelines); 1042 if (gl.isProgramPipeline(pipelines[0])) 1043 { 1044 TCU_FAIL("IsProgramPipeline failed"); 1045 } 1046 gl.deleteProgramPipelines(1, pipelines); 1047 GLU_EXPECT_NO_ERROR(gl.getError(), "IsProgramPipeline failed"); 1048 1049 // ProgramParameteri PROGRAM_SEPARABLE 1050 // NOTE: The query for PROGRAM_SEPARABLE must query latched 1051 // state. In other words, the state of the binary after 1052 // it was linked. So in the tests below, the queries 1053 // should return the default state GL_FALSE since the 1054 // program has no linked binary. 1055 1056 glw::GLuint programSep = gl.createProgram(); 1057 int separable; 1058 gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE); 1059 gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable); 1060 if (separable != GL_FALSE) 1061 { 1062 TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed"); 1063 } 1064 gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_FALSE); 1065 gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable); 1066 if (separable != 0) 1067 { 1068 TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed"); 1069 } 1070 1071 // Negative Case for ProgramParameteri PROGRAM_SEPARABLE 1072 1073 gl.deleteProgram(programSep); 1074 gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE); 1075 err = gl.getError(); 1076 if (err != GL_INVALID_VALUE) 1077 { 1078 TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed"); 1079 } 1080 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, 501); 1081 err = gl.getError(); 1082 if (err != GL_INVALID_VALUE) 1083 { 1084 TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed"); 1085 } 1086 1087 // GetProgramPipelineiv 1088 1089 gl.genProgramPipelines(1, pipelines); 1090 gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value); 1091 if (value != 0) 1092 { 1093 TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM"); 1094 } 1095 gl.getProgramPipelineiv(pipelines[0], GL_VERTEX_SHADER, (glw::GLint*)&value); 1096 if (value != 0) 1097 { 1098 TCU_FAIL("GetProgramPipelineiv failed for VERTEX_SHADER"); 1099 } 1100 gl.getProgramPipelineiv(pipelines[0], GL_FRAGMENT_SHADER, (glw::GLint*)&value); 1101 if (value != 0) 1102 { 1103 TCU_FAIL("GetProgramPipelineiv failed for FRAGMENT_SHADER"); 1104 } 1105 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1106 if (value != 0) 1107 { 1108 TCU_FAIL("GetProgramPipelineiv failed for VALIDATE_STATUS"); 1109 } 1110 gl.getProgramPipelineiv(pipelines[0], GL_INFO_LOG_LENGTH, (glw::GLint*)&value); 1111 if (value != 0) 1112 { 1113 TCU_FAIL("GetProgramPipelineiv failed for INFO_LOG_LENGTH"); 1114 } 1115 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineiv failed"); 1116 1117 // Negative Case for GetProgramPipelineiv 1118 1119 gl.deleteProgramPipelines(1, pipelines); 1120 gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value); 1121 err = gl.getError(); 1122 if (err != GL_INVALID_OPERATION) 1123 { 1124 TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM"); 1125 } 1126 1127 // ValidateProgramPipeline 1128 1129 gl.genProgramPipelines(1, pipelines); // Unvalidated 1130 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1131 if (value != 0) 1132 { 1133 TCU_FAIL("ValidateProgramPipeline failed"); 1134 } 1135 1136 gl.validateProgramPipeline(pipelines[0]); // Not bound yet 1137 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1138 if (value != 0) 1139 { 1140 TCU_FAIL("ValidateProgramPipeline failed"); 1141 } 1142 1143 gl.bindProgramPipeline(pipelines[0]); 1144 1145 gl.validateProgramPipeline(pipelines[0]); // Still empty program pipeline. 1146 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1147 if (value != 0) 1148 { 1149 TCU_FAIL("ValidateProgramPipeline failed with empty program pipeline"); 1150 } 1151 1152 gl.useProgramStages(pipelines[0], GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram()); 1153 gl.validateProgramPipeline(pipelines[0]); 1154 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1155 if (value != 1) 1156 { 1157 TCU_FAIL("ValidateProgramPipeline failed"); 1158 } 1159 1160 // GetProgramPipelineInfoLog 1161 checkProgInfoLog(gl, pipelines[0]); 1162 1163 // ValidateProgramPipeline additional 1164 // Relink the bound separable program as not separable 1165 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE); 1166 gl.linkProgram(progVF.getProgram()); 1167 err = gl.getError(); 1168 gl.validateProgramPipeline(pipelines[0]); 1169 gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value); 1170 if (value != 0) 1171 { 1172 TCU_FAIL("ValidateProgramPipeline failed"); 1173 } 1174 GLU_EXPECT_NO_ERROR(gl.getError(), "ValidateProgramPipeline failed"); 1175 1176 // GetProgramPipelineInfoLog 1177 checkProgInfoLog(gl, pipelines[0]); 1178 1179 // Negative Case for ValidateProgramPipeline 1180 1181 gl.deleteProgramPipelines(1, pipelines); 1182 gl.validateProgramPipeline(pipelines[0]); 1183 err = gl.getError(); 1184 if (err != GL_INVALID_OPERATION) 1185 { 1186 TCU_FAIL("ValidateProgramPipeline failed"); 1187 } 1188 1189 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1190 return STOP; 1191 } 1192 1193 private: 1194 glu::GLSLVersion m_glslVersion; 1195 }; 1196 1197 // Testcase for glProgramUniform 1198 class ProgramUniformCase : public TestCase 1199 { 1200 public: 1201 ProgramUniformCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion) 1202 : TestCase(context, name, description), m_glslVersion(glslVersion) 1203 { 1204 } 1205 1206 ~ProgramUniformCase(void) 1207 { 1208 } 1209 1210 bool isDataTypeSquareMatrix(glu::DataType dtyp) 1211 { 1212 return (dtyp == glu::TYPE_FLOAT_MAT2) || (dtyp == glu::TYPE_FLOAT_MAT3) || (dtyp == glu::TYPE_FLOAT_MAT4); 1213 } 1214 1215 // outFragSrc will hold a fragment program that is DataType specific 1216 void generateUniformFragSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, glu::DataType dType) 1217 { 1218 std::ostringstream fragSrc; 1219 1220 fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 1221 if (isDataTypeMatrix(dType) && isDataTypeSquareMatrix(dType)) 1222 { 1223 fragSrc << s_unifFragSquareMatShaderSrc; 1224 } 1225 else if (isDataTypeMatrix(dType) && !isDataTypeSquareMatrix(dType)) 1226 { 1227 fragSrc << s_unifFragNonSquareMatShaderSrc; 1228 } 1229 else 1230 { 1231 fragSrc << s_unifFragShaderSrc; 1232 } 1233 1234 std::map<std::string, std::string> params; 1235 1236 if (dType == glu::TYPE_INT) 1237 { 1238 params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "int")); 1239 params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "ivec")); 1240 params.insert(std::pair<std::string, std::string>("SFX", "")); 1241 } 1242 else if (dType == glu::TYPE_UINT) 1243 { 1244 params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "uint")); 1245 params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "uvec")); 1246 params.insert(std::pair<std::string, std::string>("SFX", "u")); 1247 } 1248 else if (dType == glu::TYPE_FLOAT) 1249 { 1250 params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "float")); 1251 params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "vec")); 1252 params.insert(std::pair<std::string, std::string>("SFX", ".0")); 1253 } 1254 1255 tcu::StringTemplate fragTmpl(fragSrc.str().c_str()); 1256 outFragSrc = fragTmpl.specialize(params); 1257 } 1258 1259 // Set the integer programUniforms 1260 void progUniformi(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, int* value) 1261 { 1262 gl.programUniform1i(prog, location[0], value[0]); 1263 value += 1; 1264 gl.programUniform2i(prog, location[1], value[0], value[1]); 1265 value += 2; 1266 gl.programUniform3i(prog, location[2], value[0], value[1], value[2]); 1267 value += 3; 1268 gl.programUniform4i(prog, location[3], value[0], value[1], value[2], value[3]); 1269 value += 4; 1270 1271 gl.programUniform1iv(prog, location[4], arraySize, value); 1272 value += 1 * arraySize; 1273 gl.programUniform2iv(prog, location[6], arraySize, value); 1274 value += 2 * arraySize; 1275 gl.programUniform3iv(prog, location[8], arraySize, value); 1276 value += 3 * arraySize; 1277 gl.programUniform4iv(prog, location[10], arraySize, value); 1278 } 1279 1280 // Set the unsigned integer programUniforms 1281 void progUniformui(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, unsigned int* value) 1282 { 1283 gl.programUniform1ui(prog, location[0], value[0]); 1284 value += 1; 1285 gl.programUniform2ui(prog, location[1], value[0], value[1]); 1286 value += 2; 1287 gl.programUniform3ui(prog, location[2], value[0], value[1], value[2]); 1288 value += 3; 1289 gl.programUniform4ui(prog, location[3], value[0], value[1], value[2], value[3]); 1290 value += 4; 1291 1292 gl.programUniform1uiv(prog, location[4], arraySize, value); 1293 value += 1 * arraySize; 1294 gl.programUniform2uiv(prog, location[6], arraySize, value); 1295 value += 2 * arraySize; 1296 gl.programUniform3uiv(prog, location[8], arraySize, value); 1297 value += 3 * arraySize; 1298 gl.programUniform4uiv(prog, location[10], arraySize, value); 1299 } 1300 1301 // Set the float programUniforms 1302 void progUniformf(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, float* value) 1303 { 1304 gl.programUniform1f(prog, location[0], value[0]); 1305 value += 1; 1306 gl.programUniform2f(prog, location[1], value[0], value[1]); 1307 value += 2; 1308 gl.programUniform3f(prog, location[2], value[0], value[1], value[2]); 1309 value += 3; 1310 gl.programUniform4f(prog, location[3], value[0], value[1], value[2], value[3]); 1311 value += 4; 1312 1313 gl.programUniform1fv(prog, location[4], arraySize, value); 1314 value += 1 * arraySize; 1315 gl.programUniform2fv(prog, location[6], arraySize, value); 1316 value += 2 * arraySize; 1317 gl.programUniform3fv(prog, location[8], arraySize, value); 1318 value += 3 * arraySize; 1319 gl.programUniform4fv(prog, location[10], arraySize, value); 1320 } 1321 1322 // Set the integer uniforms with conventional glUniformi 1323 void activeUniformi(const glw::Functions& gl, int arraySize, int* location, int* value) 1324 { 1325 gl.uniform1i(location[0], value[0]); 1326 value += 1; 1327 gl.uniform2i(location[1], value[0], value[1]); 1328 value += 2; 1329 gl.uniform3i(location[2], value[0], value[1], value[2]); 1330 value += 3; 1331 gl.uniform4i(location[3], value[0], value[1], value[2], value[3]); 1332 value += 4; 1333 1334 gl.uniform1iv(location[4], arraySize, value); 1335 value += 1 * arraySize; 1336 gl.uniform2iv(location[6], arraySize, value); 1337 value += 2 * arraySize; 1338 gl.uniform3iv(location[8], arraySize, value); 1339 value += 3 * arraySize; 1340 gl.uniform4iv(location[10], arraySize, value); 1341 } 1342 1343 // Set the unsigned integer uniforms with conventional glUniformui 1344 void activeUniformui(const glw::Functions& gl, int arraySize, int* location, unsigned int* value) 1345 { 1346 gl.uniform1ui(location[0], value[0]); 1347 value += 1; 1348 gl.uniform2ui(location[1], value[0], value[1]); 1349 value += 2; 1350 gl.uniform3ui(location[2], value[0], value[1], value[2]); 1351 value += 3; 1352 gl.uniform4ui(location[3], value[0], value[1], value[2], value[3]); 1353 value += 4; 1354 1355 gl.uniform1uiv(location[4], arraySize, value); 1356 value += 1 * arraySize; 1357 gl.uniform2uiv(location[6], arraySize, value); 1358 value += 2 * arraySize; 1359 gl.uniform3uiv(location[8], arraySize, value); 1360 value += 3 * arraySize; 1361 gl.uniform4uiv(location[10], arraySize, value); 1362 } 1363 1364 // Set the float uniforms with conventional glUniformui 1365 void activeUniformf(const glw::Functions& gl, int arraySize, int* location, float* value) 1366 { 1367 gl.uniform1f(location[0], value[0]); 1368 value += 1; 1369 gl.uniform2f(location[1], value[0], value[1]); 1370 value += 2; 1371 gl.uniform3f(location[2], value[0], value[1], value[2]); 1372 value += 3; 1373 gl.uniform4f(location[3], value[0], value[1], value[2], value[3]); 1374 value += 4; 1375 1376 gl.uniform1fv(location[4], arraySize, value); 1377 value += 1 * arraySize; 1378 gl.uniform2fv(location[6], arraySize, value); 1379 value += 2 * arraySize; 1380 gl.uniform3fv(location[8], arraySize, value); 1381 value += 3 * arraySize; 1382 gl.uniform4fv(location[10], arraySize, value); 1383 } 1384 1385 // Call programUniform and verify for non-Matrix uniforms 1386 // Two programs are verified independently and against each other 1387 bool setAndCompareUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB, glu::DataType dType, 1388 int seed) 1389 { 1390 TestLog& log = m_testCtx.getLog(); 1391 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1392 // The fragment shader has defined uniforms of type: 1393 // scalar, vec2, vec3, vec4, and then length 2 arrays of 1394 // scalar, vec2, vec3, and vec4. 1395 // 4 uniforms in array form and 4 not in arrays. 1396 // We query a total of 12 uniform locations 1397 const int nonarrayUnifCount = 4; 1398 const int arrayUnifCount = 4; 1399 const int arraySize = 2; 1400 const int locationCount = nonarrayUnifCount + arraySize * arrayUnifCount; 1401 // dwordCount represents the number of dwords to compare for each uniform location 1402 // scalar, vec2, vec3, vec4, scalar[0], scalar[1], vec2[0], vec2[1], etc. 1403 const int dwordCount[locationCount] = { 1, 2, 3, 4, 1, 1, 2, 2, 3, 3, 4, 4 }; 1404 glw::GLint locationA[locationCount]; 1405 glw::GLint locationB[locationCount]; 1406 // The total amount of data the uniforms take up: 1+2+3+4 + 2*(1+2+3+4) 1407 const int udataCount = 30; 1408 unsigned int udata[udataCount]; // 1409 int* data = (int*)&udata[0]; 1410 float* fdata = (float*)&udata[0]; 1411 int i, j, k; 1412 std::string uniformBaseName("uVal"); 1413 1414 // ProgramUniform API verification 1415 log << TestLog::Message << "Begin:ProgramUniformCase iterate" << TestLog::EndMessage; 1416 1417 // get uniform locations 1418 // scalar and vec uniforms 1419 for (i = 0; i < nonarrayUnifCount; i++) 1420 { 1421 string name = uniformBaseName + de::toString(i); 1422 locationA[i] = gl.getUniformLocation(programA, name.c_str()); 1423 locationB[i] = gl.getUniformLocation(programB, name.c_str()); 1424 } 1425 // uniform arrays 1426 for (j = 0; j < arrayUnifCount; j++) 1427 { 1428 for (k = 0; k < arraySize; k++) 1429 { 1430 string name = uniformBaseName + de::toString(nonarrayUnifCount + j) + "[" + de::toString(k) + "]"; 1431 locationA[i] = gl.getUniformLocation(programA, name.c_str()); 1432 locationB[i] = gl.getUniformLocation(programB, name.c_str()); 1433 i++; 1434 } 1435 } 1436 1437 // seed data buffer with unique values 1438 if (dType == glu::TYPE_FLOAT) 1439 { 1440 for (i = 0; i < udataCount; i++) 1441 { 1442 fdata[i] = (float)(seed + i); 1443 } 1444 } 1445 else 1446 { 1447 for (i = 0; i < udataCount; i++) 1448 { 1449 data[i] = seed + i; 1450 } 1451 } 1452 1453 // set uniforms in program A 1454 if (dType == glu::TYPE_INT) 1455 { 1456 progUniformi(gl, programA, arraySize, locationA, data); 1457 } 1458 else if (dType == glu::TYPE_UINT) 1459 { 1460 progUniformui(gl, programA, arraySize, locationA, udata); 1461 } 1462 else if (dType == glu::TYPE_FLOAT) 1463 { 1464 progUniformf(gl, programA, arraySize, locationA, fdata); 1465 } 1466 1467 // get and compare uniforms 1468 unsigned int* uValue = &udata[0]; 1469 for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++) 1470 { 1471 unsigned int retValA[4], retValB[4]; 1472 1473 if (dType == glu::TYPE_INT) 1474 { 1475 gl.getUniformiv(programA, locationA[i], (int*)&retValA[0]); 1476 gl.getUniformiv(programB, locationB[i], (int*)&retValB[0]); 1477 } 1478 else if (dType == glu::TYPE_UINT) 1479 { 1480 gl.getUniformuiv(programA, locationA[i], &retValA[0]); 1481 gl.getUniformuiv(programB, locationB[i], &retValB[0]); 1482 } 1483 else if (dType == glu::TYPE_FLOAT) 1484 { 1485 gl.getUniformfv(programA, locationA[i], (float*)&retValA[0]); 1486 gl.getUniformfv(programB, locationB[i], (float*)&retValB[0]); 1487 } 1488 1489 for (j = 0; j < dwordCount[i]; j++) 1490 { 1491 // Compare programA uniform to expected value and 1492 // test to see if programB picked up the value. 1493 if ((retValA[j] != *uValue++) || (retValA[j] == retValB[j])) 1494 { 1495 TCU_FAIL("ProgramUniformi failed"); 1496 } 1497 } 1498 } 1499 1500 // reseed data buffer, continuing to increment 1501 if (dType == glu::TYPE_FLOAT) 1502 { 1503 fdata[0] = fdata[udataCount - 1] + 1.0f; 1504 for (i = 1; i < udataCount; i++) 1505 { 1506 fdata[i] = fdata[i - 1] + 1.0f; 1507 } 1508 } 1509 else 1510 { 1511 data[0] = data[udataCount - 1] + 1; 1512 for (i = 1; i < udataCount; i++) 1513 { 1514 data[i] = data[i - 1] + 1; 1515 } 1516 } 1517 1518 // set uniforms in program B 1519 1520 if (dType == glu::TYPE_INT) 1521 { 1522 progUniformi(gl, programB, arraySize, locationB, data); 1523 } 1524 else if (dType == glu::TYPE_UINT) 1525 { 1526 progUniformui(gl, programB, arraySize, locationB, udata); 1527 } 1528 else if (dType == glu::TYPE_FLOAT) 1529 { 1530 progUniformf(gl, programB, arraySize, locationB, fdata); 1531 } 1532 1533 // get and compare uniforms 1534 uValue = &udata[0]; 1535 for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++) 1536 { 1537 unsigned int retValA[4], retValB[4]; 1538 1539 if (dType == glu::TYPE_INT) 1540 { 1541 gl.getUniformiv(programA, locationA[i], (int*)&retValA[0]); 1542 gl.getUniformiv(programB, locationB[i], (int*)&retValB[0]); 1543 } 1544 else if (dType == glu::TYPE_UINT) 1545 { 1546 gl.getUniformuiv(programA, locationA[i], &retValA[0]); 1547 gl.getUniformuiv(programB, locationB[i], &retValB[0]); 1548 } 1549 else if (dType == glu::TYPE_FLOAT) 1550 { 1551 gl.getUniformfv(programA, locationA[i], (float*)&retValA[0]); 1552 gl.getUniformfv(programB, locationB[i], (float*)&retValB[0]); 1553 } 1554 1555 for (j = 0; j < dwordCount[i]; j++) 1556 { 1557 // Compare programB uniform to expected value and 1558 // test to see if programA picked up the value. 1559 if ((retValB[j] != *uValue++) || (retValA[j] == retValB[j])) 1560 { 1561 TCU_FAIL("ProgramUniformi failed"); 1562 } 1563 } 1564 } 1565 1566 // Test the conventional uniform interfaces on an ACTIVE_PROGRAM 1567 glw::GLuint activeProgram = 0; 1568 if (pipeline != 0) 1569 { 1570 gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int*)&activeProgram); 1571 } 1572 if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB))) 1573 { 1574 glw::GLint* location; 1575 1576 location = (activeProgram == programA) ? locationA : locationB; 1577 1578 // reseed data buffer, continuing to increment 1579 if (dType == glu::TYPE_FLOAT) 1580 { 1581 fdata[0] = fdata[udataCount - 1] + 1.0f; 1582 for (i = 1; i < udataCount; i++) 1583 { 1584 fdata[i] = fdata[i - 1] + 1.0f; 1585 } 1586 } 1587 else 1588 { 1589 data[0] = data[udataCount - 1] + 1; 1590 for (i = 1; i < udataCount; i++) 1591 { 1592 data[i] = data[i - 1] + 1; 1593 } 1594 } 1595 1596 // set uniforms using original glUniform* 1597 1598 if (dType == glu::TYPE_INT) 1599 { 1600 activeUniformi(gl, arraySize, location, data); 1601 } 1602 else if (dType == glu::TYPE_UINT) 1603 { 1604 activeUniformui(gl, arraySize, location, udata); 1605 } 1606 else if (dType == glu::TYPE_FLOAT) 1607 { 1608 activeUniformf(gl, arraySize, location, fdata); 1609 } 1610 1611 // get and compare uniforms 1612 uValue = &udata[0]; 1613 for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++) 1614 { 1615 unsigned int retVal[4]; 1616 1617 if (dType == glu::TYPE_INT) 1618 { 1619 gl.getUniformiv(activeProgram, location[i], (int*)&retVal[0]); 1620 } 1621 else if (dType == glu::TYPE_UINT) 1622 { 1623 gl.getUniformuiv(activeProgram, location[i], &retVal[0]); 1624 } 1625 else if (dType == glu::TYPE_FLOAT) 1626 { 1627 gl.getUniformfv(activeProgram, location[i], (float*)&retVal[0]); 1628 } 1629 1630 for (j = 0; j < dwordCount[i]; j++) 1631 { 1632 // Compare activeProgram uniform to expected value 1633 if ((retVal[j] != *uValue++)) 1634 { 1635 TCU_FAIL("ActiveShaderProgram failed"); 1636 } 1637 } 1638 } 1639 } 1640 1641 return true; 1642 } 1643 1644 // Call programUniform for Matrix uniforms 1645 // Two programs are verified independently and against each other 1646 bool setAndCompareMatrixUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB, 1647 glu::DataType dType, int seed) 1648 { 1649 TestLog& log = m_testCtx.getLog(); 1650 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1651 bool isSquareMat = isDataTypeSquareMatrix(dType); 1652 // The matrix versions of the fragment shader have two element arrays 1653 // of each uniform. 1654 // There are 3 * 2 uniforms for the square matrix shader and 1655 // 6 * 2 uniforms in the non-square matrix shader. 1656 const int maxUniforms = 12; 1657 int numUniforms; 1658 const int arraySize = 2; 1659 glw::GLint locationA[maxUniforms]; 1660 glw::GLint locationB[maxUniforms]; 1661 // These arrays represent the number of floats for each uniform location 1662 // 2x2[0], 2x2[1], 3x3[0], 3x3[1], 4x4[0], 4x4[1] 1663 const int floatCountSqu[maxUniforms] = { 4, 4, 9, 9, 16, 16, 0, 0, 0, 0, 0, 0 }; 1664 // 2x3[0], 2x3[1], 2x4[0], 2x4[1], 3x2[0], 3x2[1], 3x4[0], 3x4[1], 4x2[0]... 1665 const int floatCountNonSqu[maxUniforms] = { 6, 6, 8, 8, 6, 6, 12, 12, 8, 8, 12, 12 }; 1666 const int* floatCount; 1667 // Max data for the uniforms = 2*(2*3 + 3*2 + 2*4 + 4*2 + 3*4 + 4*3) 1668 const int maxDataCount = 104; 1669 float data[maxDataCount]; 1670 int i, j, k; 1671 std::string uniformBaseName("uValM"); 1672 1673 // ProgramUniform API verification 1674 log << TestLog::Message << "Begin:ProgramUniformCase for Matrix iterate" << TestLog::EndMessage; 1675 1676 numUniforms = 0; 1677 // get uniform locations 1678 for (i = 2; i <= 4; i++) // matrix dimension m 1679 { 1680 for (j = 2; j <= 4; j++) // matrix dimension n 1681 { 1682 for (k = 0; k < arraySize; k++) 1683 { 1684 if ((i == j) && isSquareMat) 1685 { 1686 string name = uniformBaseName + de::toString(i) + "[" + de::toString(k) + "]"; 1687 locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str()); 1688 locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str()); 1689 numUniforms++; 1690 } 1691 else if ((i != j) && !isSquareMat) 1692 { 1693 string name = 1694 uniformBaseName + de::toString(i) + "x" + de::toString(j) + "[" + de::toString(k) + "]"; 1695 locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str()); 1696 locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str()); 1697 numUniforms++; 1698 } 1699 } 1700 } 1701 } 1702 DE_ASSERT((numUniforms == 6) || (numUniforms == 12)); 1703 1704 // init the float data array 1705 for (i = 0; i < maxDataCount; i++) 1706 { 1707 data[i] = (float)(seed + i); 1708 } 1709 1710 // Set the uniforms in programA 1711 float* value = &data[0]; 1712 if (isSquareMat) 1713 { 1714 floatCount = floatCountSqu; 1715 gl.programUniformMatrix2fv(programA, locationA[0], arraySize, GL_FALSE, value); 1716 value += 2 * 2 * arraySize; 1717 gl.programUniformMatrix3fv(programA, locationA[2], arraySize, GL_FALSE, value); 1718 value += 3 * 3 * arraySize; 1719 gl.programUniformMatrix4fv(programA, locationA[4], arraySize, GL_FALSE, value); 1720 } 1721 else 1722 { 1723 floatCount = floatCountNonSqu; 1724 gl.programUniformMatrix2x3fv(programA, locationA[0], arraySize, GL_FALSE, value); 1725 value += 2 * 3 * arraySize; 1726 gl.programUniformMatrix2x4fv(programA, locationA[2], arraySize, GL_FALSE, value); 1727 value += 2 * 4 * arraySize; 1728 gl.programUniformMatrix3x2fv(programA, locationA[4], arraySize, GL_FALSE, value); 1729 value += 3 * 2 * arraySize; 1730 gl.programUniformMatrix3x4fv(programA, locationA[6], arraySize, GL_FALSE, value); 1731 value += 3 * 4 * arraySize; 1732 gl.programUniformMatrix4x2fv(programA, locationA[8], arraySize, GL_FALSE, value); 1733 value += 4 * 2 * arraySize; 1734 gl.programUniformMatrix4x3fv(programA, locationA[10], arraySize, GL_FALSE, value); 1735 } 1736 1737 // get and compare the uniform data 1738 value = &data[0]; 1739 for (i = 0; i < numUniforms; i++) 1740 { 1741 float retValA[16], retValB[16]; 1742 1743 gl.getUniformfv(programA, locationA[i], retValA); 1744 gl.getUniformfv(programB, locationB[i], retValB); 1745 1746 for (j = 0; j < floatCount[i]; j++) 1747 { 1748 // Compare programA uniform to expected value and 1749 // test to see if programB picked up the value. 1750 if ((retValA[j] != *value++) || (retValA[j] == retValB[j])) 1751 { 1752 TCU_FAIL("ProgramUniformi failed"); 1753 } 1754 } 1755 } 1756 1757 // reseed the float buffer 1758 data[0] = data[maxDataCount - 1]; 1759 for (i = 1; i < maxDataCount; i++) 1760 { 1761 data[i] = data[i - 1] + 1.0f; 1762 } 1763 1764 // set uniforms in program B 1765 value = &data[0]; 1766 if (isSquareMat) 1767 { 1768 floatCount = floatCountSqu; 1769 gl.programUniformMatrix2fv(programB, locationB[0], arraySize, GL_FALSE, value); 1770 value += 2 * 2 * arraySize; 1771 gl.programUniformMatrix3fv(programB, locationB[2], arraySize, GL_FALSE, value); 1772 value += 3 * 3 * arraySize; 1773 gl.programUniformMatrix4fv(programB, locationB[4], arraySize, GL_FALSE, value); 1774 } 1775 else 1776 { 1777 floatCount = floatCountNonSqu; 1778 gl.programUniformMatrix2x3fv(programB, locationB[0], arraySize, GL_FALSE, value); 1779 value += 2 * 3 * arraySize; 1780 gl.programUniformMatrix2x4fv(programB, locationB[2], arraySize, GL_FALSE, value); 1781 value += 2 * 4 * arraySize; 1782 gl.programUniformMatrix3x2fv(programB, locationB[4], arraySize, GL_FALSE, value); 1783 value += 3 * 2 * arraySize; 1784 gl.programUniformMatrix3x4fv(programB, locationB[6], arraySize, GL_FALSE, value); 1785 value += 3 * 4 * arraySize; 1786 gl.programUniformMatrix4x2fv(programB, locationB[8], arraySize, GL_FALSE, value); 1787 value += 4 * 2 * arraySize; 1788 gl.programUniformMatrix4x3fv(programB, locationB[10], arraySize, GL_FALSE, value); 1789 } 1790 1791 // get and compare the uniform data 1792 value = &data[0]; 1793 for (i = 0; i < numUniforms; i++) 1794 { 1795 float retValA[16], retValB[16]; 1796 1797 gl.getUniformfv(programA, locationA[i], retValA); 1798 gl.getUniformfv(programB, locationB[i], retValB); 1799 1800 for (j = 0; j < floatCount[i]; j++) 1801 { 1802 // Compare programB uniform to expected value and 1803 // test to see if programA picked up the value. 1804 if ((retValB[j] != *value++) || (retValA[j] == retValB[j])) 1805 { 1806 TCU_FAIL("ProgramUniformi failed"); 1807 } 1808 } 1809 } 1810 1811 // Use the conventional uniform interfaces on an ACTIVE_PROGRAM 1812 glw::GLuint activeProgram = 0; 1813 if (pipeline != 0) 1814 { 1815 gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int*)&activeProgram); 1816 } 1817 if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB))) 1818 { 1819 glw::GLint* location; 1820 1821 location = (activeProgram == programA) ? locationA : locationB; 1822 1823 // reseed the float buffer 1824 data[0] = data[maxDataCount - 1]; 1825 for (i = 1; i < maxDataCount; i++) 1826 { 1827 data[i] = data[i - 1] + 1.0f; 1828 } 1829 1830 // set uniforms with conventional uniform calls 1831 value = &data[0]; 1832 if (isSquareMat) 1833 { 1834 floatCount = floatCountSqu; 1835 gl.uniformMatrix2fv(location[0], arraySize, GL_FALSE, value); 1836 value += 2 * 2 * arraySize; 1837 gl.uniformMatrix3fv(location[2], arraySize, GL_FALSE, value); 1838 value += 3 * 3 * arraySize; 1839 gl.uniformMatrix4fv(location[4], arraySize, GL_FALSE, value); 1840 } 1841 else 1842 { 1843 floatCount = floatCountNonSqu; 1844 gl.uniformMatrix2x3fv(location[0], arraySize, GL_FALSE, value); 1845 value += 2 * 3 * arraySize; 1846 gl.uniformMatrix2x4fv(location[2], arraySize, GL_FALSE, value); 1847 value += 2 * 4 * arraySize; 1848 gl.uniformMatrix3x2fv(location[4], arraySize, GL_FALSE, value); 1849 value += 3 * 2 * arraySize; 1850 gl.uniformMatrix3x4fv(location[6], arraySize, GL_FALSE, value); 1851 value += 3 * 4 * arraySize; 1852 gl.uniformMatrix4x2fv(location[8], arraySize, GL_FALSE, value); 1853 value += 4 * 2 * arraySize; 1854 gl.uniformMatrix4x3fv(location[10], arraySize, GL_FALSE, value); 1855 } 1856 1857 // get and compare the uniform data 1858 value = &data[0]; 1859 for (i = 0; i < numUniforms; i++) 1860 { 1861 float retVal[16]; 1862 1863 gl.getUniformfv(activeProgram, location[i], retVal); 1864 1865 for (j = 0; j < floatCount[i]; j++) 1866 { 1867 // Compare activeshaderprogram uniform to expected value 1868 if (retVal[j] != *value++) 1869 { 1870 TCU_FAIL("ActiveShaderProgram with glUniform failed"); 1871 } 1872 } 1873 } 1874 } 1875 1876 return true; 1877 } 1878 1879 IterateResult iterate(void) 1880 { 1881 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1882 glu::DataType dType[5] = { glu::TYPE_INT, glu::TYPE_UINT, glu::TYPE_FLOAT, glu::TYPE_FLOAT_MAT2, 1883 glu::TYPE_FLOAT_MAT2X3 }; 1884 1885 // Loop over the various data types, generate fragment programs, and test uniforms 1886 // (MAT2 means stands for all square matrices, MAT2x3 stands for all non-square matrices) 1887 for (int i = 0; i < 5; i++) 1888 { 1889 glw::GLuint programA, programB; 1890 glw::GLuint pipeline = 0; 1891 const char* shaderSrc[1]; 1892 std::string fragSrc; 1893 int seed = 1000 + (1000 * i); 1894 1895 generateUniformFragSrc(fragSrc, m_glslVersion, dType[i]); 1896 1897 size_t length = fragSrc.size(); 1898 std::vector<char> shaderbuf(length + 1); 1899 fragSrc.copy(&shaderbuf[0], length); 1900 shaderbuf[length] = '\0'; 1901 shaderSrc[0] = &shaderbuf[0]; 1902 programA = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc); 1903 programB = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc); 1904 1905 if (isDataTypeMatrix(dType[i])) 1906 { 1907 // programs are unbound 1908 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed); 1909 1910 // bind one program with useProgramStages 1911 gl.genProgramPipelines(1, &pipeline); 1912 gl.bindProgramPipeline(pipeline); 1913 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA); 1914 seed += 100; 1915 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed); 1916 1917 // make an active program with activeShaderProgram 1918 gl.activeShaderProgram(pipeline, programB); 1919 seed += 100; 1920 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed); 1921 } 1922 else 1923 { 1924 // programs are unbound 1925 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed); 1926 1927 // bind one program with useProgramStages 1928 gl.genProgramPipelines(1, &pipeline); 1929 gl.bindProgramPipeline(pipeline); 1930 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA); 1931 seed += 100; 1932 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed); 1933 1934 // make an active program with activeShaderProgram 1935 gl.activeShaderProgram(pipeline, programB); 1936 seed += 100; 1937 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed); 1938 } 1939 1940 gl.deleteProgram(programA); 1941 gl.deleteProgram(programB); 1942 gl.deleteProgramPipelines(1, &pipeline); 1943 } 1944 1945 // Negative Cases 1946 1947 // Program that is not successfully linked 1948 glw::GLenum err; 1949 std::string vtx; 1950 std::string frag; 1951 1952 vtx = generateBasicVertexSrc(m_glslVersion); 1953 frag = generateBasicFragmentSrc(m_glslVersion); 1954 1955 // remove the main keyword so it doesn't link 1956 std::string fragNoMain = frag; 1957 unsigned int pos = (unsigned int)fragNoMain.find("main"); 1958 fragNoMain.replace(pos, 4, "niaM"); 1959 glu::ShaderProgram progNoLink(m_context.getRenderContext(), 1960 glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str())); 1961 gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 1962 gl.linkProgram(progNoLink.getProgram()); 1963 int unifLocation = gl.getUniformLocation(progNoLink.getProgram(), "u_color"); 1964 gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0); 1965 err = gl.getError(); 1966 if (err != GL_INVALID_OPERATION) 1967 { 1968 TCU_FAIL("ProgramUniformi failed"); 1969 } 1970 1971 // deleted program 1972 gl.deleteProgram(progNoLink.getProgram()); 1973 gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0); 1974 err = gl.getError(); 1975 if (err != GL_INVALID_VALUE) 1976 { 1977 TCU_FAIL("ProgramUniformi failed"); 1978 } 1979 1980 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1981 return STOP; 1982 } 1983 1984 private: 1985 glu::GLSLVersion m_glslVersion; 1986 }; 1987 1988 // Testcase for state interactions 1989 class StateInteractionCase : public TestCase 1990 { 1991 public: 1992 StateInteractionCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion) 1993 : TestCase(context, name, description), m_glslVersion(glslVersion) 1994 { 1995 } 1996 1997 ~StateInteractionCase(void) 1998 { 1999 } 2000 2001 // Log the program info log 2002 void logProgramInfoLog(const glw::Functions& gl, glw::GLuint program) 2003 { 2004 TestLog& log = m_testCtx.getLog(); 2005 glw::GLint value = 0; 2006 glw::GLsizei bufSize = 0; 2007 glw::GLsizei length = 0; 2008 2009 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value); 2010 std::vector<char> infoLogBuf(value + 1); 2011 2012 gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]); 2013 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed"); 2014 2015 log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage; 2016 } 2017 2018 // Check program validity created with CreateShaderProgram 2019 bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedLink = GL_TRUE) 2020 { 2021 int linked = GL_FALSE; 2022 if (program != 0) 2023 { 2024 gl.getProgramiv(program, GL_LINK_STATUS, &linked); 2025 2026 if (expectedLink && !linked) 2027 { 2028 logProgramInfoLog(gl, program); 2029 } 2030 } 2031 2032 return (program != 0) && (linked == expectedLink); 2033 } 2034 2035 // Generate a vertex shader for variable input/output testing 2036 void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, int numOutputs) 2037 { 2038 std::ostringstream vtxSrc; 2039 2040 vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2041 if (glslVersion >= glu::GLSL_VERSION_410) 2042 { 2043 vtxSrc << "out gl_PerVertex {\n" 2044 " vec4 gl_Position;\n" 2045 "};\n"; 2046 } 2047 vtxSrc << "in highp vec4 a_position;\n"; 2048 vtxSrc << "uniform highp vec4 u_color;\n"; 2049 2050 switch (numOutputs) 2051 { 2052 // Note all these cases fall through 2053 case 5: 2054 vtxSrc << "layout(location = 3) out vec4 o_val5;\n"; 2055 case 4: 2056 vtxSrc << "flat out uvec4 val4;\n"; 2057 case 3: 2058 vtxSrc << "flat out ivec2 val3;\n"; 2059 case 2: 2060 vtxSrc << "out vec3 val2[2];\n"; 2061 case 1: 2062 vtxSrc << "out vec4 val1;\n"; 2063 default: 2064 vtxSrc << "out float val0;\n"; 2065 } 2066 2067 vtxSrc << "void main (void)\n"; 2068 vtxSrc << "{\n"; 2069 vtxSrc << " gl_Position = a_position;\n"; 2070 2071 // The color uniform is passed in the last declared output variable 2072 switch (numOutputs) 2073 { 2074 case 5: 2075 vtxSrc << " o_val5 = u_color;\n"; 2076 break; 2077 case 4: 2078 vtxSrc << " val4 = uvec4(u_color);\n"; 2079 break; 2080 case 3: 2081 vtxSrc << " val3 = ivec2(u_color);\n"; 2082 break; 2083 case 2: 2084 vtxSrc << " val2[0] = vec3(u_color);\n"; 2085 break; 2086 case 1: 2087 vtxSrc << " val1 = u_color;\n"; 2088 break; 2089 default: 2090 vtxSrc << " val0 = u_color.x;\n"; 2091 break; 2092 } 2093 vtxSrc << "}\n"; 2094 2095 outVtxSrc = vtxSrc.str(); 2096 } 2097 2098 // Generate a fragment shader for variable input/output testing 2099 void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, int numInputs) 2100 { 2101 std::ostringstream fragSrc; 2102 2103 fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2104 fragSrc << "precision highp float;\n"; 2105 fragSrc << "precision highp int;\n"; 2106 2107 switch (numInputs) 2108 { 2109 // Note all these cases fall through 2110 case 5: 2111 fragSrc << "layout(location = 3) in vec4 i_val5;\n"; 2112 case 4: 2113 fragSrc << "flat in uvec4 val4;\n"; 2114 case 3: 2115 fragSrc << "flat in ivec2 val3;\n"; 2116 case 2: 2117 fragSrc << "in vec3 val2[2];\n"; 2118 case 1: 2119 fragSrc << "in vec4 val1;\n"; 2120 default: 2121 fragSrc << "in float val0;\n"; 2122 } 2123 2124 fragSrc << "layout(location = 0) out mediump vec4 o_color;\n"; 2125 fragSrc << "void main (void)\n"; 2126 fragSrc << "{\n"; 2127 2128 switch (numInputs) 2129 { 2130 case 5: 2131 fragSrc << " o_color = i_val5;\n"; 2132 break; 2133 case 4: 2134 fragSrc << " o_color = vec4(val4);\n"; 2135 break; 2136 case 3: 2137 fragSrc << " o_color = vec4(val3, 1.0, 1.0);\n"; 2138 break; 2139 case 2: 2140 fragSrc << " o_color = vec4(val2[0], 1.0);\n"; 2141 break; 2142 case 1: 2143 fragSrc << " o_color = vec4(val1);\n"; 2144 break; 2145 default: 2146 fragSrc << " o_color = vec4(val0, val0, val0, 1.0);\n"; 2147 break; 2148 } 2149 2150 fragSrc << "}\n"; 2151 2152 outFragSrc = fragSrc.str(); 2153 } 2154 2155 // Verify the surface is filled with the expected color 2156 bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor) 2157 { 2158 int numFailedPixels = 0; 2159 for (int y = 0; y < surface.getHeight(); y++) 2160 { 2161 for (int x = 0; x < surface.getWidth(); x++) 2162 { 2163 if (surface.getPixel(x, y) != expectedColor) 2164 numFailedPixels += 1; 2165 } 2166 } 2167 2168 return (numFailedPixels == 0); 2169 } 2170 2171 IterateResult iterate(void) 2172 { 2173 TestLog& log = m_testCtx.getLog(); 2174 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2175 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 2176 int viewportW = de::min(16, renderTarget.getWidth()); 2177 int viewportH = de::min(16, renderTarget.getHeight()); 2178 tcu::Surface renderedFrame(viewportW, viewportH); 2179 2180 glw::GLuint programA, programB; 2181 glw::GLuint vao, vertexBuf, indexBuf; 2182 std::string vtx; 2183 std::string frag, frag2; 2184 glw::GLuint pipeline; 2185 const char* srcStrings[1]; 2186 glw::GLenum err; 2187 2188 log << TestLog::Message << "Begin:StateInteractionCase iterate" << TestLog::EndMessage; 2189 2190 gl.viewport(0, 0, viewportW, viewportH); 2191 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 2192 gl.clear(GL_COLOR_BUFFER_BIT); 2193 2194 // Check the precedence of glUseProgram over glBindProgramPipeline 2195 // The program bound with glUseProgram will draw green, the programs 2196 // bound with glBindProgramPipeline will render blue. 2197 vtx = generateBasicVertexSrc(m_glslVersion); 2198 frag = generateBasicFragmentSrc(m_glslVersion); 2199 2200 glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str())); 2201 2202 gl.useProgram(progVF.getProgram()); 2203 // Ouput green in the fragment shader 2204 gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f); 2205 2206 // Create and bind a pipeline with a different fragment shader 2207 gl.genProgramPipelines(1, &pipeline); 2208 // Use a different uniform name in another fragment shader 2209 frag2 = frag; 2210 size_t pos = 0; 2211 while ((pos = frag2.find("u_color", pos)) != std::string::npos) 2212 { 2213 frag2.replace(pos, 7, "u_clrPB"); 2214 pos += 7; 2215 } 2216 2217 srcStrings[0] = vtx.c_str(); 2218 programA = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings); 2219 if (!checkCSProg(gl, programA)) 2220 { 2221 TCU_FAIL("CreateShaderProgramv failed for vertex shader"); 2222 } 2223 srcStrings[0] = frag2.c_str(); 2224 programB = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings); 2225 if (!checkCSProg(gl, programB)) 2226 { 2227 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 2228 } 2229 // Program B outputs blue. 2230 gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 0.0f, 1.0f, 1.0f); 2231 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA); 2232 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2233 gl.bindProgramPipeline(pipeline); 2234 2235 static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 2236 const float position[] = { -1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f, 2237 +1.0f, -1.0f, 0.0f, 1.0f, +1.0f, +1.0f, -1.0f, 1.0f }; 2238 2239 // Draw a quad with glu::draw 2240 glu::VertexArrayBinding posArray = glu::va::Float("a_position", 4, 4, 0, &position[0]); 2241 glu::draw(m_context.getRenderContext(), progVF.getProgram(), 1, &posArray, 2242 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); 2243 GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction glu::draw failure"); 2244 2245 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2246 2247 // useProgram takes precedence and the buffer should be green 2248 if (!checkSurface(renderedFrame, tcu::RGBA::green())) 2249 { 2250 TCU_FAIL("StateInteraction failed; surface should be green"); 2251 } 2252 2253 // The position attribute locations may be different. 2254 int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position"); 2255 2256 if (glu::isContextTypeES(m_context.getRenderContext().getType())) 2257 gl.disableVertexAttribArray(posLoc); 2258 2259 /* Set up a vertex array object */ 2260 gl.genVertexArrays(1, &vao); 2261 gl.bindVertexArray(vao); 2262 2263 gl.genBuffers(1, &indexBuf); 2264 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf); 2265 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW); 2266 2267 gl.genBuffers(1, &vertexBuf); 2268 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf); 2269 gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW); 2270 2271 posLoc = gl.getAttribLocation(programA, "a_position"); 2272 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0); 2273 gl.enableVertexAttribArray(posLoc); 2274 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 2275 2276 GLU_EXPECT_NO_ERROR(gl.getError(), "VAO setup failure"); 2277 2278 // bindProgramPipeline without a program installed by useProgram 2279 // Rerender the quad. Don't use glu::draw because it takes the 2280 // program as a parameter and sets state. 2281 gl.useProgram(0); 2282 gl.bindProgramPipeline(pipeline); 2283 2284 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2285 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2286 2287 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2288 2289 // bindProgramPipeline will render blue 2290 if (!checkSurface(renderedFrame, tcu::RGBA::blue())) 2291 { 2292 TCU_FAIL("StateInteraction failed; surface should be blue"); 2293 } 2294 2295 // Test rendering with no program bound. Rendering is undefined 2296 // but shouldn't produce an error. 2297 gl.useProgram(0); 2298 gl.bindProgramPipeline(0); 2299 2300 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2301 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2302 2303 // Render call with missing pipeline stages should not generate an error 2304 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0); 2305 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2306 gl.bindProgramPipeline(pipeline); 2307 2308 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2309 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2310 2311 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA); 2312 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, 0); 2313 2314 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2315 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2316 2317 // Missing program for fragment shader 2318 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, programA); 2319 2320 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2321 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2322 2323 // Separable program with both vertex and fragment shaders attached to only one stage 2324 2325 gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 2326 gl.linkProgram(progVF.getProgram()); 2327 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, progVF.getProgram()); 2328 2329 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2330 err = gl.getError(); 2331 if (err != GL_INVALID_OPERATION) 2332 { 2333 TCU_FAIL("DrawElements failed"); 2334 } 2335 2336 gl.validateProgramPipeline(pipeline); 2337 glw::GLint value; 2338 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value); 2339 if (value != 0) 2340 { 2341 TCU_FAIL("Program pipeline validation failed"); 2342 } 2343 2344 // attached to just the fragment shader 2345 // Call validateProgramPipeline before rendering this time 2346 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0); 2347 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, progVF.getProgram()); 2348 2349 gl.validateProgramPipeline(pipeline); 2350 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value); 2351 if (value != 0) 2352 { 2353 TCU_FAIL("Program pipeline validation failed"); 2354 } 2355 2356 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2357 err = gl.getError(); 2358 if (err != GL_INVALID_OPERATION) 2359 { 2360 TCU_FAIL("DrawElements failed"); 2361 } 2362 2363 // Program deletion 2364 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA); 2365 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2366 2367 // Program B renders red this time 2368 gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 0.0f, 0.0f, 1.0f); 2369 2370 gl.deleteProgram(programB); 2371 2372 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2373 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2374 2375 // expect red 2376 if (!checkSurface(renderedFrame, tcu::RGBA::red())) 2377 { 2378 TCU_FAIL("StateInteraction failed; surface should be red"); 2379 } 2380 2381 // Attach new shader 2382 srcStrings[0] = frag2.c_str(); 2383 programB = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings); 2384 if (!checkCSProg(gl, programB)) 2385 { 2386 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 2387 } 2388 // Render green 2389 gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 1.0f, 0.0f, 1.0f); 2390 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2391 2392 // new shader 2393 glw::GLuint vshader = gl.createShader(GL_FRAGMENT_SHADER); 2394 srcStrings[0] = frag.c_str(); // First frag shader with u_color uniform 2395 gl.shaderSource(vshader, 1, srcStrings, NULL); 2396 gl.compileShader(vshader); 2397 gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value); 2398 DE_ASSERT(value == GL_TRUE); 2399 gl.attachShader(programB, vshader); 2400 2401 // changing shader shouldn't affect link_status 2402 gl.getProgramiv(programB, GL_LINK_STATUS, &value); 2403 if (value != 1) 2404 { 2405 TCU_FAIL("Shader attachment shouldn't affect link status"); 2406 } 2407 2408 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2409 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2410 2411 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2412 2413 // expect green 2414 if (!checkSurface(renderedFrame, tcu::RGBA::green())) 2415 { 2416 TCU_FAIL("StateInteraction failed; surface should be green"); 2417 } 2418 2419 // Negative Case: Unsuccessfully linked program should not affect current program 2420 2421 // Render white 2422 gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 1.0f, 1.0f, 1.0f); 2423 std::string noMain = frag; 2424 pos = noMain.find("main", 0); 2425 noMain.replace(pos, 4, "niaM"); 2426 2427 srcStrings[0] = noMain.c_str(); 2428 gl.shaderSource(vshader, 1, srcStrings, NULL); 2429 gl.compileShader(vshader); 2430 gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value); 2431 gl.attachShader(programB, vshader); 2432 gl.linkProgram(programB); 2433 err = gl.getError(); 2434 2435 // link_status should be false 2436 gl.getProgramiv(programB, GL_LINK_STATUS, &value); 2437 if (value != 0) 2438 { 2439 TCU_FAIL("StateInteraction failed; link failure"); 2440 } 2441 2442 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2443 2444 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2445 2446 // expect white 2447 if (!checkSurface(renderedFrame, tcu::RGBA::white())) 2448 { 2449 TCU_FAIL("StateInteraction failed; surface should be white"); 2450 } 2451 2452 gl.deleteProgram(programA); 2453 gl.deleteProgram(programB); 2454 2455 // Shader interface matching inputs/outputs 2456 2457 int maxVars = 6; // generate code supports 6 variables 2458 for (int numInputs = 0; numInputs < maxVars; numInputs++) 2459 { 2460 for (int numOutputs = 0; numOutputs < maxVars; numOutputs++) 2461 { 2462 2463 generateVarLinkVertexShaderSrc(vtx, m_glslVersion, numOutputs); 2464 generateVarLinkFragmentShaderSrc(frag, m_glslVersion, numInputs); 2465 2466 srcStrings[0] = vtx.c_str(); 2467 programA = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings); 2468 if (!checkCSProg(gl, programA)) 2469 { 2470 TCU_FAIL("CreateShaderProgramv failed for vertex shader"); 2471 } 2472 2473 srcStrings[0] = frag.c_str(); 2474 programB = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings); 2475 if (!checkCSProg(gl, programB)) 2476 { 2477 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 2478 } 2479 2480 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA); 2481 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2482 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failure"); 2483 2484 gl.validateProgramPipeline(pipeline); 2485 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value); 2486 2487 // Matched input and output variables should render 2488 if (numInputs == numOutputs) 2489 { 2490 if (value != 1) 2491 { 2492 log << TestLog::Message << "Matched input and output variables should validate successfully.\n" 2493 << "Vertex Shader:\n" 2494 << vtx << "Fragment Shader:\n" 2495 << frag << TestLog::EndMessage; 2496 TCU_FAIL("StateInteraction failed"); 2497 } 2498 gl.clear(GL_COLOR_BUFFER_BIT); 2499 // white 2500 gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); 2501 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2502 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2503 2504 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2505 2506 // expect white 2507 if (!checkSurface(renderedFrame, tcu::RGBA::white())) 2508 { 2509 TCU_FAIL("StateInteraction failed; surface should be white"); 2510 } 2511 } 2512 else 2513 { 2514 // Mismatched input and output variables 2515 // For OpenGL ES contexts, this should cause a validation failure 2516 // For OpenGL contexts, validation should succeed. 2517 if (glu::isContextTypeES(m_context.getRenderContext().getType()) != (value == 0)) 2518 { 2519 log << TestLog::Message << "Mismatched input and output variables; validation should " 2520 << (glu::isContextTypeES(m_context.getRenderContext().getType()) ? "fail.\n" : "succeed.\n") 2521 << "Vertex Shader:\n" 2522 << vtx << "Fragment Shader:\n" 2523 << frag << TestLog::EndMessage; 2524 TCU_FAIL("StateInteraction failed"); 2525 } 2526 } 2527 2528 gl.deleteProgram(programA); 2529 gl.deleteProgram(programB); 2530 } 2531 } 2532 2533 gl.bindProgramPipeline(0); 2534 gl.bindVertexArray(0); 2535 gl.deleteProgramPipelines(1, &pipeline); 2536 gl.deleteShader(vshader); 2537 gl.deleteVertexArrays(1, &vao); 2538 gl.deleteBuffers(1, &indexBuf); 2539 gl.deleteBuffers(1, &vertexBuf); 2540 2541 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2542 return STOP; 2543 } 2544 2545 private: 2546 glu::GLSLVersion m_glslVersion; 2547 }; 2548 2549 // Testcase for interface qualifiers matching 2550 class InterfaceMatchingCase : public TestCase 2551 { 2552 public: 2553 enum TestType 2554 { 2555 DEFAULT_PRECISION, 2556 SET_DEFAULT_PRECISION, 2557 SET_PRECISION 2558 }; 2559 2560 std::string getTestTypeName(TestType testType) 2561 { 2562 switch (testType) 2563 { 2564 case DEFAULT_PRECISION: 2565 return "use predeclared precision"; 2566 case SET_DEFAULT_PRECISION: 2567 return "set default precision"; 2568 case SET_PRECISION: 2569 return "explicit precision"; 2570 } 2571 return ""; 2572 } 2573 2574 InterfaceMatchingCase(Context& context, const char* name, glu::GLSLVersion glslVersion) 2575 : TestCase(context, name, "matching precision qualifiers between stages"), m_glslVersion(glslVersion) 2576 { 2577 } 2578 2579 ~InterfaceMatchingCase(void) 2580 { 2581 } 2582 2583 string getDefaultFragmentPrecision() 2584 { 2585 return ""; 2586 } 2587 2588 // Generate a vertex shader for variable input/output precision testing 2589 virtual void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, 2590 const string& precision, TestType testMode) = 0; 2591 2592 // Generate a fragment shader for variable input/output precision testing 2593 virtual void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, 2594 const string& precision, TestType testMode) = 0; 2595 2596 // Verify the surface is filled with the expected color 2597 bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor) 2598 { 2599 int numFailedPixels = 0; 2600 for (int y = 0; y < surface.getHeight(); y++) 2601 { 2602 for (int x = 0; x < surface.getWidth(); x++) 2603 { 2604 if (surface.getPixel(x, y) != expectedColor) 2605 numFailedPixels += 1; 2606 } 2607 } 2608 return (numFailedPixels == 0); 2609 } 2610 2611 // Log the program info log 2612 void logProgramInfoLog(const glw::Functions& gl, glw::GLuint program) 2613 { 2614 TestLog& log = m_testCtx.getLog(); 2615 glw::GLint value = 0; 2616 glw::GLsizei bufSize = 0; 2617 glw::GLsizei length = 0; 2618 2619 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value); 2620 std::vector<char> infoLogBuf(value + 1); 2621 2622 gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]); 2623 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed"); 2624 2625 log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage; 2626 } 2627 2628 // Check program validity created with CreateShaderProgram 2629 bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedLink = GL_TRUE) 2630 { 2631 int linked = GL_FALSE; 2632 if (program != 0) 2633 { 2634 gl.getProgramiv(program, GL_LINK_STATUS, &linked); 2635 2636 if (expectedLink && !linked) 2637 { 2638 logProgramInfoLog(gl, program); 2639 } 2640 } 2641 2642 return (program != 0) && (linked == expectedLink); 2643 } 2644 2645 IterateResult iterate(void) 2646 { 2647 TestLog& log = m_testCtx.getLog(); 2648 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2649 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 2650 int viewportW = de::min(16, renderTarget.getWidth()); 2651 int viewportH = de::min(16, renderTarget.getHeight()); 2652 tcu::Surface renderedFrame(viewportW, viewportH); 2653 2654 glw::GLuint programA, programB; 2655 glw::GLuint vao, vertexBuf, indexBuf; 2656 std::string vtx; 2657 std::string frag, frag2; 2658 glw::GLuint pipeline; 2659 const char* srcStrings[1]; 2660 glw::GLuint value; 2661 2662 gl.viewport(0, 0, viewportW, viewportH); 2663 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 2664 gl.clear(GL_COLOR_BUFFER_BIT); 2665 2666 static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 2667 const float position[] = { -1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f, 2668 +1.0f, -1.0f, 0.0f, 1.0f, +1.0f, +1.0f, -1.0f, 1.0f }; 2669 2670 /* Set up a vertex array object */ 2671 gl.genVertexArrays(1, &vao); 2672 gl.bindVertexArray(vao); 2673 2674 gl.genBuffers(1, &indexBuf); 2675 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf); 2676 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW); 2677 2678 gl.genBuffers(1, &vertexBuf); 2679 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf); 2680 gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW); 2681 2682 /* Set up shader pipeline */ 2683 gl.genProgramPipelines(1, &pipeline); 2684 gl.bindProgramPipeline(pipeline); 2685 2686 struct PrecisionTests 2687 { 2688 TestType testType; 2689 std::string precision; 2690 }; 2691 2692 PrecisionTests vertexPrecisionTests[] = { 2693 { DEFAULT_PRECISION, "highp" }, { SET_DEFAULT_PRECISION, "highp" }, { SET_DEFAULT_PRECISION, "mediump" }, 2694 { SET_DEFAULT_PRECISION, "lowp" }, { SET_PRECISION, "highp" }, { SET_PRECISION, "mediump" }, 2695 { SET_PRECISION, "lowp" } 2696 }; 2697 2698 PrecisionTests fragmentPrecisionTests[] = { { DEFAULT_PRECISION, getDefaultFragmentPrecision() }, 2699 { SET_DEFAULT_PRECISION, "highp" }, 2700 { SET_DEFAULT_PRECISION, "mediump" }, 2701 { SET_DEFAULT_PRECISION, "lowp" }, 2702 { SET_PRECISION, "highp" }, 2703 { SET_PRECISION, "mediump" }, 2704 { SET_PRECISION, "lowp" } }; 2705 2706 // Shader interface matching inputs/outputs precision 2707 int maxTests = 7; 2708 for (int vertexTestIteration = 0; vertexTestIteration < maxTests; vertexTestIteration++) 2709 { 2710 std::string vertexPrecision = vertexPrecisionTests[vertexTestIteration].precision; 2711 TestType vertexTestType = vertexPrecisionTests[vertexTestIteration].testType; 2712 for (int fragmentTestIteration = 0; fragmentTestIteration < maxTests; fragmentTestIteration++) 2713 { 2714 std::string fragmentPrecision = fragmentPrecisionTests[fragmentTestIteration].precision; 2715 TestType fragmentTestType = fragmentPrecisionTests[fragmentTestIteration].testType; 2716 if (fragmentPrecision.empty()) 2717 continue; 2718 2719 log << TestLog::Message << "vertex shader precision: " << vertexPrecision 2720 << ", shader test mode: " << getTestTypeName(vertexTestType) << TestLog::EndMessage; 2721 2722 log << TestLog::Message << "fragment shader precision: " << fragmentPrecision 2723 << ", shader test mode: " << getTestTypeName(fragmentTestType) << TestLog::EndMessage; 2724 2725 generateVarLinkVertexShaderSrc(vtx, m_glslVersion, vertexPrecision, vertexTestType); 2726 generateVarLinkFragmentShaderSrc(frag, m_glslVersion, fragmentPrecision, fragmentTestType); 2727 2728 srcStrings[0] = vtx.c_str(); 2729 programA = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings); 2730 if (!checkCSProg(gl, programA)) 2731 { 2732 TCU_FAIL("CreateShaderProgramv failed for vertex shader"); 2733 } 2734 srcStrings[0] = frag.c_str(); 2735 programB = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings); 2736 if (!checkCSProg(gl, programB)) 2737 { 2738 TCU_FAIL("CreateShaderProgramv failed for fragment shader"); 2739 } 2740 2741 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA); 2742 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB); 2743 GLU_EXPECT_NO_ERROR(gl.getError(), "InterfaceMatching failure"); 2744 2745 // Mismatched input and output qualifiers 2746 // For OpenGL ES contexts, this should result in a validation failure. 2747 // For OpenGL contexts, validation should succeed. 2748 gl.validateProgramPipeline(pipeline); 2749 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value); 2750 int precisionCompareResult = fragmentPrecision.compare(vertexPrecision); 2751 if (glu::isContextTypeES(m_context.getRenderContext().getType()) && (precisionCompareResult != 0)) 2752 { 2753 // precision mismatch 2754 if (value != GL_FALSE) 2755 { 2756 log.startShaderProgram( 2757 false, "Precision mismatch, pipeline validation status GL_TRUE expected GL_FALSE"); 2758 log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, ""); 2759 log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, ""); 2760 log.endShaderProgram(); 2761 TCU_FAIL("InterfaceMatchingCase failed"); 2762 } 2763 else 2764 { 2765 log << TestLog::Message << "Precision mismatch, Pipeline validation status GL_FALSE -> OK" 2766 << TestLog::EndMessage; 2767 } 2768 } 2769 else 2770 { 2771 if (value != GL_TRUE) 2772 { 2773 std::stringstream str; 2774 str << "Precision " << (precisionCompareResult ? "mismatch" : "matches") 2775 << ", pipeline validation status GL_FALSE expected GL_TRUE"; 2776 2777 log.startShaderProgram(false, str.str().c_str()); 2778 log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, ""); 2779 log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, ""); 2780 log.endShaderProgram(); 2781 TCU_FAIL("InterfaceMatchingCase failed"); 2782 } 2783 else 2784 { 2785 log << TestLog::Message << "Precision " << (precisionCompareResult ? "mismatch" : "matches") 2786 << ", pipeline validation status GL_TRUE -> OK" << TestLog::EndMessage; 2787 // precision matches 2788 gl.clear(GL_COLOR_BUFFER_BIT); 2789 // white 2790 int posLoc = gl.getAttribLocation(programA, "a_position"); 2791 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0); 2792 gl.enableVertexAttribArray(posLoc); 2793 gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f, 2794 1.0f); 2795 GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, set uniform value"); 2796 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2797 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure"); 2798 gl.disableVertexAttribArray(posLoc); 2799 2800 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2801 2802 // expect white 2803 if (!checkSurface(renderedFrame, tcu::RGBA::white())) 2804 { 2805 TCU_FAIL("InterfaceMatchingCase failed; surface should be white"); 2806 } 2807 } 2808 } 2809 2810 // validate non separable program 2811 2812 glu::ShaderProgram progVF(m_context.getRenderContext(), 2813 glu::makeVtxFragSources(vtx.c_str(), frag.c_str())); 2814 2815 gl.useProgram(progVF.getProgram()); 2816 gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); 2817 if (!progVF.getProgramInfo().linkOk) 2818 { 2819 log << progVF; 2820 log << TestLog::Message << "Non separable program link status GL_FALSE expected GL_TRUE" 2821 << TestLog::EndMessage; 2822 TCU_FAIL("InterfaceMatchingCase failed, non separable program should link"); 2823 } 2824 2825 int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position"); 2826 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0); 2827 gl.enableVertexAttribArray(posLoc); 2828 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL); 2829 gl.disableVertexAttribArray(posLoc); 2830 2831 GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, non separable program draw call"); 2832 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess()); 2833 // expect white 2834 if (!checkSurface(renderedFrame, tcu::RGBA::white())) 2835 { 2836 TCU_FAIL("InterfaceMatchingCase failed, non separable program, unexpected color found"); 2837 } 2838 2839 gl.deleteProgram(programA); 2840 gl.deleteProgram(programB); 2841 gl.useProgram(0); 2842 } 2843 } 2844 gl.bindVertexArray(0); 2845 gl.deleteVertexArrays(1, &vao); 2846 gl.deleteBuffers(1, &indexBuf); 2847 gl.deleteBuffers(1, &vertexBuf); 2848 gl.bindProgramPipeline(0); 2849 gl.deleteProgramPipelines(1, &pipeline); 2850 2851 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2852 return STOP; 2853 } 2854 2855 protected: 2856 glu::GLSLVersion m_glslVersion; 2857 }; 2858 2859 class InterfaceMatchingCaseFloat : public InterfaceMatchingCase 2860 { 2861 public: 2862 InterfaceMatchingCaseFloat(Context& context, const char* name, glu::GLSLVersion glslVersion) 2863 : InterfaceMatchingCase(context, name, glslVersion) 2864 { 2865 } 2866 2867 void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision, 2868 TestType testMode) 2869 { 2870 std::ostringstream vtxSrc; 2871 vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2872 if (glslVersion >= glu::GLSL_VERSION_410) 2873 { 2874 vtxSrc << "out gl_PerVertex {\n" 2875 " vec4 gl_Position;\n" 2876 "};\n"; 2877 } 2878 vtxSrc << "in highp vec4 a_position;\n"; 2879 vtxSrc << "uniform highp vec4 u_color;\n"; 2880 switch (testMode) 2881 { 2882 case SET_DEFAULT_PRECISION: 2883 vtxSrc << "precision " << precision << " float;\n"; 2884 case DEFAULT_PRECISION: 2885 vtxSrc << "out float var;\n"; 2886 break; 2887 case SET_PRECISION: 2888 vtxSrc << "out " << precision << " float var;\n"; 2889 break; 2890 } 2891 vtxSrc << "void main (void)\n"; 2892 vtxSrc << "{\n"; 2893 vtxSrc << " gl_Position = a_position;\n"; 2894 vtxSrc << " var = u_color.r;\n"; 2895 vtxSrc << "}\n"; 2896 outVtxSrc = vtxSrc.str(); 2897 } 2898 2899 void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, 2900 const string& precision, TestType testMode) 2901 { 2902 std::ostringstream fragSrc; 2903 fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2904 switch (testMode) 2905 { 2906 case SET_DEFAULT_PRECISION: 2907 fragSrc << "precision " << precision << " float;\n"; 2908 case DEFAULT_PRECISION: 2909 fragSrc << "in float var;\n"; 2910 break; 2911 case SET_PRECISION: 2912 fragSrc << "in " << precision << " float var;\n"; 2913 break; 2914 } 2915 fragSrc << "layout(location = 0) out mediump vec4 o_color;\n"; 2916 fragSrc << "void main (void)\n"; 2917 fragSrc << "{\n"; 2918 fragSrc << " o_color = vec4(var);\n"; 2919 fragSrc << "}\n"; 2920 outFragSrc = fragSrc.str(); 2921 } 2922 }; 2923 2924 class InterfaceMatchingCaseInt : public InterfaceMatchingCase 2925 { 2926 public: 2927 InterfaceMatchingCaseInt(Context& context, const char* name, glu::GLSLVersion glslVersion) 2928 : InterfaceMatchingCase(context, name, glslVersion) 2929 { 2930 } 2931 2932 std::string getDefaultFragmentPrecision() 2933 { 2934 return "mediump"; 2935 } 2936 2937 void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision, 2938 TestType testMode) 2939 { 2940 std::ostringstream vtxSrc; 2941 vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2942 if (glslVersion >= glu::GLSL_VERSION_410) 2943 { 2944 vtxSrc << "out gl_PerVertex {\n" 2945 " vec4 gl_Position;\n" 2946 "};\n"; 2947 } 2948 vtxSrc << "in highp vec4 a_position;\n"; 2949 vtxSrc << "uniform highp vec4 u_color;\n"; 2950 switch (testMode) 2951 { 2952 case SET_DEFAULT_PRECISION: 2953 vtxSrc << "precision " << precision << " int;\n"; 2954 case DEFAULT_PRECISION: 2955 vtxSrc << "flat out int var;\n"; 2956 break; 2957 case SET_PRECISION: 2958 vtxSrc << "flat out " << precision << " int var;\n"; 2959 break; 2960 } 2961 vtxSrc << "void main (void)\n"; 2962 vtxSrc << "{\n"; 2963 vtxSrc << " gl_Position = a_position;\n"; 2964 vtxSrc << " var = int(u_color.r);\n"; 2965 vtxSrc << "}\n"; 2966 outVtxSrc = vtxSrc.str(); 2967 } 2968 2969 void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, 2970 const string& precision, TestType testMode) 2971 { 2972 std::ostringstream fragSrc; 2973 fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 2974 switch (testMode) 2975 { 2976 case SET_DEFAULT_PRECISION: 2977 fragSrc << "precision " << precision << " int;\n"; 2978 case DEFAULT_PRECISION: 2979 fragSrc << "flat in int var;\n"; 2980 break; 2981 case SET_PRECISION: 2982 fragSrc << "flat in " << precision << " int var;\n"; 2983 break; 2984 } 2985 fragSrc << "layout(location = 0) out mediump vec4 o_color;\n"; 2986 fragSrc << "void main (void)\n"; 2987 fragSrc << "{\n"; 2988 fragSrc << " o_color = vec4(var);\n"; 2989 fragSrc << "}\n"; 2990 outFragSrc = fragSrc.str(); 2991 } 2992 }; 2993 2994 class InterfaceMatchingCaseUInt : public InterfaceMatchingCase 2995 { 2996 public: 2997 InterfaceMatchingCaseUInt(Context& context, const char* name, glu::GLSLVersion glslVersion) 2998 : InterfaceMatchingCase(context, name, glslVersion) 2999 { 3000 } 3001 3002 std::string getDefaultFragmentPrecision() 3003 { 3004 return "mediump"; 3005 } 3006 3007 void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision, 3008 TestType testMode) 3009 { 3010 std::ostringstream vtxSrc; 3011 vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 3012 if (glslVersion >= glu::GLSL_VERSION_410) 3013 { 3014 vtxSrc << "out gl_PerVertex {\n" 3015 " vec4 gl_Position;\n" 3016 "};\n"; 3017 } 3018 vtxSrc << "in highp vec4 a_position;\n"; 3019 vtxSrc << "uniform highp vec4 u_color;\n"; 3020 switch (testMode) 3021 { 3022 case SET_DEFAULT_PRECISION: 3023 vtxSrc << "precision " << precision << " int;\n"; 3024 case DEFAULT_PRECISION: 3025 vtxSrc << "flat out uint var;\n"; 3026 break; 3027 case SET_PRECISION: 3028 vtxSrc << "flat out " << precision << " uint var;\n"; 3029 break; 3030 } 3031 vtxSrc << "void main (void)\n"; 3032 vtxSrc << "{\n"; 3033 vtxSrc << " gl_Position = a_position;\n"; 3034 vtxSrc << " var = uint(u_color.r);\n"; 3035 vtxSrc << "}\n"; 3036 outVtxSrc = vtxSrc.str(); 3037 } 3038 3039 void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, 3040 const string& precision, TestType testMode) 3041 { 3042 std::ostringstream fragSrc; 3043 fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n"; 3044 switch (testMode) 3045 { 3046 case SET_DEFAULT_PRECISION: 3047 fragSrc << "precision " << precision << " int;\n"; 3048 case DEFAULT_PRECISION: 3049 fragSrc << "flat in uint var;\n"; 3050 break; 3051 case SET_PRECISION: 3052 fragSrc << "flat in " << precision << " uint var;\n"; 3053 break; 3054 } 3055 fragSrc << "layout(location = 0) out mediump vec4 o_color;\n"; 3056 fragSrc << "void main (void)\n"; 3057 fragSrc << "{\n"; 3058 fragSrc << " o_color = vec4(var);\n"; 3059 fragSrc << "}\n"; 3060 outFragSrc = fragSrc.str(); 3061 } 3062 }; 3063 3064 SeparateShaderObjsTests::SeparateShaderObjsTests(Context& context, glu::GLSLVersion glslVersion) 3065 : TestCaseGroup(context, "sepshaderobjs", "separate_shader_object tests"), m_glslVersion(glslVersion) 3066 { 3067 DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440); 3068 } 3069 3070 SeparateShaderObjsTests::~SeparateShaderObjsTests(void) 3071 { 3072 } 3073 3074 void SeparateShaderObjsTests::init(void) 3075 { 3076 3077 // API validation for CreateShaderProgram 3078 addChild(new CreateShadProgCase(m_context, "CreateShadProgApi", "createShaderProgram API", m_glslVersion)); 3079 // API validation for UseProgramStages 3080 addChild(new UseProgStagesCase(m_context, "UseProgStagesApi", "useProgramStages API", m_glslVersion)); 3081 // API validation for pipeline related functions 3082 addChild(new PipelineApiCase(m_context, "PipelineApi", "Pipeline API", m_glslVersion)); 3083 // API validation for variations of ProgramUniform 3084 addChild(new ProgramUniformCase(m_context, "ProgUniformAPI", "ProgramUniform API", m_glslVersion)); 3085 // State interactions 3086 addChild(new StateInteractionCase(m_context, "StateInteraction", "SSO State Interactions", m_glslVersion)); 3087 // input / output precision matching 3088 addChild(new InterfaceMatchingCaseFloat(m_context, "InterfacePrecisionMatchingFloat", m_glslVersion)); 3089 addChild(new InterfaceMatchingCaseInt(m_context, "InterfacePrecisionMatchingInt", m_glslVersion)); 3090 addChild(new InterfaceMatchingCaseUInt(m_context, "InterfacePrecisionMatchingUInt", m_glslVersion)); 3091 } 3092 3093 } // glcts 3094