1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fShaderStructTests.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
56 FLAG_USES_TEXTURES = (1<<0),
57 FLAG_REQUIRES_DYNAMIC_LOOPS = (1<<1),
58 FLAG_REQUIRES_DYNAMIC_INDEXING = (1<<2),
61 typedef void (*SetupUniformsFunc) (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords);
63 class ShaderStructCase : public ShaderRenderCase
66 ShaderStructCase (Context& context, const char* name, const char* description, bool isVertexCase, deUint32 flags, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource);
67 ~ShaderStructCase (void);
72 virtual void setupUniforms (int programID, const tcu::Vec4& constCoords);
75 ShaderStructCase (const ShaderStructCase&);
76 ShaderStructCase& operator= (const ShaderStructCase&);
78 const SetupUniformsFunc m_setupUniforms;
79 const deUint32 m_flags;
81 glu::Texture2D* m_brickTexture;
84 ShaderStructCase::ShaderStructCase (Context& context, const char* name, const char* description, bool isVertexCase, deUint32 flags, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource)
85 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc)
86 , m_setupUniforms (setupUniformsFunc)
88 , m_brickTexture (DE_NULL)
90 m_vertShaderSource = vertShaderSource;
91 m_fragShaderSource = fragShaderSource;
94 ShaderStructCase::~ShaderStructCase (void)
96 delete m_brickTexture;
99 void ShaderStructCase::init (void)
103 gls::ShaderRenderCase::init();
105 catch (const CompileFailed&)
107 if (m_flags & FLAG_REQUIRES_DYNAMIC_LOOPS)
109 const bool isSupported = m_isVertexCase ? m_ctxInfo.isVertexDynamicLoopSupported() : m_ctxInfo.isFragmentDynamicLoopSupported();
111 throw tcu::NotSupportedError("Dynamic loops not supported");
114 if ((m_flags && FLAG_USES_TEXTURES) && m_isVertexCase)
117 m_renderCtx.getFunctions().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numTextures);
118 if (numTextures == 0)
119 throw tcu::NotSupportedError("Vertex shader texture access not supported");
122 if (m_flags & FLAG_REQUIRES_DYNAMIC_INDEXING)
123 throw tcu::NotSupportedError("Dynamic indexing not supported");
128 if (m_flags & FLAG_USES_TEXTURES)
130 m_brickTexture = glu::Texture2D::create(m_renderCtx, m_ctxInfo, m_testCtx.getArchive(), "data/brick.png");
131 m_textures.push_back(TextureBinding(m_brickTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
132 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR)));
133 DE_ASSERT(m_textures.size() == 1);
137 void ShaderStructCase::deinit (void)
139 gls::ShaderRenderCase::deinit();
140 delete m_brickTexture;
141 m_brickTexture = DE_NULL;
144 void ShaderStructCase::setupUniforms (int programID, const tcu::Vec4& constCoords)
146 ShaderRenderCase::setupUniforms(programID, constCoords);
148 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
151 static ShaderStructCase* createStructCase (Context& context, const char* name, const char* description, bool isVertexCase, deUint32 flags, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms, const LineStream& shaderSrc)
153 static const char* defaultVertSrc =
154 "attribute highp vec4 a_position;\n"
155 "attribute highp vec4 a_coords;\n"
156 "varying mediump vec4 v_coords;\n\n"
159 " v_coords = a_coords;\n"
160 " gl_Position = a_position;\n"
162 static const char* defaultFragSrc =
163 "varying mediump vec4 v_color;\n\n"
166 " gl_FragColor = v_color;\n"
169 // Fill in specialization parameters.
170 std::map<std::string, std::string> spParams;
173 spParams["DECLARATIONS"] =
174 "attribute highp vec4 a_position;\n"
175 "attribute highp vec4 a_coords;\n"
176 "varying mediump vec4 v_color;";
177 spParams["COORDS"] = "a_coords";
178 spParams["DST"] = "v_color";
179 spParams["ASSIGN_POS"] = "gl_Position = a_position;";
183 spParams["DECLARATIONS"] = "varying mediump vec4 v_coords;";
184 spParams["COORDS"] = "v_coords";
185 spParams["DST"] = "gl_FragColor";
186 spParams["ASSIGN_POS"] = "";
190 return new ShaderStructCase(context, name, description, isVertexCase, flags, evalFunc, setupUniforms, StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), defaultFragSrc);
192 return new ShaderStructCase(context, name, description, isVertexCase, flags, evalFunc, setupUniforms, defaultVertSrc, StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
195 class LocalStructTests : public TestCaseGroup
198 LocalStructTests (Context& context)
199 : TestCaseGroup(context, "local", "Local structs")
203 ~LocalStructTests (void)
207 virtual void init (void);
210 void LocalStructTests::init (void)
212 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, FLAGS, SHADER_SRC, EVAL_FUNC_BODY) \
214 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
215 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, FLAGS, &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
216 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, FLAGS,&Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
217 } while (deGetFalse())
219 LOCAL_STRUCT_CASE(basic, "Basic struct usage", 0,
222 << "uniform int ui_one;"
225 << " mediump float a;"
226 << " mediump vec3 b;"
230 << "void main (void)"
232 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
233 << " s.b = ${COORDS}.yzw;"
234 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
238 c.color.xyz() = c.coords.swizzle(0,1,2);
241 LOCAL_STRUCT_CASE(nested, "Nested struct", 0,
244 << "uniform int ui_zero;"
245 << "uniform int ui_one;"
249 << " mediump vec2 b;"
252 << " mediump float a;"
257 << "void main (void)"
259 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
260 << " s.b = T(ui_zero, ${COORDS}.yz);"
261 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
265 c.color.xyz() = c.coords.swizzle(0,1,2);
268 LOCAL_STRUCT_CASE(array_member, "Struct with array member", 0,
271 << "uniform int ui_one;"
274 << " mediump float a;"
275 << " mediump float b[3];"
279 << "void main (void)"
282 << " s.a = ${COORDS}.w;"
284 << " s.b[0] = ${COORDS}.z;"
285 << " s.b[1] = ${COORDS}.y;"
286 << " s.b[2] = ${COORDS}.x;"
287 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
291 c.color.xyz() = c.coords.swizzle(3,2,1);
294 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
297 << "uniform int ui_zero;"
298 << "uniform int ui_one;"
299 << "uniform int ui_two;"
302 << " mediump float a;"
303 << " mediump float b[3];"
307 << "void main (void)"
310 << " s.a = ${COORDS}.w;"
312 << " s.b[0] = ${COORDS}.z;"
313 << " s.b[1] = ${COORDS}.y;"
314 << " s.b[2] = ${COORDS}.x;"
315 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
319 c.color.xyz() = c.coords.swizzle(1,2,0);
322 LOCAL_STRUCT_CASE(struct_array, "Struct array", 0,
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[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
345 c.color.xyz() = c.coords.swizzle(2,1,0);
348 LOCAL_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
351 << "uniform int ui_zero;"
352 << "uniform int ui_one;"
353 << "uniform int ui_two;"
356 << " mediump float a;"
360 << "void main (void)"
363 << " s[0] = S(${COORDS}.x, ui_zero);"
364 << " s[1].a = ${COORDS}.y;"
365 << " s[1].b = ui_one;"
366 << " s[2] = S(${COORDS}.z, ui_two);"
367 << " ${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);"
371 c.color.xyz() = c.coords.swizzle(2,1,0);
374 LOCAL_STRUCT_CASE(nested_struct_array, "Nested struct array", 0,
377 << "uniform int ui_zero;"
378 << "uniform int ui_one;"
379 << "uniform int ui_two;"
380 << "uniform mediump float uf_two;"
381 << "uniform mediump float uf_three;"
382 << "uniform mediump float uf_four;"
383 << "uniform mediump float uf_half;"
384 << "uniform mediump float uf_third;"
385 << "uniform mediump float uf_fourth;"
388 << " mediump float a;"
389 << " mediump vec2 b[2];"
392 << " mediump float a;"
397 << "void main (void)"
402 << " s[0].a = ${COORDS}.x;"
403 << " s[0].b[0].a = uf_half;"
404 << " s[0].b[0].b[0] = ${COORDS}.xy;"
405 << " s[0].b[0].b[1] = ${COORDS}.zw;"
406 << " s[0].b[1].a = uf_third;"
407 << " s[0].b[1].b[0] = ${COORDS}.zw;"
408 << " s[0].b[1].b[1] = ${COORDS}.xy;"
409 << " s[0].b[2].a = uf_fourth;"
410 << " s[0].b[2].b[0] = ${COORDS}.xz;"
411 << " s[0].b[2].b[1] = ${COORDS}.yw;"
412 << " s[0].c = ui_zero;"
415 << " s[1].a = ${COORDS}.w;"
416 << " s[1].b[0].a = uf_two;"
417 << " s[1].b[0].b[0] = ${COORDS}.xx;"
418 << " s[1].b[0].b[1] = ${COORDS}.yy;"
419 << " s[1].b[1].a = uf_three;"
420 << " s[1].b[1].b[0] = ${COORDS}.zz;"
421 << " s[1].b[1].b[1] = ${COORDS}.ww;"
422 << " s[1].b[2].a = uf_four;"
423 << " s[1].b[2].b[0] = ${COORDS}.yx;"
424 << " s[1].b[2].b[1] = ${COORDS}.wz;"
425 << " s[1].c = ui_one;"
427 << " 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"
428 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
429 << " 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"
430 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
431 << " ${DST} = vec4(r, g, b, a);"
435 c.color.xyz() = c.coords.swizzle(2,0,3);
438 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
441 << "uniform int ui_zero;"
442 << "uniform int ui_one;"
443 << "uniform int ui_two;"
444 << "uniform mediump float uf_two;"
445 << "uniform mediump float uf_three;"
446 << "uniform mediump float uf_four;"
447 << "uniform mediump float uf_half;"
448 << "uniform mediump float uf_third;"
449 << "uniform mediump float uf_fourth;"
452 << " mediump float a;"
453 << " mediump vec2 b[2];"
456 << " mediump float a;"
461 << "void main (void)"
466 << " s[0].a = ${COORDS}.x;"
467 << " s[0].b[0].a = uf_half;"
468 << " s[0].b[0].b[0] = ${COORDS}.xy;"
469 << " s[0].b[0].b[1] = ${COORDS}.zw;"
470 << " s[0].b[1].a = uf_third;"
471 << " s[0].b[1].b[0] = ${COORDS}.zw;"
472 << " s[0].b[1].b[1] = ${COORDS}.xy;"
473 << " s[0].b[2].a = uf_fourth;"
474 << " s[0].b[2].b[0] = ${COORDS}.xz;"
475 << " s[0].b[2].b[1] = ${COORDS}.yw;"
476 << " s[0].c = ui_zero;"
479 << " s[1].a = ${COORDS}.w;"
480 << " s[1].b[0].a = uf_two;"
481 << " s[1].b[0].b[0] = ${COORDS}.xx;"
482 << " s[1].b[0].b[1] = ${COORDS}.yy;"
483 << " s[1].b[1].a = uf_three;"
484 << " s[1].b[1].b[0] = ${COORDS}.zz;"
485 << " s[1].b[1].b[1] = ${COORDS}.ww;"
486 << " s[1].b[2].a = uf_four;"
487 << " s[1].b[2].b[0] = ${COORDS}.yx;"
488 << " s[1].b[2].b[1] = ${COORDS}.wz;"
489 << " s[1].c = ui_one;"
491 << " 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"
492 << " 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"
493 << " 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"
494 << " 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"
495 << " ${DST} = vec4(r, g, b, a);"
499 c.color.xyz() = c.coords.swizzle(2,0,3);
502 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter", 0,
505 << "uniform int ui_one;"
508 << " mediump float a;"
509 << " mediump vec3 b;"
513 << "mediump vec4 myFunc (S s)"
515 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
518 << "void main (void)"
520 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
521 << " s.b = ${COORDS}.yzw;"
522 << " ${DST} = myFunc(s);"
526 c.color.xyz() = c.coords.swizzle(0,1,2);
529 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter", 0,
532 << "uniform int ui_zero;"
533 << "uniform int ui_one;"
537 << " mediump vec2 b;"
540 << " mediump float a;"
545 << "mediump vec4 myFunc (S s)"
547 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
550 << "void main (void)"
552 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
553 << " s.b = T(ui_zero, ${COORDS}.yz);"
554 << " ${DST} = myFunc(s);"
558 c.color.xyz() = c.coords.swizzle(0,1,2);
561 LOCAL_STRUCT_CASE(return, "Struct as a return value", 0,
564 << "uniform int ui_one;"
567 << " mediump float a;"
568 << " mediump vec3 b;"
574 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
575 << " s.b = ${COORDS}.yzw;"
579 << "void main (void)"
581 << " S s = myFunc();"
582 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
586 c.color.xyz() = c.coords.swizzle(0,1,2);
589 LOCAL_STRUCT_CASE(return_nested, "Nested struct", 0,
592 << "uniform int ui_zero;"
593 << "uniform int ui_one;"
597 << " mediump vec2 b;"
600 << " mediump float a;"
607 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
608 << " s.b = T(ui_zero, ${COORDS}.yz);"
612 << "void main (void)"
614 << " S s = myFunc();"
615 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
619 c.color.xyz() = c.coords.swizzle(0,1,2);
622 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment", 0,
625 << "uniform int ui_zero;"
626 << "uniform int ui_one;"
627 << "uniform mediump float uf_one;"
630 << " mediump float a;"
631 << " mediump vec3 b;"
635 << "void main (void)"
637 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
638 << " if (uf_one > 0.0)"
639 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
640 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
644 c.color.xyz() = c.coords.swizzle(3,2,1);
647 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop", 0,
650 << "uniform int ui_zero;"
651 << "uniform int ui_one;"
654 << " mediump float a;"
655 << " mediump vec3 b;"
659 << "void main (void)"
661 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
662 << " for (int i = 0; i < 3; i++)"
665 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
667 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
671 c.color.xyz() = c.coords.swizzle(3,2,1);
674 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop", FLAG_REQUIRES_DYNAMIC_INDEXING,
677 << "uniform int ui_zero;"
678 << "uniform int ui_one;"
679 << "uniform int ui_three;"
682 << " mediump float a;"
683 << " mediump vec3 b;"
687 << "void main (void)"
689 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
690 << " for (int i = 0; i < ui_three; i++)"
692 << " if (i == ui_one)"
693 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
695 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
699 c.color.xyz() = c.coords.swizzle(3,2,1);
702 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct", 0,
705 << "uniform int ui_zero;"
706 << "uniform int ui_one;"
707 << "uniform mediump float uf_one;"
711 << " mediump vec2 b;"
714 << " mediump float a;"
719 << "void main (void)"
721 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
722 << " if (uf_one > 0.0)"
723 << " s.b = T(ui_zero, ${COORDS}.zw);"
724 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
728 c.color.xyz() = c.coords.swizzle(0,2,3);
731 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop", 0,
734 << "uniform int ui_zero;"
735 << "uniform int ui_one;"
736 << "uniform mediump float uf_one;"
740 << " mediump vec2 b;"
743 << " mediump float a;"
748 << "void main (void)"
750 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
751 << " for (int i = 0; i < 3; i++)"
754 << " s.b = T(ui_zero, ${COORDS}.zw);"
756 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
760 c.color.xyz() = c.coords.swizzle(0,2,3);
763 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING,
766 << "uniform int ui_zero;"
767 << "uniform int ui_one;"
768 << "uniform int ui_three;"
769 << "uniform mediump float uf_one;"
773 << " mediump vec2 b;"
776 << " mediump float a;"
781 << "void main (void)"
783 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
784 << " for (int i = 0; i < ui_three; i++)"
786 << " if (i == ui_one)"
787 << " s.b = T(ui_zero, ${COORDS}.zw);"
789 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
793 c.color.xyz() = c.coords.swizzle(0,2,3);
796 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 0,
799 << "uniform int ui_zero;"
800 << "uniform int ui_one;"
801 << "uniform int ui_two;"
804 << " mediump float a;"
808 << "void main (void)"
811 << " s[0] = S(${COORDS}.x, ui_zero);"
812 << " s[1].a = ${COORDS}.y;"
813 << " s[1].b = -ui_one;"
814 << " s[2] = S(${COORDS}.z, ui_two);"
816 << " mediump float rgb[3];"
818 << " for (int i = 0; i < 3; i++)"
820 << " rgb[i] = s[2-i].a;"
821 << " alpha += s[i].b;"
823 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
827 c.color.xyz() = c.coords.swizzle(2,1,0);
830 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 0,
833 << "uniform int ui_zero;"
834 << "uniform int ui_one;"
835 << "uniform int ui_two;"
836 << "uniform mediump float uf_two;"
837 << "uniform mediump float uf_three;"
838 << "uniform mediump float uf_four;"
839 << "uniform mediump float uf_half;"
840 << "uniform mediump float uf_third;"
841 << "uniform mediump float uf_fourth;"
842 << "uniform mediump float uf_sixth;"
845 << " mediump float a;"
846 << " mediump vec2 b[2];"
849 << " mediump float a;"
854 << "void main (void)"
859 << " s[0].a = ${COORDS}.x;"
860 << " s[0].b[0].a = uf_half;"
861 << " s[0].b[0].b[0] = ${COORDS}.yx;"
862 << " s[0].b[0].b[1] = ${COORDS}.zx;"
863 << " s[0].b[1].a = uf_third;"
864 << " s[0].b[1].b[0] = ${COORDS}.yy;"
865 << " s[0].b[1].b[1] = ${COORDS}.wy;"
866 << " s[0].b[2].a = uf_fourth;"
867 << " s[0].b[2].b[0] = ${COORDS}.zx;"
868 << " s[0].b[2].b[1] = ${COORDS}.zy;"
869 << " s[0].c = ui_zero;"
872 << " s[1].a = ${COORDS}.w;"
873 << " s[1].b[0].a = uf_two;"
874 << " s[1].b[0].b[0] = ${COORDS}.zx;"
875 << " s[1].b[0].b[1] = ${COORDS}.zy;"
876 << " s[1].b[1].a = uf_three;"
877 << " s[1].b[1].b[0] = ${COORDS}.zz;"
878 << " s[1].b[1].b[1] = ${COORDS}.ww;"
879 << " s[1].b[2].a = uf_four;"
880 << " s[1].b[2].b[0] = ${COORDS}.yx;"
881 << " s[1].b[2].b[1] = ${COORDS}.wz;"
882 << " s[1].c = ui_one;"
884 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
885 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
886 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
887 << " mediump float a = 1.0;"
888 << " for (int i = 0; i < 2; i++)"
890 << " for (int j = 0; j < 3; j++)"
892 << " r += s[0].b[j].b[i].y;"
893 << " g += s[i].b[j].b[0].x;"
894 << " b += s[i].b[j].b[1].x;"
895 << " a *= s[i].b[j].a;"
898 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
902 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
905 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
908 << "uniform int ui_zero;"
909 << "uniform int ui_one;"
910 << "uniform int ui_two;"
911 << "uniform int ui_three;"
914 << " mediump float a;"
918 << "void main (void)"
921 << " s[0] = S(${COORDS}.x, ui_zero);"
922 << " s[1].a = ${COORDS}.y;"
923 << " s[1].b = -ui_one;"
924 << " s[2] = S(${COORDS}.z, ui_two);"
926 << " mediump float rgb[3];"
928 << " for (int i = 0; i < ui_three; i++)"
930 << " rgb[i] = s[2-i].a;"
931 << " alpha += s[i].b;"
933 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
937 c.color.xyz() = c.coords.swizzle(2,1,0);
940 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
943 << "uniform int ui_zero;"
944 << "uniform int ui_one;"
945 << "uniform int ui_two;"
946 << "uniform int ui_three;"
947 << "uniform mediump float uf_two;"
948 << "uniform mediump float uf_three;"
949 << "uniform mediump float uf_four;"
950 << "uniform mediump float uf_half;"
951 << "uniform mediump float uf_third;"
952 << "uniform mediump float uf_fourth;"
953 << "uniform mediump float uf_sixth;"
956 << " mediump float a;"
957 << " mediump vec2 b[2];"
960 << " mediump float a;"
965 << "void main (void)"
970 << " s[0].a = ${COORDS}.x;"
971 << " s[0].b[0].a = uf_half;"
972 << " s[0].b[0].b[0] = ${COORDS}.yx;"
973 << " s[0].b[0].b[1] = ${COORDS}.zx;"
974 << " s[0].b[1].a = uf_third;"
975 << " s[0].b[1].b[0] = ${COORDS}.yy;"
976 << " s[0].b[1].b[1] = ${COORDS}.wy;"
977 << " s[0].b[2].a = uf_fourth;"
978 << " s[0].b[2].b[0] = ${COORDS}.zx;"
979 << " s[0].b[2].b[1] = ${COORDS}.zy;"
980 << " s[0].c = ui_zero;"
983 << " s[1].a = ${COORDS}.w;"
984 << " s[1].b[0].a = uf_two;"
985 << " s[1].b[0].b[0] = ${COORDS}.zx;"
986 << " s[1].b[0].b[1] = ${COORDS}.zy;"
987 << " s[1].b[1].a = uf_three;"
988 << " s[1].b[1].b[0] = ${COORDS}.zz;"
989 << " s[1].b[1].b[1] = ${COORDS}.ww;"
990 << " s[1].b[2].a = uf_four;"
991 << " s[1].b[2].b[0] = ${COORDS}.yx;"
992 << " s[1].b[2].b[1] = ${COORDS}.wz;"
993 << " s[1].c = ui_one;"
995 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
996 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
997 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
998 << " mediump float a = 1.0;"
999 << " for (int i = 0; i < ui_two; i++)"
1001 << " for (int j = 0; j < ui_three; j++)"
1003 << " r += s[0].b[j].b[i].y;"
1004 << " g += s[i].b[j].b[0].x;"
1005 << " b += s[i].b[j].b[1].x;"
1006 << " a *= s[i].b[j].a;"
1009 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1013 c.color.xyz() = (c.coords.swizzle(0,1,2) + c.coords.swizzle(1,2,3)) * 0.5f;
1016 LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality", 0,
1018 << "${DECLARATIONS}"
1019 << "uniform int ui_one;"
1020 << "uniform int ui_two;"
1023 << " mediump float a;"
1024 << " mediump vec3 b;"
1028 << "void main (void)"
1030 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1031 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1032 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1033 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1034 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1035 << " if (a == b) ${DST}.x = 1.0;"
1036 << " if (a == c) ${DST}.y = 1.0;"
1037 << " if (a == d) ${DST}.z = 1.0;"
1041 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1043 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1047 LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality", 0,
1049 << "${DECLARATIONS}"
1050 << "uniform int ui_one;"
1051 << "uniform int ui_two;"
1054 << " mediump float a;"
1055 << " mediump vec3 b;"
1059 << "void main (void)"
1061 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1062 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1063 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1064 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1065 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1066 << " if (a != b) ${DST}.x = 1.0;"
1067 << " if (a != c) ${DST}.y = 1.0;"
1068 << " if (a != d) ${DST}.z = 1.0;"
1072 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1074 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1079 LOCAL_STRUCT_CASE(nested_equal, "Nested struct struct equality", 0,
1081 << "${DECLARATIONS}"
1082 << "uniform int ui_one;"
1083 << "uniform int ui_two;"
1086 << " mediump vec3 a;"
1090 << " mediump float a;"
1095 << "void main (void)"
1097 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1098 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1099 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1100 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1101 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1102 << " if (a == b) ${DST}.x = 1.0;"
1103 << " if (a == c) ${DST}.y = 1.0;"
1104 << " if (a == d) ${DST}.z = 1.0;"
1108 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0]+0.5f))
1110 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1]+0.5f))
1114 LOCAL_STRUCT_CASE(nested_not_equal, "Nested struct struct equality", 0,
1116 << "${DECLARATIONS}"
1117 << "uniform int ui_one;"
1118 << "uniform int ui_two;"
1121 << " mediump vec3 a;"
1125 << " mediump float a;"
1130 << "void main (void)"
1132 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1133 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1134 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1135 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1136 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1137 << " if (a != b) ${DST}.x = 1.0;"
1138 << " if (a != c) ${DST}.y = 1.0;"
1139 << " if (a != d) ${DST}.z = 1.0;"
1143 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0]+0.5f))
1145 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1]+0.5f))
1151 class UniformStructTests : public TestCaseGroup
1154 UniformStructTests (Context& context)
1155 : TestCaseGroup(context, "uniform", "Uniform structs")
1159 ~UniformStructTests (void)
1163 virtual void init (void);
1169 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + (NAME)).c_str())
1171 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \
1172 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \
1174 int loc = gl.getUniformLocation(programID, name); \
1175 SETUNIFORM(loc, 1, vec.getPtr()); \
1176 CHECK_SET_UNIFORM(name); \
1178 struct SetUniform##VECTYPE##Dummy_s { int unused; }
1180 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM) \
1181 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, int arraySize) \
1183 int loc = gl.getUniformLocation(programID, name); \
1184 SETUNIFORM(loc, arraySize, vec->getPtr()); \
1185 CHECK_SET_UNIFORM(name); \
1187 struct SetUniformPtr##VECTYPE##Dummy_s { int unused; }
1189 MAKE_SET_VEC_UNIFORM (Vec2, gl.uniform2fv);
1190 MAKE_SET_VEC_UNIFORM (Vec3, gl.uniform3fv);
1191 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv);
1193 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, float value)
1195 int loc = gl.getUniformLocation(programID, name);
1196 gl.uniform1f(loc, value);
1197 CHECK_SET_UNIFORM(name);
1200 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, int value)
1202 int loc = gl.getUniformLocation(programID, name);
1203 gl.uniform1i(loc, value);
1204 CHECK_SET_UNIFORM(name);
1207 void setUniform (const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize)
1209 int loc = gl.getUniformLocation(programID, name);
1210 gl.uniform1fv(loc, arraySize, value);
1211 CHECK_SET_UNIFORM(name);
1216 void UniformStructTests::init (void)
1218 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, FLAGS, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1220 struct SetUniforms_##NAME { \
1221 static void setUniforms (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY /* NOLINT(SET_UNIFORMS_BODY) */ \
1223 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \
1224 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, FLAGS, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1225 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, FLAGS, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1226 } while (deGetFalse())
1228 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", 0,
1230 << "${DECLARATIONS}"
1231 << "uniform int ui_one;"
1234 << " mediump float a;"
1235 << " mediump vec3 b;"
1240 << "void main (void)"
1242 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1246 setUniform(gl, programID, "s.a", constCoords.x());
1247 setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1248 setUniform(gl, programID, "s.c", 1);
1251 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1254 UNIFORM_STRUCT_CASE(nested, "Nested struct", 0,
1256 << "${DECLARATIONS}"
1257 << "uniform int ui_zero;"
1258 << "uniform int ui_one;"
1262 << " mediump vec2 b;"
1265 << " mediump float a;"
1271 << "void main (void)"
1273 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1277 setUniform(gl, programID, "s.a", constCoords.x());
1278 setUniform(gl, programID, "s.b.a", 0);
1279 setUniform(gl, programID, "s.b.b", constCoords.swizzle(1,2));
1280 setUniform(gl, programID, "s.c", 1);
1283 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1286 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", 0,
1288 << "${DECLARATIONS}"
1289 << "uniform int ui_one;"
1292 << " mediump float a;"
1293 << " mediump float b[3];"
1298 << "void main (void)"
1300 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1304 setUniform(gl, programID, "s.a", constCoords.w());
1305 setUniform(gl, programID, "s.c", 1);
1308 b[0] = constCoords.z();
1309 b[1] = constCoords.y();
1310 b[2] = constCoords.x();
1311 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1314 c.color.xyz() = c.constCoords.swizzle(3,2,1);
1317 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1319 << "${DECLARATIONS}"
1320 << "uniform int ui_zero;"
1321 << "uniform int ui_one;"
1322 << "uniform int ui_two;"
1325 << " mediump float a;"
1326 << " mediump float b[3];"
1331 << "void main (void)"
1333 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1337 setUniform(gl, programID, "s.a", constCoords.w());
1338 setUniform(gl, programID, "s.c", 1);
1341 b[0] = constCoords.z();
1342 b[1] = constCoords.y();
1343 b[2] = constCoords.x();
1344 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1347 c.color.xyz() = c.constCoords.swizzle(1,2,0);
1350 UNIFORM_STRUCT_CASE(struct_array, "Struct array", 0,
1352 << "${DECLARATIONS}"
1353 << "uniform int ui_zero;"
1354 << "uniform int ui_one;"
1355 << "uniform int ui_two;"
1358 << " mediump float a;"
1359 << " mediump int b;"
1361 << "uniform S s[3];"
1363 << "void main (void)"
1365 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1369 setUniform(gl, programID, "s[0].a", constCoords.x());
1370 setUniform(gl, programID, "s[0].b", 0);
1371 setUniform(gl, programID, "s[1].a", constCoords.y());
1372 setUniform(gl, programID, "s[1].b", 1);
1373 setUniform(gl, programID, "s[2].a", constCoords.z());
1374 setUniform(gl, programID, "s[2].b", 2);
1377 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1380 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1382 << "${DECLARATIONS}"
1383 << "uniform int ui_zero;"
1384 << "uniform int ui_one;"
1385 << "uniform int ui_two;"
1388 << " mediump float a;"
1389 << " mediump int b;"
1391 << "uniform S s[3];"
1393 << "void main (void)"
1395 << " ${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);"
1399 setUniform(gl, programID, "s[0].a", constCoords.x());
1400 setUniform(gl, programID, "s[0].b", 0);
1401 setUniform(gl, programID, "s[1].a", constCoords.y());
1402 setUniform(gl, programID, "s[1].b", 1);
1403 setUniform(gl, programID, "s[2].a", constCoords.z());
1404 setUniform(gl, programID, "s[2].b", 2);
1407 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1410 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", 0,
1412 << "${DECLARATIONS}"
1414 << " mediump float a;"
1415 << " mediump vec2 b[2];"
1418 << " mediump float a;"
1422 << "uniform S s[2];"
1424 << "void main (void)"
1426 << " 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"
1427 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1428 << " 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"
1429 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1430 << " ${DST} = vec4(r, g, b, a);"
1436 setUniform(gl, programID, "s[0].a", constCoords.x());
1437 arr[0] = constCoords.swizzle(0,1);
1438 arr[1] = constCoords.swizzle(2,3);
1439 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1440 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1441 arr[0] = constCoords.swizzle(2,3);
1442 arr[1] = constCoords.swizzle(0,1);
1443 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1444 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1445 arr[0] = constCoords.swizzle(0,2);
1446 arr[1] = constCoords.swizzle(1,3);
1447 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1448 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1449 setUniform(gl, programID, "s[0].c", 0);
1451 setUniform(gl, programID, "s[1].a", constCoords.w());
1452 arr[0] = constCoords.swizzle(0,0);
1453 arr[1] = constCoords.swizzle(1,1);
1454 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1455 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1456 arr[0] = constCoords.swizzle(2,2);
1457 arr[1] = constCoords.swizzle(3,3);
1458 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1459 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1460 arr[0] = constCoords.swizzle(1,0);
1461 arr[1] = constCoords.swizzle(3,2);
1462 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1463 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1464 setUniform(gl, programID, "s[1].c", 1);
1467 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1470 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1472 << "${DECLARATIONS}"
1473 << "uniform int ui_zero;"
1474 << "uniform int ui_one;"
1475 << "uniform int ui_two;"
1478 << " mediump float a;"
1479 << " mediump vec2 b[2];"
1482 << " mediump float a;"
1486 << "uniform S s[2];"
1488 << "void main (void)"
1490 << " 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"
1491 << " 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"
1492 << " 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"
1493 << " 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"
1494 << " ${DST} = vec4(r, g, b, a);"
1500 setUniform(gl, programID, "s[0].a", constCoords.x());
1501 arr[0] = constCoords.swizzle(0,1);
1502 arr[1] = constCoords.swizzle(2,3);
1503 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1504 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1505 arr[0] = constCoords.swizzle(2,3);
1506 arr[1] = constCoords.swizzle(0,1);
1507 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1508 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1509 arr[0] = constCoords.swizzle(0,2);
1510 arr[1] = constCoords.swizzle(1,3);
1511 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1512 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1513 setUniform(gl, programID, "s[0].c", 0);
1515 setUniform(gl, programID, "s[1].a", constCoords.w());
1516 arr[0] = constCoords.swizzle(0,0);
1517 arr[1] = constCoords.swizzle(1,1);
1518 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1519 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1520 arr[0] = constCoords.swizzle(2,2);
1521 arr[1] = constCoords.swizzle(3,3);
1522 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1523 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1524 arr[0] = constCoords.swizzle(1,0);
1525 arr[1] = constCoords.swizzle(3,2);
1526 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1527 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1528 setUniform(gl, programID, "s[1].c", 1);
1531 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1534 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 0,
1536 << "${DECLARATIONS}"
1537 << "uniform int ui_zero;"
1538 << "uniform int ui_one;"
1539 << "uniform int ui_two;"
1542 << " mediump float a;"
1543 << " mediump int b;"
1545 << "uniform S s[3];"
1547 << "void main (void)"
1549 << " mediump float rgb[3];"
1550 << " int alpha = 0;"
1551 << " for (int i = 0; i < 3; i++)"
1553 << " rgb[i] = s[2-i].a;"
1554 << " alpha += s[i].b;"
1556 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1560 setUniform(gl, programID, "s[0].a", constCoords.x());
1561 setUniform(gl, programID, "s[0].b", 0);
1562 setUniform(gl, programID, "s[1].a", constCoords.y());
1563 setUniform(gl, programID, "s[1].b", -1);
1564 setUniform(gl, programID, "s[2].a", constCoords.z());
1565 setUniform(gl, programID, "s[2].b", 2);
1568 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1571 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 0,
1573 << "${DECLARATIONS}"
1574 << "uniform int ui_zero;"
1575 << "uniform int ui_one;"
1576 << "uniform int ui_two;"
1577 << "uniform mediump float uf_two;"
1578 << "uniform mediump float uf_three;"
1579 << "uniform mediump float uf_four;"
1580 << "uniform mediump float uf_half;"
1581 << "uniform mediump float uf_third;"
1582 << "uniform mediump float uf_fourth;"
1583 << "uniform mediump float uf_sixth;"
1586 << " mediump float a;"
1587 << " mediump vec2 b[2];"
1590 << " mediump float a;"
1594 << "uniform S s[2];"
1596 << "void main (void)"
1598 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1599 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1600 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1601 << " mediump float a = 1.0;"
1602 << " for (int i = 0; i < 2; i++)"
1604 << " for (int j = 0; j < 3; j++)"
1606 << " r += s[0].b[j].b[i].y;"
1607 << " g += s[i].b[j].b[0].x;"
1608 << " b += s[i].b[j].b[1].x;"
1609 << " a *= s[i].b[j].a;"
1612 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1618 setUniform(gl, programID, "s[0].a", constCoords.x());
1619 arr[0] = constCoords.swizzle(1,0);
1620 arr[1] = constCoords.swizzle(2,0);
1621 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1622 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1623 arr[0] = constCoords.swizzle(1,1);
1624 arr[1] = constCoords.swizzle(3,1);
1625 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1626 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1627 arr[0] = constCoords.swizzle(2,1);
1628 arr[1] = constCoords.swizzle(2,1);
1629 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1630 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1631 setUniform(gl, programID, "s[0].c", 0);
1633 setUniform(gl, programID, "s[1].a", constCoords.w());
1634 arr[0] = constCoords.swizzle(2,0);
1635 arr[1] = constCoords.swizzle(2,1);
1636 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1637 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1638 arr[0] = constCoords.swizzle(2,2);
1639 arr[1] = constCoords.swizzle(3,3);
1640 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1641 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1642 arr[0] = constCoords.swizzle(1,0);
1643 arr[1] = constCoords.swizzle(3,2);
1644 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1645 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1646 setUniform(gl, programID, "s[1].c", 1);
1649 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1652 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
1654 << "${DECLARATIONS}"
1655 << "uniform int ui_zero;"
1656 << "uniform int ui_one;"
1657 << "uniform int ui_two;"
1658 << "uniform int ui_three;"
1661 << " mediump float a;"
1662 << " mediump int b;"
1664 << "uniform S s[3];"
1666 << "void main (void)"
1668 << " mediump float rgb[3];"
1669 << " int alpha = 0;"
1670 << " for (int i = 0; i < ui_three; i++)"
1672 << " rgb[i] = s[2-i].a;"
1673 << " alpha += s[i].b;"
1675 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1679 setUniform(gl, programID, "s[0].a", constCoords.x());
1680 setUniform(gl, programID, "s[0].b", 0);
1681 setUniform(gl, programID, "s[1].a", constCoords.y());
1682 setUniform(gl, programID, "s[1].b", -1);
1683 setUniform(gl, programID, "s[2].a", constCoords.z());
1684 setUniform(gl, programID, "s[2].b", 2);
1687 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1690 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
1692 << "${DECLARATIONS}"
1693 << "uniform int ui_zero;"
1694 << "uniform int ui_one;"
1695 << "uniform int ui_two;"
1696 << "uniform int ui_three;"
1697 << "uniform mediump float uf_two;"
1698 << "uniform mediump float uf_three;"
1699 << "uniform mediump float uf_four;"
1700 << "uniform mediump float uf_half;"
1701 << "uniform mediump float uf_third;"
1702 << "uniform mediump float uf_fourth;"
1703 << "uniform mediump float uf_sixth;"
1706 << " mediump float a;"
1707 << " mediump vec2 b[2];"
1710 << " mediump float a;"
1714 << "uniform S s[2];"
1716 << "void main (void)"
1718 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1719 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1720 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1721 << " mediump float a = 1.0;"
1722 << " for (int i = 0; i < ui_two; i++)"
1724 << " for (int j = 0; j < ui_three; j++)"
1726 << " r += s[0].b[j].b[i].y;"
1727 << " g += s[i].b[j].b[0].x;"
1728 << " b += s[i].b[j].b[1].x;"
1729 << " a *= s[i].b[j].a;"
1732 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1738 setUniform(gl, programID, "s[0].a", constCoords.x());
1739 arr[0] = constCoords.swizzle(1,0);
1740 arr[1] = constCoords.swizzle(2,0);
1741 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1742 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1743 arr[0] = constCoords.swizzle(1,1);
1744 arr[1] = constCoords.swizzle(3,1);
1745 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1746 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1747 arr[0] = constCoords.swizzle(2,1);
1748 arr[1] = constCoords.swizzle(2,1);
1749 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1750 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1751 setUniform(gl, programID, "s[0].c", 0);
1753 setUniform(gl, programID, "s[1].a", constCoords.w());
1754 arr[0] = constCoords.swizzle(2,0);
1755 arr[1] = constCoords.swizzle(2,1);
1756 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1757 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1758 arr[0] = constCoords.swizzle(2,2);
1759 arr[1] = constCoords.swizzle(3,3);
1760 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1761 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1762 arr[0] = constCoords.swizzle(1,0);
1763 arr[1] = constCoords.swizzle(3,2);
1764 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1765 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1766 setUniform(gl, programID, "s[1].c", 1);
1769 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1772 UNIFORM_STRUCT_CASE(sampler, "Sampler in struct", FLAG_USES_TEXTURES,
1774 << "${DECLARATIONS}"
1775 << "uniform int ui_one;"
1778 << " mediump float a;"
1779 << " mediump vec3 b;"
1784 << "void main (void)"
1786 << " ${DST} = vec4(texture2D(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1790 DE_UNREF(constCoords);
1791 setUniform(gl, programID, "s.a", 1.0f);
1792 setUniform(gl, programID, "s.b", tcu::Vec3(0.25f, 0.25f, 0.5f));
1793 setUniform(gl, programID, "s.c", 0);
1796 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1799 UNIFORM_STRUCT_CASE(sampler_nested, "Sampler in nested struct", FLAG_USES_TEXTURES,
1801 << "${DECLARATIONS}"
1802 << "uniform int ui_zero;"
1803 << "uniform int ui_one;"
1807 << " mediump vec2 b;"
1810 << " mediump float a;"
1816 << "void main (void)"
1818 << " ${DST} = vec4(texture2D(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1822 DE_UNREF(constCoords);
1823 setUniform(gl, programID, "s.a", 0.5f);
1824 setUniform(gl, programID, "s.b.a", 0);
1825 setUniform(gl, programID, "s.b.b", tcu::Vec2(0.25f, 0.25f));
1826 setUniform(gl, programID, "s.c", 1);
1829 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1832 UNIFORM_STRUCT_CASE(sampler_array, "Sampler in struct array", FLAG_USES_TEXTURES,
1834 << "${DECLARATIONS}"
1835 << "uniform int ui_one;"
1838 << " mediump float a;"
1839 << " mediump vec3 b;"
1842 << "uniform S s[2];"
1844 << "void main (void)"
1846 << " ${DST} = vec4(texture2D(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1850 DE_UNREF(constCoords);
1851 setUniform(gl, programID, "s[0].a", 1.0f);
1852 setUniform(gl, programID, "s[0].b", tcu::Vec3(0.25f, 0.25f, 0.25f));
1853 setUniform(gl, programID, "s[0].c", 1);
1854 setUniform(gl, programID, "s[1].a", 0.0f);
1855 setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.5f));
1856 setUniform(gl, programID, "s[1].c", 0);
1859 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1862 UNIFORM_STRUCT_CASE(equal, "Struct equality", 0,
1864 << "${DECLARATIONS}"
1865 << "uniform mediump float uf_one;"
1866 << "uniform int ui_two;"
1869 << " mediump float a;"
1870 << " mediump vec3 b;"
1877 << "void main (void)"
1879 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1880 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1881 << " if (a == b) ${DST}.x = 1.0;"
1882 << " if (a == c) ${DST}.y = 1.0;"
1883 << " if (a == d) ${DST}.z = 1.0;"
1887 DE_UNREF(constCoords);
1888 setUniform(gl, programID, "a.a", 1.0f);
1889 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1890 setUniform(gl, programID, "a.c", 2);
1891 setUniform(gl, programID, "b.a", 1.0f);
1892 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1893 setUniform(gl, programID, "b.c", 2);
1894 setUniform(gl, programID, "c.a", 1.0f);
1895 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1896 setUniform(gl, programID, "c.c", 2);
1899 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
1900 if (deFloatFloor(c.coords[1]+1.0f) == deFloatFloor(1.1f))
1904 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", 0,
1906 << "${DECLARATIONS}"
1907 << "uniform mediump float uf_one;"
1908 << "uniform int ui_two;"
1911 << " mediump float a;"
1912 << " mediump vec3 b;"
1919 << "void main (void)"
1921 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1922 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1923 << " if (a != b) ${DST}.x = 1.0;"
1924 << " if (a != c) ${DST}.y = 1.0;"
1925 << " if (a != d) ${DST}.z = 1.0;"
1929 DE_UNREF(constCoords);
1930 setUniform(gl, programID, "a.a", 1.0f);
1931 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1932 setUniform(gl, programID, "a.c", 2);
1933 setUniform(gl, programID, "b.a", 1.0f);
1934 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1935 setUniform(gl, programID, "b.c", 2);
1936 setUniform(gl, programID, "c.a", 1.0f);
1937 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1938 setUniform(gl, programID, "c.c", 2);
1941 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
1942 if (deFloatFloor(c.coords[1]+1.0f) != deFloatFloor(1.1f))
1947 ShaderStructTests::ShaderStructTests (Context& context)
1948 : TestCaseGroup(context, "struct", "Struct Tests")
1952 ShaderStructTests::~ShaderStructTests (void)
1956 void ShaderStructTests::init (void)
1958 addChild(new LocalStructTests(m_context));
1959 addChild(new UniformStructTests(m_context));