1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2016 Google Inc.
6 * Copyright (c) 2016 The Khronos Group Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Shader struct tests.
23 */ /*-------------------------------------------------------------------*/
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"
33 using tcu::StringTemplate;
37 using std::ostringstream;
46 TEXTURE_GRADIENT = 0 //!< Unit index for gradient texture
49 typedef void (*SetupUniformsFunc)(const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords);
51 class ShaderStructCase : public ShaderRenderCase
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);
62 virtual void setupUniforms(deUint32 programID, const tcu::Vec4& constCoords);
65 ShaderStructCase(const ShaderStructCase&);
66 ShaderStructCase& operator=(const ShaderStructCase&);
68 SetupUniformsFunc m_setupUniforms;
71 glu::Texture2D* m_gradientTexture;
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)
83 m_vertShaderSource = vertShaderSource;
84 m_fragShaderSource = fragShaderSource;
87 ShaderStructCase::~ShaderStructCase(void)
91 void ShaderStructCase::init(void)
95 m_gradientTexture = new glu::Texture2D(m_renderCtx, GL_RGBA8, 128, 128);
97 m_gradientTexture->getRefTexture().allocLevel(0);
98 tcu::fillWithComponentGradients(m_gradientTexture->getRefTexture().getLevel(0), tcu::Vec4(0.0f),
100 m_gradientTexture->upload();
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);
107 ShaderRenderCase::init();
110 void ShaderStructCase::deinit(void)
114 delete m_gradientTexture;
116 ShaderRenderCase::deinit();
119 void ShaderStructCase::setupUniforms(deUint32 programID, const tcu::Vec4& constCoords)
121 ShaderRenderCase::setupUniforms(programID, constCoords);
123 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
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)
131 const std::string versionDecl = glu::getGLSLVersionDeclaration(glslVersion);
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"
139 " v_coords = a_coords;\n"
140 " gl_Position = a_position;\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"
147 " o_color = v_color;\n"
150 // Fill in specialization parameters.
151 std::map<std::string, std::string> spParams;
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;";
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"] = "";
173 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
174 StringTemplate(shaderSrc.str()).specialize(spParams).c_str(),
175 defaultFragSrc.c_str());
177 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
178 defaultVertSrc.c_str(),
179 StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
182 class LocalStructTests : public TestCaseGroup
185 LocalStructTests(Context& context, glu::GLSLVersion glslVersion)
186 : TestCaseGroup(context, "local", "Local structs"), m_glslVersion(glslVersion)
190 ~LocalStructTests(void)
194 virtual void init(void);
197 glu::GLSLVersion m_glslVersion;
200 void LocalStructTests::init(void)
202 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \
207 static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \
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())
215 LOCAL_STRUCT_CASE(basic, "Basic struct usage",
216 LineStream() << "${HEADER}"
217 << "uniform int ui_one;"
220 << " mediump float a;"
221 << " mediump vec3 b;"
225 << "void main (void)"
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);"
232 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
234 LOCAL_STRUCT_CASE(nested, "Nested struct",
235 LineStream() << "${HEADER}"
236 << "uniform int ui_zero;"
237 << "uniform int ui_one;"
241 << " mediump vec2 b;"
244 << " mediump float a;"
249 << "void main (void)"
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);"
256 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
258 LOCAL_STRUCT_CASE(array_member, "Struct with array member",
259 LineStream() << "${HEADER}"
260 << "uniform int ui_one;"
263 << " mediump float a;"
264 << " mediump float b[3];"
268 << "void main (void)"
271 << " s.a = ${COORDS}.w;"
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);"
279 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
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;"
288 << " mediump float a;"
289 << " mediump float b[3];"
293 << "void main (void)"
296 << " s.a = ${COORDS}.w;"
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);"
304 { c.color.xyz() = c.coords.swizzle(1, 2, 0); });
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;"
313 << " mediump float a;"
317 << "void main (void)"
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);"
327 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
330 struct_array_dynamic_index, "Struct array with dynamic indexing",
333 << "uniform int ui_zero;"
334 << "uniform int ui_one;"
335 << "uniform int ui_two;"
338 << " mediump float a;"
342 << "void main (void)"
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);"
352 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
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;"
368 << " mediump float a;"
369 << " mediump vec2 b[2];"
372 << " mediump float a;"
377 << "void main (void)"
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;"
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;"
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 "
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);"
415 { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
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;"
430 << " mediump float a;"
431 << " mediump vec2 b[2];"
434 << " mediump float a;"
439 << "void main (void)"
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;"
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;"
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 + "
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);"
481 { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
483 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
484 LineStream() << "${HEADER}"
485 << "uniform int ui_one;"
488 << " mediump float a;"
489 << " mediump vec3 b;"
493 << "mediump vec4 myFunc (S s)"
495 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
498 << "void main (void)"
500 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
501 << " s.b = ${COORDS}.yzw;"
502 << " ${DST} = myFunc(s);"
505 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
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;"
514 << " mediump vec2 b;"
517 << " mediump float a;"
522 << "mediump vec4 myFunc (S s)"
524 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
527 << "void main (void)"
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);"
534 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
536 LOCAL_STRUCT_CASE(return, "Struct as a return value",
537 LineStream() << "${HEADER}"
538 << "uniform int ui_one;"
541 << " mediump float a;"
542 << " mediump vec3 b;"
548 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
549 << " s.b = ${COORDS}.yzw;"
553 << "void main (void)"
555 << " S s = myFunc();"
556 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
559 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
561 LOCAL_STRUCT_CASE(return_nested, "Nested struct",
562 LineStream() << "${HEADER}"
563 << "uniform int ui_zero;"
564 << "uniform int ui_one;"
568 << " mediump vec2 b;"
571 << " mediump float a;"
578 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
579 << " s.b = T(ui_zero, ${COORDS}.yz);"
583 << "void main (void)"
585 << " S s = myFunc();"
586 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
589 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
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;"
598 << " mediump float a;"
599 << " mediump vec3 b;"
603 << "void main (void)"
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);"
611 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
613 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
614 LineStream() << "${HEADER}"
615 << "uniform int ui_zero;"
616 << "uniform int ui_one;"
619 << " mediump float a;"
620 << " mediump vec3 b;"
624 << "void main (void)"
626 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
627 << " for (int i = 0; i < 3; i++)"
630 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
632 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
635 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
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;"
644 << " mediump float a;"
645 << " mediump vec3 b;"
649 << "void main (void)"
651 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
652 << " for (int i = 0; i < ui_three; i++)"
654 << " if (i == ui_one)"
655 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
657 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
660 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
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;"
670 << " mediump vec2 b;"
673 << " mediump float a;"
678 << "void main (void)"
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);"
686 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
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;"
696 << " mediump vec2 b;"
699 << " mediump float a;"
704 << "void main (void)"
706 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
707 << " for (int i = 0; i < 3; i++)"
710 << " s.b = T(ui_zero, ${COORDS}.zw);"
712 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
715 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
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;"
726 << " mediump vec2 b;"
729 << " mediump float a;"
734 << "void main (void)"
736 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
737 << " for (int i = 0; i < ui_three; i++)"
739 << " if (i == ui_one)"
740 << " s.b = T(ui_zero, ${COORDS}.zw);"
742 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
745 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
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;"
754 << " mediump float a;"
758 << "void main (void)"
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);"
766 << " mediump float rgb[3];"
768 << " for (int i = 0; i < 3; i++)"
770 << " rgb[i] = s[2-i].a;"
771 << " alpha += s[i].b;"
773 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
776 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
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;"
792 << " mediump float a;"
793 << " mediump vec2 b[2];"
796 << " mediump float a;"
801 << "void main (void)"
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;"
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;"
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++)"
837 << " for (int j = 0; j < 3; j++)"
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;"
845 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
848 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
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;"
858 << " mediump float a;"
862 << "void main (void)"
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);"
870 << " mediump float rgb[3];"
872 << " for (int i = 0; i < ui_three; i++)"
874 << " rgb[i] = s[2-i].a;"
875 << " alpha += s[i].b;"
877 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
880 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
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;"
897 << " mediump float a;"
898 << " mediump vec2 b[2];"
901 << " mediump float a;"
906 << "void main (void)"
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;"
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;"
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++)"
942 << " for (int j = 0; j < ui_three; j++)"
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;"
950 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
953 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
956 class UniformStructTests : public TestCaseGroup
959 UniformStructTests(Context& context, glu::GLSLVersion glslVersion)
960 : TestCaseGroup(context, "uniform", "Uniform structs"), m_glslVersion(glslVersion)
964 ~UniformStructTests(void)
968 virtual void init(void);
971 glu::GLSLVersion m_glslVersion;
977 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + NAME).c_str())
979 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \
980 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \
982 int loc = gl.getUniformLocation(programID, name); \
983 SETUNIFORM(loc, 1, vec.getPtr()); \
984 CHECK_SET_UNIFORM(name); \
986 struct SetUniform##VECTYPE##Dummy_s \
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, \
995 int loc = gl.getUniformLocation(programID, name); \
996 SETUNIFORM(loc, arraySize, vec->getPtr()); \
997 CHECK_SET_UNIFORM(name); \
999 struct SetUniformPtr##VECTYPE##Dummy_s \
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);
1008 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, float value)
1010 int loc = gl.getUniformLocation(programID, name);
1011 gl.uniform1f(loc, value);
1012 CHECK_SET_UNIFORM(name);
1015 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, int value)
1017 int loc = gl.getUniformLocation(programID, name);
1018 gl.uniform1i(loc, value);
1019 CHECK_SET_UNIFORM(name);
1022 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize)
1024 int loc = gl.getUniformLocation(programID, name);
1025 gl.uniform1fv(loc, arraySize, value);
1026 CHECK_SET_UNIFORM(name);
1031 void UniformStructTests::init(void)
1033 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1036 struct SetUniforms_##NAME \
1038 static void setUniforms(const glw::Functions& gl, deUint32 programID, \
1039 const tcu::Vec4& constCoords) SET_UNIFORMS_BODY \
1041 struct Eval_##NAME \
1043 static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \
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())
1051 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false,
1052 LineStream() << "${HEADER}"
1053 << "uniform int ui_one;"
1056 << " mediump float a;"
1057 << " mediump vec3 b;"
1062 << "void main (void)"
1064 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
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);
1072 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1074 UNIFORM_STRUCT_CASE(nested, "Nested struct", false,
1075 LineStream() << "${HEADER}"
1076 << "uniform int ui_zero;"
1077 << "uniform int ui_one;"
1081 << " mediump vec2 b;"
1084 << " mediump float a;"
1090 << "void main (void)"
1092 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
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);
1101 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1103 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false,
1104 LineStream() << "${HEADER}"
1105 << "uniform int ui_one;"
1108 << " mediump float a;"
1109 << " mediump float b[3];"
1114 << "void main (void)"
1116 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1120 setUniform(gl, programID, "s.a", constCoords.w());
1121 setUniform(gl, programID, "s.c", 1);
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));
1129 { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); });
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;"
1138 << " mediump float a;"
1139 << " mediump float b[3];"
1144 << "void main (void)"
1146 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1150 setUniform(gl, programID, "s.a", constCoords.w());
1151 setUniform(gl, programID, "s.c", 1);
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));
1159 { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); });
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;"
1168 << " mediump float a;"
1169 << " mediump int b;"
1171 << "uniform S s[3];"
1173 << "void main (void)"
1175 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
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);
1186 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1188 UNIFORM_STRUCT_CASE(
1189 struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1192 << "uniform int ui_zero;"
1193 << "uniform int ui_one;"
1194 << "uniform int ui_two;"
1197 << " mediump float a;"
1198 << " mediump int b;"
1200 << "uniform S s[3];"
1202 << "void main (void)"
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);"
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);
1215 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1217 UNIFORM_STRUCT_CASE(
1218 nested_struct_array, "Nested struct array", false,
1219 LineStream() << "${HEADER}"
1221 << " mediump float a;"
1222 << " mediump vec2 b[2];"
1225 << " mediump float a;"
1229 << "uniform S s[2];"
1231 << "void main (void)"
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 "
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);"
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);
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);
1274 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
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;"
1283 << " mediump float a;"
1284 << " mediump vec2 b[2];"
1287 << " mediump float a;"
1291 << "uniform S s[2];"
1293 << "void main (void)"
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 "
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);"
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);
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);
1340 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
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;"
1349 << " mediump float a;"
1350 << " mediump int b;"
1352 << "uniform S s[3];"
1354 << "void main (void)"
1356 << " mediump float rgb[3];"
1357 << " int alpha = 0;"
1358 << " for (int i = 0; i < 3; i++)"
1360 << " rgb[i] = s[2-i].a;"
1361 << " alpha += s[i].b;"
1363 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
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);
1374 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
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;"
1390 << " mediump float a;"
1391 << " mediump vec2 b[2];"
1394 << " mediump float a;"
1398 << "uniform S s[2];"
1400 << "void main (void)"
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++)"
1408 << " for (int j = 0; j < 3; j++)"
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;"
1416 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
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);
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);
1452 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
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;"
1462 << " mediump float a;"
1463 << " mediump int b;"
1465 << "uniform S s[3];"
1467 << "void main (void)"
1469 << " mediump float rgb[3];"
1470 << " int alpha = 0;"
1471 << " for (int i = 0; i < ui_three; i++)"
1473 << " rgb[i] = s[2-i].a;"
1474 << " alpha += s[i].b;"
1476 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
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);
1487 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
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;"
1504 << " mediump float a;"
1505 << " mediump vec2 b[2];"
1508 << " mediump float a;"
1512 << "uniform S s[2];"
1514 << "void main (void)"
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++)"
1522 << " for (int j = 0; j < ui_three; j++)"
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;"
1530 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
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);
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);
1566 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1568 UNIFORM_STRUCT_CASE(
1569 sampler, "Sampler in struct", true,
1570 LineStream() << "${HEADER}"
1571 << "uniform int ui_one;"
1574 << " mediump float a;"
1575 << " mediump vec3 b;"
1580 << "void main (void)"
1582 << " ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
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);
1591 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
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;"
1601 << " mediump vec2 b;"
1604 << " mediump float a;"
1610 << "void main (void)"
1612 << " ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
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);
1622 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1624 UNIFORM_STRUCT_CASE(
1625 sampler_array, "Sampler in struct array", true,
1626 LineStream() << "${HEADER}"
1627 << "uniform int ui_one;"
1630 << " mediump float a;"
1631 << " mediump vec3 b;"
1634 << "uniform S s[2];"
1636 << "void main (void)"
1638 << " ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
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);
1650 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1653 ShaderStructTests::ShaderStructTests(Context& context, glu::GLSLVersion glslVersion)
1654 : TestCaseGroup(context, "struct", "Struct Tests"), m_glslVersion(glslVersion)
1658 ShaderStructTests::~ShaderStructTests(void)
1662 void ShaderStructTests::init(void)
1664 addChild(new LocalStructTests(m_context, m_glslVersion));
1665 addChild(new UniformStructTests(m_context, m_glslVersion));