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