1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Shader struct tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es3fShaderStructTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "tcuStringTemplate.hpp"
27 #include "gluTexture.hpp"
28 #include "tcuTextureUtil.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
33 using tcu::StringTemplate;
37 using std::ostringstream;
40 using namespace deqp::gls;
51 TEXTURE_BRICK = 0 //!< Unit index for brick texture
54 typedef void (*SetupUniformsFunc) (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords);
56 class ShaderStructCase : public ShaderRenderCase
59 ShaderStructCase (Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource);
60 ~ShaderStructCase (void);
65 virtual void setupUniforms (int programID, const tcu::Vec4& constCoords);
68 ShaderStructCase (const ShaderStructCase&);
69 ShaderStructCase& operator= (const ShaderStructCase&);
71 SetupUniformsFunc m_setupUniforms;
74 glu::Texture2D* m_brickTexture;
77 ShaderStructCase::ShaderStructCase (Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource)
78 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc)
79 , m_setupUniforms (setupUniformsFunc)
80 , m_usesTexture (usesTextures)
81 , m_brickTexture (DE_NULL)
83 m_vertShaderSource = vertShaderSource;
84 m_fragShaderSource = fragShaderSource;
87 ShaderStructCase::~ShaderStructCase (void)
89 delete m_brickTexture;
92 void ShaderStructCase::init (void)
96 m_brickTexture = glu::Texture2D::create(m_renderCtx, m_ctxInfo, m_testCtx.getArchive(), "data/brick.png");
97 m_textures.push_back(TextureBinding(m_brickTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
98 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR)));
99 DE_ASSERT(m_textures.size() == 1);
101 gls::ShaderRenderCase::init();
104 void ShaderStructCase::deinit (void)
106 gls::ShaderRenderCase::deinit();
107 delete m_brickTexture;
108 m_brickTexture = DE_NULL;
111 void ShaderStructCase::setupUniforms (int programID, const tcu::Vec4& constCoords)
113 ShaderRenderCase::setupUniforms(programID, constCoords);
115 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
118 static ShaderStructCase* createStructCase (Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms, const LineStream& shaderSrc)
120 static const char* defaultVertSrc =
122 "in highp vec4 a_position;\n"
123 "in highp vec4 a_coords;\n"
124 "out mediump vec4 v_coords;\n\n"
127 " v_coords = a_coords;\n"
128 " gl_Position = a_position;\n"
130 static const char* defaultFragSrc =
132 "in mediump vec4 v_color;\n"
133 "layout(location = 0) out mediump vec4 o_color;\n\n"
136 " o_color = v_color;\n"
139 // Fill in specialization parameters.
140 std::map<std::string, std::string> spParams;
145 "in highp vec4 a_position;\n"
146 "in highp vec4 a_coords;\n"
147 "out mediump vec4 v_color;";
148 spParams["COORDS"] = "a_coords";
149 spParams["DST"] = "v_color";
150 spParams["ASSIGN_POS"] = "gl_Position = a_position;";
156 "in mediump vec4 v_coords;\n"
157 "layout(location = 0) out mediump vec4 o_color;";
158 spParams["COORDS"] = "v_coords";
159 spParams["DST"] = "o_color";
160 spParams["ASSIGN_POS"] = "";
164 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), defaultFragSrc);
166 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, defaultVertSrc, StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
169 class LocalStructTests : public TestCaseGroup
172 LocalStructTests (Context& context)
173 : TestCaseGroup(context, "local", "Local structs")
177 ~LocalStructTests (void)
181 virtual void init (void);
184 void LocalStructTests::init (void)
186 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \
188 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
189 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, false, &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
190 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, false,&Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
191 } while (deGetFalse())
193 LOCAL_STRUCT_CASE(basic, "Basic struct usage",
196 << "uniform int ui_one;"
199 << " mediump float a;"
200 << " mediump vec3 b;"
204 << "void main (void)"
206 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
207 << " s.b = ${COORDS}.yzw;"
208 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
212 c.color.xyz() = c.coords.swizzle(0,1,2);
215 LOCAL_STRUCT_CASE(nested, "Nested struct",
218 << "uniform int ui_zero;"
219 << "uniform int ui_one;"
223 << " mediump vec2 b;"
226 << " mediump float a;"
231 << "void main (void)"
233 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
234 << " s.b = T(ui_zero, ${COORDS}.yz);"
235 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
239 c.color.xyz() = c.coords.swizzle(0,1,2);
242 LOCAL_STRUCT_CASE(array_member, "Struct with array member",
245 << "uniform int ui_one;"
248 << " mediump float a;"
249 << " mediump float b[3];"
253 << "void main (void)"
256 << " s.a = ${COORDS}.w;"
258 << " s.b[0] = ${COORDS}.z;"
259 << " s.b[1] = ${COORDS}.y;"
260 << " s.b[2] = ${COORDS}.x;"
261 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
265 c.color.xyz() = c.coords.swizzle(3,2,1);
268 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
271 << "uniform int ui_zero;"
272 << "uniform int ui_one;"
273 << "uniform int ui_two;"
276 << " mediump float a;"
277 << " mediump float b[3];"
281 << "void main (void)"
284 << " s.a = ${COORDS}.w;"
286 << " s.b[0] = ${COORDS}.z;"
287 << " s.b[1] = ${COORDS}.y;"
288 << " s.b[2] = ${COORDS}.x;"
289 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
293 c.color.xyz() = c.coords.swizzle(1,2,0);
296 LOCAL_STRUCT_CASE(struct_array, "Struct array",
299 << "uniform int ui_zero;"
300 << "uniform int ui_one;"
301 << "uniform int ui_two;"
304 << " mediump float a;"
308 << "void main (void)"
311 << " s[0] = S(${COORDS}.x, ui_zero);"
312 << " s[1].a = ${COORDS}.y;"
313 << " s[1].b = ui_one;"
314 << " s[2] = S(${COORDS}.z, ui_two);"
315 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
319 c.color.xyz() = c.coords.swizzle(2,1,0);
322 LOCAL_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing",
325 << "uniform int ui_zero;"
326 << "uniform int ui_one;"
327 << "uniform int ui_two;"
330 << " mediump float a;"
334 << "void main (void)"
337 << " s[0] = S(${COORDS}.x, ui_zero);"
338 << " s[1].a = ${COORDS}.y;"
339 << " s[1].b = ui_one;"
340 << " s[2] = S(${COORDS}.z, ui_two);"
341 << " ${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);"
345 c.color.xyz() = c.coords.swizzle(2,1,0);
348 LOCAL_STRUCT_CASE(nested_struct_array, "Nested struct array",
351 << "uniform int ui_zero;"
352 << "uniform int ui_one;"
353 << "uniform int ui_two;"
354 << "uniform mediump float uf_two;"
355 << "uniform mediump float uf_three;"
356 << "uniform mediump float uf_four;"
357 << "uniform mediump float uf_half;"
358 << "uniform mediump float uf_third;"
359 << "uniform mediump float uf_fourth;"
362 << " mediump float a;"
363 << " mediump vec2 b[2];"
366 << " mediump float a;"
371 << "void main (void)"
376 << " s[0].a = ${COORDS}.x;"
377 << " s[0].b[0].a = uf_half;"
378 << " s[0].b[0].b[0] = ${COORDS}.xy;"
379 << " s[0].b[0].b[1] = ${COORDS}.zw;"
380 << " s[0].b[1].a = uf_third;"
381 << " s[0].b[1].b[0] = ${COORDS}.zw;"
382 << " s[0].b[1].b[1] = ${COORDS}.xy;"
383 << " s[0].b[2].a = uf_fourth;"
384 << " s[0].b[2].b[0] = ${COORDS}.xz;"
385 << " s[0].b[2].b[1] = ${COORDS}.yw;"
386 << " s[0].c = ui_zero;"
389 << " s[1].a = ${COORDS}.w;"
390 << " s[1].b[0].a = uf_two;"
391 << " s[1].b[0].b[0] = ${COORDS}.xx;"
392 << " s[1].b[0].b[1] = ${COORDS}.yy;"
393 << " s[1].b[1].a = uf_three;"
394 << " s[1].b[1].b[0] = ${COORDS}.zz;"
395 << " s[1].b[1].b[1] = ${COORDS}.ww;"
396 << " s[1].b[2].a = uf_four;"
397 << " s[1].b[2].b[0] = ${COORDS}.yx;"
398 << " s[1].b[2].b[1] = ${COORDS}.wz;"
399 << " s[1].c = ui_one;"
401 << " 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"
402 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
403 << " 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 + w) * 0.333"
404 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
405 << " ${DST} = vec4(r, g, b, a);"
409 c.color.xyz() = c.coords.swizzle(2,0,3);
412 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
415 << "uniform int ui_zero;"
416 << "uniform int ui_one;"
417 << "uniform int ui_two;"
418 << "uniform mediump float uf_two;"
419 << "uniform mediump float uf_three;"
420 << "uniform mediump float uf_four;"
421 << "uniform mediump float uf_half;"
422 << "uniform mediump float uf_third;"
423 << "uniform mediump float uf_fourth;"
426 << " mediump float a;"
427 << " mediump vec2 b[2];"
430 << " mediump float a;"
435 << "void main (void)"
440 << " s[0].a = ${COORDS}.x;"
441 << " s[0].b[0].a = uf_half;"
442 << " s[0].b[0].b[0] = ${COORDS}.xy;"
443 << " s[0].b[0].b[1] = ${COORDS}.zw;"
444 << " s[0].b[1].a = uf_third;"
445 << " s[0].b[1].b[0] = ${COORDS}.zw;"
446 << " s[0].b[1].b[1] = ${COORDS}.xy;"
447 << " s[0].b[2].a = uf_fourth;"
448 << " s[0].b[2].b[0] = ${COORDS}.xz;"
449 << " s[0].b[2].b[1] = ${COORDS}.yw;"
450 << " s[0].c = ui_zero;"
453 << " s[1].a = ${COORDS}.w;"
454 << " s[1].b[0].a = uf_two;"
455 << " s[1].b[0].b[0] = ${COORDS}.xx;"
456 << " s[1].b[0].b[1] = ${COORDS}.yy;"
457 << " s[1].b[1].a = uf_three;"
458 << " s[1].b[1].b[0] = ${COORDS}.zz;"
459 << " s[1].b[1].b[1] = ${COORDS}.ww;"
460 << " s[1].b[2].a = uf_four;"
461 << " s[1].b[2].b[0] = ${COORDS}.yx;"
462 << " s[1].b[2].b[1] = ${COORDS}.wz;"
463 << " s[1].c = ui_one;"
465 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5"
466 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4"
467 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333"
468 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
469 << " ${DST} = vec4(r, g, b, a);"
473 c.color.xyz() = c.coords.swizzle(2,0,3);
476 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
479 << "uniform int ui_one;"
482 << " mediump float a;"
483 << " mediump vec3 b;"
487 << "mediump vec4 myFunc (S s)"
489 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
492 << "void main (void)"
494 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
495 << " s.b = ${COORDS}.yzw;"
496 << " ${DST} = myFunc(s);"
500 c.color.xyz() = c.coords.swizzle(0,1,2);
503 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter",
506 << "uniform int ui_zero;"
507 << "uniform int ui_one;"
511 << " mediump vec2 b;"
514 << " mediump float a;"
519 << "mediump vec4 myFunc (S s)"
521 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
524 << "void main (void)"
526 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
527 << " s.b = T(ui_zero, ${COORDS}.yz);"
528 << " ${DST} = myFunc(s);"
532 c.color.xyz() = c.coords.swizzle(0,1,2);
535 LOCAL_STRUCT_CASE(return, "Struct as a return value",
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);"
560 c.color.xyz() = c.coords.swizzle(0,1,2);
563 LOCAL_STRUCT_CASE(return_nested, "Nested struct",
566 << "uniform int ui_zero;"
567 << "uniform int ui_one;"
571 << " mediump vec2 b;"
574 << " mediump float a;"
581 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
582 << " s.b = T(ui_zero, ${COORDS}.yz);"
586 << "void main (void)"
588 << " S s = myFunc();"
589 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
593 c.color.xyz() = c.coords.swizzle(0,1,2);
596 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment",
599 << "uniform int ui_zero;"
600 << "uniform int ui_one;"
601 << "uniform mediump float uf_one;"
604 << " mediump float a;"
605 << " mediump vec3 b;"
609 << "void main (void)"
611 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
612 << " if (uf_one > 0.0)"
613 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
614 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
618 c.color.xyz() = c.coords.swizzle(3,2,1);
621 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
624 << "uniform int ui_zero;"
625 << "uniform int ui_one;"
628 << " mediump float a;"
629 << " mediump vec3 b;"
633 << "void main (void)"
635 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
636 << " for (int i = 0; i < 3; i++)"
639 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
641 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
645 c.color.xyz() = c.coords.swizzle(3,2,1);
648 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop",
651 << "uniform int ui_zero;"
652 << "uniform int ui_one;"
653 << "uniform int ui_three;"
656 << " mediump float a;"
657 << " mediump vec3 b;"
661 << "void main (void)"
663 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
664 << " for (int i = 0; i < ui_three; i++)"
666 << " if (i == ui_one)"
667 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
669 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
673 c.color.xyz() = c.coords.swizzle(3,2,1);
676 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct",
679 << "uniform int ui_zero;"
680 << "uniform int ui_one;"
681 << "uniform mediump float uf_one;"
685 << " mediump vec2 b;"
688 << " mediump float a;"
693 << "void main (void)"
695 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
696 << " if (uf_one > 0.0)"
697 << " s.b = T(ui_zero, ${COORDS}.zw);"
698 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
702 c.color.xyz() = c.coords.swizzle(0,2,3);
705 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop",
708 << "uniform int ui_zero;"
709 << "uniform int ui_one;"
710 << "uniform mediump float uf_one;"
714 << " mediump vec2 b;"
717 << " mediump float a;"
722 << "void main (void)"
724 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
725 << " for (int i = 0; i < 3; i++)"
728 << " s.b = T(ui_zero, ${COORDS}.zw);"
730 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
734 c.color.xyz() = c.coords.swizzle(0,2,3);
737 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop",
740 << "uniform int ui_zero;"
741 << "uniform int ui_one;"
742 << "uniform int ui_three;"
743 << "uniform mediump float uf_one;"
747 << " mediump vec2 b;"
750 << " mediump float a;"
755 << "void main (void)"
757 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
758 << " for (int i = 0; i < ui_three; i++)"
760 << " if (i == ui_one)"
761 << " s.b = T(ui_zero, ${COORDS}.zw);"
763 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
767 c.color.xyz() = c.coords.swizzle(0,2,3);
770 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
773 << "uniform int ui_zero;"
774 << "uniform int ui_one;"
775 << "uniform int ui_two;"
778 << " mediump float a;"
782 << "void main (void)"
785 << " s[0] = S(${COORDS}.x, ui_zero);"
786 << " s[1].a = ${COORDS}.y;"
787 << " s[1].b = -ui_one;"
788 << " s[2] = S(${COORDS}.z, ui_two);"
790 << " mediump float rgb[3];"
792 << " for (int i = 0; i < 3; i++)"
794 << " rgb[i] = s[2-i].a;"
795 << " alpha += s[i].b;"
797 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
801 c.color.xyz() = c.coords.swizzle(2,1,0);
804 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
807 << "uniform int ui_zero;"
808 << "uniform int ui_one;"
809 << "uniform int ui_two;"
810 << "uniform mediump float uf_two;"
811 << "uniform mediump float uf_three;"
812 << "uniform mediump float uf_four;"
813 << "uniform mediump float uf_half;"
814 << "uniform mediump float uf_third;"
815 << "uniform mediump float uf_fourth;"
816 << "uniform mediump float uf_sixth;"
819 << " mediump float a;"
820 << " mediump vec2 b[2];"
823 << " mediump float a;"
828 << "void main (void)"
833 << " s[0].a = ${COORDS}.x;"
834 << " s[0].b[0].a = uf_half;"
835 << " s[0].b[0].b[0] = ${COORDS}.yx;"
836 << " s[0].b[0].b[1] = ${COORDS}.zx;"
837 << " s[0].b[1].a = uf_third;"
838 << " s[0].b[1].b[0] = ${COORDS}.yy;"
839 << " s[0].b[1].b[1] = ${COORDS}.wy;"
840 << " s[0].b[2].a = uf_fourth;"
841 << " s[0].b[2].b[0] = ${COORDS}.zx;"
842 << " s[0].b[2].b[1] = ${COORDS}.zy;"
843 << " s[0].c = ui_zero;"
846 << " s[1].a = ${COORDS}.w;"
847 << " s[1].b[0].a = uf_two;"
848 << " s[1].b[0].b[0] = ${COORDS}.zx;"
849 << " s[1].b[0].b[1] = ${COORDS}.zy;"
850 << " s[1].b[1].a = uf_three;"
851 << " s[1].b[1].b[0] = ${COORDS}.zz;"
852 << " s[1].b[1].b[1] = ${COORDS}.ww;"
853 << " s[1].b[2].a = uf_four;"
854 << " s[1].b[2].b[0] = ${COORDS}.yx;"
855 << " s[1].b[2].b[1] = ${COORDS}.wz;"
856 << " s[1].c = ui_one;"
858 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
859 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
860 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
861 << " mediump float a = 1.0;"
862 << " for (int i = 0; i < 2; i++)"
864 << " for (int j = 0; j < 3; j++)"
866 << " r += s[0].b[j].b[i].y;"
867 << " g += s[i].b[j].b[0].x;"
868 << " b += s[i].b[j].b[1].x;"
869 << " a *= s[i].b[j].a;"
872 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
876 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
879 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
882 << "uniform int ui_zero;"
883 << "uniform int ui_one;"
884 << "uniform int ui_two;"
885 << "uniform int ui_three;"
888 << " mediump float a;"
892 << "void main (void)"
895 << " s[0] = S(${COORDS}.x, ui_zero);"
896 << " s[1].a = ${COORDS}.y;"
897 << " s[1].b = -ui_one;"
898 << " s[2] = S(${COORDS}.z, ui_two);"
900 << " mediump float rgb[3];"
902 << " for (int i = 0; i < ui_three; i++)"
904 << " rgb[i] = s[2-i].a;"
905 << " alpha += s[i].b;"
907 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
911 c.color.xyz() = c.coords.swizzle(2,1,0);
914 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
917 << "uniform int ui_zero;"
918 << "uniform int ui_one;"
919 << "uniform int ui_two;"
920 << "uniform int ui_three;"
921 << "uniform mediump float uf_two;"
922 << "uniform mediump float uf_three;"
923 << "uniform mediump float uf_four;"
924 << "uniform mediump float uf_half;"
925 << "uniform mediump float uf_third;"
926 << "uniform mediump float uf_fourth;"
927 << "uniform mediump float uf_sixth;"
930 << " mediump float a;"
931 << " mediump vec2 b[2];"
934 << " mediump float a;"
939 << "void main (void)"
944 << " s[0].a = ${COORDS}.x;"
945 << " s[0].b[0].a = uf_half;"
946 << " s[0].b[0].b[0] = ${COORDS}.yx;"
947 << " s[0].b[0].b[1] = ${COORDS}.zx;"
948 << " s[0].b[1].a = uf_third;"
949 << " s[0].b[1].b[0] = ${COORDS}.yy;"
950 << " s[0].b[1].b[1] = ${COORDS}.wy;"
951 << " s[0].b[2].a = uf_fourth;"
952 << " s[0].b[2].b[0] = ${COORDS}.zx;"
953 << " s[0].b[2].b[1] = ${COORDS}.zy;"
954 << " s[0].c = ui_zero;"
957 << " s[1].a = ${COORDS}.w;"
958 << " s[1].b[0].a = uf_two;"
959 << " s[1].b[0].b[0] = ${COORDS}.zx;"
960 << " s[1].b[0].b[1] = ${COORDS}.zy;"
961 << " s[1].b[1].a = uf_three;"
962 << " s[1].b[1].b[0] = ${COORDS}.zz;"
963 << " s[1].b[1].b[1] = ${COORDS}.ww;"
964 << " s[1].b[2].a = uf_four;"
965 << " s[1].b[2].b[0] = ${COORDS}.yx;"
966 << " s[1].b[2].b[1] = ${COORDS}.wz;"
967 << " s[1].c = ui_one;"
969 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
970 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
971 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
972 << " mediump float a = 1.0;"
973 << " for (int i = 0; i < ui_two; i++)"
975 << " for (int j = 0; j < ui_three; j++)"
977 << " r += s[0].b[j].b[i].y;"
978 << " g += s[i].b[j].b[0].x;"
979 << " b += s[i].b[j].b[1].x;"
980 << " a *= s[i].b[j].a;"
983 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
987 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
990 LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality",
993 << "uniform int ui_one;"
994 << "uniform int ui_two;"
997 << " mediump float a;"
998 << " mediump vec3 b;"
1002 << "void main (void)"
1004 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1005 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1006 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1007 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1008 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1009 << " if (a == b) ${DST}.x = 1.0;"
1010 << " if (a == c) ${DST}.y = 1.0;"
1011 << " if (a == d) ${DST}.z = 1.0;"
1015 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1017 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1021 LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality",
1024 << "uniform int ui_one;"
1025 << "uniform int ui_two;"
1028 << " mediump float a;"
1029 << " mediump vec3 b;"
1033 << "void main (void)"
1035 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1036 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1037 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1038 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1039 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1040 << " if (a != b) ${DST}.x = 1.0;"
1041 << " if (a != c) ${DST}.y = 1.0;"
1042 << " if (a != d) ${DST}.z = 1.0;"
1046 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1048 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1053 LOCAL_STRUCT_CASE(nested_equal, "Nested struct struct equality",
1056 << "uniform int ui_one;"
1057 << "uniform int ui_two;"
1060 << " mediump vec3 a;"
1064 << " mediump float a;"
1069 << "void main (void)"
1071 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1072 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1073 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1074 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1075 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1076 << " if (a == b) ${DST}.x = 1.0;"
1077 << " if (a == c) ${DST}.y = 1.0;"
1078 << " if (a == d) ${DST}.z = 1.0;"
1082 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1084 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1088 LOCAL_STRUCT_CASE(nested_not_equal, "Nested struct struct equality",
1091 << "uniform int ui_one;"
1092 << "uniform int ui_two;"
1095 << " mediump vec3 a;"
1099 << " mediump float a;"
1104 << "void main (void)"
1106 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1107 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1108 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1109 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1110 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1111 << " if (a != b) ${DST}.x = 1.0;"
1112 << " if (a != c) ${DST}.y = 1.0;"
1113 << " if (a != d) ${DST}.z = 1.0;"
1117 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1119 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1125 class UniformStructTests : public TestCaseGroup
1128 UniformStructTests (Context& context)
1129 : TestCaseGroup(context, "uniform", "Uniform structs")
1133 ~UniformStructTests (void)
1137 virtual void init (void);
1143 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + (NAME)).c_str())
1145 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \
1146 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \
1148 int loc = gl.getUniformLocation(programID, name); \
1149 SETUNIFORM(loc, 1, vec.getPtr()); \
1150 CHECK_SET_UNIFORM(name); \
1152 struct SetUniform##VECTYPE##Dummy_s { int unused; }
1154 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM) \
1155 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, int arraySize) \
1157 int loc = gl.getUniformLocation(programID, name); \
1158 SETUNIFORM(loc, arraySize, vec->getPtr()); \
1159 CHECK_SET_UNIFORM(name); \
1161 struct SetUniformPtr##VECTYPE##Dummy_s { int unused; }
1163 MAKE_SET_VEC_UNIFORM (Vec2, gl.uniform2fv);
1164 MAKE_SET_VEC_UNIFORM (Vec3, gl.uniform3fv);
1165 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv);
1167 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, float value)
1169 int loc = gl.getUniformLocation(programID, name);
1170 gl.uniform1f(loc, value);
1171 CHECK_SET_UNIFORM(name);
1174 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, int value)
1176 int loc = gl.getUniformLocation(programID, name);
1177 gl.uniform1i(loc, value);
1178 CHECK_SET_UNIFORM(name);
1181 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize)
1183 int loc = gl.getUniformLocation(programID, name);
1184 gl.uniform1fv(loc, arraySize, value);
1185 CHECK_SET_UNIFORM(name);
1190 void UniformStructTests::init (void)
1192 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1194 struct SetUniforms_##NAME { \
1195 static void setUniforms (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY /* NOLINT(SET_UNIFORMS_BODY) */ \
1197 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
1198 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1199 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1200 } while (deGetFalse())
1202 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false,
1205 << "uniform int ui_one;"
1208 << " mediump float a;"
1209 << " mediump vec3 b;"
1214 << "void main (void)"
1216 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1220 setUniform(gl, programID, "s.a", constCoords.x());
1221 setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1222 setUniform(gl, programID, "s.c", 1);
1225 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1228 UNIFORM_STRUCT_CASE(nested, "Nested struct", false,
1231 << "uniform int ui_zero;"
1232 << "uniform int ui_one;"
1236 << " mediump vec2 b;"
1239 << " mediump float a;"
1245 << "void main (void)"
1247 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1251 setUniform(gl, programID, "s.a", constCoords.x());
1252 setUniform(gl, programID, "s.b.a", 0);
1253 setUniform(gl, programID, "s.b.b", constCoords.swizzle(1,2));
1254 setUniform(gl, programID, "s.c", 1);
1257 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1260 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false,
1263 << "uniform int ui_one;"
1266 << " mediump float a;"
1267 << " mediump float b[3];"
1272 << "void main (void)"
1274 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1278 setUniform(gl, programID, "s.a", constCoords.w());
1279 setUniform(gl, programID, "s.c", 1);
1282 b[0] = constCoords.z();
1283 b[1] = constCoords.y();
1284 b[2] = constCoords.x();
1285 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1288 c.color.xyz() = c.constCoords.swizzle(3,2,1);
1291 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false,
1294 << "uniform int ui_zero;"
1295 << "uniform int ui_one;"
1296 << "uniform int ui_two;"
1299 << " mediump float a;"
1300 << " mediump float b[3];"
1305 << "void main (void)"
1307 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1311 setUniform(gl, programID, "s.a", constCoords.w());
1312 setUniform(gl, programID, "s.c", 1);
1315 b[0] = constCoords.z();
1316 b[1] = constCoords.y();
1317 b[2] = constCoords.x();
1318 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1321 c.color.xyz() = c.constCoords.swizzle(1,2,0);
1324 UNIFORM_STRUCT_CASE(struct_array, "Struct array", false,
1327 << "uniform int ui_zero;"
1328 << "uniform int ui_one;"
1329 << "uniform int ui_two;"
1332 << " mediump float a;"
1333 << " mediump int b;"
1335 << "uniform S s[3];"
1337 << "void main (void)"
1339 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1343 setUniform(gl, programID, "s[0].a", constCoords.x());
1344 setUniform(gl, programID, "s[0].b", 0);
1345 setUniform(gl, programID, "s[1].a", constCoords.y());
1346 setUniform(gl, programID, "s[1].b", 1);
1347 setUniform(gl, programID, "s[2].a", constCoords.z());
1348 setUniform(gl, programID, "s[2].b", 2);
1351 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1354 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1357 << "uniform int ui_zero;"
1358 << "uniform int ui_one;"
1359 << "uniform int ui_two;"
1362 << " mediump float a;"
1363 << " mediump int b;"
1365 << "uniform S s[3];"
1367 << "void main (void)"
1369 << " ${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);"
1373 setUniform(gl, programID, "s[0].a", constCoords.x());
1374 setUniform(gl, programID, "s[0].b", 0);
1375 setUniform(gl, programID, "s[1].a", constCoords.y());
1376 setUniform(gl, programID, "s[1].b", 1);
1377 setUniform(gl, programID, "s[2].a", constCoords.z());
1378 setUniform(gl, programID, "s[2].b", 2);
1381 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1384 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", false,
1388 << " mediump float a;"
1389 << " mediump vec2 b[2];"
1392 << " mediump float a;"
1396 << "uniform S s[2];"
1398 << "void main (void)"
1400 << " 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"
1401 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1402 << " 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 + w) * 0.333"
1403 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1404 << " ${DST} = vec4(r, g, b, a);"
1410 setUniform(gl, programID, "s[0].a", constCoords.x());
1411 arr[0] = constCoords.swizzle(0,1);
1412 arr[1] = constCoords.swizzle(2,3);
1413 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1414 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1415 arr[0] = constCoords.swizzle(2,3);
1416 arr[1] = constCoords.swizzle(0,1);
1417 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1418 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1419 arr[0] = constCoords.swizzle(0,2);
1420 arr[1] = constCoords.swizzle(1,3);
1421 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1422 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1423 setUniform(gl, programID, "s[0].c", 0);
1425 setUniform(gl, programID, "s[1].a", constCoords.w());
1426 arr[0] = constCoords.swizzle(0,0);
1427 arr[1] = constCoords.swizzle(1,1);
1428 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1429 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1430 arr[0] = constCoords.swizzle(2,2);
1431 arr[1] = constCoords.swizzle(3,3);
1432 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1433 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1434 arr[0] = constCoords.swizzle(1,0);
1435 arr[1] = constCoords.swizzle(3,2);
1436 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1437 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1438 setUniform(gl, programID, "s[1].c", 1);
1441 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1444 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false,
1447 << "uniform int ui_zero;"
1448 << "uniform int ui_one;"
1449 << "uniform int ui_two;"
1452 << " mediump float a;"
1453 << " mediump vec2 b[2];"
1456 << " mediump float a;"
1460 << "uniform S s[2];"
1462 << "void main (void)"
1464 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5"
1465 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4"
1466 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333"
1467 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
1468 << " ${DST} = vec4(r, g, b, a);"
1474 setUniform(gl, programID, "s[0].a", constCoords.x());
1475 arr[0] = constCoords.swizzle(0,1);
1476 arr[1] = constCoords.swizzle(2,3);
1477 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1478 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1479 arr[0] = constCoords.swizzle(2,3);
1480 arr[1] = constCoords.swizzle(0,1);
1481 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1482 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1483 arr[0] = constCoords.swizzle(0,2);
1484 arr[1] = constCoords.swizzle(1,3);
1485 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1486 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1487 setUniform(gl, programID, "s[0].c", 0);
1489 setUniform(gl, programID, "s[1].a", constCoords.w());
1490 arr[0] = constCoords.swizzle(0,0);
1491 arr[1] = constCoords.swizzle(1,1);
1492 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1493 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1494 arr[0] = constCoords.swizzle(2,2);
1495 arr[1] = constCoords.swizzle(3,3);
1496 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1497 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1498 arr[0] = constCoords.swizzle(1,0);
1499 arr[1] = constCoords.swizzle(3,2);
1500 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1501 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1502 setUniform(gl, programID, "s[1].c", 1);
1505 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1508 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false,
1511 << "uniform int ui_zero;"
1512 << "uniform int ui_one;"
1513 << "uniform int ui_two;"
1516 << " mediump float a;"
1517 << " mediump int b;"
1519 << "uniform S s[3];"
1521 << "void main (void)"
1523 << " mediump float rgb[3];"
1524 << " int alpha = 0;"
1525 << " for (int i = 0; i < 3; i++)"
1527 << " rgb[i] = s[2-i].a;"
1528 << " alpha += s[i].b;"
1530 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1534 setUniform(gl, programID, "s[0].a", constCoords.x());
1535 setUniform(gl, programID, "s[0].b", 0);
1536 setUniform(gl, programID, "s[1].a", constCoords.y());
1537 setUniform(gl, programID, "s[1].b", -1);
1538 setUniform(gl, programID, "s[2].a", constCoords.z());
1539 setUniform(gl, programID, "s[2].b", 2);
1542 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1545 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false,
1548 << "uniform int ui_zero;"
1549 << "uniform int ui_one;"
1550 << "uniform int ui_two;"
1551 << "uniform mediump float uf_two;"
1552 << "uniform mediump float uf_three;"
1553 << "uniform mediump float uf_four;"
1554 << "uniform mediump float uf_half;"
1555 << "uniform mediump float uf_third;"
1556 << "uniform mediump float uf_fourth;"
1557 << "uniform mediump float uf_sixth;"
1560 << " mediump float a;"
1561 << " mediump vec2 b[2];"
1564 << " mediump float a;"
1568 << "uniform S s[2];"
1570 << "void main (void)"
1572 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1573 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1574 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1575 << " mediump float a = 1.0;"
1576 << " for (int i = 0; i < 2; i++)"
1578 << " for (int j = 0; j < 3; j++)"
1580 << " r += s[0].b[j].b[i].y;"
1581 << " g += s[i].b[j].b[0].x;"
1582 << " b += s[i].b[j].b[1].x;"
1583 << " a *= s[i].b[j].a;"
1586 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1592 setUniform(gl, programID, "s[0].a", constCoords.x());
1593 arr[0] = constCoords.swizzle(1,0);
1594 arr[1] = constCoords.swizzle(2,0);
1595 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1596 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1597 arr[0] = constCoords.swizzle(1,1);
1598 arr[1] = constCoords.swizzle(3,1);
1599 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1600 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1601 arr[0] = constCoords.swizzle(2,1);
1602 arr[1] = constCoords.swizzle(2,1);
1603 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1604 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1605 setUniform(gl, programID, "s[0].c", 0);
1607 setUniform(gl, programID, "s[1].a", constCoords.w());
1608 arr[0] = constCoords.swizzle(2,0);
1609 arr[1] = constCoords.swizzle(2,1);
1610 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1611 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1612 arr[0] = constCoords.swizzle(2,2);
1613 arr[1] = constCoords.swizzle(3,3);
1614 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1615 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1616 arr[0] = constCoords.swizzle(1,0);
1617 arr[1] = constCoords.swizzle(3,2);
1618 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1619 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1620 setUniform(gl, programID, "s[1].c", 1);
1623 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1626 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false,
1629 << "uniform int ui_zero;"
1630 << "uniform int ui_one;"
1631 << "uniform int ui_two;"
1632 << "uniform int ui_three;"
1635 << " mediump float a;"
1636 << " mediump int b;"
1638 << "uniform S s[3];"
1640 << "void main (void)"
1642 << " mediump float rgb[3];"
1643 << " int alpha = 0;"
1644 << " for (int i = 0; i < ui_three; i++)"
1646 << " rgb[i] = s[2-i].a;"
1647 << " alpha += s[i].b;"
1649 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1653 setUniform(gl, programID, "s[0].a", constCoords.x());
1654 setUniform(gl, programID, "s[0].b", 0);
1655 setUniform(gl, programID, "s[1].a", constCoords.y());
1656 setUniform(gl, programID, "s[1].b", -1);
1657 setUniform(gl, programID, "s[2].a", constCoords.z());
1658 setUniform(gl, programID, "s[2].b", 2);
1661 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1664 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false,
1667 << "uniform int ui_zero;"
1668 << "uniform int ui_one;"
1669 << "uniform int ui_two;"
1670 << "uniform int ui_three;"
1671 << "uniform mediump float uf_two;"
1672 << "uniform mediump float uf_three;"
1673 << "uniform mediump float uf_four;"
1674 << "uniform mediump float uf_half;"
1675 << "uniform mediump float uf_third;"
1676 << "uniform mediump float uf_fourth;"
1677 << "uniform mediump float uf_sixth;"
1680 << " mediump float a;"
1681 << " mediump vec2 b[2];"
1684 << " mediump float a;"
1688 << "uniform S s[2];"
1690 << "void main (void)"
1692 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1693 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1694 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1695 << " mediump float a = 1.0;"
1696 << " for (int i = 0; i < ui_two; i++)"
1698 << " for (int j = 0; j < ui_three; j++)"
1700 << " r += s[0].b[j].b[i].y;"
1701 << " g += s[i].b[j].b[0].x;"
1702 << " b += s[i].b[j].b[1].x;"
1703 << " a *= s[i].b[j].a;"
1706 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1712 setUniform(gl, programID, "s[0].a", constCoords.x());
1713 arr[0] = constCoords.swizzle(1,0);
1714 arr[1] = constCoords.swizzle(2,0);
1715 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1716 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1717 arr[0] = constCoords.swizzle(1,1);
1718 arr[1] = constCoords.swizzle(3,1);
1719 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1720 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1721 arr[0] = constCoords.swizzle(2,1);
1722 arr[1] = constCoords.swizzle(2,1);
1723 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1724 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1725 setUniform(gl, programID, "s[0].c", 0);
1727 setUniform(gl, programID, "s[1].a", constCoords.w());
1728 arr[0] = constCoords.swizzle(2,0);
1729 arr[1] = constCoords.swizzle(2,1);
1730 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1731 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1732 arr[0] = constCoords.swizzle(2,2);
1733 arr[1] = constCoords.swizzle(3,3);
1734 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1735 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1736 arr[0] = constCoords.swizzle(1,0);
1737 arr[1] = constCoords.swizzle(3,2);
1738 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1739 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1740 setUniform(gl, programID, "s[1].c", 1);
1743 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1746 UNIFORM_STRUCT_CASE(sampler, "Sampler in struct", true,
1749 << "uniform int ui_one;"
1752 << " mediump float a;"
1753 << " mediump vec3 b;"
1758 << "void main (void)"
1760 << " ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1764 DE_UNREF(constCoords);
1765 setUniform(gl, programID, "s.a", 1.0f);
1766 setUniform(gl, programID, "s.b", tcu::Vec3(0.25f, 0.25f, 0.5f));
1767 setUniform(gl, programID, "s.c", 0);
1770 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1773 UNIFORM_STRUCT_CASE(sampler_nested, "Sampler in nested struct", true,
1776 << "uniform int ui_zero;"
1777 << "uniform int ui_one;"
1781 << " mediump vec2 b;"
1784 << " mediump float a;"
1790 << "void main (void)"
1792 << " ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1796 DE_UNREF(constCoords);
1797 setUniform(gl, programID, "s.a", 0.5f);
1798 setUniform(gl, programID, "s.b.a", 0);
1799 setUniform(gl, programID, "s.b.b", tcu::Vec2(0.25f, 0.25f));
1800 setUniform(gl, programID, "s.c", 1);
1803 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1806 UNIFORM_STRUCT_CASE(sampler_array, "Sampler in struct array", true,
1809 << "uniform int ui_one;"
1812 << " mediump float a;"
1813 << " mediump vec3 b;"
1816 << "uniform S s[2];"
1818 << "void main (void)"
1820 << " ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1824 DE_UNREF(constCoords);
1825 setUniform(gl, programID, "s[0].a", 1.0f);
1826 setUniform(gl, programID, "s[0].b", tcu::Vec3(0.25f, 0.25f, 0.25f));
1827 setUniform(gl, programID, "s[0].c", 1);
1828 setUniform(gl, programID, "s[1].a", 0.0f);
1829 setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.5f));
1830 setUniform(gl, programID, "s[1].c", 0);
1833 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1836 UNIFORM_STRUCT_CASE(equal, "Struct equality", false,
1839 << "uniform mediump float uf_one;"
1840 << "uniform int ui_two;"
1843 << " mediump float a;"
1844 << " mediump vec3 b;"
1851 << "void main (void)"
1853 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1854 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1855 << " if (a == b) ${DST}.x = 1.0;"
1856 << " if (a == c) ${DST}.y = 1.0;"
1857 << " if (a == d) ${DST}.z = 1.0;"
1861 DE_UNREF(constCoords);
1862 setUniform(gl, programID, "a.a", 1.0f);
1863 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1864 setUniform(gl, programID, "a.c", 2);
1865 setUniform(gl, programID, "b.a", 1.0f);
1866 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1867 setUniform(gl, programID, "b.c", 2);
1868 setUniform(gl, programID, "c.a", 1.0f);
1869 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1870 setUniform(gl, programID, "c.c", 2);
1873 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
1874 if (deFloatFloor(c.coords[1]+1.0f) == deFloatFloor(1.1f))
1878 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", false,
1881 << "uniform mediump float uf_one;"
1882 << "uniform int ui_two;"
1885 << " mediump float a;"
1886 << " mediump vec3 b;"
1893 << "void main (void)"
1895 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1896 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1897 << " if (a != b) ${DST}.x = 1.0;"
1898 << " if (a != c) ${DST}.y = 1.0;"
1899 << " if (a != d) ${DST}.z = 1.0;"
1903 DE_UNREF(constCoords);
1904 setUniform(gl, programID, "a.a", 1.0f);
1905 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1906 setUniform(gl, programID, "a.c", 2);
1907 setUniform(gl, programID, "b.a", 1.0f);
1908 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1909 setUniform(gl, programID, "b.c", 2);
1910 setUniform(gl, programID, "c.a", 1.0f);
1911 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1912 setUniform(gl, programID, "c.c", 2);
1915 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
1916 if (deFloatFloor(c.coords[1]+1.0f) != deFloatFloor(1.1f))
1921 ShaderStructTests::ShaderStructTests (Context& context)
1922 : TestCaseGroup(context, "struct", "Struct Tests")
1926 ShaderStructTests::~ShaderStructTests (void)
1930 void ShaderStructTests::init (void)
1932 addChild(new LocalStructTests(m_context));
1933 addChild(new UniformStructTests(m_context));