1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Shader struct tests.
24 *//*--------------------------------------------------------------------*/
26 #include "vktShaderRenderStructTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "tcuStringTemplate.hpp"
38 class ShaderStructCase : public ShaderRenderCase
41 ShaderStructCase (tcu::TestContext& testCtx,
42 const std::string& name,
43 const std::string& description,
45 ShaderEvalFunc evalFunc,
46 UniformSetupFunc setupUniformsFunc,
47 const std::string& vertShaderSource,
48 const std::string& fragShaderSource);
49 ~ShaderStructCase (void);
52 ShaderStructCase (const ShaderStructCase&);
53 ShaderStructCase& operator= (const ShaderStructCase&);
56 ShaderStructCase::ShaderStructCase (tcu::TestContext& testCtx,
57 const std::string& name,
58 const std::string& description,
60 ShaderEvalFunc evalFunc,
61 UniformSetupFunc setupUniformsFunc,
62 const std::string& vertShaderSource,
63 const std::string& fragShaderSource)
64 : ShaderRenderCase (testCtx, name, description, isVertexCase, evalFunc, new UniformSetup(setupUniformsFunc), DE_NULL)
66 m_vertShaderSource = vertShaderSource;
67 m_fragShaderSource = fragShaderSource;
70 ShaderStructCase::~ShaderStructCase (void)
74 static de::MovePtr<ShaderStructCase> createStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool isVertexCase, ShaderEvalFunc evalFunc, UniformSetupFunc uniformFunc, const LineStream& shaderSrc)
76 static std::string defaultVertSrc =
78 "layout(location = 0) in highp vec4 a_position;\n"
79 "layout(location = 1) in highp vec4 a_coords;\n"
80 "layout(location = 0) out mediump vec4 v_coords;\n\n"
83 " v_coords = a_coords;\n"
84 " gl_Position = a_position;\n"
86 static std::string defaultFragSrc =
88 "layout(location = 0) in mediump vec4 v_color;\n"
89 "layout(location = 0) out mediump vec4 o_color;\n\n"
92 " o_color = v_color;\n"
95 // Fill in specialization parameters and build the shader source.
98 std::map<std::string, std::string> spParams;
104 "layout(location = 0) in highp vec4 a_position;\n"
105 "layout(location = 1) in highp vec4 a_coords;\n"
106 "layout(location = 0) out mediump vec4 v_color;";
107 spParams["COORDS"] = "a_coords";
108 spParams["DST"] = "v_color";
109 spParams["ASSIGN_POS"] = "gl_Position = a_position;";
111 vertSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams);
112 fragSrc = defaultFragSrc;
118 "layout(location = 0) in mediump vec4 v_coords;\n"
119 "layout(location = 0) out mediump vec4 o_color;";
120 spParams["COORDS"] = "v_coords";
121 spParams["DST"] = "o_color";
122 spParams["ASSIGN_POS"] = "";
124 vertSrc = defaultVertSrc;
125 fragSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams);
128 return de::MovePtr<ShaderStructCase>(new ShaderStructCase(testCtx, name, description, isVertexCase, evalFunc, uniformFunc, vertSrc, fragSrc));
131 class LocalStructTests : public tcu::TestCaseGroup
134 LocalStructTests (tcu::TestContext& testCtx)
135 : TestCaseGroup(testCtx, "local", "Local structs")
139 ~LocalStructTests (void)
143 virtual void init (void);
146 void LocalStructTests::init (void)
148 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
150 struct SetUniforms_##NAME { static void setUniforms (ShaderRenderCaseInstance& instance, const tcu::Vec4&) SET_UNIFORMS_BODY }; \
151 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \
152 addChild(createStructCase(m_testCtx, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, &SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \
153 addChild(createStructCase(m_testCtx, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, &SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \
154 } while (deGetFalse())
156 LOCAL_STRUCT_CASE(basic, "Basic struct usage",
159 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
162 << " mediump float a;"
163 << " mediump vec3 b;"
167 << "void main (void)"
169 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
170 << " s.b = ${COORDS}.yzw;"
171 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
175 instance.useUniform(0u, UI_ONE);
178 c.color.xyz() = c.coords.swizzle(0, 1, 2);
181 LOCAL_STRUCT_CASE(nested, "Nested struct",
184 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
185 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
189 << " mediump vec2 b;"
192 << " mediump float a;"
197 << "void main (void)"
199 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
200 << " s.b = T(ui_zero, ${COORDS}.yz);"
201 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
205 instance.useUniform(0u, UI_ZERO);
206 instance.useUniform(1u, UI_ONE);
209 c.color.xyz() = c.coords.swizzle(0, 1, 2);
212 LOCAL_STRUCT_CASE(array_member, "Struct with array member",
215 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
218 << " mediump float a;"
219 << " mediump float b[3];"
223 << "void main (void)"
226 << " s.a = ${COORDS}.w;"
228 << " s.b[0] = ${COORDS}.z;"
229 << " s.b[1] = ${COORDS}.y;"
230 << " s.b[2] = ${COORDS}.x;"
231 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
235 instance.useUniform(0u, UI_ONE);
238 c.color.xyz() = c.coords.swizzle(3, 2, 1);
241 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
244 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
245 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
246 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
249 << " mediump float a;"
250 << " mediump float b[3];"
254 << "void main (void)"
257 << " s.a = ${COORDS}.w;"
259 << " s.b[0] = ${COORDS}.z;"
260 << " s.b[1] = ${COORDS}.y;"
261 << " s.b[2] = ${COORDS}.x;"
262 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
266 instance.useUniform(0u, UI_ZERO);
267 instance.useUniform(1u, UI_ONE);
268 instance.useUniform(2u, UI_TWO);
271 c.color.xyz() = c.coords.swizzle(1,2,0);
274 LOCAL_STRUCT_CASE(struct_array, "Struct array",
277 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
278 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
279 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
282 << " mediump float a;"
286 << "void main (void)"
289 << " s[0] = S(${COORDS}.x, ui_zero);"
290 << " s[1].a = ${COORDS}.y;"
291 << " s[1].b = ui_one;"
292 << " s[2] = S(${COORDS}.z, ui_two);"
293 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
297 instance.useUniform(0u, UI_ZERO);
298 instance.useUniform(1u, UI_ONE);
299 instance.useUniform(2u, UI_TWO);
302 c.color.xyz() = c.coords.swizzle(2, 1, 0);
305 LOCAL_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing",
308 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
309 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
310 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
313 << " mediump float a;"
317 << "void main (void)"
320 << " s[0] = S(${COORDS}.x, ui_zero);"
321 << " s[1].a = ${COORDS}.y;"
322 << " s[1].b = ui_one;"
323 << " s[2] = S(${COORDS}.z, ui_two);"
324 << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);"
328 instance.useUniform(0u, UI_ZERO);
329 instance.useUniform(1u, UI_ONE);
330 instance.useUniform(2u, UI_TWO);
333 c.color.xyz() = c.coords.swizzle(2, 1, 0);
336 LOCAL_STRUCT_CASE(nested_struct_array, "Nested struct array",
339 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
340 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
341 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
342 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
343 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
344 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
345 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
346 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
347 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
350 << " mediump float a;"
351 << " mediump vec2 b[2];"
354 << " mediump float a;"
359 << "void main (void)"
364 << " s[0].a = ${COORDS}.x;"
365 << " s[0].b[0].a = uf_half;"
366 << " s[0].b[0].b[0] = ${COORDS}.xy;"
367 << " s[0].b[0].b[1] = ${COORDS}.zw;"
368 << " s[0].b[1].a = uf_third;"
369 << " s[0].b[1].b[0] = ${COORDS}.zw;"
370 << " s[0].b[1].b[1] = ${COORDS}.xy;"
371 << " s[0].b[2].a = uf_fourth;"
372 << " s[0].b[2].b[0] = ${COORDS}.xz;"
373 << " s[0].b[2].b[1] = ${COORDS}.yw;"
374 << " s[0].c = ui_zero;"
377 << " s[1].a = ${COORDS}.w;"
378 << " s[1].b[0].a = uf_two;"
379 << " s[1].b[0].b[0] = ${COORDS}.xx;"
380 << " s[1].b[0].b[1] = ${COORDS}.yy;"
381 << " s[1].b[1].a = uf_three;"
382 << " s[1].b[1].b[0] = ${COORDS}.zz;"
383 << " s[1].b[1].b[1] = ${COORDS}.ww;"
384 << " s[1].b[2].a = uf_four;"
385 << " s[1].b[2].b[0] = ${COORDS}.yx;"
386 << " s[1].b[2].b[1] = ${COORDS}.wz;"
387 << " s[1].c = ui_one;"
389 << " 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"
390 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
391 << " 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"
392 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
393 << " ${DST} = vec4(r, g, b, a);"
397 instance.useUniform(0u, UI_ZERO);
398 instance.useUniform(1u, UI_ONE);
399 instance.useUniform(2u, UI_TWO);
400 instance.useUniform(3u, UF_TWO);
401 instance.useUniform(4u, UF_THREE);
402 instance.useUniform(5u, UF_FOUR);
403 instance.useUniform(6u, UF_HALF);
404 instance.useUniform(7u, UF_THIRD);
405 instance.useUniform(8u, UF_FOURTH);
408 c.color.xyz() = c.coords.swizzle(2, 0, 3);
411 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
414 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
415 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
416 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
417 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
418 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
419 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
420 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
421 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
422 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
425 << " mediump float a;"
426 << " mediump vec2 b[2];"
429 << " mediump float a;"
434 << "void main (void)"
439 << " s[0].a = ${COORDS}.x;"
440 << " s[0].b[0].a = uf_half;"
441 << " s[0].b[0].b[0] = ${COORDS}.xy;"
442 << " s[0].b[0].b[1] = ${COORDS}.zw;"
443 << " s[0].b[1].a = uf_third;"
444 << " s[0].b[1].b[0] = ${COORDS}.zw;"
445 << " s[0].b[1].b[1] = ${COORDS}.xy;"
446 << " s[0].b[2].a = uf_fourth;"
447 << " s[0].b[2].b[0] = ${COORDS}.xz;"
448 << " s[0].b[2].b[1] = ${COORDS}.yw;"
449 << " s[0].c = ui_zero;"
452 << " s[1].a = ${COORDS}.w;"
453 << " s[1].b[0].a = uf_two;"
454 << " s[1].b[0].b[0] = ${COORDS}.xx;"
455 << " s[1].b[0].b[1] = ${COORDS}.yy;"
456 << " s[1].b[1].a = uf_three;"
457 << " s[1].b[1].b[0] = ${COORDS}.zz;"
458 << " s[1].b[1].b[1] = ${COORDS}.ww;"
459 << " s[1].b[2].a = uf_four;"
460 << " s[1].b[2].b[0] = ${COORDS}.yx;"
461 << " s[1].b[2].b[1] = ${COORDS}.wz;"
462 << " s[1].c = ui_one;"
464 << " 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"
465 << " 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"
466 << " 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"
467 << " 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"
468 << " ${DST} = vec4(r, g, b, a);"
472 instance.useUniform(0u, UI_ZERO);
473 instance.useUniform(1u, UI_ONE);
474 instance.useUniform(2u, UI_TWO);
475 instance.useUniform(3u, UF_TWO);
476 instance.useUniform(4u, UF_THREE);
477 instance.useUniform(5u, UF_FOUR);
478 instance.useUniform(6u, UF_HALF);
479 instance.useUniform(7u, UF_THIRD);
480 instance.useUniform(8u, UF_FOURTH);
483 c.color.xyz() = c.coords.swizzle(2, 0, 3);
486 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
489 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
492 << " mediump float a;"
493 << " mediump vec3 b;"
497 << "mediump vec4 myFunc (S s)"
499 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
502 << "void main (void)"
504 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
505 << " s.b = ${COORDS}.yzw;"
506 << " ${DST} = myFunc(s);"
510 instance.useUniform(0u, UI_ONE);
513 c.color.xyz() = c.coords.swizzle(0, 1, 2);
516 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter",
519 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
520 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
524 << " mediump vec2 b;"
527 << " mediump float a;"
532 << "mediump vec4 myFunc (S s)"
534 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
537 << "void main (void)"
539 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
540 << " s.b = T(ui_zero, ${COORDS}.yz);"
541 << " ${DST} = myFunc(s);"
545 instance.useUniform(0u, UI_ZERO);
546 instance.useUniform(1u, UI_ONE);
549 c.color.xyz() = c.coords.swizzle(0, 1, 2);
552 LOCAL_STRUCT_CASE(return, "Struct as a return value",
555 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
558 << " mediump float a;"
559 << " mediump vec3 b;"
565 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
566 << " s.b = ${COORDS}.yzw;"
570 << "void main (void)"
572 << " S s = myFunc();"
573 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
577 instance.useUniform(0u, UI_ONE);
580 c.color.xyz() = c.coords.swizzle(0, 1, 2);
583 LOCAL_STRUCT_CASE(return_nested, "Nested struct",
586 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
587 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
591 << " mediump vec2 b;"
594 << " mediump float a;"
601 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
602 << " s.b = T(ui_zero, ${COORDS}.yz);"
606 << "void main (void)"
608 << " S s = myFunc();"
609 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
613 instance.useUniform(0u, UI_ZERO);
614 instance.useUniform(1u, UI_ONE);
617 c.color.xyz() = c.coords.swizzle(0, 1, 2);
620 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment",
623 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
624 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
625 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
628 << " mediump float a;"
629 << " mediump vec3 b;"
633 << "void main (void)"
635 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
636 << " if (uf_one > 0.0)"
637 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
638 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
642 instance.useUniform(0u, UI_ZERO);
643 instance.useUniform(1u, UI_ONE);
644 instance.useUniform(2u, UF_ONE);
647 c.color.xyz() = c.coords.swizzle(3, 2, 1);
650 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
653 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
654 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
657 << " mediump float a;"
658 << " mediump vec3 b;"
662 << "void main (void)"
664 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
665 << " for (int i = 0; i < 3; i++)"
668 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
670 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
674 instance.useUniform(0u, UI_ZERO);
675 instance.useUniform(1u, UI_ONE);
678 c.color.xyz() = c.coords.swizzle(3, 2, 1);
681 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop",
684 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
685 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
686 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };"
689 << " mediump float a;"
690 << " mediump vec3 b;"
694 << "void main (void)"
696 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
697 << " for (int i = 0; i < ui_three; i++)"
699 << " if (i == ui_one)"
700 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
702 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
706 instance.useUniform(0u, UI_ZERO);
707 instance.useUniform(1u, UI_ONE);
708 instance.useUniform(2u, UI_THREE);
711 c.color.xyz() = c.coords.swizzle(3, 2, 1);
714 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct",
717 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
718 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
719 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
723 << " mediump vec2 b;"
726 << " mediump float a;"
731 << "void main (void)"
733 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
734 << " if (uf_one > 0.0)"
735 << " s.b = T(ui_zero, ${COORDS}.zw);"
736 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
740 instance.useUniform(0u, UI_ZERO);
741 instance.useUniform(1u, UI_ONE);
742 instance.useUniform(2u, UF_ONE);
745 c.color.xyz() = c.coords.swizzle(0, 2, 3);
748 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop",
751 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
752 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
753 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
757 << " mediump vec2 b;"
760 << " mediump float a;"
765 << "void main (void)"
767 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
768 << " for (int i = 0; i < 3; i++)"
771 << " s.b = T(ui_zero, ${COORDS}.zw);"
773 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
777 instance.useUniform(0u, UI_ZERO);
778 instance.useUniform(1u, UI_ONE);
779 instance.useUniform(2u, UF_ONE);
782 c.color.xyz() = c.coords.swizzle(0, 2, 3);
785 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop",
788 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
789 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
790 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };"
791 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_one; };"
795 << " mediump vec2 b;"
798 << " mediump float a;"
803 << "void main (void)"
805 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
806 << " for (int i = 0; i < ui_three; i++)"
808 << " if (i == ui_one)"
809 << " s.b = T(ui_zero, ${COORDS}.zw);"
811 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
815 instance.useUniform(0u, UI_ZERO);
816 instance.useUniform(1u, UI_ONE);
817 instance.useUniform(2u, UI_THREE);
818 instance.useUniform(3u, UF_ONE);
821 c.color.xyz() = c.coords.swizzle(0, 2, 3);
824 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
827 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
828 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
829 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
832 << " mediump float a;"
836 << "void main (void)"
839 << " s[0] = S(${COORDS}.x, ui_zero);"
840 << " s[1].a = ${COORDS}.y;"
841 << " s[1].b = -ui_one;"
842 << " s[2] = S(${COORDS}.z, ui_two);"
844 << " mediump float rgb[3];"
846 << " for (int i = 0; i < 3; i++)"
848 << " rgb[i] = s[2-i].a;"
849 << " alpha += s[i].b;"
851 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
855 instance.useUniform(0u, UI_ZERO);
856 instance.useUniform(1u, UI_ONE);
857 instance.useUniform(2u, UI_TWO);
860 c.color.xyz() = c.coords.swizzle(2, 1, 0);
863 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
866 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
867 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
868 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
869 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
870 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
871 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
872 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
873 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
874 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
875 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };"
878 << " mediump float a;"
879 << " mediump vec2 b[2];"
882 << " mediump float a;"
887 << "void main (void)"
892 << " s[0].a = ${COORDS}.x;"
893 << " s[0].b[0].a = uf_half;"
894 << " s[0].b[0].b[0] = ${COORDS}.yx;"
895 << " s[0].b[0].b[1] = ${COORDS}.zx;"
896 << " s[0].b[1].a = uf_third;"
897 << " s[0].b[1].b[0] = ${COORDS}.yy;"
898 << " s[0].b[1].b[1] = ${COORDS}.wy;"
899 << " s[0].b[2].a = uf_fourth;"
900 << " s[0].b[2].b[0] = ${COORDS}.zx;"
901 << " s[0].b[2].b[1] = ${COORDS}.zy;"
902 << " s[0].c = ui_zero;"
905 << " s[1].a = ${COORDS}.w;"
906 << " s[1].b[0].a = uf_two;"
907 << " s[1].b[0].b[0] = ${COORDS}.zx;"
908 << " s[1].b[0].b[1] = ${COORDS}.zy;"
909 << " s[1].b[1].a = uf_three;"
910 << " s[1].b[1].b[0] = ${COORDS}.zz;"
911 << " s[1].b[1].b[1] = ${COORDS}.ww;"
912 << " s[1].b[2].a = uf_four;"
913 << " s[1].b[2].b[0] = ${COORDS}.yx;"
914 << " s[1].b[2].b[1] = ${COORDS}.wz;"
915 << " s[1].c = ui_one;"
917 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
918 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
919 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
920 << " mediump float a = 1.0;"
921 << " for (int i = 0; i < 2; i++)"
923 << " for (int j = 0; j < 3; j++)"
925 << " r += s[0].b[j].b[i].y;"
926 << " g += s[i].b[j].b[0].x;"
927 << " b += s[i].b[j].b[1].x;"
928 << " a *= s[i].b[j].a;"
931 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
935 instance.useUniform(0u, UI_ZERO);
936 instance.useUniform(1u, UI_ONE);
937 instance.useUniform(2u, UI_TWO);
938 instance.useUniform(3u, UF_TWO);
939 instance.useUniform(4u, UF_THREE);
940 instance.useUniform(5u, UF_FOUR);
941 instance.useUniform(6u, UF_HALF);
942 instance.useUniform(7u, UF_THIRD);
943 instance.useUniform(8u, UF_FOURTH);
944 instance.useUniform(9u, UF_SIXTH);
947 c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f;
950 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
953 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
954 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
955 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
956 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
959 << " mediump float a;"
963 << "void main (void)"
966 << " s[0] = S(${COORDS}.x, ui_zero);"
967 << " s[1].a = ${COORDS}.y;"
968 << " s[1].b = -ui_one;"
969 << " s[2] = S(${COORDS}.z, ui_two);"
971 << " mediump float rgb[3];"
973 << " for (int i = 0; i < ui_three; i++)"
975 << " rgb[i] = s[2-i].a;"
976 << " alpha += s[i].b;"
978 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
982 instance.useUniform(0u, UI_ZERO);
983 instance.useUniform(1u, UI_ONE);
984 instance.useUniform(2u, UI_TWO);
985 instance.useUniform(3u, UI_THREE);
988 c.color.xyz() = c.coords.swizzle(2, 1, 0);
991 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
994 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
995 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
996 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
997 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
998 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };"
999 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };"
1000 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };"
1001 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };"
1002 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };"
1003 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };"
1004 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };"
1007 << " mediump float a;"
1008 << " mediump vec2 b[2];"
1011 << " mediump float a;"
1016 << "void main (void)"
1020 << " s[0].a = ${COORDS}.x;"
1021 << " s[0].b[0].a = uf_half;"
1022 << " s[0].b[0].b[0] = ${COORDS}.yx;"
1023 << " s[0].b[0].b[1] = ${COORDS}.zx;"
1024 << " s[0].b[1].a = uf_third;"
1025 << " s[0].b[1].b[0] = ${COORDS}.yy;"
1026 << " s[0].b[1].b[1] = ${COORDS}.wy;"
1027 << " s[0].b[2].a = uf_fourth;"
1028 << " s[0].b[2].b[0] = ${COORDS}.zx;"
1029 << " s[0].b[2].b[1] = ${COORDS}.zy;"
1030 << " s[0].c = ui_zero;"
1032 << " s[1].a = ${COORDS}.w;"
1033 << " s[1].b[0].a = uf_two;"
1034 << " s[1].b[0].b[0] = ${COORDS}.zx;"
1035 << " s[1].b[0].b[1] = ${COORDS}.zy;"
1036 << " s[1].b[1].a = uf_three;"
1037 << " s[1].b[1].b[0] = ${COORDS}.zz;"
1038 << " s[1].b[1].b[1] = ${COORDS}.ww;"
1039 << " s[1].b[2].a = uf_four;"
1040 << " s[1].b[2].b[0] = ${COORDS}.yx;"
1041 << " s[1].b[2].b[1] = ${COORDS}.wz;"
1042 << " s[1].c = ui_one;"
1044 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1045 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1046 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1047 << " mediump float a = 1.0;"
1048 << " for (int i = 0; i < ui_two; i++)"
1050 << " for (int j = 0; j < ui_three; j++)"
1052 << " r += s[0].b[j].b[i].y;"
1053 << " g += s[i].b[j].b[0].x;"
1054 << " b += s[i].b[j].b[1].x;"
1055 << " a *= s[i].b[j].a;"
1058 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1062 instance.useUniform(0u, UI_ZERO);
1063 instance.useUniform(1u, UI_ONE);
1064 instance.useUniform(2u, UI_TWO);
1065 instance.useUniform(3u, UI_THREE);
1066 instance.useUniform(4u, UF_TWO);
1067 instance.useUniform(5u, UF_THREE);
1068 instance.useUniform(6u, UF_FOUR);
1069 instance.useUniform(7u, UF_HALF);
1070 instance.useUniform(8u, UF_THIRD);
1071 instance.useUniform(9u, UF_FOURTH);
1072 instance.useUniform(10u, UF_SIXTH);
1075 c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f;
1078 LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality",
1081 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1082 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1085 << " mediump float a;"
1086 << " mediump vec3 b;"
1090 << "void main (void)"
1092 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1093 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1094 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1095 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1096 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1097 << " if (a == b) ${DST}.x = 1.0;"
1098 << " if (a == c) ${DST}.y = 1.0;"
1099 << " if (a == d) ${DST}.z = 1.0;"
1103 instance.useUniform(0u, UI_ONE);
1104 instance.useUniform(1u, UI_TWO);
1107 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
1109 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
1113 LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality",
1116 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1117 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1120 << " mediump float a;"
1121 << " mediump vec3 b;"
1125 << "void main (void)"
1127 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1128 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1129 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1130 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1131 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1132 << " if (a != b) ${DST}.x = 1.0;"
1133 << " if (a != c) ${DST}.y = 1.0;"
1134 << " if (a != d) ${DST}.z = 1.0;"
1138 instance.useUniform(0u, UI_ONE);
1139 instance.useUniform(1u, UI_TWO);
1142 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1144 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1149 LOCAL_STRUCT_CASE(nested_equal, "Nested struct struct equality",
1152 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1153 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1156 << " mediump vec3 a;"
1160 << " mediump float a;"
1165 << "void main (void)"
1167 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1168 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1169 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1170 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1171 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1172 << " if (a == b) ${DST}.x = 1.0;"
1173 << " if (a == c) ${DST}.y = 1.0;"
1174 << " if (a == d) ${DST}.z = 1.0;"
1178 instance.useUniform(0u, UI_ONE);
1179 instance.useUniform(1u, UI_TWO);
1182 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
1184 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
1188 LOCAL_STRUCT_CASE(nested_not_equal, "Nested struct struct equality",
1191 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1192 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1195 << " mediump vec3 a;"
1199 << " mediump float a;"
1204 << "void main (void)"
1206 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1207 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1208 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1209 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1210 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1211 << " if (a != b) ${DST}.x = 1.0;"
1212 << " if (a != c) ${DST}.y = 1.0;"
1213 << " if (a != d) ${DST}.z = 1.0;"
1217 instance.useUniform(0u, UI_ONE);
1218 instance.useUniform(1u, UI_TWO);
1221 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1223 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1229 class UniformStructTests : public tcu::TestCaseGroup
1232 UniformStructTests (tcu::TestContext& testCtx)
1233 : TestCaseGroup(testCtx, "uniform", "Uniform structs")
1237 ~UniformStructTests (void)
1241 virtual void init (void);
1244 void UniformStructTests::init (void)
1246 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1248 struct SetUniforms_##NAME { static void setUniforms (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY }; \
1249 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \
1250 addChild(createStructCase(m_testCtx, #NAME "_vertex", DESCRIPTION, true, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \
1251 addChild(createStructCase(m_testCtx, #NAME "_fragment", DESCRIPTION, false, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \
1252 } while (deGetFalse())
1254 UNIFORM_STRUCT_CASE(basic, "Basic struct usage",
1257 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1260 << " mediump float a;"
1261 << " mediump vec3 b;"
1264 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };"
1266 << "void main (void)"
1268 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1272 instance.useUniform(0u, UI_ONE);
1282 s.a = constCoords.x();
1283 s.b = constCoords.swizzle(1, 2, 3);
1285 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1288 c.color.xyz() = c.constCoords.swizzle(0, 1, 2);
1291 UNIFORM_STRUCT_CASE(nested, "Nested struct",
1294 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1295 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1299 << " mediump vec2 b;"
1302 << " mediump float a;"
1306 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S s; };"
1308 << "void main (void)"
1310 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1314 instance.useUniform(0u, UI_ZERO);
1315 instance.useUniform(1u, UI_ONE);
1332 s.a = constCoords.x();
1334 s.b.b = constCoords.swizzle(1, 2);
1336 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s);
1339 c.color.xyz() = c.constCoords.swizzle(0, 1, 2);
1342 UNIFORM_STRUCT_CASE(array_member, "Struct with array member",
1345 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1348 << " mediump float a;"
1349 << " mediump float b[3];"
1352 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };"
1354 << "void main (void)"
1356 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1360 instance.useUniform(0u, UI_ONE);
1362 struct paddedFloat {
1374 s.a.value = constCoords.w();
1375 s.b[0].value = constCoords.z();
1376 s.b[1].value = constCoords.y();
1377 s.b[2].value = constCoords.x();
1379 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s);
1382 c.color.xyz() = c.constCoords.swizzle(3, 2, 1);
1385 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
1388 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1389 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1390 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1393 << " mediump float a;"
1394 << " mediump float b[3];"
1397 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s; };"
1399 << "void main (void)"
1401 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1405 instance.useUniform(0u, UI_ZERO);
1406 instance.useUniform(1u, UI_ONE);
1407 instance.useUniform(2u, UI_TWO);
1409 struct paddedFloat {
1421 s.a.value = constCoords.w();
1422 s.b[0].value = constCoords.z();
1423 s.b[1].value = constCoords.y();
1424 s.b[2].value = constCoords.x();
1426 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1429 c.color.xyz() = c.constCoords.swizzle(1, 2, 0);
1432 UNIFORM_STRUCT_CASE(struct_array, "Struct array",
1435 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1436 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1437 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1440 << " mediump float a;"
1441 << " mediump int b;"
1443 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1445 << "void main (void)"
1447 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1451 instance.useUniform(0u, UI_ZERO);
1452 instance.useUniform(1u, UI_ONE);
1453 instance.useUniform(2u, UI_TWO);
1462 s[0].a = constCoords.x();
1464 s[1].a = constCoords.y();
1466 s[2].a = constCoords.z();
1468 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s);
1471 c.color.xyz() = c.constCoords.swizzle(2, 1, 0);
1474 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing",
1477 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1478 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1479 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1482 << " mediump float a;"
1483 << " mediump int b;"
1485 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1487 << "void main (void)"
1489 << " ${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);"
1493 instance.useUniform(0u, UI_ZERO);
1494 instance.useUniform(1u, UI_ONE);
1495 instance.useUniform(2u, UI_TWO);
1504 s[0].a = constCoords.x();
1506 s[1].a = constCoords.y();
1508 s[2].a = constCoords.z();
1510 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s);
1513 c.color.xyz() = c.constCoords.swizzle(2, 1, 0);
1516 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array",
1520 << " mediump float a;"
1521 << " mediump vec2 b[2];"
1524 << " mediump float a;"
1528 << "layout (std140, set = 0, binding = 0) uniform buffer0 { S s[2]; };"
1530 << "void main (void)"
1532 << " 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"
1533 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1534 << " 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"
1535 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1536 << " ${DST} = vec4(r, g, b, a);"
1556 s[0].a = constCoords.x();
1558 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0);
1559 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0);
1560 s[0].b[1].a = 1.0f / 3.0f;
1561 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0);
1562 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0);
1563 s[0].b[2].a = 1.0f / 4.0f;
1564 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0);
1565 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0);
1568 s[1].a = constCoords.w();
1570 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0);
1571 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0);
1573 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0);
1574 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0);
1576 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0);
1577 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0);
1580 instance.addUniform(0u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1583 c.color.xyz() = c.constCoords.swizzle(2, 0, 3);
1586 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
1589 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1590 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1591 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1594 << " mediump float a;"
1595 << " mediump vec2 b[2];"
1598 << " mediump float a;"
1602 << "layout (set = 0, binding = 3) uniform buffer3 { S s[2]; };"
1604 << "void main (void)"
1606 << " 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"
1607 << " 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"
1608 << " 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"
1609 << " 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"
1610 << " ${DST} = vec4(r, g, b, a);"
1629 s[0].a = constCoords.x();
1631 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0);
1632 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0);
1633 s[0].b[1].a = 1.0f / 3.0f;
1634 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0);
1635 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0);
1636 s[0].b[2].a = 1.0f / 4.0f;
1637 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0);
1638 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0);
1641 s[1].a = constCoords.w();
1643 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0);
1644 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0);
1646 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0);
1647 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0);
1649 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0);
1650 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0);
1653 instance.useUniform(0u, UI_ZERO);
1654 instance.useUniform(1u, UI_ONE);
1655 instance.useUniform(2u, UI_TWO);
1656 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1659 c.color.xyz() = c.constCoords.swizzle(2, 0, 3);
1661 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
1664 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1665 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1666 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1669 << " mediump float a;"
1670 << " mediump int b;"
1672 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1674 << "void main (void)"
1676 << " mediump float rgb[3];"
1677 << " int alpha = 0;"
1678 << " for (int i = 0; i < 3; i++)"
1680 << " rgb[i] = s[2-i].a;"
1681 << " alpha += s[i].b;"
1683 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1687 instance.useUniform(0u, UI_ZERO);
1688 instance.useUniform(1u, UI_ONE);
1689 instance.useUniform(2u, UI_TWO);
1698 s[0].a = constCoords.x();
1700 s[1].a = constCoords.y();
1702 s[2].a = constCoords.z();
1704 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s);
1707 c.color.xyz() = c.constCoords.swizzle(2, 1, 0);
1710 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
1713 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1714 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1715 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1716 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
1717 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
1718 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
1719 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
1720 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
1721 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
1722 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };"
1725 << " mediump float a;"
1726 << " mediump vec2 b[2];"
1729 << " mediump float a;"
1733 << "layout (std140, set = 0, binding = 10) uniform buffer10 { S s[2]; };"
1735 << "void main (void)"
1737 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1738 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1739 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1740 << " mediump float a = 1.0;"
1741 << " for (int i = 0; i < 2; i++)"
1743 << " for (int j = 0; j < 3; j++)"
1745 << " r += s[0].b[j].b[i].y;"
1746 << " g += s[i].b[j].b[0].x;"
1747 << " b += s[i].b[j].b[1].x;"
1748 << " a *= s[i].b[j].a;"
1751 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1755 instance.useUniform(0u, UI_ZERO);
1756 instance.useUniform(1u, UI_ONE);
1757 instance.useUniform(2u, UI_TWO);
1758 instance.useUniform(3u, UF_TWO);
1759 instance.useUniform(4u, UF_THREE);
1760 instance.useUniform(5u, UF_FOUR);
1761 instance.useUniform(6u, UF_HALF);
1762 instance.useUniform(7u, UF_THIRD);
1763 instance.useUniform(8u, UF_FOURTH);
1764 instance.useUniform(9u, UF_SIXTH);
1781 s[0].a = constCoords.x();
1783 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0);
1784 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0);
1785 s[0].b[1].a = 1.0f / 3.0f;
1786 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0);
1787 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0);
1788 s[0].b[2].a = 1.0f / 4.0f;
1789 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0);
1790 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0);
1793 s[1].a = constCoords.w();
1795 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0);
1796 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0);
1798 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0);
1799 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0);
1801 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0);
1802 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0);
1805 instance.addUniform(10u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1809 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f;
1812 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
1815 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1816 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1817 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1818 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
1821 << " mediump float a;"
1822 << " mediump int b;"
1824 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S s[3]; };"
1826 << "void main (void)"
1828 << " mediump float rgb[3];"
1829 << " int alpha = 0;"
1830 << " for (int i = 0; i < ui_three; i++)"
1832 << " rgb[i] = s[2-i].a;"
1833 << " alpha += s[i].b;"
1835 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1839 instance.useUniform(0u, UI_ZERO);
1840 instance.useUniform(1u, UI_ONE);
1841 instance.useUniform(2u, UI_TWO);
1842 instance.useUniform(3u, UI_THREE);
1851 s[0].a = constCoords.x();
1853 s[1].a = constCoords.y();
1855 s[2].a = constCoords.z();
1857 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s);
1861 c.color.xyz() = c.constCoords.swizzle(2, 1, 0);
1864 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
1867 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1868 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1869 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1870 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
1871 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };"
1872 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };"
1873 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };"
1874 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };"
1875 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };"
1876 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };"
1877 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };"
1880 << " mediump float a;"
1881 << " mediump vec2 b[2];"
1884 << " mediump float a;"
1888 << "layout (std140, set = 0, binding = 11) uniform buffer11 { S s[2]; };"
1890 << "void main (void)"
1892 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1893 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1894 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1895 << " mediump float a = 1.0;"
1896 << " for (int i = 0; i < ui_two; i++)"
1898 << " for (int j = 0; j < ui_three; j++)"
1900 << " r += s[0].b[j].b[i].y;"
1901 << " g += s[i].b[j].b[0].x;"
1902 << " b += s[i].b[j].b[1].x;"
1903 << " a *= s[i].b[j].a;"
1906 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1910 instance.useUniform(0u, UI_ZERO);
1911 instance.useUniform(1u, UI_ONE);
1912 instance.useUniform(2u, UI_TWO);
1913 instance.useUniform(3u, UI_THREE);
1914 instance.useUniform(4u, UF_TWO);
1915 instance.useUniform(5u, UF_THREE);
1916 instance.useUniform(6u, UF_FOUR);
1917 instance.useUniform(7u, UF_HALF);
1918 instance.useUniform(8u, UF_THIRD);
1919 instance.useUniform(9u, UF_FOURTH);
1920 instance.useUniform(10u, UF_SIXTH);
1937 s[0].a = constCoords.x();
1939 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0);
1940 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0);
1941 s[0].b[1].a = 1.0f / 3.0f;
1942 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0);
1943 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0);
1944 s[0].b[2].a = 1.0f / 4.0f;
1945 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0);
1946 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0);
1949 s[1].a = constCoords.w();
1951 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0);
1952 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0);
1954 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0);
1955 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0);
1957 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0);
1958 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0);
1961 instance.addUniform(11u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1965 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f;
1968 UNIFORM_STRUCT_CASE(equal, "Struct equality",
1971 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };"
1972 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1975 << " mediump float a;"
1976 << " mediump vec3 b;"
1979 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };"
1980 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };"
1981 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };"
1983 << "void main (void)"
1985 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1986 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1987 << " if (a == b) ${DST}.x = 1.0;"
1988 << " if (a == c) ${DST}.y = 1.0;"
1989 << " if (a == d) ${DST}.z = 1.0;"
1993 DE_UNREF(constCoords);
1994 instance.useUniform(0u, UF_ONE);
1995 instance.useUniform(1u, UI_TWO);
2006 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2008 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa);
2012 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2014 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb);
2018 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f);
2020 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc);
2023 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
2024 if (deFloatFloor(c.coords[1] + 1.0f) == deFloatFloor(1.1f))
2028 UNIFORM_STRUCT_CASE(not_equal, "Struct equality",
2031 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };"
2032 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
2035 << " mediump float a;"
2036 << " mediump vec3 b;"
2039 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };"
2040 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };"
2041 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };"
2043 << "void main (void)"
2045 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
2046 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
2047 << " if (a != b) ${DST}.x = 1.0;"
2048 << " if (a != c) ${DST}.y = 1.0;"
2049 << " if (a != d) ${DST}.z = 1.0;"
2053 DE_UNREF(constCoords);
2054 instance.useUniform(0u, UF_ONE);
2055 instance.useUniform(1u, UI_TWO);
2066 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2068 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa);
2072 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2074 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb);
2078 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f);
2080 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc);
2083 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
2084 if (deFloatFloor(c.coords[1] + 1.0f) != deFloatFloor(1.1f))
2089 class ShaderStructTests : public tcu::TestCaseGroup
2092 ShaderStructTests (tcu::TestContext& context);
2093 virtual ~ShaderStructTests (void);
2095 virtual void init (void);
2098 ShaderStructTests (const ShaderStructTests&); // not allowed!
2099 ShaderStructTests& operator= (const ShaderStructTests&); // not allowed!
2102 ShaderStructTests::ShaderStructTests (tcu::TestContext& testCtx)
2103 : TestCaseGroup(testCtx, "struct", "Struct Tests")
2107 ShaderStructTests::~ShaderStructTests (void)
2111 void ShaderStructTests::init (void)
2113 addChild(new LocalStructTests(m_testCtx));
2114 addChild(new UniformStructTests(m_testCtx));
2119 tcu::TestCaseGroup* createStructTests (tcu::TestContext& testCtx)
2121 return new ShaderStructTests(testCtx);