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