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