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