1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2016 Google Inc. 6 * Copyright (c) 2016 The Khronos Group Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 */ /*! 21 * \file 22 * \brief Shader struct tests. 23 */ /*-------------------------------------------------------------------*/ 24 25 #include "glcShaderStructTests.hpp" 26 #include "glcShaderRenderCase.hpp" 27 #include "gluTexture.hpp" 28 #include "glwEnums.hpp" 29 #include "glwFunctions.hpp" 30 #include "tcuStringTemplate.hpp" 31 #include "tcuTextureUtil.hpp" 32 33 using tcu::StringTemplate; 34 35 using std::string; 36 using std::vector; 37 using std::ostringstream; 38 39 using namespace glu; 40 41 namespace deqp 42 { 43 44 enum 45 { 46 TEXTURE_GRADIENT = 0 //!< Unit index for gradient texture 47 }; 48 49 typedef void (*SetupUniformsFunc)(const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords); 50 51 class ShaderStructCase : public ShaderRenderCase 52 { 53 public: 54 ShaderStructCase(Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, 55 ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, 56 const char* fragShaderSource); 57 ~ShaderStructCase(void); 58 59 void init(void); 60 void deinit(void); 61 62 virtual void setupUniforms(deUint32 programID, const tcu::Vec4& constCoords); 63 64 private: 65 ShaderStructCase(const ShaderStructCase&); 66 ShaderStructCase& operator=(const ShaderStructCase&); 67 68 SetupUniformsFunc m_setupUniforms; 69 bool m_usesTexture; 70 71 glu::Texture2D* m_gradientTexture; 72 }; 73 74 ShaderStructCase::ShaderStructCase(Context& context, const char* name, const char* description, bool isVertexCase, 75 bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, 76 const char* vertShaderSource, const char* fragShaderSource) 77 : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, 78 description, isVertexCase, evalFunc) 79 , m_setupUniforms(setupUniformsFunc) 80 , m_usesTexture(usesTextures) 81 , m_gradientTexture(DE_NULL) 82 { 83 m_vertShaderSource = vertShaderSource; 84 m_fragShaderSource = fragShaderSource; 85 } 86 87 ShaderStructCase::~ShaderStructCase(void) 88 { 89 } 90 91 void ShaderStructCase::init(void) 92 { 93 if (m_usesTexture) 94 { 95 m_gradientTexture = new glu::Texture2D(m_renderCtx, GL_RGBA8, 128, 128); 96 97 m_gradientTexture->getRefTexture().allocLevel(0); 98 tcu::fillWithComponentGradients(m_gradientTexture->getRefTexture().getLevel(0), tcu::Vec4(0.0f), 99 tcu::Vec4(1.0f)); 100 m_gradientTexture->upload(); 101 102 m_textures.push_back(TextureBinding( 103 m_gradientTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, 104 tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR))); 105 DE_ASSERT(m_textures.size() == 1); 106 } 107 ShaderRenderCase::init(); 108 } 109 110 void ShaderStructCase::deinit(void) 111 { 112 if (m_usesTexture) 113 { 114 delete m_gradientTexture; 115 } 116 ShaderRenderCase::deinit(); 117 } 118 119 void ShaderStructCase::setupUniforms(deUint32 programID, const tcu::Vec4& constCoords) 120 { 121 ShaderRenderCase::setupUniforms(programID, constCoords); 122 if (m_setupUniforms) 123 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords); 124 } 125 126 static ShaderStructCase* createStructCase(Context& context, const char* name, const char* description, 127 glu::GLSLVersion glslVersion, bool isVertexCase, bool usesTextures, 128 ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms, 129 const LineStream& shaderSrc) 130 { 131 const std::string versionDecl = glu::getGLSLVersionDeclaration(glslVersion); 132 133 const std::string defaultVertSrc = versionDecl + "\n" 134 "in highp vec4 a_position;\n" 135 "in highp vec4 a_coords;\n" 136 "out mediump vec4 v_coords;\n\n" 137 "void main (void)\n" 138 "{\n" 139 " v_coords = a_coords;\n" 140 " gl_Position = a_position;\n" 141 "}\n"; 142 const std::string defaultFragSrc = versionDecl + "\n" 143 "in mediump vec4 v_color;\n" 144 "layout(location = 0) out mediump vec4 o_color;\n\n" 145 "void main (void)\n" 146 "{\n" 147 " o_color = v_color;\n" 148 "}\n"; 149 150 // Fill in specialization parameters. 151 std::map<std::string, std::string> spParams; 152 if (isVertexCase) 153 { 154 spParams["HEADER"] = versionDecl + "\n" 155 "in highp vec4 a_position;\n" 156 "in highp vec4 a_coords;\n" 157 "out mediump vec4 v_color;"; 158 spParams["COORDS"] = "a_coords"; 159 spParams["DST"] = "v_color"; 160 spParams["ASSIGN_POS"] = "gl_Position = a_position;"; 161 } 162 else 163 { 164 spParams["HEADER"] = versionDecl + "\n" 165 "in mediump vec4 v_coords;\n" 166 "layout(location = 0) out mediump vec4 o_color;"; 167 spParams["COORDS"] = "v_coords"; 168 spParams["DST"] = "o_color"; 169 spParams["ASSIGN_POS"] = ""; 170 } 171 172 if (isVertexCase) 173 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, 174 StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), 175 defaultFragSrc.c_str()); 176 else 177 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, 178 defaultVertSrc.c_str(), 179 StringTemplate(shaderSrc.str()).specialize(spParams).c_str()); 180 } 181 182 class LocalStructTests : public TestCaseGroup 183 { 184 public: 185 LocalStructTests(Context& context, glu::GLSLVersion glslVersion) 186 : TestCaseGroup(context, "local", "Local structs"), m_glslVersion(glslVersion) 187 { 188 } 189 190 ~LocalStructTests(void) 191 { 192 } 193 194 virtual void init(void); 195 196 private: 197 glu::GLSLVersion m_glslVersion; 198 }; 199 200 void LocalStructTests::init(void) 201 { 202 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \ 203 do \ 204 { \ 205 struct Eval_##NAME \ 206 { \ 207 static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \ 208 }; \ 209 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, false, \ 210 &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \ 211 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, false, \ 212 &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \ 213 } while (deGetFalse()) 214 215 LOCAL_STRUCT_CASE(basic, "Basic struct usage", 216 LineStream() << "${HEADER}" 217 << "uniform int ui_one;" 218 << "" 219 << "struct S {" 220 << " mediump float a;" 221 << " mediump vec3 b;" 222 << " int c;" 223 << "};" 224 << "" 225 << "void main (void)" 226 << "{" 227 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 228 << " s.b = ${COORDS}.yzw;" 229 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 230 << " ${ASSIGN_POS}" 231 << "}", 232 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 233 234 LOCAL_STRUCT_CASE(nested, "Nested struct", 235 LineStream() << "${HEADER}" 236 << "uniform int ui_zero;" 237 << "uniform int ui_one;" 238 << "" 239 << "struct T {" 240 << " int a;" 241 << " mediump vec2 b;" 242 << "};" 243 << "struct S {" 244 << " mediump float a;" 245 << " T b;" 246 << " int c;" 247 << "};" 248 << "" 249 << "void main (void)" 250 << "{" 251 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 252 << " s.b = T(ui_zero, ${COORDS}.yz);" 253 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 254 << " ${ASSIGN_POS}" 255 << "}", 256 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 257 258 LOCAL_STRUCT_CASE(array_member, "Struct with array member", 259 LineStream() << "${HEADER}" 260 << "uniform int ui_one;" 261 << "" 262 << "struct S {" 263 << " mediump float a;" 264 << " mediump float b[3];" 265 << " int c;" 266 << "};" 267 << "" 268 << "void main (void)" 269 << "{" 270 << " S s;" 271 << " s.a = ${COORDS}.w;" 272 << " s.c = ui_one;" 273 << " s.b[0] = ${COORDS}.z;" 274 << " s.b[1] = ${COORDS}.y;" 275 << " s.b[2] = ${COORDS}.x;" 276 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" 277 << " ${ASSIGN_POS}" 278 << "}", 279 { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); 280 281 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", 282 LineStream() << "${HEADER}" 283 << "uniform int ui_zero;" 284 << "uniform int ui_one;" 285 << "uniform int ui_two;" 286 << "" 287 << "struct S {" 288 << " mediump float a;" 289 << " mediump float b[3];" 290 << " int c;" 291 << "};" 292 << "" 293 << "void main (void)" 294 << "{" 295 << " S s;" 296 << " s.a = ${COORDS}.w;" 297 << " s.c = ui_one;" 298 << " s.b[0] = ${COORDS}.z;" 299 << " s.b[1] = ${COORDS}.y;" 300 << " s.b[2] = ${COORDS}.x;" 301 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" 302 << " ${ASSIGN_POS}" 303 << "}", 304 { c.color.xyz() = c.coords.swizzle(1, 2, 0); }); 305 306 LOCAL_STRUCT_CASE(struct_array, "Struct array", 307 LineStream() << "${HEADER}" 308 << "uniform int ui_zero;" 309 << "uniform int ui_one;" 310 << "uniform int ui_two;" 311 << "" 312 << "struct S {" 313 << " mediump float a;" 314 << " mediump int b;" 315 << "};" 316 << "" 317 << "void main (void)" 318 << "{" 319 << " S s[3];" 320 << " s[0] = S(${COORDS}.x, ui_zero);" 321 << " s[1].a = ${COORDS}.y;" 322 << " s[1].b = ui_one;" 323 << " s[2] = S(${COORDS}.z, ui_two);" 324 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" 325 << " ${ASSIGN_POS}" 326 << "}", 327 { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); 328 329 LOCAL_STRUCT_CASE( 330 struct_array_dynamic_index, "Struct array with dynamic indexing", 331 LineStream() 332 << "${HEADER}" 333 << "uniform int ui_zero;" 334 << "uniform int ui_one;" 335 << "uniform int ui_two;" 336 << "" 337 << "struct S {" 338 << " mediump float a;" 339 << " mediump int b;" 340 << "};" 341 << "" 342 << "void main (void)" 343 << "{" 344 << " S s[3];" 345 << " s[0] = S(${COORDS}.x, ui_zero);" 346 << " s[1].a = ${COORDS}.y;" 347 << " s[1].b = ui_one;" 348 << " s[2] = S(${COORDS}.z, ui_two);" 349 << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" 350 << " ${ASSIGN_POS}" 351 << "}", 352 { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); 353 354 LOCAL_STRUCT_CASE( 355 nested_struct_array, "Nested struct array", 356 LineStream() << "${HEADER}" 357 << "uniform int ui_zero;" 358 << "uniform int ui_one;" 359 << "uniform int ui_two;" 360 << "uniform mediump float uf_two;" 361 << "uniform mediump float uf_three;" 362 << "uniform mediump float uf_four;" 363 << "uniform mediump float uf_half;" 364 << "uniform mediump float uf_third;" 365 << "uniform mediump float uf_fourth;" 366 << "" 367 << "struct T {" 368 << " mediump float a;" 369 << " mediump vec2 b[2];" 370 << "};" 371 << "struct S {" 372 << " mediump float a;" 373 << " T b[3];" 374 << " int c;" 375 << "};" 376 << "" 377 << "void main (void)" 378 << "{" 379 << " S s[2];" 380 << "" 381 << " // S[0]" 382 << " s[0].a = ${COORDS}.x;" 383 << " s[0].b[0].a = uf_half;" 384 << " s[0].b[0].b[0] = ${COORDS}.xy;" 385 << " s[0].b[0].b[1] = ${COORDS}.zw;" 386 << " s[0].b[1].a = uf_third;" 387 << " s[0].b[1].b[0] = ${COORDS}.zw;" 388 << " s[0].b[1].b[1] = ${COORDS}.xy;" 389 << " s[0].b[2].a = uf_fourth;" 390 << " s[0].b[2].b[0] = ${COORDS}.xz;" 391 << " s[0].b[2].b[1] = ${COORDS}.yw;" 392 << " s[0].c = ui_zero;" 393 << "" 394 << " // S[1]" 395 << " s[1].a = ${COORDS}.w;" 396 << " s[1].b[0].a = uf_two;" 397 << " s[1].b[0].b[0] = ${COORDS}.xx;" 398 << " s[1].b[0].b[1] = ${COORDS}.yy;" 399 << " s[1].b[1].a = uf_three;" 400 << " s[1].b[1].b[0] = ${COORDS}.zz;" 401 << " s[1].b[1].b[1] = ${COORDS}.ww;" 402 << " s[1].b[2].a = uf_four;" 403 << " s[1].b[2].b[0] = ${COORDS}.yx;" 404 << " s[1].b[2].b[1] = ${COORDS}.wz;" 405 << " s[1].c = ui_one;" 406 << "" 407 << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" 408 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" 409 << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w " 410 "+ w) * 0.333" 411 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" 412 << " ${DST} = vec4(r, g, b, a);" 413 << " ${ASSIGN_POS}" 414 << "}", 415 { c.color.xyz() = c.coords.swizzle(2, 0, 3); }); 416 417 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", 418 LineStream() << "${HEADER}" 419 << "uniform int ui_zero;" 420 << "uniform int ui_one;" 421 << "uniform int ui_two;" 422 << "uniform mediump float uf_two;" 423 << "uniform mediump float uf_three;" 424 << "uniform mediump float uf_four;" 425 << "uniform mediump float uf_half;" 426 << "uniform mediump float uf_third;" 427 << "uniform mediump float uf_fourth;" 428 << "" 429 << "struct T {" 430 << " mediump float a;" 431 << " mediump vec2 b[2];" 432 << "};" 433 << "struct S {" 434 << " mediump float a;" 435 << " T b[3];" 436 << " int c;" 437 << "};" 438 << "" 439 << "void main (void)" 440 << "{" 441 << " S s[2];" 442 << "" 443 << " // S[0]" 444 << " s[0].a = ${COORDS}.x;" 445 << " s[0].b[0].a = uf_half;" 446 << " s[0].b[0].b[0] = ${COORDS}.xy;" 447 << " s[0].b[0].b[1] = ${COORDS}.zw;" 448 << " s[0].b[1].a = uf_third;" 449 << " s[0].b[1].b[0] = ${COORDS}.zw;" 450 << " s[0].b[1].b[1] = ${COORDS}.xy;" 451 << " s[0].b[2].a = uf_fourth;" 452 << " s[0].b[2].b[0] = ${COORDS}.xz;" 453 << " s[0].b[2].b[1] = ${COORDS}.yw;" 454 << " s[0].c = ui_zero;" 455 << "" 456 << " // S[1]" 457 << " s[1].a = ${COORDS}.w;" 458 << " s[1].b[0].a = uf_two;" 459 << " s[1].b[0].b[0] = ${COORDS}.xx;" 460 << " s[1].b[0].b[1] = ${COORDS}.yy;" 461 << " s[1].b[1].a = uf_three;" 462 << " s[1].b[1].b[0] = ${COORDS}.zz;" 463 << " s[1].b[1].b[1] = ${COORDS}.ww;" 464 << " s[1].b[2].a = uf_four;" 465 << " s[1].b[2].b[0] = ${COORDS}.yx;" 466 << " s[1].b[2].b[1] = ${COORDS}.wz;" 467 << " s[1].c = ui_one;" 468 << "" 469 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + " 470 "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" 471 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * " 472 "s[ui_one].b[2].a; // x * 0.25 * 4" 473 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + " 474 "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + " 475 "w + w) * 0.333" 476 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - " 477 "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" 478 << " ${DST} = vec4(r, g, b, a);" 479 << " ${ASSIGN_POS}" 480 << "}", 481 { c.color.xyz() = c.coords.swizzle(2, 0, 3); }); 482 483 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter", 484 LineStream() << "${HEADER}" 485 << "uniform int ui_one;" 486 << "" 487 << "struct S {" 488 << " mediump float a;" 489 << " mediump vec3 b;" 490 << " int c;" 491 << "};" 492 << "" 493 << "mediump vec4 myFunc (S s)" 494 << "{" 495 << " return vec4(s.a, s.b.x, s.b.y, s.c);" 496 << "}" 497 << "" 498 << "void main (void)" 499 << "{" 500 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 501 << " s.b = ${COORDS}.yzw;" 502 << " ${DST} = myFunc(s);" 503 << " ${ASSIGN_POS}" 504 << "}", 505 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 506 507 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter", 508 LineStream() << "${HEADER}" 509 << "uniform int ui_zero;" 510 << "uniform int ui_one;" 511 << "" 512 << "struct T {" 513 << " int a;" 514 << " mediump vec2 b;" 515 << "};" 516 << "struct S {" 517 << " mediump float a;" 518 << " T b;" 519 << " int c;" 520 << "};" 521 << "" 522 << "mediump vec4 myFunc (S s)" 523 << "{" 524 << " return vec4(s.a, s.b.b, s.b.a + s.c);" 525 << "}" 526 << "" 527 << "void main (void)" 528 << "{" 529 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 530 << " s.b = T(ui_zero, ${COORDS}.yz);" 531 << " ${DST} = myFunc(s);" 532 << " ${ASSIGN_POS}" 533 << "}", 534 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 535 536 LOCAL_STRUCT_CASE(return, "Struct as a return value", 537 LineStream() << "${HEADER}" 538 << "uniform int ui_one;" 539 << "" 540 << "struct S {" 541 << " mediump float a;" 542 << " mediump vec3 b;" 543 << " int c;" 544 << "};" 545 << "" 546 << "S myFunc (void)" 547 << "{" 548 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 549 << " s.b = ${COORDS}.yzw;" 550 << " return s;" 551 << "}" 552 << "" 553 << "void main (void)" 554 << "{" 555 << " S s = myFunc();" 556 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 557 << " ${ASSIGN_POS}" 558 << "}", 559 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 560 561 LOCAL_STRUCT_CASE(return_nested, "Nested struct", 562 LineStream() << "${HEADER}" 563 << "uniform int ui_zero;" 564 << "uniform int ui_one;" 565 << "" 566 << "struct T {" 567 << " int a;" 568 << " mediump vec2 b;" 569 << "};" 570 << "struct S {" 571 << " mediump float a;" 572 << " T b;" 573 << " int c;" 574 << "};" 575 << "" 576 << "S myFunc (void)" 577 << "{" 578 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 579 << " s.b = T(ui_zero, ${COORDS}.yz);" 580 << " return s;" 581 << "}" 582 << "" 583 << "void main (void)" 584 << "{" 585 << " S s = myFunc();" 586 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 587 << " ${ASSIGN_POS}" 588 << "}", 589 { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); 590 591 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment", 592 LineStream() << "${HEADER}" 593 << "uniform int ui_zero;" 594 << "uniform int ui_one;" 595 << "uniform mediump float uf_one;" 596 << "" 597 << "struct S {" 598 << " mediump float a;" 599 << " mediump vec3 b;" 600 << " int c;" 601 << "};" 602 << "" 603 << "void main (void)" 604 << "{" 605 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 606 << " if (uf_one > 0.0)" 607 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 608 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 609 << " ${ASSIGN_POS}" 610 << "}", 611 { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); 612 613 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop", 614 LineStream() << "${HEADER}" 615 << "uniform int ui_zero;" 616 << "uniform int ui_one;" 617 << "" 618 << "struct S {" 619 << " mediump float a;" 620 << " mediump vec3 b;" 621 << " int c;" 622 << "};" 623 << "" 624 << "void main (void)" 625 << "{" 626 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 627 << " for (int i = 0; i < 3; i++)" 628 << " {" 629 << " if (i == 1)" 630 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 631 << " }" 632 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 633 << " ${ASSIGN_POS}" 634 << "}", 635 { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); 636 637 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop", 638 LineStream() << "${HEADER}" 639 << "uniform int ui_zero;" 640 << "uniform int ui_one;" 641 << "uniform int ui_three;" 642 << "" 643 << "struct S {" 644 << " mediump float a;" 645 << " mediump vec3 b;" 646 << " int c;" 647 << "};" 648 << "" 649 << "void main (void)" 650 << "{" 651 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 652 << " for (int i = 0; i < ui_three; i++)" 653 << " {" 654 << " if (i == ui_one)" 655 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 656 << " }" 657 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 658 << " ${ASSIGN_POS}" 659 << "}", 660 { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); 661 662 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct", 663 LineStream() << "${HEADER}" 664 << "uniform int ui_zero;" 665 << "uniform int ui_one;" 666 << "uniform mediump float uf_one;" 667 << "" 668 << "struct T {" 669 << " int a;" 670 << " mediump vec2 b;" 671 << "};" 672 << "struct S {" 673 << " mediump float a;" 674 << " T b;" 675 << " int c;" 676 << "};" 677 << "" 678 << "void main (void)" 679 << "{" 680 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 681 << " if (uf_one > 0.0)" 682 << " s.b = T(ui_zero, ${COORDS}.zw);" 683 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 684 << " ${ASSIGN_POS}" 685 << "}", 686 { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); 687 688 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop", 689 LineStream() << "${HEADER}" 690 << "uniform int ui_zero;" 691 << "uniform int ui_one;" 692 << "uniform mediump float uf_one;" 693 << "" 694 << "struct T {" 695 << " int a;" 696 << " mediump vec2 b;" 697 << "};" 698 << "struct S {" 699 << " mediump float a;" 700 << " T b;" 701 << " int c;" 702 << "};" 703 << "" 704 << "void main (void)" 705 << "{" 706 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 707 << " for (int i = 0; i < 3; i++)" 708 << " {" 709 << " if (i == 1)" 710 << " s.b = T(ui_zero, ${COORDS}.zw);" 711 << " }" 712 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 713 << " ${ASSIGN_POS}" 714 << "}", 715 { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); 716 717 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop", 718 LineStream() << "${HEADER}" 719 << "uniform int ui_zero;" 720 << "uniform int ui_one;" 721 << "uniform int ui_three;" 722 << "uniform mediump float uf_one;" 723 << "" 724 << "struct T {" 725 << " int a;" 726 << " mediump vec2 b;" 727 << "};" 728 << "struct S {" 729 << " mediump float a;" 730 << " T b;" 731 << " int c;" 732 << "};" 733 << "" 734 << "void main (void)" 735 << "{" 736 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 737 << " for (int i = 0; i < ui_three; i++)" 738 << " {" 739 << " if (i == ui_one)" 740 << " s.b = T(ui_zero, ${COORDS}.zw);" 741 << " }" 742 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 743 << " ${ASSIGN_POS}" 744 << "}", 745 { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); 746 747 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 748 LineStream() << "${HEADER}" 749 << "uniform int ui_zero;" 750 << "uniform int ui_one;" 751 << "uniform int ui_two;" 752 << "" 753 << "struct S {" 754 << " mediump float a;" 755 << " mediump int b;" 756 << "};" 757 << "" 758 << "void main (void)" 759 << "{" 760 << " S s[3];" 761 << " s[0] = S(${COORDS}.x, ui_zero);" 762 << " s[1].a = ${COORDS}.y;" 763 << " s[1].b = -ui_one;" 764 << " s[2] = S(${COORDS}.z, ui_two);" 765 << "" 766 << " mediump float rgb[3];" 767 << " int alpha = 0;" 768 << " for (int i = 0; i < 3; i++)" 769 << " {" 770 << " rgb[i] = s[2-i].a;" 771 << " alpha += s[i].b;" 772 << " }" 773 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 774 << " ${ASSIGN_POS}" 775 << "}", 776 { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); 777 778 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 779 LineStream() << "${HEADER}" 780 << "uniform int ui_zero;" 781 << "uniform int ui_one;" 782 << "uniform int ui_two;" 783 << "uniform mediump float uf_two;" 784 << "uniform mediump float uf_three;" 785 << "uniform mediump float uf_four;" 786 << "uniform mediump float uf_half;" 787 << "uniform mediump float uf_third;" 788 << "uniform mediump float uf_fourth;" 789 << "uniform mediump float uf_sixth;" 790 << "" 791 << "struct T {" 792 << " mediump float a;" 793 << " mediump vec2 b[2];" 794 << "};" 795 << "struct S {" 796 << " mediump float a;" 797 << " T b[3];" 798 << " int c;" 799 << "};" 800 << "" 801 << "void main (void)" 802 << "{" 803 << " S s[2];" 804 << "" 805 << " // S[0]" 806 << " s[0].a = ${COORDS}.x;" 807 << " s[0].b[0].a = uf_half;" 808 << " s[0].b[0].b[0] = ${COORDS}.yx;" 809 << " s[0].b[0].b[1] = ${COORDS}.zx;" 810 << " s[0].b[1].a = uf_third;" 811 << " s[0].b[1].b[0] = ${COORDS}.yy;" 812 << " s[0].b[1].b[1] = ${COORDS}.wy;" 813 << " s[0].b[2].a = uf_fourth;" 814 << " s[0].b[2].b[0] = ${COORDS}.zx;" 815 << " s[0].b[2].b[1] = ${COORDS}.zy;" 816 << " s[0].c = ui_zero;" 817 << "" 818 << " // S[1]" 819 << " s[1].a = ${COORDS}.w;" 820 << " s[1].b[0].a = uf_two;" 821 << " s[1].b[0].b[0] = ${COORDS}.zx;" 822 << " s[1].b[0].b[1] = ${COORDS}.zy;" 823 << " s[1].b[1].a = uf_three;" 824 << " s[1].b[1].b[0] = ${COORDS}.zz;" 825 << " s[1].b[1].b[1] = ${COORDS}.ww;" 826 << " s[1].b[2].a = uf_four;" 827 << " s[1].b[2].b[0] = ${COORDS}.yx;" 828 << " s[1].b[2].b[1] = ${COORDS}.wz;" 829 << " s[1].c = ui_one;" 830 << "" 831 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 832 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 833 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 834 << " mediump float a = 1.0;" 835 << " for (int i = 0; i < 2; i++)" 836 << " {" 837 << " for (int j = 0; j < 3; j++)" 838 << " {" 839 << " r += s[0].b[j].b[i].y;" 840 << " g += s[i].b[j].b[0].x;" 841 << " b += s[i].b[j].b[1].x;" 842 << " a *= s[i].b[j].a;" 843 << " }" 844 << " }" 845 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 846 << " ${ASSIGN_POS}" 847 << "}", 848 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; }); 849 850 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", 851 LineStream() << "${HEADER}" 852 << "uniform int ui_zero;" 853 << "uniform int ui_one;" 854 << "uniform int ui_two;" 855 << "uniform int ui_three;" 856 << "" 857 << "struct S {" 858 << " mediump float a;" 859 << " mediump int b;" 860 << "};" 861 << "" 862 << "void main (void)" 863 << "{" 864 << " S s[3];" 865 << " s[0] = S(${COORDS}.x, ui_zero);" 866 << " s[1].a = ${COORDS}.y;" 867 << " s[1].b = -ui_one;" 868 << " s[2] = S(${COORDS}.z, ui_two);" 869 << "" 870 << " mediump float rgb[3];" 871 << " int alpha = 0;" 872 << " for (int i = 0; i < ui_three; i++)" 873 << " {" 874 << " rgb[i] = s[2-i].a;" 875 << " alpha += s[i].b;" 876 << " }" 877 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 878 << " ${ASSIGN_POS}" 879 << "}", 880 { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); 881 882 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", 883 LineStream() << "${HEADER}" 884 << "uniform int ui_zero;" 885 << "uniform int ui_one;" 886 << "uniform int ui_two;" 887 << "uniform int ui_three;" 888 << "uniform mediump float uf_two;" 889 << "uniform mediump float uf_three;" 890 << "uniform mediump float uf_four;" 891 << "uniform mediump float uf_half;" 892 << "uniform mediump float uf_third;" 893 << "uniform mediump float uf_fourth;" 894 << "uniform mediump float uf_sixth;" 895 << "" 896 << "struct T {" 897 << " mediump float a;" 898 << " mediump vec2 b[2];" 899 << "};" 900 << "struct S {" 901 << " mediump float a;" 902 << " T b[3];" 903 << " int c;" 904 << "};" 905 << "" 906 << "void main (void)" 907 << "{" 908 << " S s[2];" 909 << "" 910 << " // S[0]" 911 << " s[0].a = ${COORDS}.x;" 912 << " s[0].b[0].a = uf_half;" 913 << " s[0].b[0].b[0] = ${COORDS}.yx;" 914 << " s[0].b[0].b[1] = ${COORDS}.zx;" 915 << " s[0].b[1].a = uf_third;" 916 << " s[0].b[1].b[0] = ${COORDS}.yy;" 917 << " s[0].b[1].b[1] = ${COORDS}.wy;" 918 << " s[0].b[2].a = uf_fourth;" 919 << " s[0].b[2].b[0] = ${COORDS}.zx;" 920 << " s[0].b[2].b[1] = ${COORDS}.zy;" 921 << " s[0].c = ui_zero;" 922 << "" 923 << " // S[1]" 924 << " s[1].a = ${COORDS}.w;" 925 << " s[1].b[0].a = uf_two;" 926 << " s[1].b[0].b[0] = ${COORDS}.zx;" 927 << " s[1].b[0].b[1] = ${COORDS}.zy;" 928 << " s[1].b[1].a = uf_three;" 929 << " s[1].b[1].b[0] = ${COORDS}.zz;" 930 << " s[1].b[1].b[1] = ${COORDS}.ww;" 931 << " s[1].b[2].a = uf_four;" 932 << " s[1].b[2].b[0] = ${COORDS}.yx;" 933 << " s[1].b[2].b[1] = ${COORDS}.wz;" 934 << " s[1].c = ui_one;" 935 << "" 936 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 937 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 938 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 939 << " mediump float a = 1.0;" 940 << " for (int i = 0; i < ui_two; i++)" 941 << " {" 942 << " for (int j = 0; j < ui_three; j++)" 943 << " {" 944 << " r += s[0].b[j].b[i].y;" 945 << " g += s[i].b[j].b[0].x;" 946 << " b += s[i].b[j].b[1].x;" 947 << " a *= s[i].b[j].a;" 948 << " }" 949 << " }" 950 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 951 << " ${ASSIGN_POS}" 952 << "}", 953 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; }); 954 } 955 956 class UniformStructTests : public TestCaseGroup 957 { 958 public: 959 UniformStructTests(Context& context, glu::GLSLVersion glslVersion) 960 : TestCaseGroup(context, "uniform", "Uniform structs"), m_glslVersion(glslVersion) 961 { 962 } 963 964 ~UniformStructTests(void) 965 { 966 } 967 968 virtual void init(void); 969 970 private: 971 glu::GLSLVersion m_glslVersion; 972 }; 973 974 namespace 975 { 976 977 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + NAME).c_str()) 978 979 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \ 980 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \ 981 { \ 982 int loc = gl.getUniformLocation(programID, name); \ 983 SETUNIFORM(loc, 1, vec.getPtr()); \ 984 CHECK_SET_UNIFORM(name); \ 985 } \ 986 struct SetUniform##VECTYPE##Dummy_s \ 987 { \ 988 int unused; \ 989 } 990 991 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM) \ 992 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, \ 993 int arraySize) \ 994 { \ 995 int loc = gl.getUniformLocation(programID, name); \ 996 SETUNIFORM(loc, arraySize, vec->getPtr()); \ 997 CHECK_SET_UNIFORM(name); \ 998 } \ 999 struct SetUniformPtr##VECTYPE##Dummy_s \ 1000 { \ 1001 int unused; \ 1002 } 1003 1004 MAKE_SET_VEC_UNIFORM(Vec2, gl.uniform2fv); 1005 MAKE_SET_VEC_UNIFORM(Vec3, gl.uniform3fv); 1006 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv); 1007 1008 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, float value) 1009 { 1010 int loc = gl.getUniformLocation(programID, name); 1011 gl.uniform1f(loc, value); 1012 CHECK_SET_UNIFORM(name); 1013 } 1014 1015 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, int value) 1016 { 1017 int loc = gl.getUniformLocation(programID, name); 1018 gl.uniform1i(loc, value); 1019 CHECK_SET_UNIFORM(name); 1020 } 1021 1022 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize) 1023 { 1024 int loc = gl.getUniformLocation(programID, name); 1025 gl.uniform1fv(loc, arraySize, value); 1026 CHECK_SET_UNIFORM(name); 1027 } 1028 1029 } // anonymous 1030 1031 void UniformStructTests::init(void) 1032 { 1033 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \ 1034 do \ 1035 { \ 1036 struct SetUniforms_##NAME \ 1037 { \ 1038 static void setUniforms(const glw::Functions& gl, deUint32 programID, \ 1039 const tcu::Vec4& constCoords) SET_UNIFORMS_BODY \ 1040 }; \ 1041 struct Eval_##NAME \ 1042 { \ 1043 static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \ 1044 }; \ 1045 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, TEXTURES, \ 1046 Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \ 1047 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, TEXTURES, \ 1048 Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \ 1049 } while (deGetFalse()) 1050 1051 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false, 1052 LineStream() << "${HEADER}" 1053 << "uniform int ui_one;" 1054 << "" 1055 << "struct S {" 1056 << " mediump float a;" 1057 << " mediump vec3 b;" 1058 << " int c;" 1059 << "};" 1060 << "uniform S s;" 1061 << "" 1062 << "void main (void)" 1063 << "{" 1064 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 1065 << " ${ASSIGN_POS}" 1066 << "}", 1067 { 1068 setUniform(gl, programID, "s.a", constCoords.x()); 1069 setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3)); 1070 setUniform(gl, programID, "s.c", 1); 1071 }, 1072 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); }); 1073 1074 UNIFORM_STRUCT_CASE(nested, "Nested struct", false, 1075 LineStream() << "${HEADER}" 1076 << "uniform int ui_zero;" 1077 << "uniform int ui_one;" 1078 << "" 1079 << "struct T {" 1080 << " int a;" 1081 << " mediump vec2 b;" 1082 << "};" 1083 << "struct S {" 1084 << " mediump float a;" 1085 << " T b;" 1086 << " int c;" 1087 << "};" 1088 << "uniform S s;" 1089 << "" 1090 << "void main (void)" 1091 << "{" 1092 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 1093 << " ${ASSIGN_POS}" 1094 << "}", 1095 { 1096 setUniform(gl, programID, "s.a", constCoords.x()); 1097 setUniform(gl, programID, "s.b.a", 0); 1098 setUniform(gl, programID, "s.b.b", constCoords.swizzle(1, 2)); 1099 setUniform(gl, programID, "s.c", 1); 1100 }, 1101 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); }); 1102 1103 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false, 1104 LineStream() << "${HEADER}" 1105 << "uniform int ui_one;" 1106 << "" 1107 << "struct S {" 1108 << " mediump float a;" 1109 << " mediump float b[3];" 1110 << " int c;" 1111 << "};" 1112 << "uniform S s;" 1113 << "" 1114 << "void main (void)" 1115 << "{" 1116 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" 1117 << " ${ASSIGN_POS}" 1118 << "}", 1119 { 1120 setUniform(gl, programID, "s.a", constCoords.w()); 1121 setUniform(gl, programID, "s.c", 1); 1122 1123 float b[3]; 1124 b[0] = constCoords.z(); 1125 b[1] = constCoords.y(); 1126 b[2] = constCoords.x(); 1127 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b)); 1128 }, 1129 { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); }); 1130 1131 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false, 1132 LineStream() << "${HEADER}" 1133 << "uniform int ui_zero;" 1134 << "uniform int ui_one;" 1135 << "uniform int ui_two;" 1136 << "" 1137 << "struct S {" 1138 << " mediump float a;" 1139 << " mediump float b[3];" 1140 << " int c;" 1141 << "};" 1142 << "uniform S s;" 1143 << "" 1144 << "void main (void)" 1145 << "{" 1146 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" 1147 << " ${ASSIGN_POS}" 1148 << "}", 1149 { 1150 setUniform(gl, programID, "s.a", constCoords.w()); 1151 setUniform(gl, programID, "s.c", 1); 1152 1153 float b[3]; 1154 b[0] = constCoords.z(); 1155 b[1] = constCoords.y(); 1156 b[2] = constCoords.x(); 1157 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b)); 1158 }, 1159 { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); }); 1160 1161 UNIFORM_STRUCT_CASE(struct_array, "Struct array", false, 1162 LineStream() << "${HEADER}" 1163 << "uniform int ui_zero;" 1164 << "uniform int ui_one;" 1165 << "uniform int ui_two;" 1166 << "" 1167 << "struct S {" 1168 << " mediump float a;" 1169 << " mediump int b;" 1170 << "};" 1171 << "uniform S s[3];" 1172 << "" 1173 << "void main (void)" 1174 << "{" 1175 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" 1176 << " ${ASSIGN_POS}" 1177 << "}", 1178 { 1179 setUniform(gl, programID, "s[0].a", constCoords.x()); 1180 setUniform(gl, programID, "s[0].b", 0); 1181 setUniform(gl, programID, "s[1].a", constCoords.y()); 1182 setUniform(gl, programID, "s[1].b", 1); 1183 setUniform(gl, programID, "s[2].a", constCoords.z()); 1184 setUniform(gl, programID, "s[2].b", 2); 1185 }, 1186 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); 1187 1188 UNIFORM_STRUCT_CASE( 1189 struct_array_dynamic_index, "Struct array with dynamic indexing", false, 1190 LineStream() 1191 << "${HEADER}" 1192 << "uniform int ui_zero;" 1193 << "uniform int ui_one;" 1194 << "uniform int ui_two;" 1195 << "" 1196 << "struct S {" 1197 << " mediump float a;" 1198 << " mediump int b;" 1199 << "};" 1200 << "uniform S s[3];" 1201 << "" 1202 << "void main (void)" 1203 << "{" 1204 << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" 1205 << " ${ASSIGN_POS}" 1206 << "}", 1207 { 1208 setUniform(gl, programID, "s[0].a", constCoords.x()); 1209 setUniform(gl, programID, "s[0].b", 0); 1210 setUniform(gl, programID, "s[1].a", constCoords.y()); 1211 setUniform(gl, programID, "s[1].b", 1); 1212 setUniform(gl, programID, "s[2].a", constCoords.z()); 1213 setUniform(gl, programID, "s[2].b", 2); 1214 }, 1215 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); 1216 1217 UNIFORM_STRUCT_CASE( 1218 nested_struct_array, "Nested struct array", false, 1219 LineStream() << "${HEADER}" 1220 << "struct T {" 1221 << " mediump float a;" 1222 << " mediump vec2 b[2];" 1223 << "};" 1224 << "struct S {" 1225 << " mediump float a;" 1226 << " T b[3];" 1227 << " int c;" 1228 << "};" 1229 << "uniform S s[2];" 1230 << "" 1231 << "void main (void)" 1232 << "{" 1233 << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" 1234 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" 1235 << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w " 1236 "+ w) * 0.333" 1237 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" 1238 << " ${DST} = vec4(r, g, b, a);" 1239 << " ${ASSIGN_POS}" 1240 << "}", 1241 { 1242 tcu::Vec2 arr[2]; 1243 1244 setUniform(gl, programID, "s[0].a", constCoords.x()); 1245 arr[0] = constCoords.swizzle(0, 1); 1246 arr[1] = constCoords.swizzle(2, 3); 1247 setUniform(gl, programID, "s[0].b[0].a", 0.5f); 1248 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1249 arr[0] = constCoords.swizzle(2, 3); 1250 arr[1] = constCoords.swizzle(0, 1); 1251 setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); 1252 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1253 arr[0] = constCoords.swizzle(0, 2); 1254 arr[1] = constCoords.swizzle(1, 3); 1255 setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); 1256 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1257 setUniform(gl, programID, "s[0].c", 0); 1258 1259 setUniform(gl, programID, "s[1].a", constCoords.w()); 1260 arr[0] = constCoords.swizzle(0, 0); 1261 arr[1] = constCoords.swizzle(1, 1); 1262 setUniform(gl, programID, "s[1].b[0].a", 2.0f); 1263 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1264 arr[0] = constCoords.swizzle(2, 2); 1265 arr[1] = constCoords.swizzle(3, 3); 1266 setUniform(gl, programID, "s[1].b[1].a", 3.0f); 1267 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1268 arr[0] = constCoords.swizzle(1, 0); 1269 arr[1] = constCoords.swizzle(3, 2); 1270 setUniform(gl, programID, "s[1].b[2].a", 4.0f); 1271 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1272 setUniform(gl, programID, "s[1].c", 1); 1273 }, 1274 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); }); 1275 1276 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false, 1277 LineStream() << "${HEADER}" 1278 << "uniform int ui_zero;" 1279 << "uniform int ui_one;" 1280 << "uniform int ui_two;" 1281 << "" 1282 << "struct T {" 1283 << " mediump float a;" 1284 << " mediump vec2 b[2];" 1285 << "};" 1286 << "struct S {" 1287 << " mediump float a;" 1288 << " T b[3];" 1289 << " int c;" 1290 << "};" 1291 << "uniform S s[2];" 1292 << "" 1293 << "void main (void)" 1294 << "{" 1295 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + " 1296 "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" 1297 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a " 1298 "* s[ui_one].b[2].a; // x * 0.25 * 4" 1299 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + " 1300 "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w " 1301 "+ w + w) * 0.333" 1302 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - " 1303 "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" 1304 << " ${DST} = vec4(r, g, b, a);" 1305 << " ${ASSIGN_POS}" 1306 << "}", 1307 { 1308 tcu::Vec2 arr[2]; 1309 1310 setUniform(gl, programID, "s[0].a", constCoords.x()); 1311 arr[0] = constCoords.swizzle(0, 1); 1312 arr[1] = constCoords.swizzle(2, 3); 1313 setUniform(gl, programID, "s[0].b[0].a", 0.5f); 1314 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1315 arr[0] = constCoords.swizzle(2, 3); 1316 arr[1] = constCoords.swizzle(0, 1); 1317 setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); 1318 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1319 arr[0] = constCoords.swizzle(0, 2); 1320 arr[1] = constCoords.swizzle(1, 3); 1321 setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); 1322 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1323 setUniform(gl, programID, "s[0].c", 0); 1324 1325 setUniform(gl, programID, "s[1].a", constCoords.w()); 1326 arr[0] = constCoords.swizzle(0, 0); 1327 arr[1] = constCoords.swizzle(1, 1); 1328 setUniform(gl, programID, "s[1].b[0].a", 2.0f); 1329 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1330 arr[0] = constCoords.swizzle(2, 2); 1331 arr[1] = constCoords.swizzle(3, 3); 1332 setUniform(gl, programID, "s[1].b[1].a", 3.0f); 1333 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1334 arr[0] = constCoords.swizzle(1, 0); 1335 arr[1] = constCoords.swizzle(3, 2); 1336 setUniform(gl, programID, "s[1].b[2].a", 4.0f); 1337 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1338 setUniform(gl, programID, "s[1].c", 1); 1339 }, 1340 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); }); 1341 1342 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false, 1343 LineStream() << "${HEADER}" 1344 << "uniform int ui_zero;" 1345 << "uniform int ui_one;" 1346 << "uniform int ui_two;" 1347 << "" 1348 << "struct S {" 1349 << " mediump float a;" 1350 << " mediump int b;" 1351 << "};" 1352 << "uniform S s[3];" 1353 << "" 1354 << "void main (void)" 1355 << "{" 1356 << " mediump float rgb[3];" 1357 << " int alpha = 0;" 1358 << " for (int i = 0; i < 3; i++)" 1359 << " {" 1360 << " rgb[i] = s[2-i].a;" 1361 << " alpha += s[i].b;" 1362 << " }" 1363 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1364 << " ${ASSIGN_POS}" 1365 << "}", 1366 { 1367 setUniform(gl, programID, "s[0].a", constCoords.x()); 1368 setUniform(gl, programID, "s[0].b", 0); 1369 setUniform(gl, programID, "s[1].a", constCoords.y()); 1370 setUniform(gl, programID, "s[1].b", -1); 1371 setUniform(gl, programID, "s[2].a", constCoords.z()); 1372 setUniform(gl, programID, "s[2].b", 2); 1373 }, 1374 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); 1375 1376 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false, 1377 LineStream() << "${HEADER}" 1378 << "uniform int ui_zero;" 1379 << "uniform int ui_one;" 1380 << "uniform int ui_two;" 1381 << "uniform mediump float uf_two;" 1382 << "uniform mediump float uf_three;" 1383 << "uniform mediump float uf_four;" 1384 << "uniform mediump float uf_half;" 1385 << "uniform mediump float uf_third;" 1386 << "uniform mediump float uf_fourth;" 1387 << "uniform mediump float uf_sixth;" 1388 << "" 1389 << "struct T {" 1390 << " mediump float a;" 1391 << " mediump vec2 b[2];" 1392 << "};" 1393 << "struct S {" 1394 << " mediump float a;" 1395 << " T b[3];" 1396 << " int c;" 1397 << "};" 1398 << "uniform S s[2];" 1399 << "" 1400 << "void main (void)" 1401 << "{" 1402 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1403 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1404 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1405 << " mediump float a = 1.0;" 1406 << " for (int i = 0; i < 2; i++)" 1407 << " {" 1408 << " for (int j = 0; j < 3; j++)" 1409 << " {" 1410 << " r += s[0].b[j].b[i].y;" 1411 << " g += s[i].b[j].b[0].x;" 1412 << " b += s[i].b[j].b[1].x;" 1413 << " a *= s[i].b[j].a;" 1414 << " }" 1415 << " }" 1416 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1417 << " ${ASSIGN_POS}" 1418 << "}", 1419 { 1420 tcu::Vec2 arr[2]; 1421 1422 setUniform(gl, programID, "s[0].a", constCoords.x()); 1423 arr[0] = constCoords.swizzle(1, 0); 1424 arr[1] = constCoords.swizzle(2, 0); 1425 setUniform(gl, programID, "s[0].b[0].a", 0.5f); 1426 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1427 arr[0] = constCoords.swizzle(1, 1); 1428 arr[1] = constCoords.swizzle(3, 1); 1429 setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); 1430 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1431 arr[0] = constCoords.swizzle(2, 1); 1432 arr[1] = constCoords.swizzle(2, 1); 1433 setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); 1434 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1435 setUniform(gl, programID, "s[0].c", 0); 1436 1437 setUniform(gl, programID, "s[1].a", constCoords.w()); 1438 arr[0] = constCoords.swizzle(2, 0); 1439 arr[1] = constCoords.swizzle(2, 1); 1440 setUniform(gl, programID, "s[1].b[0].a", 2.0f); 1441 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1442 arr[0] = constCoords.swizzle(2, 2); 1443 arr[1] = constCoords.swizzle(3, 3); 1444 setUniform(gl, programID, "s[1].b[1].a", 3.0f); 1445 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1446 arr[0] = constCoords.swizzle(1, 0); 1447 arr[1] = constCoords.swizzle(3, 2); 1448 setUniform(gl, programID, "s[1].b[2].a", 4.0f); 1449 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1450 setUniform(gl, programID, "s[1].c", 1); 1451 }, 1452 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; }); 1453 1454 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false, 1455 LineStream() << "${HEADER}" 1456 << "uniform int ui_zero;" 1457 << "uniform int ui_one;" 1458 << "uniform int ui_two;" 1459 << "uniform int ui_three;" 1460 << "" 1461 << "struct S {" 1462 << " mediump float a;" 1463 << " mediump int b;" 1464 << "};" 1465 << "uniform S s[3];" 1466 << "" 1467 << "void main (void)" 1468 << "{" 1469 << " mediump float rgb[3];" 1470 << " int alpha = 0;" 1471 << " for (int i = 0; i < ui_three; i++)" 1472 << " {" 1473 << " rgb[i] = s[2-i].a;" 1474 << " alpha += s[i].b;" 1475 << " }" 1476 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1477 << " ${ASSIGN_POS}" 1478 << "}", 1479 { 1480 setUniform(gl, programID, "s[0].a", constCoords.x()); 1481 setUniform(gl, programID, "s[0].b", 0); 1482 setUniform(gl, programID, "s[1].a", constCoords.y()); 1483 setUniform(gl, programID, "s[1].b", -1); 1484 setUniform(gl, programID, "s[2].a", constCoords.z()); 1485 setUniform(gl, programID, "s[2].b", 2); 1486 }, 1487 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); 1488 1489 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false, 1490 LineStream() << "${HEADER}" 1491 << "uniform int ui_zero;" 1492 << "uniform int ui_one;" 1493 << "uniform int ui_two;" 1494 << "uniform int ui_three;" 1495 << "uniform mediump float uf_two;" 1496 << "uniform mediump float uf_three;" 1497 << "uniform mediump float uf_four;" 1498 << "uniform mediump float uf_half;" 1499 << "uniform mediump float uf_third;" 1500 << "uniform mediump float uf_fourth;" 1501 << "uniform mediump float uf_sixth;" 1502 << "" 1503 << "struct T {" 1504 << " mediump float a;" 1505 << " mediump vec2 b[2];" 1506 << "};" 1507 << "struct S {" 1508 << " mediump float a;" 1509 << " T b[3];" 1510 << " int c;" 1511 << "};" 1512 << "uniform S s[2];" 1513 << "" 1514 << "void main (void)" 1515 << "{" 1516 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1517 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1518 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1519 << " mediump float a = 1.0;" 1520 << " for (int i = 0; i < ui_two; i++)" 1521 << " {" 1522 << " for (int j = 0; j < ui_three; j++)" 1523 << " {" 1524 << " r += s[0].b[j].b[i].y;" 1525 << " g += s[i].b[j].b[0].x;" 1526 << " b += s[i].b[j].b[1].x;" 1527 << " a *= s[i].b[j].a;" 1528 << " }" 1529 << " }" 1530 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1531 << " ${ASSIGN_POS}" 1532 << "}", 1533 { 1534 tcu::Vec2 arr[2]; 1535 1536 setUniform(gl, programID, "s[0].a", constCoords.x()); 1537 arr[0] = constCoords.swizzle(1, 0); 1538 arr[1] = constCoords.swizzle(2, 0); 1539 setUniform(gl, programID, "s[0].b[0].a", 0.5f); 1540 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1541 arr[0] = constCoords.swizzle(1, 1); 1542 arr[1] = constCoords.swizzle(3, 1); 1543 setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); 1544 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1545 arr[0] = constCoords.swizzle(2, 1); 1546 arr[1] = constCoords.swizzle(2, 1); 1547 setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); 1548 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1549 setUniform(gl, programID, "s[0].c", 0); 1550 1551 setUniform(gl, programID, "s[1].a", constCoords.w()); 1552 arr[0] = constCoords.swizzle(2, 0); 1553 arr[1] = constCoords.swizzle(2, 1); 1554 setUniform(gl, programID, "s[1].b[0].a", 2.0f); 1555 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1556 arr[0] = constCoords.swizzle(2, 2); 1557 arr[1] = constCoords.swizzle(3, 3); 1558 setUniform(gl, programID, "s[1].b[1].a", 3.0f); 1559 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1560 arr[0] = constCoords.swizzle(1, 0); 1561 arr[1] = constCoords.swizzle(3, 2); 1562 setUniform(gl, programID, "s[1].b[2].a", 4.0f); 1563 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); 1564 setUniform(gl, programID, "s[1].c", 1); 1565 }, 1566 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; }); 1567 1568 UNIFORM_STRUCT_CASE( 1569 sampler, "Sampler in struct", true, 1570 LineStream() << "${HEADER}" 1571 << "uniform int ui_one;" 1572 << "" 1573 << "struct S {" 1574 << " mediump float a;" 1575 << " mediump vec3 b;" 1576 << " sampler2D c;" 1577 << "};" 1578 << "uniform S s;" 1579 << "" 1580 << "void main (void)" 1581 << "{" 1582 << " ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);" 1583 << " ${ASSIGN_POS}" 1584 << "}", 1585 { 1586 DE_UNREF(constCoords); 1587 setUniform(gl, programID, "s.a", 1.0f); 1588 setUniform(gl, programID, "s.b", tcu::Vec3(0.75f, 0.75f, 0.1f)); 1589 setUniform(gl, programID, "s.c", TEXTURE_GRADIENT); 1590 }, 1591 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); 1592 1593 UNIFORM_STRUCT_CASE( 1594 sampler_nested, "Sampler in nested struct", true, 1595 LineStream() << "${HEADER}" 1596 << "uniform int ui_zero;" 1597 << "uniform int ui_one;" 1598 << "" 1599 << "struct T {" 1600 << " sampler2D a;" 1601 << " mediump vec2 b;" 1602 << "};" 1603 << "struct S {" 1604 << " mediump float a;" 1605 << " T b;" 1606 << " int c;" 1607 << "};" 1608 << "uniform S s;" 1609 << "" 1610 << "void main (void)" 1611 << "{" 1612 << " ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);" 1613 << " ${ASSIGN_POS}" 1614 << "}", 1615 { 1616 DE_UNREF(constCoords); 1617 setUniform(gl, programID, "s.a", 0.1f); 1618 setUniform(gl, programID, "s.b.a", TEXTURE_GRADIENT); 1619 setUniform(gl, programID, "s.b.b", tcu::Vec2(0.75f, 0.75f)); 1620 setUniform(gl, programID, "s.c", 1); 1621 }, 1622 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); 1623 1624 UNIFORM_STRUCT_CASE( 1625 sampler_array, "Sampler in struct array", true, 1626 LineStream() << "${HEADER}" 1627 << "uniform int ui_one;" 1628 << "" 1629 << "struct S {" 1630 << " mediump float a;" 1631 << " mediump vec3 b;" 1632 << " sampler2D c;" 1633 << "};" 1634 << "uniform S s[2];" 1635 << "" 1636 << "void main (void)" 1637 << "{" 1638 << " ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);" 1639 << " ${ASSIGN_POS}" 1640 << "}", 1641 { 1642 DE_UNREF(constCoords); 1643 setUniform(gl, programID, "s[0].a", 1.0f); 1644 setUniform(gl, programID, "s[0].b", tcu::Vec3(0.75f, 0.75f, 0.25f)); 1645 setUniform(gl, programID, "s[0].c", 1); 1646 setUniform(gl, programID, "s[1].a", 0.0f); 1647 setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.1f)); 1648 setUniform(gl, programID, "s[1].c", TEXTURE_GRADIENT); 1649 }, 1650 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); 1651 } 1652 1653 ShaderStructTests::ShaderStructTests(Context& context, glu::GLSLVersion glslVersion) 1654 : TestCaseGroup(context, "struct", "Struct Tests"), m_glslVersion(glslVersion) 1655 { 1656 } 1657 1658 ShaderStructTests::~ShaderStructTests(void) 1659 { 1660 } 1661 1662 void ShaderStructTests::init(void) 1663 { 1664 addChild(new LocalStructTests(m_context, m_glslVersion)); 1665 addChild(new UniformStructTests(m_context, m_glslVersion)); 1666 } 1667 1668 } // deqp 1669