1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
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
8 *
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
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
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.
20 *
21 *//*!
22 * \file
23 * \brief Shader struct tests.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderStructTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "deMath.h"
30
31 namespace vkt
32 {
33 namespace sr
34 {
35 namespace
36 {
37
38 class ShaderStructCase : public ShaderRenderCase
39 {
40 public:
41 ShaderStructCase(tcu::TestContext &testCtx, const std::string &name, bool isVertexCase, ShaderEvalFunc evalFunc,
42 UniformSetupFunc setupUniformsFunc, const std::string &vertShaderSource,
43 const std::string &fragShaderSource);
44 ~ShaderStructCase(void);
45
46 private:
47 ShaderStructCase(const ShaderStructCase &);
48 ShaderStructCase &operator=(const ShaderStructCase &);
49 };
50
ShaderStructCase(tcu::TestContext & testCtx,const std::string & name,bool isVertexCase,ShaderEvalFunc evalFunc,UniformSetupFunc setupUniformsFunc,const std::string & vertShaderSource,const std::string & fragShaderSource)51 ShaderStructCase::ShaderStructCase(tcu::TestContext &testCtx, const std::string &name, bool isVertexCase,
52 ShaderEvalFunc evalFunc, UniformSetupFunc setupUniformsFunc,
53 const std::string &vertShaderSource, const std::string &fragShaderSource)
54 : ShaderRenderCase(testCtx, name, isVertexCase, evalFunc, new UniformSetup(setupUniformsFunc), DE_NULL)
55 {
56 m_vertShaderSource = vertShaderSource;
57 m_fragShaderSource = fragShaderSource;
58 }
59
~ShaderStructCase(void)60 ShaderStructCase::~ShaderStructCase(void)
61 {
62 }
63
createStructCase(tcu::TestContext & testCtx,const std::string & name,bool isVertexCase,ShaderEvalFunc evalFunc,UniformSetupFunc uniformFunc,const LineStream & shaderSrc)64 static de::MovePtr<ShaderStructCase> createStructCase(tcu::TestContext &testCtx, const std::string &name,
65 bool isVertexCase, ShaderEvalFunc evalFunc,
66 UniformSetupFunc uniformFunc, const LineStream &shaderSrc)
67 {
68 static std::string defaultVertSrc = "#version 310 es\n"
69 "layout(location = 0) in highp vec4 a_position;\n"
70 "layout(location = 1) in highp vec4 a_coords;\n"
71 "layout(location = 0) out mediump vec4 v_coords;\n\n"
72 "void main (void)\n"
73 "{\n"
74 " v_coords = a_coords;\n"
75 " gl_Position = a_position;\n"
76 "}\n";
77 static std::string defaultFragSrc = "#version 310 es\n"
78 "layout(location = 0) in mediump vec4 v_color;\n"
79 "layout(location = 0) out mediump vec4 o_color;\n\n"
80 "void main (void)\n"
81 "{\n"
82 " o_color = v_color;\n"
83 "}\n";
84
85 // Fill in specialization parameters and build the shader source.
86 std::string vertSrc;
87 std::string fragSrc;
88 std::map<std::string, std::string> spParams;
89
90 if (isVertexCase)
91 {
92 spParams["HEADER"] = "#version 310 es\n"
93 "layout(location = 0) in highp vec4 a_position;\n"
94 "layout(location = 1) in highp vec4 a_coords;\n"
95 "layout(location = 0) out mediump vec4 v_color;";
96 spParams["COORDS"] = "a_coords";
97 spParams["DST"] = "v_color";
98 spParams["ASSIGN_POS"] = "gl_Position = a_position;";
99
100 vertSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams);
101 fragSrc = defaultFragSrc;
102 }
103 else
104 {
105 spParams["HEADER"] = "#version 310 es\n"
106 "layout(location = 0) in mediump vec4 v_coords;\n"
107 "layout(location = 0) out mediump vec4 o_color;";
108 spParams["COORDS"] = "v_coords";
109 spParams["DST"] = "o_color";
110 spParams["ASSIGN_POS"] = "";
111
112 vertSrc = defaultVertSrc;
113 fragSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams);
114 }
115
116 return de::MovePtr<ShaderStructCase>(
117 new ShaderStructCase(testCtx, name, isVertexCase, evalFunc, uniformFunc, vertSrc, fragSrc));
118 }
119
120 class LocalStructTests : public tcu::TestCaseGroup
121 {
122 public:
LocalStructTests(tcu::TestContext & testCtx)123 LocalStructTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "local")
124 {
125 }
126
~LocalStructTests(void)127 ~LocalStructTests(void)
128 {
129 }
130
131 virtual void init(void);
132 };
133
init(void)134 void LocalStructTests::init(void)
135 {
136 #define LOCAL_STRUCT_CASE(NAME, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
137 do \
138 { \
139 struct SetUniforms_##NAME \
140 { \
141 static void setUniforms(ShaderRenderCaseInstance &instance, const tcu::Vec4 &) SET_UNIFORMS_BODY \
142 }; /* NOLINT(SET_UNIFORMS_BODY) */ \
143 struct Eval_##NAME \
144 { \
145 static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY \
146 }; /* NOLINT(EVAL_FUNC_BODY) */ \
147 addChild(createStructCase(m_testCtx, #NAME "_vertex", true, &Eval_##NAME::eval, \
148 &SetUniforms_##NAME::setUniforms, SHADER_SRC) \
149 .release()); \
150 addChild(createStructCase(m_testCtx, #NAME "_fragment", false, &Eval_##NAME::eval, \
151 &SetUniforms_##NAME::setUniforms, SHADER_SRC) \
152 .release()); \
153 } while (false)
154
155 // Basic struct usage
156 LOCAL_STRUCT_CASE(
157 basic,
158 LineStream() << "${HEADER}"
159 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
160 << ""
161 << "struct S {"
162 << " mediump float a;"
163 << " mediump vec3 b;"
164 << " int c;"
165 << "};"
166 << ""
167 << "void main (void)"
168 << "{"
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);"
172 << " ${ASSIGN_POS}"
173 << "}",
174 { instance.useUniform(0u, UI_ONE); }, { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
175
176 // Nested struct
177 LOCAL_STRUCT_CASE(
178 nested,
179 LineStream() << "${HEADER}"
180 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
181 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
182 << ""
183 << "struct T {"
184 << " int a;"
185 << " mediump vec2 b;"
186 << "};"
187 << "struct S {"
188 << " mediump float a;"
189 << " T b;"
190 << " int c;"
191 << "};"
192 << ""
193 << "void main (void)"
194 << "{"
195 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
196 << " s.b = T(ui_zero, ${COORDS}.yz);"
197 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
198 << " ${ASSIGN_POS}"
199 << "}",
200 {
201 instance.useUniform(0u, UI_ZERO);
202 instance.useUniform(1u, UI_ONE);
203 },
204 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
205
206 // Struct with array member
207 LOCAL_STRUCT_CASE(
208 array_member,
209 LineStream() << "${HEADER}"
210 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
211 << ""
212 << "struct S {"
213 << " mediump float a;"
214 << " mediump float b[3];"
215 << " int c;"
216 << "};"
217 << ""
218 << "void main (void)"
219 << "{"
220 << " S s;"
221 << " s.a = ${COORDS}.w;"
222 << " s.c = ui_one;"
223 << " s.b[0] = ${COORDS}.z;"
224 << " s.b[1] = ${COORDS}.y;"
225 << " s.b[2] = ${COORDS}.x;"
226 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
227 << " ${ASSIGN_POS}"
228 << "}",
229 { instance.useUniform(0u, UI_ONE); }, { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
230
231 // Struct with array member, dynamic indexing
232 LOCAL_STRUCT_CASE(
233 array_member_dynamic_index,
234 LineStream() << "${HEADER}"
235 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
236 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
237 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
238 << ""
239 << "struct S {"
240 << " mediump float a;"
241 << " mediump float b[3];"
242 << " int c;"
243 << "};"
244 << ""
245 << "void main (void)"
246 << "{"
247 << " S s;"
248 << " s.a = ${COORDS}.w;"
249 << " s.c = ui_one;"
250 << " s.b[0] = ${COORDS}.z;"
251 << " s.b[1] = ${COORDS}.y;"
252 << " s.b[2] = ${COORDS}.x;"
253 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
254 << " ${ASSIGN_POS}"
255 << "}",
256 {
257 instance.useUniform(0u, UI_ZERO);
258 instance.useUniform(1u, UI_ONE);
259 instance.useUniform(2u, UI_TWO);
260 },
261 { c.color.xyz() = c.coords.swizzle(1, 2, 0); });
262
263 // Struct array
264 LOCAL_STRUCT_CASE(
265 struct_array,
266 LineStream() << "${HEADER}"
267 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
268 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
269 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
270 << ""
271 << "struct S {"
272 << " mediump float a;"
273 << " mediump int b;"
274 << "};"
275 << ""
276 << "void main (void)"
277 << "{"
278 << " S s[3];"
279 << " s[0] = S(${COORDS}.x, ui_zero);"
280 << " s[1].a = ${COORDS}.y;"
281 << " s[1].b = ui_one;"
282 << " s[2] = S(${COORDS}.z, ui_two);"
283 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
284 << " ${ASSIGN_POS}"
285 << "}",
286 {
287 instance.useUniform(0u, UI_ZERO);
288 instance.useUniform(1u, UI_ONE);
289 instance.useUniform(2u, UI_TWO);
290 },
291 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
292
293 // Struct array with dynamic indexing
294 LOCAL_STRUCT_CASE(
295 struct_array_dynamic_index,
296 LineStream()
297 << "${HEADER}"
298 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
299 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
300 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
301 << ""
302 << "struct S {"
303 << " mediump float a;"
304 << " mediump int b;"
305 << "};"
306 << ""
307 << "void main (void)"
308 << "{"
309 << " S s[3];"
310 << " s[0] = S(${COORDS}.x, ui_zero);"
311 << " s[1].a = ${COORDS}.y;"
312 << " s[1].b = ui_one;"
313 << " s[2] = S(${COORDS}.z, ui_two);"
314 << " ${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);"
315 << " ${ASSIGN_POS}"
316 << "}",
317 {
318 instance.useUniform(0u, UI_ZERO);
319 instance.useUniform(1u, UI_ONE);
320 instance.useUniform(2u, UI_TWO);
321 },
322 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
323
324 // Nested struct array
325 LOCAL_STRUCT_CASE(
326 nested_struct_array,
327 LineStream() << "${HEADER}"
328 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
329 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
330 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
331 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
332 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
333 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
334 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
335 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
336 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
337 << ""
338 << "struct T {"
339 << " mediump float a;"
340 << " mediump vec2 b[2];"
341 << "};"
342 << "struct S {"
343 << " mediump float a;"
344 << " T b[3];"
345 << " int c;"
346 << "};"
347 << ""
348 << "void main (void)"
349 << "{"
350 << " S s[2];"
351 << ""
352 << " // S[0]"
353 << " s[0].a = ${COORDS}.x;"
354 << " s[0].b[0].a = uf_half;"
355 << " s[0].b[0].b[0] = ${COORDS}.xy;"
356 << " s[0].b[0].b[1] = ${COORDS}.zw;"
357 << " s[0].b[1].a = uf_third;"
358 << " s[0].b[1].b[0] = ${COORDS}.zw;"
359 << " s[0].b[1].b[1] = ${COORDS}.xy;"
360 << " s[0].b[2].a = uf_fourth;"
361 << " s[0].b[2].b[0] = ${COORDS}.xz;"
362 << " s[0].b[2].b[1] = ${COORDS}.yw;"
363 << " s[0].c = ui_zero;"
364 << ""
365 << " // S[1]"
366 << " s[1].a = ${COORDS}.w;"
367 << " s[1].b[0].a = uf_two;"
368 << " s[1].b[0].b[0] = ${COORDS}.xx;"
369 << " s[1].b[0].b[1] = ${COORDS}.yy;"
370 << " s[1].b[1].a = uf_three;"
371 << " s[1].b[1].b[0] = ${COORDS}.zz;"
372 << " s[1].b[1].b[1] = ${COORDS}.ww;"
373 << " s[1].b[2].a = uf_four;"
374 << " s[1].b[2].b[0] = ${COORDS}.yx;"
375 << " s[1].b[2].b[1] = ${COORDS}.wz;"
376 << " s[1].c = ui_one;"
377 << ""
378 << " 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"
379 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
380 << " 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 "
381 "+ w) * 0.333"
382 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
383 << " ${DST} = vec4(r, g, b, a);"
384 << " ${ASSIGN_POS}"
385 << "}",
386 {
387 instance.useUniform(0u, UI_ZERO);
388 instance.useUniform(1u, UI_ONE);
389 instance.useUniform(2u, UI_TWO);
390 instance.useUniform(3u, UF_TWO);
391 instance.useUniform(4u, UF_THREE);
392 instance.useUniform(5u, UF_FOUR);
393 instance.useUniform(6u, UF_HALF);
394 instance.useUniform(7u, UF_THIRD);
395 instance.useUniform(8u, UF_FOURTH);
396 },
397 { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
398
399 // Nested struct array with dynamic indexing
400 LOCAL_STRUCT_CASE(
401 nested_struct_array_dynamic_index,
402 LineStream() << "${HEADER}"
403 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
404 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
405 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
406 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
407 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
408 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
409 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
410 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
411 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
412 << ""
413 << "struct T {"
414 << " mediump float a;"
415 << " mediump vec2 b[2];"
416 << "};"
417 << "struct S {"
418 << " mediump float a;"
419 << " T b[3];"
420 << " int c;"
421 << "};"
422 << ""
423 << "void main (void)"
424 << "{"
425 << " S s[2];"
426 << ""
427 << " // S[0]"
428 << " s[0].a = ${COORDS}.x;"
429 << " s[0].b[0].a = uf_half;"
430 << " s[0].b[0].b[0] = ${COORDS}.xy;"
431 << " s[0].b[0].b[1] = ${COORDS}.zw;"
432 << " s[0].b[1].a = uf_third;"
433 << " s[0].b[1].b[0] = ${COORDS}.zw;"
434 << " s[0].b[1].b[1] = ${COORDS}.xy;"
435 << " s[0].b[2].a = uf_fourth;"
436 << " s[0].b[2].b[0] = ${COORDS}.xz;"
437 << " s[0].b[2].b[1] = ${COORDS}.yw;"
438 << " s[0].c = ui_zero;"
439 << ""
440 << " // S[1]"
441 << " s[1].a = ${COORDS}.w;"
442 << " s[1].b[0].a = uf_two;"
443 << " s[1].b[0].b[0] = ${COORDS}.xx;"
444 << " s[1].b[0].b[1] = ${COORDS}.yy;"
445 << " s[1].b[1].a = uf_three;"
446 << " s[1].b[1].b[0] = ${COORDS}.zz;"
447 << " s[1].b[1].b[1] = ${COORDS}.ww;"
448 << " s[1].b[2].a = uf_four;"
449 << " s[1].b[2].b[0] = ${COORDS}.yx;"
450 << " s[1].b[2].b[1] = ${COORDS}.wz;"
451 << " s[1].c = ui_one;"
452 << ""
453 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * "
454 "s[0].b[0].a; // (z + z) * 0.5"
455 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * "
456 "s[ui_one].b[2].a; // x * 0.25 * 4"
457 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + "
458 "s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333"
459 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
460 "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
461 << " ${DST} = vec4(r, g, b, a);"
462 << " ${ASSIGN_POS}"
463 << "}",
464 {
465 instance.useUniform(0u, UI_ZERO);
466 instance.useUniform(1u, UI_ONE);
467 instance.useUniform(2u, UI_TWO);
468 instance.useUniform(3u, UF_TWO);
469 instance.useUniform(4u, UF_THREE);
470 instance.useUniform(5u, UF_FOUR);
471 instance.useUniform(6u, UF_HALF);
472 instance.useUniform(7u, UF_THIRD);
473 instance.useUniform(8u, UF_FOURTH);
474 },
475 { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
476
477 // Struct as a function parameter
478 LOCAL_STRUCT_CASE(
479 parameter,
480 LineStream() << "${HEADER}"
481 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
482 << ""
483 << "struct S {"
484 << " mediump float a;"
485 << " mediump vec3 b;"
486 << " int c;"
487 << "};"
488 << ""
489 << "mediump vec4 myFunc (S s)"
490 << "{"
491 << " return vec4(s.a, s.b.x, s.b.y, s.c);"
492 << "}"
493 << ""
494 << "void main (void)"
495 << "{"
496 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
497 << " s.b = ${COORDS}.yzw;"
498 << " ${DST} = myFunc(s);"
499 << " ${ASSIGN_POS}"
500 << "}",
501 { instance.useUniform(0u, UI_ONE); }, { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
502
503 // Nested struct as a function parameter
504 LOCAL_STRUCT_CASE(
505 parameter_nested,
506 LineStream() << "${HEADER}"
507 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
508 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
509 << ""
510 << "struct T {"
511 << " int a;"
512 << " mediump vec2 b;"
513 << "};"
514 << "struct S {"
515 << " mediump float a;"
516 << " T b;"
517 << " int c;"
518 << "};"
519 << ""
520 << "mediump vec4 myFunc (S s)"
521 << "{"
522 << " return vec4(s.a, s.b.b, s.b.a + s.c);"
523 << "}"
524 << ""
525 << "void main (void)"
526 << "{"
527 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
528 << " s.b = T(ui_zero, ${COORDS}.yz);"
529 << " ${DST} = myFunc(s);"
530 << " ${ASSIGN_POS}"
531 << "}",
532 {
533 instance.useUniform(0u, UI_ZERO);
534 instance.useUniform(1u, UI_ONE);
535 },
536 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
537
538 // Struct as a return value
539 LOCAL_STRUCT_CASE(
540 return,
541 LineStream() << "${HEADER}"
542 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
543 << ""
544 << "struct S {"
545 << " mediump float a;"
546 << " mediump vec3 b;"
547 << " int c;"
548 << "};"
549 << ""
550 << "S myFunc (void)"
551 << "{"
552 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);"
553 << " s.b = ${COORDS}.yzw;"
554 << " return s;"
555 << "}"
556 << ""
557 << "void main (void)"
558 << "{"
559 << " S s = myFunc();"
560 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
561 << " ${ASSIGN_POS}"
562 << "}",
563 { instance.useUniform(0u, UI_ONE); }, { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
564
565 // Nested struct
566 LOCAL_STRUCT_CASE(
567 return_nested,
568 LineStream() << "${HEADER}"
569 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
570 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
571 << ""
572 << "struct T {"
573 << " int a;"
574 << " mediump vec2 b;"
575 << "};"
576 << "struct S {"
577 << " mediump float a;"
578 << " T b;"
579 << " int c;"
580 << "};"
581 << ""
582 << "S myFunc (void)"
583 << "{"
584 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
585 << " s.b = T(ui_zero, ${COORDS}.yz);"
586 << " return s;"
587 << "}"
588 << ""
589 << "void main (void)"
590 << "{"
591 << " S s = myFunc();"
592 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
593 << " ${ASSIGN_POS}"
594 << "}",
595 {
596 instance.useUniform(0u, UI_ZERO);
597 instance.useUniform(1u, UI_ONE);
598 },
599 { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
600
601 // Conditional struct assignment
602 LOCAL_STRUCT_CASE(
603 conditional_assignment,
604 LineStream() << "${HEADER}"
605 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
606 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
607 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
608 << ""
609 << "struct S {"
610 << " mediump float a;"
611 << " mediump vec3 b;"
612 << " int c;"
613 << "};"
614 << ""
615 << "void main (void)"
616 << "{"
617 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
618 << " if (uf_one > 0.0)"
619 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
620 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
621 << " ${ASSIGN_POS}"
622 << "}",
623 {
624 instance.useUniform(0u, UI_ZERO);
625 instance.useUniform(1u, UI_ONE);
626 instance.useUniform(2u, UF_ONE);
627 },
628 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
629
630 // Struct assignment in loop
631 LOCAL_STRUCT_CASE(
632 loop_assignment,
633 LineStream() << "${HEADER}"
634 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
635 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
636 << ""
637 << "struct S {"
638 << " mediump float a;"
639 << " mediump vec3 b;"
640 << " int c;"
641 << "};"
642 << ""
643 << "void main (void)"
644 << "{"
645 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
646 << " for (int i = 0; i < 3; i++)"
647 << " {"
648 << " if (i == 1)"
649 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
650 << " }"
651 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
652 << " ${ASSIGN_POS}"
653 << "}",
654 {
655 instance.useUniform(0u, UI_ZERO);
656 instance.useUniform(1u, UI_ONE);
657 },
658 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
659
660 // Struct assignment in loop
661 LOCAL_STRUCT_CASE(
662 dynamic_loop_assignment,
663 LineStream() << "${HEADER}"
664 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
665 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
666 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };"
667 << ""
668 << "struct S {"
669 << " mediump float a;"
670 << " mediump vec3 b;"
671 << " int c;"
672 << "};"
673 << ""
674 << "void main (void)"
675 << "{"
676 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
677 << " for (int i = 0; i < ui_three; i++)"
678 << " {"
679 << " if (i == ui_one)"
680 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
681 << " }"
682 << " ${DST} = vec4(s.a, s.b.xy, s.c);"
683 << " ${ASSIGN_POS}"
684 << "}",
685 {
686 instance.useUniform(0u, UI_ZERO);
687 instance.useUniform(1u, UI_ONE);
688 instance.useUniform(2u, UI_THREE);
689 },
690 { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
691
692 // Conditional assignment of nested struct
693 LOCAL_STRUCT_CASE(
694 nested_conditional_assignment,
695 LineStream() << "${HEADER}"
696 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
697 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
698 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
699 << ""
700 << "struct T {"
701 << " int a;"
702 << " mediump vec2 b;"
703 << "};"
704 << "struct S {"
705 << " mediump float a;"
706 << " T b;"
707 << " int c;"
708 << "};"
709 << ""
710 << "void main (void)"
711 << "{"
712 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
713 << " if (uf_one > 0.0)"
714 << " s.b = T(ui_zero, ${COORDS}.zw);"
715 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
716 << " ${ASSIGN_POS}"
717 << "}",
718 {
719 instance.useUniform(0u, UI_ZERO);
720 instance.useUniform(1u, UI_ONE);
721 instance.useUniform(2u, UF_ONE);
722 },
723 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
724
725 // Nested struct assignment in loop
726 LOCAL_STRUCT_CASE(
727 nested_loop_assignment,
728 LineStream() << "${HEADER}"
729 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
730 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
731 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };"
732 << ""
733 << "struct T {"
734 << " int a;"
735 << " mediump vec2 b;"
736 << "};"
737 << "struct S {"
738 << " mediump float a;"
739 << " T b;"
740 << " int c;"
741 << "};"
742 << ""
743 << "void main (void)"
744 << "{"
745 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
746 << " for (int i = 0; i < 3; i++)"
747 << " {"
748 << " if (i == 1)"
749 << " s.b = T(ui_zero, ${COORDS}.zw);"
750 << " }"
751 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
752 << " ${ASSIGN_POS}"
753 << "}",
754 {
755 instance.useUniform(0u, UI_ZERO);
756 instance.useUniform(1u, UI_ONE);
757 instance.useUniform(2u, UF_ONE);
758 },
759 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
760
761 // Nested struct assignment in dynamic loop
762 LOCAL_STRUCT_CASE(
763 nested_dynamic_loop_assignment,
764 LineStream() << "${HEADER}"
765 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
766 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
767 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };"
768 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_one; };"
769 << ""
770 << "struct T {"
771 << " int a;"
772 << " mediump vec2 b;"
773 << "};"
774 << "struct S {"
775 << " mediump float a;"
776 << " T b;"
777 << " int c;"
778 << "};"
779 << ""
780 << "void main (void)"
781 << "{"
782 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
783 << " for (int i = 0; i < ui_three; i++)"
784 << " {"
785 << " if (i == ui_one)"
786 << " s.b = T(ui_zero, ${COORDS}.zw);"
787 << " }"
788 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
789 << " ${ASSIGN_POS}"
790 << "}",
791 {
792 instance.useUniform(0u, UI_ZERO);
793 instance.useUniform(1u, UI_ONE);
794 instance.useUniform(2u, UI_THREE);
795 instance.useUniform(3u, UF_ONE);
796 },
797 { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
798
799 // Struct array usage in loop
800 LOCAL_STRUCT_CASE(
801 loop_struct_array,
802 LineStream() << "${HEADER}"
803 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
804 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
805 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
806 << ""
807 << "struct S {"
808 << " mediump float a;"
809 << " mediump int b;"
810 << "};"
811 << ""
812 << "void main (void)"
813 << "{"
814 << " S s[3];"
815 << " s[0] = S(${COORDS}.x, ui_zero);"
816 << " s[1].a = ${COORDS}.y;"
817 << " s[1].b = -ui_one;"
818 << " s[2] = S(${COORDS}.z, ui_two);"
819 << ""
820 << " mediump float rgb[3];"
821 << " int alpha = 0;"
822 << " for (int i = 0; i < 3; i++)"
823 << " {"
824 << " rgb[i] = s[2-i].a;"
825 << " alpha += s[i].b;"
826 << " }"
827 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
828 << " ${ASSIGN_POS}"
829 << "}",
830 {
831 instance.useUniform(0u, UI_ZERO);
832 instance.useUniform(1u, UI_ONE);
833 instance.useUniform(2u, UI_TWO);
834 },
835 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
836
837 // Nested struct array usage in loop
838 LOCAL_STRUCT_CASE(
839 loop_nested_struct_array,
840 LineStream() << "${HEADER}"
841 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
842 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
843 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
844 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
845 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
846 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
847 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
848 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
849 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
850 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };"
851 << ""
852 << "struct T {"
853 << " mediump float a;"
854 << " mediump vec2 b[2];"
855 << "};"
856 << "struct S {"
857 << " mediump float a;"
858 << " T b[3];"
859 << " int c;"
860 << "};"
861 << ""
862 << "void main (void)"
863 << "{"
864 << " S s[2];"
865 << ""
866 << " // S[0]"
867 << " s[0].a = ${COORDS}.x;"
868 << " s[0].b[0].a = uf_half;"
869 << " s[0].b[0].b[0] = ${COORDS}.yx;"
870 << " s[0].b[0].b[1] = ${COORDS}.zx;"
871 << " s[0].b[1].a = uf_third;"
872 << " s[0].b[1].b[0] = ${COORDS}.yy;"
873 << " s[0].b[1].b[1] = ${COORDS}.wy;"
874 << " s[0].b[2].a = uf_fourth;"
875 << " s[0].b[2].b[0] = ${COORDS}.zx;"
876 << " s[0].b[2].b[1] = ${COORDS}.zy;"
877 << " s[0].c = ui_zero;"
878 << ""
879 << " // S[1]"
880 << " s[1].a = ${COORDS}.w;"
881 << " s[1].b[0].a = uf_two;"
882 << " s[1].b[0].b[0] = ${COORDS}.zx;"
883 << " s[1].b[0].b[1] = ${COORDS}.zy;"
884 << " s[1].b[1].a = uf_three;"
885 << " s[1].b[1].b[0] = ${COORDS}.zz;"
886 << " s[1].b[1].b[1] = ${COORDS}.ww;"
887 << " s[1].b[2].a = uf_four;"
888 << " s[1].b[2].b[0] = ${COORDS}.yx;"
889 << " s[1].b[2].b[1] = ${COORDS}.wz;"
890 << " s[1].c = ui_one;"
891 << ""
892 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
893 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
894 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
895 << " mediump float a = 1.0;"
896 << " for (int i = 0; i < 2; i++)"
897 << " {"
898 << " for (int j = 0; j < 3; j++)"
899 << " {"
900 << " r += s[0].b[j].b[i].y;"
901 << " g += s[i].b[j].b[0].x;"
902 << " b += s[i].b[j].b[1].x;"
903 << " a *= s[i].b[j].a;"
904 << " }"
905 << " }"
906 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
907 << " ${ASSIGN_POS}"
908 << "}",
909 {
910 instance.useUniform(0u, UI_ZERO);
911 instance.useUniform(1u, UI_ONE);
912 instance.useUniform(2u, UI_TWO);
913 instance.useUniform(3u, UF_TWO);
914 instance.useUniform(4u, UF_THREE);
915 instance.useUniform(5u, UF_FOUR);
916 instance.useUniform(6u, UF_HALF);
917 instance.useUniform(7u, UF_THIRD);
918 instance.useUniform(8u, UF_FOURTH);
919 instance.useUniform(9u, UF_SIXTH);
920 },
921 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
922
923 // Struct array usage in dynamic loop
924 LOCAL_STRUCT_CASE(
925 dynamic_loop_struct_array,
926 LineStream() << "${HEADER}"
927 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
928 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
929 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
930 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
931 << ""
932 << "struct S {"
933 << " mediump float a;"
934 << " mediump int b;"
935 << "};"
936 << ""
937 << "void main (void)"
938 << "{"
939 << " S s[3];"
940 << " s[0] = S(${COORDS}.x, ui_zero);"
941 << " s[1].a = ${COORDS}.y;"
942 << " s[1].b = -ui_one;"
943 << " s[2] = S(${COORDS}.z, ui_two);"
944 << ""
945 << " mediump float rgb[3];"
946 << " int alpha = 0;"
947 << " for (int i = 0; i < ui_three; i++)"
948 << " {"
949 << " rgb[i] = s[2-i].a;"
950 << " alpha += s[i].b;"
951 << " }"
952 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
953 << " ${ASSIGN_POS}"
954 << "}",
955 {
956 instance.useUniform(0u, UI_ZERO);
957 instance.useUniform(1u, UI_ONE);
958 instance.useUniform(2u, UI_TWO);
959 instance.useUniform(3u, UI_THREE);
960 },
961 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
962
963 // Nested struct array usage in dynamic loop
964 LOCAL_STRUCT_CASE(
965 dynamic_loop_nested_struct_array,
966 LineStream() << "${HEADER}"
967 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
968 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
969 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
970 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
971 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };"
972 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };"
973 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };"
974 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };"
975 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };"
976 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };"
977 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };"
978 << ""
979 << "struct T {"
980 << " mediump float a;"
981 << " mediump vec2 b[2];"
982 << "};"
983 << "struct S {"
984 << " mediump float a;"
985 << " T b[3];"
986 << " int c;"
987 << "};"
988 << ""
989 << "void main (void)"
990 << "{"
991 << " S s[2];"
992 << ""
993 << " s[0].a = ${COORDS}.x;"
994 << " s[0].b[0].a = uf_half;"
995 << " s[0].b[0].b[0] = ${COORDS}.yx;"
996 << " s[0].b[0].b[1] = ${COORDS}.zx;"
997 << " s[0].b[1].a = uf_third;"
998 << " s[0].b[1].b[0] = ${COORDS}.yy;"
999 << " s[0].b[1].b[1] = ${COORDS}.wy;"
1000 << " s[0].b[2].a = uf_fourth;"
1001 << " s[0].b[2].b[0] = ${COORDS}.zx;"
1002 << " s[0].b[2].b[1] = ${COORDS}.zy;"
1003 << " s[0].c = ui_zero;"
1004 << ""
1005 << " s[1].a = ${COORDS}.w;"
1006 << " s[1].b[0].a = uf_two;"
1007 << " s[1].b[0].b[0] = ${COORDS}.zx;"
1008 << " s[1].b[0].b[1] = ${COORDS}.zy;"
1009 << " s[1].b[1].a = uf_three;"
1010 << " s[1].b[1].b[0] = ${COORDS}.zz;"
1011 << " s[1].b[1].b[1] = ${COORDS}.ww;"
1012 << " s[1].b[2].a = uf_four;"
1013 << " s[1].b[2].b[0] = ${COORDS}.yx;"
1014 << " s[1].b[2].b[1] = ${COORDS}.wz;"
1015 << " s[1].c = ui_one;"
1016 << ""
1017 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1018 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1019 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1020 << " mediump float a = 1.0;"
1021 << " for (int i = 0; i < ui_two; i++)"
1022 << " {"
1023 << " for (int j = 0; j < ui_three; j++)"
1024 << " {"
1025 << " r += s[0].b[j].b[i].y;"
1026 << " g += s[i].b[j].b[0].x;"
1027 << " b += s[i].b[j].b[1].x;"
1028 << " a *= s[i].b[j].a;"
1029 << " }"
1030 << " }"
1031 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1032 << " ${ASSIGN_POS}"
1033 << "}",
1034 {
1035 instance.useUniform(0u, UI_ZERO);
1036 instance.useUniform(1u, UI_ONE);
1037 instance.useUniform(2u, UI_TWO);
1038 instance.useUniform(3u, UI_THREE);
1039 instance.useUniform(4u, UF_TWO);
1040 instance.useUniform(5u, UF_THREE);
1041 instance.useUniform(6u, UF_FOUR);
1042 instance.useUniform(7u, UF_HALF);
1043 instance.useUniform(8u, UF_THIRD);
1044 instance.useUniform(9u, UF_FOURTH);
1045 instance.useUniform(10u, UF_SIXTH);
1046 },
1047 { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
1048
1049 // Basic struct equality
1050 LOCAL_STRUCT_CASE(
1051 basic_equal,
1052 LineStream() << "${HEADER}"
1053 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1054 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1055 << ""
1056 << "struct S {"
1057 << " mediump float a;"
1058 << " mediump vec3 b;"
1059 << " int c;"
1060 << "};"
1061 << ""
1062 << "void main (void)"
1063 << "{"
1064 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1065 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1066 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1067 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1068 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1069 << " if (a == b) ${DST}.x = 1.0;"
1070 << " if (a == c) ${DST}.y = 1.0;"
1071 << " if (a == d) ${DST}.z = 1.0;"
1072 << " ${ASSIGN_POS}"
1073 << "}",
1074 {
1075 instance.useUniform(0u, UI_ONE);
1076 instance.useUniform(1u, UI_TWO);
1077 },
1078 {
1079 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
1080 c.color.x() = 1.0f;
1081 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
1082 c.color.y() = 1.0f;
1083 });
1084
1085 // Basic struct equality
1086 LOCAL_STRUCT_CASE(
1087 basic_not_equal,
1088 LineStream() << "${HEADER}"
1089 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1090 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1091 << ""
1092 << "struct S {"
1093 << " mediump float a;"
1094 << " mediump vec3 b;"
1095 << " int c;"
1096 << "};"
1097 << ""
1098 << "void main (void)"
1099 << "{"
1100 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1101 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1102 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1103 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1104 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1105 << " if (a != b) ${DST}.x = 1.0;"
1106 << " if (a != c) ${DST}.y = 1.0;"
1107 << " if (a != d) ${DST}.z = 1.0;"
1108 << " ${ASSIGN_POS}"
1109 << "}",
1110 {
1111 instance.useUniform(0u, UI_ONE);
1112 instance.useUniform(1u, UI_TWO);
1113 },
1114 {
1115 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1116 c.color.x() = 1.0f;
1117 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1118 c.color.y() = 1.0f;
1119 c.color.z() = 1.0f;
1120 });
1121
1122 // Nested struct struct equality
1123 LOCAL_STRUCT_CASE(
1124 nested_equal,
1125 LineStream() << "${HEADER}"
1126 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1127 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1128 << ""
1129 << "struct T {"
1130 << " mediump vec3 a;"
1131 << " int b;"
1132 << "};"
1133 << "struct S {"
1134 << " mediump float a;"
1135 << " T b;"
1136 << " int c;"
1137 << "};"
1138 << ""
1139 << "void main (void)"
1140 << "{"
1141 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1142 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1143 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1144 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1145 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1146 << " if (a == b) ${DST}.x = 1.0;"
1147 << " if (a == c) ${DST}.y = 1.0;"
1148 << " if (a == d) ${DST}.z = 1.0;"
1149 << " ${ASSIGN_POS}"
1150 << "}",
1151 {
1152 instance.useUniform(0u, UI_ONE);
1153 instance.useUniform(1u, UI_TWO);
1154 },
1155 {
1156 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
1157 c.color.x() = 1.0f;
1158 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
1159 c.color.y() = 1.0f;
1160 });
1161
1162 // Nested struct struct equality
1163 LOCAL_STRUCT_CASE(
1164 nested_not_equal,
1165 LineStream() << "${HEADER}"
1166 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1167 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1168 << ""
1169 << "struct T {"
1170 << " mediump vec3 a;"
1171 << " int b;"
1172 << "};"
1173 << "struct S {"
1174 << " mediump float a;"
1175 << " T b;"
1176 << " int c;"
1177 << "};"
1178 << ""
1179 << "void main (void)"
1180 << "{"
1181 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1182 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1183 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1184 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1185 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1186 << " if (a != b) ${DST}.x = 1.0;"
1187 << " if (a != c) ${DST}.y = 1.0;"
1188 << " if (a != d) ${DST}.z = 1.0;"
1189 << " ${ASSIGN_POS}"
1190 << "}",
1191 {
1192 instance.useUniform(0u, UI_ONE);
1193 instance.useUniform(1u, UI_TWO);
1194 },
1195 {
1196 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1197 c.color.x() = 1.0f;
1198 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1199 c.color.y() = 1.0f;
1200 c.color.z() = 1.0f;
1201 });
1202 }
1203
1204 class UniformStructTests : public tcu::TestCaseGroup
1205 {
1206 public:
UniformStructTests(tcu::TestContext & testCtx)1207 UniformStructTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "uniform")
1208 {
1209 }
1210
~UniformStructTests(void)1211 ~UniformStructTests(void)
1212 {
1213 }
1214
1215 virtual void init(void);
1216 };
1217
init(void)1218 void UniformStructTests::init(void)
1219 {
1220 #define UNIFORM_STRUCT_CASE(NAME, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \
1221 do \
1222 { \
1223 struct SetUniforms_##NAME \
1224 { \
1225 static void setUniforms(ShaderRenderCaseInstance &instance, \
1226 const tcu::Vec4 &constCoords) SET_UNIFORMS_BODY /* NOLINT(SET_UNIFORMS_BODY) */ \
1227 }; \
1228 struct Eval_##NAME \
1229 { \
1230 static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY \
1231 }; /* NOLINT(EVAL_FUNC_BODY) */ \
1232 addChild(createStructCase(m_testCtx, #NAME "_vertex", true, Eval_##NAME::eval, \
1233 SetUniforms_##NAME::setUniforms, SHADER_SRC) \
1234 .release()); \
1235 addChild(createStructCase(m_testCtx, #NAME "_fragment", false, Eval_##NAME::eval, \
1236 SetUniforms_##NAME::setUniforms, SHADER_SRC) \
1237 .release()); \
1238 } while (false)
1239
1240 // Basic struct usage
1241 UNIFORM_STRUCT_CASE(
1242 basic,
1243 LineStream() << "${HEADER}"
1244 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1245 << ""
1246 << "struct S {"
1247 << " mediump float a;"
1248 << " mediump vec3 b;"
1249 << " int c;"
1250 << "};"
1251 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };"
1252 << ""
1253 << "void main (void)"
1254 << "{"
1255 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1256 << " ${ASSIGN_POS}"
1257 << "}",
1258 {
1259 instance.useUniform(0u, UI_ONE);
1260
1261 struct S
1262 {
1263 float a;
1264 float _padding1[3];
1265 tcu::Vec3 b;
1266 int c;
1267 };
1268
1269 S s;
1270 s.a = constCoords.x();
1271 s.b = constCoords.swizzle(1, 2, 3);
1272 s.c = 1;
1273 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1274 },
1275 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1276
1277 // Nested struct
1278 UNIFORM_STRUCT_CASE(
1279 nested,
1280 LineStream() << "${HEADER}"
1281 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1282 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1283 << ""
1284 << "struct T {"
1285 << " int a;"
1286 << " mediump vec2 b;"
1287 << "};"
1288 << "struct S {"
1289 << " mediump float a;"
1290 << " T b;"
1291 << " int c;"
1292 << "};"
1293 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S s; };"
1294 << ""
1295 << "void main (void)"
1296 << "{"
1297 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1298 << " ${ASSIGN_POS}"
1299 << "}",
1300 {
1301 instance.useUniform(0u, UI_ZERO);
1302 instance.useUniform(1u, UI_ONE);
1303
1304 struct T
1305 {
1306 int a;
1307 float _padding1[1];
1308 tcu::Vec2 b;
1309 };
1310
1311 struct S
1312 {
1313 float a;
1314 float _padding1[3];
1315 T b;
1316 int c;
1317 float _padding2[3];
1318 };
1319
1320 S s;
1321 s.a = constCoords.x();
1322 s.b.a = 0;
1323 s.b.b = constCoords.swizzle(1, 2);
1324 s.c = 1;
1325 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1326 },
1327 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1328
1329 // Struct with array member
1330 UNIFORM_STRUCT_CASE(
1331 array_member,
1332 LineStream() << "${HEADER}"
1333 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };"
1334 << ""
1335 << "struct S {"
1336 << " mediump float a;"
1337 << " mediump float b[3];"
1338 << " int c;"
1339 << "};"
1340 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };"
1341 << ""
1342 << "void main (void)"
1343 << "{"
1344 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1345 << " ${ASSIGN_POS}"
1346 << "}",
1347 {
1348 instance.useUniform(0u, UI_ONE);
1349
1350 struct paddedFloat
1351 {
1352 float value;
1353 float _padding[3];
1354 };
1355
1356 struct S
1357 {
1358 paddedFloat a;
1359 paddedFloat b[3];
1360 int c;
1361 };
1362
1363 S s;
1364 s.a.value = constCoords.w();
1365 s.b[0].value = constCoords.z();
1366 s.b[1].value = constCoords.y();
1367 s.b[2].value = constCoords.x();
1368 s.c = 1;
1369 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1370 },
1371 { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); });
1372
1373 // Struct with array member, dynamic indexing
1374 UNIFORM_STRUCT_CASE(
1375 array_member_dynamic_index,
1376 LineStream() << "${HEADER}"
1377 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1378 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1379 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1380 << ""
1381 << "struct S {"
1382 << " mediump float a;"
1383 << " mediump float b[3];"
1384 << " int c;"
1385 << "};"
1386 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s; };"
1387 << ""
1388 << "void main (void)"
1389 << "{"
1390 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1391 << " ${ASSIGN_POS}"
1392 << "}",
1393 {
1394 instance.useUniform(0u, UI_ZERO);
1395 instance.useUniform(1u, UI_ONE);
1396 instance.useUniform(2u, UI_TWO);
1397
1398 struct paddedFloat
1399 {
1400 float value;
1401 float _padding[3];
1402 };
1403
1404 struct S
1405 {
1406 paddedFloat a;
1407 paddedFloat b[3];
1408 int c;
1409 };
1410
1411 S s;
1412 s.a.value = constCoords.w();
1413 s.b[0].value = constCoords.z();
1414 s.b[1].value = constCoords.y();
1415 s.b[2].value = constCoords.x();
1416 s.c = 1;
1417 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s);
1418 },
1419 { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); });
1420
1421 // Struct array
1422 UNIFORM_STRUCT_CASE(
1423 struct_array,
1424 LineStream() << "${HEADER}"
1425 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1426 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1427 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1428 << ""
1429 << "struct S {"
1430 << " mediump float a;"
1431 << " mediump int b;"
1432 << "};"
1433 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1434 << ""
1435 << "void main (void)"
1436 << "{"
1437 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1438 << " ${ASSIGN_POS}"
1439 << "}",
1440 {
1441 instance.useUniform(0u, UI_ZERO);
1442 instance.useUniform(1u, UI_ONE);
1443 instance.useUniform(2u, UI_TWO);
1444
1445 struct S
1446 {
1447 float a;
1448 int b;
1449 float _padding1[2];
1450 };
1451
1452 S s[3];
1453 s[0].a = constCoords.x();
1454 s[0].b = 0;
1455 s[1].a = constCoords.y();
1456 s[1].b = 1;
1457 s[2].a = constCoords.z();
1458 s[2].b = 2;
1459 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s);
1460 },
1461 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1462
1463 // Struct array with dynamic indexing
1464 UNIFORM_STRUCT_CASE(
1465 struct_array_dynamic_index,
1466 LineStream()
1467 << "${HEADER}"
1468 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1469 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1470 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1471 << ""
1472 << "struct S {"
1473 << " mediump float a;"
1474 << " mediump int b;"
1475 << "};"
1476 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1477 << ""
1478 << "void main (void)"
1479 << "{"
1480 << " ${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);"
1481 << " ${ASSIGN_POS}"
1482 << "}",
1483 {
1484 instance.useUniform(0u, UI_ZERO);
1485 instance.useUniform(1u, UI_ONE);
1486 instance.useUniform(2u, UI_TWO);
1487
1488 struct S
1489 {
1490 float a;
1491 int b;
1492 float _padding1[2];
1493 };
1494
1495 S s[3];
1496 s[0].a = constCoords.x();
1497 s[0].b = 0;
1498 s[1].a = constCoords.y();
1499 s[1].b = 1;
1500 s[2].a = constCoords.z();
1501 s[2].b = 2;
1502 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s);
1503 },
1504 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1505
1506 // Nested struct array
1507 UNIFORM_STRUCT_CASE(
1508 nested_struct_array,
1509 LineStream() << "${HEADER}"
1510 << "struct T {"
1511 << " mediump float a;"
1512 << " mediump vec2 b[2];"
1513 << "};"
1514 << "struct S {"
1515 << " mediump float a;"
1516 << " T b[3];"
1517 << " int c;"
1518 << "};"
1519 << "layout (std140, set = 0, binding = 0) uniform buffer0 { S s[2]; };"
1520 << ""
1521 << "void main (void)"
1522 << "{"
1523 << " 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"
1524 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1525 << " 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 "
1526 "+ w) * 0.333"
1527 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1528 << " ${DST} = vec4(r, g, b, a);"
1529 << " ${ASSIGN_POS}"
1530 << "}",
1531 {
1532 struct T
1533 {
1534 float a;
1535 float _padding1[3];
1536 tcu::Vec4 b[2];
1537 };
1538
1539 struct S
1540 {
1541 float a;
1542 float _padding1[3];
1543 T b[3];
1544 int c;
1545 float _padding2[3];
1546 };
1547
1548 S s[2];
1549 s[0].a = constCoords.x();
1550 s[0].b[0].a = 0.5f;
1551 s[0].b[0].b[0] = constCoords.swizzle(0, 1, 0, 0);
1552 s[0].b[0].b[1] = constCoords.swizzle(2, 3, 0, 0);
1553 s[0].b[1].a = 1.0f / 3.0f;
1554 s[0].b[1].b[0] = constCoords.swizzle(2, 3, 0, 0);
1555 s[0].b[1].b[1] = constCoords.swizzle(0, 1, 0, 0);
1556 s[0].b[2].a = 1.0f / 4.0f;
1557 s[0].b[2].b[0] = constCoords.swizzle(0, 2, 0, 0);
1558 s[0].b[2].b[1] = constCoords.swizzle(1, 3, 0, 0);
1559 s[0].c = 0;
1560
1561 s[1].a = constCoords.w();
1562 s[1].b[0].a = 2.0f;
1563 s[1].b[0].b[0] = constCoords.swizzle(0, 0, 0, 0);
1564 s[1].b[0].b[1] = constCoords.swizzle(1, 1, 0, 0);
1565 s[1].b[1].a = 3.0f;
1566 s[1].b[1].b[0] = constCoords.swizzle(2, 2, 0, 0);
1567 s[1].b[1].b[1] = constCoords.swizzle(3, 3, 0, 0);
1568 s[1].b[2].a = 4.0f;
1569 s[1].b[2].b[0] = constCoords.swizzle(1, 0, 0, 0);
1570 s[1].b[2].b[1] = constCoords.swizzle(3, 2, 0, 0);
1571 s[1].c = 1;
1572
1573 instance.addUniform(0u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1574 },
1575 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1576
1577 // Nested struct array with dynamic indexing
1578 UNIFORM_STRUCT_CASE(
1579 nested_struct_array_dynamic_index,
1580 LineStream() << "${HEADER}"
1581 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1582 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1583 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1584 << ""
1585 << "struct T {"
1586 << " mediump float a;"
1587 << " mediump vec2 b[2];"
1588 << "};"
1589 << "struct S {"
1590 << " mediump float a;"
1591 << " T b[3];"
1592 << " int c;"
1593 << "};"
1594 << "layout (set = 0, binding = 3) uniform buffer3 { S s[2]; };"
1595 << ""
1596 << "void main (void)"
1597 << "{"
1598 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * "
1599 "s[0].b[0].a; // (z + z) * 0.5"
1600 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * "
1601 "s[ui_one].b[2].a; // x * 0.25 * 4"
1602 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + "
1603 "s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333"
1604 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
1605 "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
1606 << " ${DST} = vec4(r, g, b, a);"
1607 << " ${ASSIGN_POS}"
1608 << "}",
1609 {
1610 struct T
1611 {
1612 float a;
1613 float _padding1[3];
1614 tcu::Vec4 b[2];
1615 };
1616
1617 struct S
1618 {
1619 float a;
1620 float _padding1[3];
1621 T b[3];
1622 int c;
1623 float _padding2[3];
1624 };
1625
1626 S s[2];
1627 s[0].a = constCoords.x();
1628 s[0].b[0].a = 0.5f;
1629 s[0].b[0].b[0] = constCoords.swizzle(0, 1, 0, 0);
1630 s[0].b[0].b[1] = constCoords.swizzle(2, 3, 0, 0);
1631 s[0].b[1].a = 1.0f / 3.0f;
1632 s[0].b[1].b[0] = constCoords.swizzle(2, 3, 0, 0);
1633 s[0].b[1].b[1] = constCoords.swizzle(0, 1, 0, 0);
1634 s[0].b[2].a = 1.0f / 4.0f;
1635 s[0].b[2].b[0] = constCoords.swizzle(0, 2, 0, 0);
1636 s[0].b[2].b[1] = constCoords.swizzle(1, 3, 0, 0);
1637 s[0].c = 0;
1638
1639 s[1].a = constCoords.w();
1640 s[1].b[0].a = 2.0f;
1641 s[1].b[0].b[0] = constCoords.swizzle(0, 0, 0, 0);
1642 s[1].b[0].b[1] = constCoords.swizzle(1, 1, 0, 0);
1643 s[1].b[1].a = 3.0f;
1644 s[1].b[1].b[0] = constCoords.swizzle(2, 2, 0, 0);
1645 s[1].b[1].b[1] = constCoords.swizzle(3, 3, 0, 0);
1646 s[1].b[2].a = 4.0f;
1647 s[1].b[2].b[0] = constCoords.swizzle(1, 0, 0, 0);
1648 s[1].b[2].b[1] = constCoords.swizzle(3, 2, 0, 0);
1649 s[1].c = 1;
1650
1651 instance.useUniform(0u, UI_ZERO);
1652 instance.useUniform(1u, UI_ONE);
1653 instance.useUniform(2u, UI_TWO);
1654 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1655 },
1656 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1657 // Struct array usage in loop
1658 UNIFORM_STRUCT_CASE(
1659 loop_struct_array,
1660 LineStream() << "${HEADER}"
1661 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1662 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1663 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1664 << ""
1665 << "struct S {"
1666 << " mediump float a;"
1667 << " mediump int b;"
1668 << "};"
1669 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };"
1670 << ""
1671 << "void main (void)"
1672 << "{"
1673 << " mediump float rgb[3];"
1674 << " int alpha = 0;"
1675 << " for (int i = 0; i < 3; i++)"
1676 << " {"
1677 << " rgb[i] = s[2-i].a;"
1678 << " alpha += s[i].b;"
1679 << " }"
1680 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1681 << " ${ASSIGN_POS}"
1682 << "}",
1683 {
1684 instance.useUniform(0u, UI_ZERO);
1685 instance.useUniform(1u, UI_ONE);
1686 instance.useUniform(2u, UI_TWO);
1687
1688 struct S
1689 {
1690 float a;
1691 int b;
1692 float _padding1[2];
1693 };
1694
1695 S s[3];
1696 s[0].a = constCoords.x();
1697 s[0].b = 0;
1698 s[1].a = constCoords.y();
1699 s[1].b = -1;
1700 s[2].a = constCoords.z();
1701 s[2].b = 2;
1702 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s);
1703 },
1704 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1705
1706 // Nested struct array usage in loop
1707 UNIFORM_STRUCT_CASE(
1708 loop_nested_struct_array,
1709 LineStream() << "${HEADER}"
1710 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1711 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1712 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1713 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };"
1714 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };"
1715 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };"
1716 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };"
1717 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };"
1718 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };"
1719 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };"
1720 << ""
1721 << "struct T {"
1722 << " mediump float a;"
1723 << " mediump vec2 b[2];"
1724 << "};"
1725 << "struct S {"
1726 << " mediump float a;"
1727 << " T b[3];"
1728 << " int c;"
1729 << "};"
1730 << "layout (std140, set = 0, binding = 10) uniform buffer10 { S s[2]; };"
1731 << ""
1732 << "void main (void)"
1733 << "{"
1734 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1735 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1736 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1737 << " mediump float a = 1.0;"
1738 << " for (int i = 0; i < 2; i++)"
1739 << " {"
1740 << " for (int j = 0; j < 3; j++)"
1741 << " {"
1742 << " r += s[0].b[j].b[i].y;"
1743 << " g += s[i].b[j].b[0].x;"
1744 << " b += s[i].b[j].b[1].x;"
1745 << " a *= s[i].b[j].a;"
1746 << " }"
1747 << " }"
1748 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1749 << " ${ASSIGN_POS}"
1750 << "}",
1751 {
1752 instance.useUniform(0u, UI_ZERO);
1753 instance.useUniform(1u, UI_ONE);
1754 instance.useUniform(2u, UI_TWO);
1755 instance.useUniform(3u, UF_TWO);
1756 instance.useUniform(4u, UF_THREE);
1757 instance.useUniform(5u, UF_FOUR);
1758 instance.useUniform(6u, UF_HALF);
1759 instance.useUniform(7u, UF_THIRD);
1760 instance.useUniform(8u, UF_FOURTH);
1761 instance.useUniform(9u, UF_SIXTH);
1762
1763 struct T
1764 {
1765 float a;
1766 float _padding1[3];
1767 tcu::Vec4 b[2];
1768 };
1769
1770 struct S
1771 {
1772 float a;
1773 float _padding1[3];
1774 T b[3];
1775 int c;
1776 float _padding2[3];
1777 };
1778
1779 S s[2];
1780 s[0].a = constCoords.x();
1781 s[0].b[0].a = 0.5f;
1782 s[0].b[0].b[0] = constCoords.swizzle(1, 0, 0, 0);
1783 s[0].b[0].b[1] = constCoords.swizzle(2, 0, 0, 0);
1784 s[0].b[1].a = 1.0f / 3.0f;
1785 s[0].b[1].b[0] = constCoords.swizzle(1, 1, 0, 0);
1786 s[0].b[1].b[1] = constCoords.swizzle(3, 1, 0, 0);
1787 s[0].b[2].a = 1.0f / 4.0f;
1788 s[0].b[2].b[0] = constCoords.swizzle(2, 1, 0, 0);
1789 s[0].b[2].b[1] = constCoords.swizzle(2, 1, 0, 0);
1790 s[0].c = 0;
1791
1792 s[1].a = constCoords.w();
1793 s[1].b[0].a = 2.0f;
1794 s[1].b[0].b[0] = constCoords.swizzle(2, 0, 0, 0);
1795 s[1].b[0].b[1] = constCoords.swizzle(2, 1, 0, 0);
1796 s[1].b[1].a = 3.0f;
1797 s[1].b[1].b[0] = constCoords.swizzle(2, 2, 0, 0);
1798 s[1].b[1].b[1] = constCoords.swizzle(3, 3, 0, 0);
1799 s[1].b[2].a = 4.0f;
1800 s[1].b[2].b[0] = constCoords.swizzle(1, 0, 0, 0);
1801 s[1].b[2].b[1] = constCoords.swizzle(3, 2, 0, 0);
1802 s[1].c = 1;
1803
1804 instance.addUniform(10u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1805 },
1806 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1807
1808 // Struct array usage in dynamic loop
1809 UNIFORM_STRUCT_CASE(
1810 dynamic_loop_struct_array,
1811 LineStream() << "${HEADER}"
1812 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1813 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1814 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1815 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
1816 << ""
1817 << "struct S {"
1818 << " mediump float a;"
1819 << " mediump int b;"
1820 << "};"
1821 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S s[3]; };"
1822 << ""
1823 << "void main (void)"
1824 << "{"
1825 << " mediump float rgb[3];"
1826 << " int alpha = 0;"
1827 << " for (int i = 0; i < ui_three; i++)"
1828 << " {"
1829 << " rgb[i] = s[2-i].a;"
1830 << " alpha += s[i].b;"
1831 << " }"
1832 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1833 << " ${ASSIGN_POS}"
1834 << "}",
1835 {
1836 instance.useUniform(0u, UI_ZERO);
1837 instance.useUniform(1u, UI_ONE);
1838 instance.useUniform(2u, UI_TWO);
1839 instance.useUniform(3u, UI_THREE);
1840
1841 struct S
1842 {
1843 float a;
1844 int b;
1845 float _padding1[2];
1846 };
1847
1848 S s[3];
1849 s[0].a = constCoords.x();
1850 s[0].b = 0;
1851 s[1].a = constCoords.y();
1852 s[1].b = -1;
1853 s[2].a = constCoords.z();
1854 s[2].b = 2;
1855 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s);
1856 },
1857 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1858
1859 // Nested struct array usage in dynamic loop
1860 UNIFORM_STRUCT_CASE(
1861 dynamic_loop_nested_struct_array,
1862 LineStream() << "${HEADER}"
1863 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };"
1864 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };"
1865 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };"
1866 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };"
1867 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };"
1868 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };"
1869 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };"
1870 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };"
1871 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };"
1872 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };"
1873 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };"
1874 << ""
1875 << "struct T {"
1876 << " mediump float a;"
1877 << " mediump vec2 b[2];"
1878 << "};"
1879 << "struct S {"
1880 << " mediump float a;"
1881 << " T b[3];"
1882 << " int c;"
1883 << "};"
1884 << "layout (std140, set = 0, binding = 11) uniform buffer11 { S s[2]; };"
1885 << ""
1886 << "void main (void)"
1887 << "{"
1888 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1889 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1890 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1891 << " mediump float a = 1.0;"
1892 << " for (int i = 0; i < ui_two; i++)"
1893 << " {"
1894 << " for (int j = 0; j < ui_three; j++)"
1895 << " {"
1896 << " r += s[0].b[j].b[i].y;"
1897 << " g += s[i].b[j].b[0].x;"
1898 << " b += s[i].b[j].b[1].x;"
1899 << " a *= s[i].b[j].a;"
1900 << " }"
1901 << " }"
1902 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1903 << " ${ASSIGN_POS}"
1904 << "}",
1905 {
1906 instance.useUniform(0u, UI_ZERO);
1907 instance.useUniform(1u, UI_ONE);
1908 instance.useUniform(2u, UI_TWO);
1909 instance.useUniform(3u, UI_THREE);
1910 instance.useUniform(4u, UF_TWO);
1911 instance.useUniform(5u, UF_THREE);
1912 instance.useUniform(6u, UF_FOUR);
1913 instance.useUniform(7u, UF_HALF);
1914 instance.useUniform(8u, UF_THIRD);
1915 instance.useUniform(9u, UF_FOURTH);
1916 instance.useUniform(10u, UF_SIXTH);
1917
1918 struct T
1919 {
1920 float a;
1921 float _padding1[3];
1922 tcu::Vec4 b[2];
1923 };
1924
1925 struct S
1926 {
1927 float a;
1928 float _padding1[3];
1929 T b[3];
1930 int c;
1931 float _padding2[3];
1932 };
1933
1934 S s[2];
1935 s[0].a = constCoords.x();
1936 s[0].b[0].a = 0.5f;
1937 s[0].b[0].b[0] = constCoords.swizzle(1, 0, 0, 0);
1938 s[0].b[0].b[1] = constCoords.swizzle(2, 0, 0, 0);
1939 s[0].b[1].a = 1.0f / 3.0f;
1940 s[0].b[1].b[0] = constCoords.swizzle(1, 1, 0, 0);
1941 s[0].b[1].b[1] = constCoords.swizzle(3, 1, 0, 0);
1942 s[0].b[2].a = 1.0f / 4.0f;
1943 s[0].b[2].b[0] = constCoords.swizzle(2, 1, 0, 0);
1944 s[0].b[2].b[1] = constCoords.swizzle(2, 1, 0, 0);
1945 s[0].c = 0;
1946
1947 s[1].a = constCoords.w();
1948 s[1].b[0].a = 2.0f;
1949 s[1].b[0].b[0] = constCoords.swizzle(2, 0, 0, 0);
1950 s[1].b[0].b[1] = constCoords.swizzle(2, 1, 0, 0);
1951 s[1].b[1].a = 3.0f;
1952 s[1].b[1].b[0] = constCoords.swizzle(2, 2, 0, 0);
1953 s[1].b[1].b[1] = constCoords.swizzle(3, 3, 0, 0);
1954 s[1].b[2].a = 4.0f;
1955 s[1].b[2].b[0] = constCoords.swizzle(1, 0, 0, 0);
1956 s[1].b[2].b[1] = constCoords.swizzle(3, 2, 0, 0);
1957 s[1].c = 1;
1958
1959 instance.addUniform(11u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s);
1960 },
1961 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1962
1963 // Struct equality
1964 UNIFORM_STRUCT_CASE(
1965 equal,
1966 LineStream() << "${HEADER}"
1967 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };"
1968 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
1969 << ""
1970 << "struct S {"
1971 << " mediump float a;"
1972 << " mediump vec3 b;"
1973 << " int c;"
1974 << "};"
1975 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };"
1976 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };"
1977 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };"
1978 << ""
1979 << "void main (void)"
1980 << "{"
1981 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1982 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1983 << " if (a == b) ${DST}.x = 1.0;"
1984 << " if (a == c) ${DST}.y = 1.0;"
1985 << " if (a == d) ${DST}.z = 1.0;"
1986 << " ${ASSIGN_POS}"
1987 << "}",
1988 {
1989 DE_UNREF(constCoords);
1990 instance.useUniform(0u, UF_ONE);
1991 instance.useUniform(1u, UI_TWO);
1992
1993 struct S
1994 {
1995 float a;
1996 float _padding1[3];
1997 tcu::Vec3 b;
1998 int c;
1999 };
2000
2001 S sa;
2002 sa.a = 1.0f;
2003 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2004 sa.c = 2;
2005 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa);
2006
2007 S sb;
2008 sb.a = 1.0f;
2009 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2010 sb.c = 2;
2011 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb);
2012
2013 S sc;
2014 sc.a = 1.0f;
2015 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f);
2016 sc.c = 2;
2017 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc);
2018 },
2019 {
2020 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
2021 if (deFloatFloor(c.coords[1] + 1.0f) == deFloatFloor(1.1f))
2022 c.color.z() = 1.0f;
2023 });
2024
2025 // Struct equality
2026 UNIFORM_STRUCT_CASE(
2027 not_equal,
2028 LineStream() << "${HEADER}"
2029 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };"
2030 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };"
2031 << ""
2032 << "struct S {"
2033 << " mediump float a;"
2034 << " mediump vec3 b;"
2035 << " int c;"
2036 << "};"
2037 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };"
2038 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };"
2039 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };"
2040 << ""
2041 << "void main (void)"
2042 << "{"
2043 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
2044 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
2045 << " if (a != b) ${DST}.x = 1.0;"
2046 << " if (a != c) ${DST}.y = 1.0;"
2047 << " if (a != d) ${DST}.z = 1.0;"
2048 << " ${ASSIGN_POS}"
2049 << "}",
2050 {
2051 DE_UNREF(constCoords);
2052 instance.useUniform(0u, UF_ONE);
2053 instance.useUniform(1u, UI_TWO);
2054
2055 struct S
2056 {
2057 float a;
2058 float _padding1[3];
2059 tcu::Vec3 b;
2060 int c;
2061 };
2062
2063 S sa;
2064 sa.a = 1.0f;
2065 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2066 sa.c = 2;
2067 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa);
2068
2069 S sb;
2070 sb.a = 1.0f;
2071 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f);
2072 sb.c = 2;
2073 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb);
2074
2075 S sc;
2076 sc.a = 1.0f;
2077 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f);
2078 sc.c = 2;
2079 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc);
2080 },
2081 {
2082 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
2083 if (deFloatFloor(c.coords[1] + 1.0f) != deFloatFloor(1.1f))
2084 c.color.z() = 1.0f;
2085 });
2086 }
2087
2088 class ShaderStructTests : public tcu::TestCaseGroup
2089 {
2090 public:
2091 ShaderStructTests(tcu::TestContext &context);
2092 virtual ~ShaderStructTests(void);
2093
2094 virtual void init(void);
2095
2096 private:
2097 ShaderStructTests(const ShaderStructTests &); // not allowed!
2098 ShaderStructTests &operator=(const ShaderStructTests &); // not allowed!
2099 };
2100
ShaderStructTests(tcu::TestContext & testCtx)2101 ShaderStructTests::ShaderStructTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "struct")
2102 {
2103 }
2104
~ShaderStructTests(void)2105 ShaderStructTests::~ShaderStructTests(void)
2106 {
2107 }
2108
init(void)2109 void ShaderStructTests::init(void)
2110 {
2111 addChild(new LocalStructTests(m_testCtx));
2112 addChild(new UniformStructTests(m_testCtx));
2113 }
2114
2115 } // namespace
2116
createStructTests(tcu::TestContext & testCtx)2117 tcu::TestCaseGroup *createStructTests(tcu::TestContext &testCtx)
2118 {
2119 return new ShaderStructTests(testCtx);
2120 }
2121
2122 } // namespace sr
2123 } // namespace vkt
2124