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