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, const std::map<std::string, std::string>* additionalParams)
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"] = "";
162 if (additionalParams)
163 spParams.insert(additionalParams->begin(), additionalParams->end());
166 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), defaultFragSrc);
168 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, defaultVertSrc, StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
171 class LocalStructTests : public TestCaseGroup
174 LocalStructTests (Context& context)
175 : TestCaseGroup(context, "local", "Local structs")
179 ~LocalStructTests (void)
183 virtual void init (void);
186 void LocalStructTests::init (void)
188 #define LOCAL_STRUCT_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, PARAMS) \
190 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
191 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, false, &Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS)); \
192 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, false,&Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS));\
193 } while (deGetFalse())
195 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \
196 LOCAL_STRUCT_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, DE_NULL)
198 LOCAL_STRUCT_CASE(basic, "Basic struct usage",
201 << "uniform int ui_one;"
204 << " mediump float a;"
205 << " mediump vec3 b;"
209 << "void main (void)"
211 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
212 << " s.b = ${COORDS}.yzw;"
213 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
217 c.color.xyz() = c.coords.swizzle(0,1,2);
220 LOCAL_STRUCT_CASE(nested, "Nested struct",
223 << "uniform int ui_zero;"
224 << "uniform int ui_one;"
228 << " mediump vec2 b;"
231 << " mediump float a;"
236 << "void main (void)"
238 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
239 << " s.b = T(ui_zero, ${COORDS}.yz);"
240 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
244 c.color.xyz() = c.coords.swizzle(0,1,2);
247 LOCAL_STRUCT_CASE(array_member, "Struct with array member",
250 << "uniform int ui_one;"
253 << " mediump float a;"
254 << " mediump float b[3];"
258 << "void main (void)"
261 << " s.a = ${COORDS}.w;"
263 << " s.b[0] = ${COORDS}.z;"
264 << " s.b[1] = ${COORDS}.y;"
265 << " s.b[2] = ${COORDS}.x;"
266 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
270 c.color.xyz() = c.coords.swizzle(3,2,1);
273 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
276 << "uniform int ui_zero;"
277 << "uniform int ui_one;"
278 << "uniform int ui_two;"
281 << " mediump float a;"
282 << " mediump float b[3];"
286 << "void main (void)"
289 << " s.a = ${COORDS}.w;"
291 << " s.b[0] = ${COORDS}.z;"
292 << " s.b[1] = ${COORDS}.y;"
293 << " s.b[2] = ${COORDS}.x;"
294 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
298 c.color.xyz() = c.coords.swizzle(1,2,0);
301 LOCAL_STRUCT_CASE(struct_array, "Struct array",
304 << "uniform int ui_zero;"
305 << "uniform int ui_one;"
306 << "uniform int ui_two;"
309 << " mediump float a;"
313 << "void main (void)"
316 << " s[0] = S(${COORDS}.x, ui_zero);"
317 << " s[1].a = ${COORDS}.y;"
318 << " s[1].b = ui_one;"
319 << " s[2] = S(${COORDS}.z, ui_two);"
320 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
324 c.color.xyz() = c.coords.swizzle(2,1,0);
327 LOCAL_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing",
330 << "uniform int ui_zero;"
331 << "uniform int ui_one;"
332 << "uniform int ui_two;"
335 << " mediump float a;"
339 << "void main (void)"
342 << " s[0] = S(${COORDS}.x, ui_zero);"
343 << " s[1].a = ${COORDS}.y;"
344 << " s[1].b = ui_one;"
345 << " s[2] = S(${COORDS}.z, ui_two);"
346 << " ${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 c.color.xyz() = c.coords.swizzle(2,1,0);
353 LOCAL_STRUCT_CASE(nested_struct_array, "Nested struct array",
356 << "uniform int ui_zero;"
357 << "uniform int ui_one;"
358 << "uniform int ui_two;"
359 << "uniform mediump float uf_two;"
360 << "uniform mediump float uf_three;"
361 << "uniform mediump float uf_four;"
362 << "uniform mediump float uf_half;"
363 << "uniform mediump float uf_third;"
364 << "uniform mediump float uf_fourth;"
367 << " mediump float a;"
368 << " mediump vec2 b[2];"
371 << " mediump float a;"
376 << "void main (void)"
381 << " s[0].a = ${COORDS}.x;"
382 << " s[0].b[0].a = uf_half;"
383 << " s[0].b[0].b[0] = ${COORDS}.xy;"
384 << " s[0].b[0].b[1] = ${COORDS}.zw;"
385 << " s[0].b[1].a = uf_third;"
386 << " s[0].b[1].b[0] = ${COORDS}.zw;"
387 << " s[0].b[1].b[1] = ${COORDS}.xy;"
388 << " s[0].b[2].a = uf_fourth;"
389 << " s[0].b[2].b[0] = ${COORDS}.xz;"
390 << " s[0].b[2].b[1] = ${COORDS}.yw;"
391 << " s[0].c = ui_zero;"
394 << " s[1].a = ${COORDS}.w;"
395 << " s[1].b[0].a = uf_two;"
396 << " s[1].b[0].b[0] = ${COORDS}.xx;"
397 << " s[1].b[0].b[1] = ${COORDS}.yy;"
398 << " s[1].b[1].a = uf_three;"
399 << " s[1].b[1].b[0] = ${COORDS}.zz;"
400 << " s[1].b[1].b[1] = ${COORDS}.ww;"
401 << " s[1].b[2].a = uf_four;"
402 << " s[1].b[2].b[0] = ${COORDS}.yx;"
403 << " s[1].b[2].b[1] = ${COORDS}.wz;"
404 << " s[1].c = ui_one;"
406 << " 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"
407 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
408 << " 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"
409 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
410 << " ${DST} = vec4(r, g, b, a);"
414 c.color.xyz() = c.coords.swizzle(2,0,3);
417 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
420 << "uniform int ui_zero;"
421 << "uniform int ui_one;"
422 << "uniform int ui_two;"
423 << "uniform mediump float uf_two;"
424 << "uniform mediump float uf_three;"
425 << "uniform mediump float uf_four;"
426 << "uniform mediump float uf_half;"
427 << "uniform mediump float uf_third;"
428 << "uniform mediump float uf_fourth;"
431 << " mediump float a;"
432 << " mediump vec2 b[2];"
435 << " mediump float a;"
440 << "void main (void)"
445 << " s[0].a = ${COORDS}.x;"
446 << " s[0].b[0].a = uf_half;"
447 << " s[0].b[0].b[0] = ${COORDS}.xy;"
448 << " s[0].b[0].b[1] = ${COORDS}.zw;"
449 << " s[0].b[1].a = uf_third;"
450 << " s[0].b[1].b[0] = ${COORDS}.zw;"
451 << " s[0].b[1].b[1] = ${COORDS}.xy;"
452 << " s[0].b[2].a = uf_fourth;"
453 << " s[0].b[2].b[0] = ${COORDS}.xz;"
454 << " s[0].b[2].b[1] = ${COORDS}.yw;"
455 << " s[0].c = ui_zero;"
458 << " s[1].a = ${COORDS}.w;"
459 << " s[1].b[0].a = uf_two;"
460 << " s[1].b[0].b[0] = ${COORDS}.xx;"
461 << " s[1].b[0].b[1] = ${COORDS}.yy;"
462 << " s[1].b[1].a = uf_three;"
463 << " s[1].b[1].b[0] = ${COORDS}.zz;"
464 << " s[1].b[1].b[1] = ${COORDS}.ww;"
465 << " s[1].b[2].a = uf_four;"
466 << " s[1].b[2].b[0] = ${COORDS}.yx;"
467 << " s[1].b[2].b[1] = ${COORDS}.wz;"
468 << " s[1].c = ui_one;"
470 << " 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"
471 << " 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"
472 << " 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"
473 << " 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"
474 << " ${DST} = vec4(r, g, b, a);"
478 c.color.xyz() = c.coords.swizzle(2,0,3);
481 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
484 << "uniform int ui_one;"
487 << " mediump float a;"
488 << " mediump vec3 b;"
492 << "mediump vec4 myFunc (S s)"
494 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
497 << "void main (void)"
499 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
500 << " s.b = ${COORDS}.yzw;"
501 << " ${DST} = myFunc(s);"
505 c.color.xyz() = c.coords.swizzle(0,1,2);
513 << " ${PRECISION} vec3 red;"
514 << " ${PRECISION} vec3 blue;"
517 << "void modify (inout S s)"
519 << " s.red += vec3(0.5, 0.0, 0.0);"
520 << " s.blue += vec3(0.0, 0.0, 0.5);"
523 << "void main (void)"
526 << " s.red = vec3(0.5, 0.0, 0.0);"
527 << " s.blue = vec3(0.0, 0.0, 0.5);"
529 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
530 << " if (s.red == vec3(1.0, 0.0, 0.0) && s.blue == vec3(0.0, 0.0, 1.0))"
531 << " ${DST} = vec4(1.0, 1.0, 1.0, 1.0);"
536 std::map<std::string, std::string> precisionParams;
538 precisionParams["PRECISION"] = "lowp";
539 LOCAL_STRUCT_CASE_PARAMETERIZED(
540 parameter_inout_lowp, "Struct with lowp members as an inout function parameter",
543 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
547 precisionParams["PRECISION"] = "mediump";
548 LOCAL_STRUCT_CASE_PARAMETERIZED(
549 parameter_inout_mediump, "Struct with mediump members as an inout function parameter",
552 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
556 precisionParams["PRECISION"] = "highp";
557 LOCAL_STRUCT_CASE_PARAMETERIZED(
558 parameter_inout_highp, "Struct with highp members as an inout function parameter",
561 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
565 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter",
568 << "uniform int ui_zero;"
569 << "uniform int ui_one;"
573 << " mediump vec2 b;"
576 << " mediump float a;"
581 << "mediump vec4 myFunc (S s)"
583 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
586 << "void main (void)"
588 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
589 << " s.b = T(ui_zero, ${COORDS}.yz);"
590 << " ${DST} = myFunc(s);"
594 c.color.xyz() = c.coords.swizzle(0,1,2);
602 << " ${PRECISION} vec3 red;"
603 << " ${PRECISION} vec3 blue;"
606 << "void modify (out S s)"
608 << " s.red = vec3(1.0, 0.0, 0.0);"
609 << " s.blue = vec3(0.0, 0.0, 1.0);"
612 << "void main (void)"
616 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
617 << " if (s.red == vec3(1.0, 0.0, 0.0) && s.blue == vec3(0.0, 0.0, 1.0))"
618 << " ${DST} = vec4(1.0, 1.0, 1.0, 1.0);"
622 precisionParams["PRECISION"] = "lowp";
623 LOCAL_STRUCT_CASE_PARAMETERIZED(
624 parameter_out_lowp, "Struct with lowp members as an out function parameter",
627 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
631 precisionParams["PRECISION"] = "mediump";
632 LOCAL_STRUCT_CASE_PARAMETERIZED(
633 parameter_out_mediump, "Struct with mediump members as an out function parameter",
636 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
640 precisionParams["PRECISION"] = "highp";
641 LOCAL_STRUCT_CASE_PARAMETERIZED(
642 parameter_out_highp, "Struct with highp members as an out function parameter",
645 c.color.xyz() = tcu::Vec3(1.0, 1.0, 1.0);
649 LOCAL_STRUCT_CASE(return, "Struct as a return value",
652 << "uniform int ui_one;"
655 << " mediump float a;"
656 << " mediump vec3 b;"
662 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
663 << " s.b = ${COORDS}.yzw;"
667 << "void main (void)"
669 << " S s = myFunc();"
670 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
674 c.color.xyz() = c.coords.swizzle(0,1,2);
677 LOCAL_STRUCT_CASE(return_nested, "Nested struct",
680 << "uniform int ui_zero;"
681 << "uniform int ui_one;"
685 << " mediump vec2 b;"
688 << " mediump float a;"
695 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
696 << " s.b = T(ui_zero, ${COORDS}.yz);"
700 << "void main (void)"
702 << " S s = myFunc();"
703 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
707 c.color.xyz() = c.coords.swizzle(0,1,2);
710 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment",
713 << "uniform int ui_zero;"
714 << "uniform int ui_one;"
715 << "uniform mediump float uf_one;"
718 << " mediump float a;"
719 << " mediump vec3 b;"
723 << "void main (void)"
725 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
726 << " if (uf_one > 0.0)"
727 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
728 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
732 c.color.xyz() = c.coords.swizzle(3,2,1);
735 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
738 << "uniform int ui_zero;"
739 << "uniform int ui_one;"
742 << " mediump float a;"
743 << " mediump vec3 b;"
747 << "void main (void)"
749 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
750 << " for (int i = 0; i < 3; i++)"
753 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
755 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
759 c.color.xyz() = c.coords.swizzle(3,2,1);
762 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop",
765 << "uniform int ui_zero;"
766 << "uniform int ui_one;"
767 << "uniform int ui_three;"
770 << " mediump float a;"
771 << " mediump vec3 b;"
775 << "void main (void)"
777 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
778 << " for (int i = 0; i < ui_three; i++)"
780 << " if (i == ui_one)"
781 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
783 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
787 c.color.xyz() = c.coords.swizzle(3,2,1);
790 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct",
793 << "uniform int ui_zero;"
794 << "uniform int ui_one;"
795 << "uniform mediump float uf_one;"
799 << " mediump vec2 b;"
802 << " mediump float a;"
807 << "void main (void)"
809 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
810 << " if (uf_one > 0.0)"
811 << " s.b = T(ui_zero, ${COORDS}.zw);"
812 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
816 c.color.xyz() = c.coords.swizzle(0,2,3);
819 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop",
822 << "uniform int ui_zero;"
823 << "uniform int ui_one;"
824 << "uniform mediump float uf_one;"
828 << " mediump vec2 b;"
831 << " mediump float a;"
836 << "void main (void)"
838 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
839 << " for (int i = 0; i < 3; i++)"
842 << " s.b = T(ui_zero, ${COORDS}.zw);"
844 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
848 c.color.xyz() = c.coords.swizzle(0,2,3);
851 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop",
854 << "uniform int ui_zero;"
855 << "uniform int ui_one;"
856 << "uniform int ui_three;"
857 << "uniform mediump float uf_one;"
861 << " mediump vec2 b;"
864 << " mediump float a;"
869 << "void main (void)"
871 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
872 << " for (int i = 0; i < ui_three; i++)"
874 << " if (i == ui_one)"
875 << " s.b = T(ui_zero, ${COORDS}.zw);"
877 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
881 c.color.xyz() = c.coords.swizzle(0,2,3);
884 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
887 << "uniform int ui_zero;"
888 << "uniform int ui_one;"
889 << "uniform int ui_two;"
892 << " mediump float a;"
896 << "void main (void)"
899 << " s[0] = S(${COORDS}.x, ui_zero);"
900 << " s[1].a = ${COORDS}.y;"
901 << " s[1].b = -ui_one;"
902 << " s[2] = S(${COORDS}.z, ui_two);"
904 << " mediump float rgb[3];"
906 << " for (int i = 0; i < 3; i++)"
908 << " rgb[i] = s[2-i].a;"
909 << " alpha += s[i].b;"
911 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
915 c.color.xyz() = c.coords.swizzle(2,1,0);
918 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
921 << "uniform int ui_zero;"
922 << "uniform int ui_one;"
923 << "uniform int ui_two;"
924 << "uniform mediump float uf_two;"
925 << "uniform mediump float uf_three;"
926 << "uniform mediump float uf_four;"
927 << "uniform mediump float uf_half;"
928 << "uniform mediump float uf_third;"
929 << "uniform mediump float uf_fourth;"
930 << "uniform mediump float uf_sixth;"
933 << " mediump float a;"
934 << " mediump vec2 b[2];"
937 << " mediump float a;"
942 << "void main (void)"
947 << " s[0].a = ${COORDS}.x;"
948 << " s[0].b[0].a = uf_half;"
949 << " s[0].b[0].b[0] = ${COORDS}.yx;"
950 << " s[0].b[0].b[1] = ${COORDS}.zx;"
951 << " s[0].b[1].a = uf_third;"
952 << " s[0].b[1].b[0] = ${COORDS}.yy;"
953 << " s[0].b[1].b[1] = ${COORDS}.wy;"
954 << " s[0].b[2].a = uf_fourth;"
955 << " s[0].b[2].b[0] = ${COORDS}.zx;"
956 << " s[0].b[2].b[1] = ${COORDS}.zy;"
957 << " s[0].c = ui_zero;"
960 << " s[1].a = ${COORDS}.w;"
961 << " s[1].b[0].a = uf_two;"
962 << " s[1].b[0].b[0] = ${COORDS}.zx;"
963 << " s[1].b[0].b[1] = ${COORDS}.zy;"
964 << " s[1].b[1].a = uf_three;"
965 << " s[1].b[1].b[0] = ${COORDS}.zz;"
966 << " s[1].b[1].b[1] = ${COORDS}.ww;"
967 << " s[1].b[2].a = uf_four;"
968 << " s[1].b[2].b[0] = ${COORDS}.yx;"
969 << " s[1].b[2].b[1] = ${COORDS}.wz;"
970 << " s[1].c = ui_one;"
972 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
973 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
974 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
975 << " mediump float a = 1.0;"
976 << " for (int i = 0; i < 2; i++)"
978 << " for (int j = 0; j < 3; j++)"
980 << " r += s[0].b[j].b[i].y;"
981 << " g += s[i].b[j].b[0].x;"
982 << " b += s[i].b[j].b[1].x;"
983 << " a *= s[i].b[j].a;"
986 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
990 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
993 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
996 << "uniform int ui_zero;"
997 << "uniform int ui_one;"
998 << "uniform int ui_two;"
999 << "uniform int ui_three;"
1002 << " mediump float a;"
1003 << " mediump int b;"
1006 << "void main (void)"
1009 << " s[0] = S(${COORDS}.x, ui_zero);"
1010 << " s[1].a = ${COORDS}.y;"
1011 << " s[1].b = -ui_one;"
1012 << " s[2] = S(${COORDS}.z, ui_two);"
1014 << " mediump float rgb[3];"
1015 << " int alpha = 0;"
1016 << " for (int i = 0; i < ui_three; i++)"
1018 << " rgb[i] = s[2-i].a;"
1019 << " alpha += s[i].b;"
1021 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1025 c.color.xyz() = c.coords.swizzle(2,1,0);
1028 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
1031 << "uniform int ui_zero;"
1032 << "uniform int ui_one;"
1033 << "uniform int ui_two;"
1034 << "uniform int ui_three;"
1035 << "uniform mediump float uf_two;"
1036 << "uniform mediump float uf_three;"
1037 << "uniform mediump float uf_four;"
1038 << "uniform mediump float uf_half;"
1039 << "uniform mediump float uf_third;"
1040 << "uniform mediump float uf_fourth;"
1041 << "uniform mediump float uf_sixth;"
1044 << " mediump float a;"
1045 << " mediump vec2 b[2];"
1048 << " mediump float a;"
1053 << "void main (void)"
1058 << " s[0].a = ${COORDS}.x;"
1059 << " s[0].b[0].a = uf_half;"
1060 << " s[0].b[0].b[0] = ${COORDS}.yx;"
1061 << " s[0].b[0].b[1] = ${COORDS}.zx;"
1062 << " s[0].b[1].a = uf_third;"
1063 << " s[0].b[1].b[0] = ${COORDS}.yy;"
1064 << " s[0].b[1].b[1] = ${COORDS}.wy;"
1065 << " s[0].b[2].a = uf_fourth;"
1066 << " s[0].b[2].b[0] = ${COORDS}.zx;"
1067 << " s[0].b[2].b[1] = ${COORDS}.zy;"
1068 << " s[0].c = ui_zero;"
1071 << " s[1].a = ${COORDS}.w;"
1072 << " s[1].b[0].a = uf_two;"
1073 << " s[1].b[0].b[0] = ${COORDS}.zx;"
1074 << " s[1].b[0].b[1] = ${COORDS}.zy;"
1075 << " s[1].b[1].a = uf_three;"
1076 << " s[1].b[1].b[0] = ${COORDS}.zz;"
1077 << " s[1].b[1].b[1] = ${COORDS}.ww;"
1078 << " s[1].b[2].a = uf_four;"
1079 << " s[1].b[2].b[0] = ${COORDS}.yx;"
1080 << " s[1].b[2].b[1] = ${COORDS}.wz;"
1081 << " s[1].c = ui_one;"
1083 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1084 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1085 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1086 << " mediump float a = 1.0;"
1087 << " for (int i = 0; i < ui_two; i++)"
1089 << " for (int j = 0; j < ui_three; j++)"
1091 << " r += s[0].b[j].b[i].y;"
1092 << " g += s[i].b[j].b[0].x;"
1093 << " b += s[i].b[j].b[1].x;"
1094 << " a *= s[i].b[j].a;"
1097 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1101 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
1104 LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality",
1107 << "uniform int ui_one;"
1108 << "uniform int ui_two;"
1111 << " mediump float a;"
1112 << " mediump vec3 b;"
1116 << "void main (void)"
1118 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1119 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1120 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1121 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1122 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1123 << " if (a == b) ${DST}.x = 1.0;"
1124 << " if (a == c) ${DST}.y = 1.0;"
1125 << " if (a == d) ${DST}.z = 1.0;"
1129 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1131 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1135 LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality",
1138 << "uniform int ui_one;"
1139 << "uniform int ui_two;"
1142 << " mediump float a;"
1143 << " mediump vec3 b;"
1147 << "void main (void)"
1149 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1150 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1151 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1152 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1153 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1154 << " if (a != b) ${DST}.x = 1.0;"
1155 << " if (a != c) ${DST}.y = 1.0;"
1156 << " if (a != d) ${DST}.z = 1.0;"
1160 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1162 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1167 LOCAL_STRUCT_CASE(nested_equal, "Nested struct struct equality",
1170 << "uniform int ui_one;"
1171 << "uniform int ui_two;"
1174 << " mediump vec3 a;"
1178 << " mediump float a;"
1183 << "void main (void)"
1185 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1186 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1187 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1188 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1189 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1190 << " if (a == b) ${DST}.x = 1.0;"
1191 << " if (a == c) ${DST}.y = 1.0;"
1192 << " if (a == d) ${DST}.z = 1.0;"
1196 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1198 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1202 LOCAL_STRUCT_CASE(nested_not_equal, "Nested struct struct equality",
1205 << "uniform int ui_one;"
1206 << "uniform int ui_two;"
1209 << " mediump vec3 a;"
1213 << " mediump float a;"
1218 << "void main (void)"
1220 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1221 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1222 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1223 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1224 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1225 << " if (a != b) ${DST}.x = 1.0;"
1226 << " if (a != c) ${DST}.y = 1.0;"
1227 << " if (a != d) ${DST}.z = 1.0;"
1231 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1233 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1238 LOCAL_STRUCT_CASE(array_member_equality, "Struct with array members equality",
1246 << "void main (void)"
1249 << " a.m[0] = true;"
1250 << " a.m[1] = false;"
1253 << " b.m[0] = true;"
1254 << " b.m[1] = false;"
1257 << " c.m[0] = true;"
1258 << " c.m[1] = true;"
1260 << " ${DST} = vec4(0.0, 0.0, 1.0, 1.0);"
1261 << " if (a == b) ${DST}.x = 1.0;"
1262 << " if (a != c) ${DST}.y = 1.0;"
1272 class UniformStructTests : public TestCaseGroup
1275 UniformStructTests (Context& context)
1276 : TestCaseGroup(context, "uniform", "Uniform structs")
1280 ~UniformStructTests (void)
1284 virtual void init (void);
1290 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + (NAME)).c_str())
1292 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \
1293 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \
1295 int loc = gl.getUniformLocation(programID, name); \
1296 SETUNIFORM(loc, 1, vec.getPtr()); \
1297 CHECK_SET_UNIFORM(name); \
1299 struct SetUniform##VECTYPE##Unused_s { int unused; }
1301 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM) \
1302 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, int arraySize) \
1304 int loc = gl.getUniformLocation(programID, name); \
1305 SETUNIFORM(loc, arraySize, vec->getPtr()); \
1306 CHECK_SET_UNIFORM(name); \
1308 struct SetUniformPtr##VECTYPE##Unused_s { int unused; }
1310 MAKE_SET_VEC_UNIFORM (Vec2, gl.uniform2fv);
1311 MAKE_SET_VEC_UNIFORM (Vec3, gl.uniform3fv);
1312 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv);
1314 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, float value)
1316 int loc = gl.getUniformLocation(programID, name);
1317 gl.uniform1f(loc, value);
1318 CHECK_SET_UNIFORM(name);
1321 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, int value)
1323 int loc = gl.getUniformLocation(programID, name);
1324 gl.uniform1i(loc, value);
1325 CHECK_SET_UNIFORM(name);
1328 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize)
1330 int loc = gl.getUniformLocation(programID, name);
1331 gl.uniform1fv(loc, arraySize, value);
1332 CHECK_SET_UNIFORM(name);
1337 void UniformStructTests::init (void)
1339 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1341 struct SetUniforms_##NAME { \
1342 static void setUniforms (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY /* NOLINT(SET_UNIFORMS_BODY) */ \
1344 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
1345 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC, DE_NULL));\
1346 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC, DE_NULL));\
1347 } while (deGetFalse())
1349 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false,
1352 << "uniform int ui_one;"
1355 << " mediump float a;"
1356 << " mediump vec3 b;"
1361 << "void main (void)"
1363 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1367 setUniform(gl, programID, "s.a", constCoords.x());
1368 setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1369 setUniform(gl, programID, "s.c", 1);
1372 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1375 UNIFORM_STRUCT_CASE(nested, "Nested struct", false,
1378 << "uniform int ui_zero;"
1379 << "uniform int ui_one;"
1383 << " mediump vec2 b;"
1386 << " mediump float a;"
1392 << "void main (void)"
1394 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1398 setUniform(gl, programID, "s.a", constCoords.x());
1399 setUniform(gl, programID, "s.b.a", 0);
1400 setUniform(gl, programID, "s.b.b", constCoords.swizzle(1,2));
1401 setUniform(gl, programID, "s.c", 1);
1404 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1407 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false,
1410 << "uniform int ui_one;"
1413 << " mediump float a;"
1414 << " mediump float b[3];"
1419 << "void main (void)"
1421 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1425 setUniform(gl, programID, "s.a", constCoords.w());
1426 setUniform(gl, programID, "s.c", 1);
1429 b[0] = constCoords.z();
1430 b[1] = constCoords.y();
1431 b[2] = constCoords.x();
1432 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1435 c.color.xyz() = c.constCoords.swizzle(3,2,1);
1438 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false,
1441 << "uniform int ui_zero;"
1442 << "uniform int ui_one;"
1443 << "uniform int ui_two;"
1446 << " mediump float a;"
1447 << " mediump float b[3];"
1452 << "void main (void)"
1454 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1458 setUniform(gl, programID, "s.a", constCoords.w());
1459 setUniform(gl, programID, "s.c", 1);
1462 b[0] = constCoords.z();
1463 b[1] = constCoords.y();
1464 b[2] = constCoords.x();
1465 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1468 c.color.xyz() = c.constCoords.swizzle(1,2,0);
1471 UNIFORM_STRUCT_CASE(struct_array, "Struct array", false,
1474 << "uniform int ui_zero;"
1475 << "uniform int ui_one;"
1476 << "uniform int ui_two;"
1479 << " mediump float a;"
1480 << " mediump int b;"
1482 << "uniform S s[3];"
1484 << "void main (void)"
1486 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1490 setUniform(gl, programID, "s[0].a", constCoords.x());
1491 setUniform(gl, programID, "s[0].b", 0);
1492 setUniform(gl, programID, "s[1].a", constCoords.y());
1493 setUniform(gl, programID, "s[1].b", 1);
1494 setUniform(gl, programID, "s[2].a", constCoords.z());
1495 setUniform(gl, programID, "s[2].b", 2);
1498 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1501 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1504 << "uniform int ui_zero;"
1505 << "uniform int ui_one;"
1506 << "uniform int ui_two;"
1509 << " mediump float a;"
1510 << " mediump int b;"
1512 << "uniform S s[3];"
1514 << "void main (void)"
1516 << " ${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);"
1520 setUniform(gl, programID, "s[0].a", constCoords.x());
1521 setUniform(gl, programID, "s[0].b", 0);
1522 setUniform(gl, programID, "s[1].a", constCoords.y());
1523 setUniform(gl, programID, "s[1].b", 1);
1524 setUniform(gl, programID, "s[2].a", constCoords.z());
1525 setUniform(gl, programID, "s[2].b", 2);
1528 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1531 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", false,
1535 << " mediump float a;"
1536 << " mediump vec2 b[2];"
1539 << " mediump float a;"
1543 << "uniform S s[2];"
1545 << "void main (void)"
1547 << " 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"
1548 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1549 << " 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"
1550 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1551 << " ${DST} = vec4(r, g, b, a);"
1557 setUniform(gl, programID, "s[0].a", constCoords.x());
1558 arr[0] = constCoords.swizzle(0,1);
1559 arr[1] = constCoords.swizzle(2,3);
1560 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1561 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1562 arr[0] = constCoords.swizzle(2,3);
1563 arr[1] = constCoords.swizzle(0,1);
1564 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1565 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1566 arr[0] = constCoords.swizzle(0,2);
1567 arr[1] = constCoords.swizzle(1,3);
1568 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1569 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1570 setUniform(gl, programID, "s[0].c", 0);
1572 setUniform(gl, programID, "s[1].a", constCoords.w());
1573 arr[0] = constCoords.swizzle(0,0);
1574 arr[1] = constCoords.swizzle(1,1);
1575 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1576 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1577 arr[0] = constCoords.swizzle(2,2);
1578 arr[1] = constCoords.swizzle(3,3);
1579 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1580 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1581 arr[0] = constCoords.swizzle(1,0);
1582 arr[1] = constCoords.swizzle(3,2);
1583 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1584 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1585 setUniform(gl, programID, "s[1].c", 1);
1588 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1591 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false,
1594 << "uniform int ui_zero;"
1595 << "uniform int ui_one;"
1596 << "uniform int ui_two;"
1599 << " mediump float a;"
1600 << " mediump vec2 b[2];"
1603 << " mediump float a;"
1607 << "uniform S s[2];"
1609 << "void main (void)"
1611 << " 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"
1612 << " 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"
1613 << " 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"
1614 << " 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"
1615 << " ${DST} = vec4(r, g, b, a);"
1621 setUniform(gl, programID, "s[0].a", constCoords.x());
1622 arr[0] = constCoords.swizzle(0,1);
1623 arr[1] = constCoords.swizzle(2,3);
1624 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1625 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1626 arr[0] = constCoords.swizzle(2,3);
1627 arr[1] = constCoords.swizzle(0,1);
1628 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1629 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1630 arr[0] = constCoords.swizzle(0,2);
1631 arr[1] = constCoords.swizzle(1,3);
1632 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1633 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1634 setUniform(gl, programID, "s[0].c", 0);
1636 setUniform(gl, programID, "s[1].a", constCoords.w());
1637 arr[0] = constCoords.swizzle(0,0);
1638 arr[1] = constCoords.swizzle(1,1);
1639 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1640 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1641 arr[0] = constCoords.swizzle(2,2);
1642 arr[1] = constCoords.swizzle(3,3);
1643 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1644 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1645 arr[0] = constCoords.swizzle(1,0);
1646 arr[1] = constCoords.swizzle(3,2);
1647 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1648 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1649 setUniform(gl, programID, "s[1].c", 1);
1652 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1655 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false,
1658 << "uniform int ui_zero;"
1659 << "uniform int ui_one;"
1660 << "uniform int ui_two;"
1663 << " mediump float a;"
1664 << " mediump int b;"
1666 << "uniform S s[3];"
1668 << "void main (void)"
1670 << " mediump float rgb[3];"
1671 << " int alpha = 0;"
1672 << " for (int i = 0; i < 3; i++)"
1674 << " rgb[i] = s[2-i].a;"
1675 << " alpha += s[i].b;"
1677 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1681 setUniform(gl, programID, "s[0].a", constCoords.x());
1682 setUniform(gl, programID, "s[0].b", 0);
1683 setUniform(gl, programID, "s[1].a", constCoords.y());
1684 setUniform(gl, programID, "s[1].b", -1);
1685 setUniform(gl, programID, "s[2].a", constCoords.z());
1686 setUniform(gl, programID, "s[2].b", 2);
1689 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1692 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false,
1695 << "uniform int ui_zero;"
1696 << "uniform int ui_one;"
1697 << "uniform int ui_two;"
1698 << "uniform mediump float uf_two;"
1699 << "uniform mediump float uf_three;"
1700 << "uniform mediump float uf_four;"
1701 << "uniform mediump float uf_half;"
1702 << "uniform mediump float uf_third;"
1703 << "uniform mediump float uf_fourth;"
1704 << "uniform mediump float uf_sixth;"
1707 << " mediump float a;"
1708 << " mediump vec2 b[2];"
1711 << " mediump float a;"
1715 << "uniform S s[2];"
1717 << "void main (void)"
1719 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1720 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1721 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1722 << " mediump float a = 1.0;"
1723 << " for (int i = 0; i < 2; i++)"
1725 << " for (int j = 0; j < 3; j++)"
1727 << " r += s[0].b[j].b[i].y;"
1728 << " g += s[i].b[j].b[0].x;"
1729 << " b += s[i].b[j].b[1].x;"
1730 << " a *= s[i].b[j].a;"
1733 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1739 setUniform(gl, programID, "s[0].a", constCoords.x());
1740 arr[0] = constCoords.swizzle(1,0);
1741 arr[1] = constCoords.swizzle(2,0);
1742 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1743 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1744 arr[0] = constCoords.swizzle(1,1);
1745 arr[1] = constCoords.swizzle(3,1);
1746 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1747 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1748 arr[0] = constCoords.swizzle(2,1);
1749 arr[1] = constCoords.swizzle(2,1);
1750 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1751 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1752 setUniform(gl, programID, "s[0].c", 0);
1754 setUniform(gl, programID, "s[1].a", constCoords.w());
1755 arr[0] = constCoords.swizzle(2,0);
1756 arr[1] = constCoords.swizzle(2,1);
1757 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1758 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1759 arr[0] = constCoords.swizzle(2,2);
1760 arr[1] = constCoords.swizzle(3,3);
1761 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1762 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1763 arr[0] = constCoords.swizzle(1,0);
1764 arr[1] = constCoords.swizzle(3,2);
1765 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1766 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1767 setUniform(gl, programID, "s[1].c", 1);
1770 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1773 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false,
1776 << "uniform int ui_zero;"
1777 << "uniform int ui_one;"
1778 << "uniform int ui_two;"
1779 << "uniform int ui_three;"
1782 << " mediump float a;"
1783 << " mediump int b;"
1785 << "uniform S s[3];"
1787 << "void main (void)"
1789 << " mediump float rgb[3];"
1790 << " int alpha = 0;"
1791 << " for (int i = 0; i < ui_three; i++)"
1793 << " rgb[i] = s[2-i].a;"
1794 << " alpha += s[i].b;"
1796 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1800 setUniform(gl, programID, "s[0].a", constCoords.x());
1801 setUniform(gl, programID, "s[0].b", 0);
1802 setUniform(gl, programID, "s[1].a", constCoords.y());
1803 setUniform(gl, programID, "s[1].b", -1);
1804 setUniform(gl, programID, "s[2].a", constCoords.z());
1805 setUniform(gl, programID, "s[2].b", 2);
1808 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1811 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false,
1814 << "uniform int ui_zero;"
1815 << "uniform int ui_one;"
1816 << "uniform int ui_two;"
1817 << "uniform int ui_three;"
1818 << "uniform mediump float uf_two;"
1819 << "uniform mediump float uf_three;"
1820 << "uniform mediump float uf_four;"
1821 << "uniform mediump float uf_half;"
1822 << "uniform mediump float uf_third;"
1823 << "uniform mediump float uf_fourth;"
1824 << "uniform mediump float uf_sixth;"
1827 << " mediump float a;"
1828 << " mediump vec2 b[2];"
1831 << " mediump float a;"
1835 << "uniform S s[2];"
1837 << "void main (void)"
1839 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1840 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1841 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1842 << " mediump float a = 1.0;"
1843 << " for (int i = 0; i < ui_two; i++)"
1845 << " for (int j = 0; j < ui_three; j++)"
1847 << " r += s[0].b[j].b[i].y;"
1848 << " g += s[i].b[j].b[0].x;"
1849 << " b += s[i].b[j].b[1].x;"
1850 << " a *= s[i].b[j].a;"
1853 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1859 setUniform(gl, programID, "s[0].a", constCoords.x());
1860 arr[0] = constCoords.swizzle(1,0);
1861 arr[1] = constCoords.swizzle(2,0);
1862 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1863 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1864 arr[0] = constCoords.swizzle(1,1);
1865 arr[1] = constCoords.swizzle(3,1);
1866 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1867 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1868 arr[0] = constCoords.swizzle(2,1);
1869 arr[1] = constCoords.swizzle(2,1);
1870 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1871 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1872 setUniform(gl, programID, "s[0].c", 0);
1874 setUniform(gl, programID, "s[1].a", constCoords.w());
1875 arr[0] = constCoords.swizzle(2,0);
1876 arr[1] = constCoords.swizzle(2,1);
1877 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1878 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1879 arr[0] = constCoords.swizzle(2,2);
1880 arr[1] = constCoords.swizzle(3,3);
1881 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1882 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1883 arr[0] = constCoords.swizzle(1,0);
1884 arr[1] = constCoords.swizzle(3,2);
1885 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1886 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1887 setUniform(gl, programID, "s[1].c", 1);
1890 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1893 UNIFORM_STRUCT_CASE(sampler, "Sampler in struct", true,
1896 << "uniform int ui_one;"
1899 << " mediump float a;"
1900 << " mediump vec3 b;"
1905 << "void main (void)"
1907 << " ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1911 DE_UNREF(constCoords);
1912 setUniform(gl, programID, "s.a", 1.0f);
1913 setUniform(gl, programID, "s.b", tcu::Vec3(0.25f, 0.25f, 0.5f));
1914 setUniform(gl, programID, "s.c", 0);
1917 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1920 UNIFORM_STRUCT_CASE(sampler_nested, "Sampler in nested struct", true,
1923 << "uniform int ui_zero;"
1924 << "uniform int ui_one;"
1928 << " mediump vec2 b;"
1931 << " mediump float a;"
1937 << "void main (void)"
1939 << " ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1943 DE_UNREF(constCoords);
1944 setUniform(gl, programID, "s.a", 0.5f);
1945 setUniform(gl, programID, "s.b.a", 0);
1946 setUniform(gl, programID, "s.b.b", tcu::Vec2(0.25f, 0.25f));
1947 setUniform(gl, programID, "s.c", 1);
1950 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1953 UNIFORM_STRUCT_CASE(sampler_array, "Sampler in struct array", true,
1956 << "uniform int ui_one;"
1959 << " mediump float a;"
1960 << " mediump vec3 b;"
1963 << "uniform S s[2];"
1965 << "void main (void)"
1967 << " ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1971 DE_UNREF(constCoords);
1972 setUniform(gl, programID, "s[0].a", 1.0f);
1973 setUniform(gl, programID, "s[0].b", tcu::Vec3(0.25f, 0.25f, 0.25f));
1974 setUniform(gl, programID, "s[0].c", 1);
1975 setUniform(gl, programID, "s[1].a", 0.0f);
1976 setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.5f));
1977 setUniform(gl, programID, "s[1].c", 0);
1980 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1983 UNIFORM_STRUCT_CASE(equal, "Struct equality", false,
1986 << "uniform mediump float uf_one;"
1987 << "uniform int ui_two;"
1990 << " mediump float a;"
1991 << " mediump vec3 b;"
1998 << "void main (void)"
2000 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
2001 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
2002 << " if (a == b) ${DST}.x = 1.0;"
2003 << " if (a == c) ${DST}.y = 1.0;"
2004 << " if (a == d) ${DST}.z = 1.0;"
2008 DE_UNREF(constCoords);
2009 setUniform(gl, programID, "a.a", 1.0f);
2010 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
2011 setUniform(gl, programID, "a.c", 2);
2012 setUniform(gl, programID, "b.a", 1.0f);
2013 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
2014 setUniform(gl, programID, "b.c", 2);
2015 setUniform(gl, programID, "c.a", 1.0f);
2016 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
2017 setUniform(gl, programID, "c.c", 2);
2020 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
2021 if (deFloatFloor(c.coords[1]+1.0f) == deFloatFloor(1.1f))
2025 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", false,
2028 << "uniform mediump float uf_one;"
2029 << "uniform int ui_two;"
2032 << " mediump float a;"
2033 << " mediump vec3 b;"
2040 << "void main (void)"
2042 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
2043 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
2044 << " if (a != b) ${DST}.x = 1.0;"
2045 << " if (a != c) ${DST}.y = 1.0;"
2046 << " if (a != d) ${DST}.z = 1.0;"
2050 DE_UNREF(constCoords);
2051 setUniform(gl, programID, "a.a", 1.0f);
2052 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
2053 setUniform(gl, programID, "a.c", 2);
2054 setUniform(gl, programID, "b.a", 1.0f);
2055 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
2056 setUniform(gl, programID, "b.c", 2);
2057 setUniform(gl, programID, "c.a", 1.0f);
2058 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
2059 setUniform(gl, programID, "c.c", 2);
2062 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
2063 if (deFloatFloor(c.coords[1]+1.0f) != deFloatFloor(1.1f))
2068 ShaderStructTests::ShaderStructTests (Context& context)
2069 : TestCaseGroup(context, "struct", "Struct Tests")
2073 ShaderStructTests::~ShaderStructTests (void)
2077 void ShaderStructTests::init (void)
2079 addChild(new LocalStructTests(m_context));
2080 addChild(new UniformStructTests(m_context));