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