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