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 }; \
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 { static void setUniforms (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY }; \
1221 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \
1222 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, FLAGS, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1223 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, FLAGS, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \
1224 } while (deGetFalse())
1225
1226 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", 0,
1227 LineStream()
1228 << "${DECLARATIONS}"
1229 << "uniform int ui_one;"
1230 << ""
1231 << "struct S {"
1232 << " mediump float a;"
1233 << " mediump vec3 b;"
1234 << " int c;"
1235 << "};"
1236 << "uniform S s;"
1237 << ""
1238 << "void main (void)"
1239 << "{"
1240 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1241 << " ${ASSIGN_POS}"
1242 << "}",
1243 {
1244 setUniform(gl, programID, "s.a", constCoords.x());
1245 setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1246 setUniform(gl, programID, "s.c", 1);
1247 },
1248 {
1249 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1250 });
1251
1252 UNIFORM_STRUCT_CASE(nested, "Nested struct", 0,
1253 LineStream()
1254 << "${DECLARATIONS}"
1255 << "uniform int ui_zero;"
1256 << "uniform int ui_one;"
1257 << ""
1258 << "struct T {"
1259 << " int a;"
1260 << " mediump vec2 b;"
1261 << "};"
1262 << "struct S {"
1263 << " mediump float a;"
1264 << " T b;"
1265 << " int c;"
1266 << "};"
1267 << "uniform S s;"
1268 << ""
1269 << "void main (void)"
1270 << "{"
1271 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1272 << " ${ASSIGN_POS}"
1273 << "}",
1274 {
1275 setUniform(gl, programID, "s.a", constCoords.x());
1276 setUniform(gl, programID, "s.b.a", 0);
1277 setUniform(gl, programID, "s.b.b", constCoords.swizzle(1,2));
1278 setUniform(gl, programID, "s.c", 1);
1279 },
1280 {
1281 c.color.xyz() = c.constCoords.swizzle(0,1,2);
1282 });
1283
1284 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", 0,
1285 LineStream()
1286 << "${DECLARATIONS}"
1287 << "uniform int ui_one;"
1288 << ""
1289 << "struct S {"
1290 << " mediump float a;"
1291 << " mediump float b[3];"
1292 << " int c;"
1293 << "};"
1294 << "uniform S s;"
1295 << ""
1296 << "void main (void)"
1297 << "{"
1298 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1299 << " ${ASSIGN_POS}"
1300 << "}",
1301 {
1302 setUniform(gl, programID, "s.a", constCoords.w());
1303 setUniform(gl, programID, "s.c", 1);
1304
1305 float b[3];
1306 b[0] = constCoords.z();
1307 b[1] = constCoords.y();
1308 b[2] = constCoords.x();
1309 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1310 },
1311 {
1312 c.color.xyz() = c.constCoords.swizzle(3,2,1);
1313 });
1314
1315 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1316 LineStream()
1317 << "${DECLARATIONS}"
1318 << "uniform int ui_zero;"
1319 << "uniform int ui_one;"
1320 << "uniform int ui_two;"
1321 << ""
1322 << "struct S {"
1323 << " mediump float a;"
1324 << " mediump float b[3];"
1325 << " int c;"
1326 << "};"
1327 << "uniform S s;"
1328 << ""
1329 << "void main (void)"
1330 << "{"
1331 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1332 << " ${ASSIGN_POS}"
1333 << "}",
1334 {
1335 setUniform(gl, programID, "s.a", constCoords.w());
1336 setUniform(gl, programID, "s.c", 1);
1337
1338 float b[3];
1339 b[0] = constCoords.z();
1340 b[1] = constCoords.y();
1341 b[2] = constCoords.x();
1342 setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1343 },
1344 {
1345 c.color.xyz() = c.constCoords.swizzle(1,2,0);
1346 });
1347
1348 UNIFORM_STRUCT_CASE(struct_array, "Struct array", 0,
1349 LineStream()
1350 << "${DECLARATIONS}"
1351 << "uniform int ui_zero;"
1352 << "uniform int ui_one;"
1353 << "uniform int ui_two;"
1354 << ""
1355 << "struct S {"
1356 << " mediump float a;"
1357 << " mediump int b;"
1358 << "};"
1359 << "uniform S s[3];"
1360 << ""
1361 << "void main (void)"
1362 << "{"
1363 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1364 << " ${ASSIGN_POS}"
1365 << "}",
1366 {
1367 setUniform(gl, programID, "s[0].a", constCoords.x());
1368 setUniform(gl, programID, "s[0].b", 0);
1369 setUniform(gl, programID, "s[1].a", constCoords.y());
1370 setUniform(gl, programID, "s[1].b", 1);
1371 setUniform(gl, programID, "s[2].a", constCoords.z());
1372 setUniform(gl, programID, "s[2].b", 2);
1373 },
1374 {
1375 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1376 });
1377
1378 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1379 LineStream()
1380 << "${DECLARATIONS}"
1381 << "uniform int ui_zero;"
1382 << "uniform int ui_one;"
1383 << "uniform int ui_two;"
1384 << ""
1385 << "struct S {"
1386 << " mediump float a;"
1387 << " mediump int b;"
1388 << "};"
1389 << "uniform S s[3];"
1390 << ""
1391 << "void main (void)"
1392 << "{"
1393 << " ${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);"
1394 << " ${ASSIGN_POS}"
1395 << "}",
1396 {
1397 setUniform(gl, programID, "s[0].a", constCoords.x());
1398 setUniform(gl, programID, "s[0].b", 0);
1399 setUniform(gl, programID, "s[1].a", constCoords.y());
1400 setUniform(gl, programID, "s[1].b", 1);
1401 setUniform(gl, programID, "s[2].a", constCoords.z());
1402 setUniform(gl, programID, "s[2].b", 2);
1403 },
1404 {
1405 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1406 });
1407
1408 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", 0,
1409 LineStream()
1410 << "${DECLARATIONS}"
1411 << "struct T {"
1412 << " mediump float a;"
1413 << " mediump vec2 b[2];"
1414 << "};"
1415 << "struct S {"
1416 << " mediump float a;"
1417 << " T b[3];"
1418 << " int c;"
1419 << "};"
1420 << "uniform S s[2];"
1421 << ""
1422 << "void main (void)"
1423 << "{"
1424 << " 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"
1425 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1426 << " 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"
1427 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1428 << " ${DST} = vec4(r, g, b, a);"
1429 << " ${ASSIGN_POS}"
1430 << "}",
1431 {
1432 tcu::Vec2 arr[2];
1433
1434 setUniform(gl, programID, "s[0].a", constCoords.x());
1435 arr[0] = constCoords.swizzle(0,1);
1436 arr[1] = constCoords.swizzle(2,3);
1437 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1438 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1439 arr[0] = constCoords.swizzle(2,3);
1440 arr[1] = constCoords.swizzle(0,1);
1441 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1442 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1443 arr[0] = constCoords.swizzle(0,2);
1444 arr[1] = constCoords.swizzle(1,3);
1445 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1446 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1447 setUniform(gl, programID, "s[0].c", 0);
1448
1449 setUniform(gl, programID, "s[1].a", constCoords.w());
1450 arr[0] = constCoords.swizzle(0,0);
1451 arr[1] = constCoords.swizzle(1,1);
1452 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1453 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1454 arr[0] = constCoords.swizzle(2,2);
1455 arr[1] = constCoords.swizzle(3,3);
1456 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1457 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1458 arr[0] = constCoords.swizzle(1,0);
1459 arr[1] = constCoords.swizzle(3,2);
1460 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1461 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1462 setUniform(gl, programID, "s[1].c", 1);
1463 },
1464 {
1465 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1466 });
1467
1468 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", FLAG_REQUIRES_DYNAMIC_INDEXING,
1469 LineStream()
1470 << "${DECLARATIONS}"
1471 << "uniform int ui_zero;"
1472 << "uniform int ui_one;"
1473 << "uniform int ui_two;"
1474 << ""
1475 << "struct T {"
1476 << " mediump float a;"
1477 << " mediump vec2 b[2];"
1478 << "};"
1479 << "struct S {"
1480 << " mediump float a;"
1481 << " T b[3];"
1482 << " int c;"
1483 << "};"
1484 << "uniform S s[2];"
1485 << ""
1486 << "void main (void)"
1487 << "{"
1488 << " 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"
1489 << " 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"
1490 << " 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"
1491 << " 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"
1492 << " ${DST} = vec4(r, g, b, a);"
1493 << " ${ASSIGN_POS}"
1494 << "}",
1495 {
1496 tcu::Vec2 arr[2];
1497
1498 setUniform(gl, programID, "s[0].a", constCoords.x());
1499 arr[0] = constCoords.swizzle(0,1);
1500 arr[1] = constCoords.swizzle(2,3);
1501 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1502 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1503 arr[0] = constCoords.swizzle(2,3);
1504 arr[1] = constCoords.swizzle(0,1);
1505 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1506 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1507 arr[0] = constCoords.swizzle(0,2);
1508 arr[1] = constCoords.swizzle(1,3);
1509 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1510 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1511 setUniform(gl, programID, "s[0].c", 0);
1512
1513 setUniform(gl, programID, "s[1].a", constCoords.w());
1514 arr[0] = constCoords.swizzle(0,0);
1515 arr[1] = constCoords.swizzle(1,1);
1516 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1517 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1518 arr[0] = constCoords.swizzle(2,2);
1519 arr[1] = constCoords.swizzle(3,3);
1520 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1521 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1522 arr[0] = constCoords.swizzle(1,0);
1523 arr[1] = constCoords.swizzle(3,2);
1524 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1525 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1526 setUniform(gl, programID, "s[1].c", 1);
1527 },
1528 {
1529 c.color.xyz() = c.constCoords.swizzle(2,0,3);
1530 });
1531
1532 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 0,
1533 LineStream()
1534 << "${DECLARATIONS}"
1535 << "uniform int ui_zero;"
1536 << "uniform int ui_one;"
1537 << "uniform int ui_two;"
1538 << ""
1539 << "struct S {"
1540 << " mediump float a;"
1541 << " mediump int b;"
1542 << "};"
1543 << "uniform S s[3];"
1544 << ""
1545 << "void main (void)"
1546 << "{"
1547 << " mediump float rgb[3];"
1548 << " int alpha = 0;"
1549 << " for (int i = 0; i < 3; i++)"
1550 << " {"
1551 << " rgb[i] = s[2-i].a;"
1552 << " alpha += s[i].b;"
1553 << " }"
1554 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1555 << " ${ASSIGN_POS}"
1556 << "}",
1557 {
1558 setUniform(gl, programID, "s[0].a", constCoords.x());
1559 setUniform(gl, programID, "s[0].b", 0);
1560 setUniform(gl, programID, "s[1].a", constCoords.y());
1561 setUniform(gl, programID, "s[1].b", -1);
1562 setUniform(gl, programID, "s[2].a", constCoords.z());
1563 setUniform(gl, programID, "s[2].b", 2);
1564 },
1565 {
1566 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1567 });
1568
1569 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 0,
1570 LineStream()
1571 << "${DECLARATIONS}"
1572 << "uniform int ui_zero;"
1573 << "uniform int ui_one;"
1574 << "uniform int ui_two;"
1575 << "uniform mediump float uf_two;"
1576 << "uniform mediump float uf_three;"
1577 << "uniform mediump float uf_four;"
1578 << "uniform mediump float uf_half;"
1579 << "uniform mediump float uf_third;"
1580 << "uniform mediump float uf_fourth;"
1581 << "uniform mediump float uf_sixth;"
1582 << ""
1583 << "struct T {"
1584 << " mediump float a;"
1585 << " mediump vec2 b[2];"
1586 << "};"
1587 << "struct S {"
1588 << " mediump float a;"
1589 << " T b[3];"
1590 << " int c;"
1591 << "};"
1592 << "uniform S s[2];"
1593 << ""
1594 << "void main (void)"
1595 << "{"
1596 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1597 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1598 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1599 << " mediump float a = 1.0;"
1600 << " for (int i = 0; i < 2; i++)"
1601 << " {"
1602 << " for (int j = 0; j < 3; j++)"
1603 << " {"
1604 << " r += s[0].b[j].b[i].y;"
1605 << " g += s[i].b[j].b[0].x;"
1606 << " b += s[i].b[j].b[1].x;"
1607 << " a *= s[i].b[j].a;"
1608 << " }"
1609 << " }"
1610 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1611 << " ${ASSIGN_POS}"
1612 << "}",
1613 {
1614 tcu::Vec2 arr[2];
1615
1616 setUniform(gl, programID, "s[0].a", constCoords.x());
1617 arr[0] = constCoords.swizzle(1,0);
1618 arr[1] = constCoords.swizzle(2,0);
1619 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1620 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1621 arr[0] = constCoords.swizzle(1,1);
1622 arr[1] = constCoords.swizzle(3,1);
1623 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1624 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1625 arr[0] = constCoords.swizzle(2,1);
1626 arr[1] = constCoords.swizzle(2,1);
1627 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1628 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1629 setUniform(gl, programID, "s[0].c", 0);
1630
1631 setUniform(gl, programID, "s[1].a", constCoords.w());
1632 arr[0] = constCoords.swizzle(2,0);
1633 arr[1] = constCoords.swizzle(2,1);
1634 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1635 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1636 arr[0] = constCoords.swizzle(2,2);
1637 arr[1] = constCoords.swizzle(3,3);
1638 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1639 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1640 arr[0] = constCoords.swizzle(1,0);
1641 arr[1] = constCoords.swizzle(3,2);
1642 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1643 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1644 setUniform(gl, programID, "s[1].c", 1);
1645 },
1646 {
1647 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1648 });
1649
1650 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
1651 LineStream()
1652 << "${DECLARATIONS}"
1653 << "uniform int ui_zero;"
1654 << "uniform int ui_one;"
1655 << "uniform int ui_two;"
1656 << "uniform int ui_three;"
1657 << ""
1658 << "struct S {"
1659 << " mediump float a;"
1660 << " mediump int b;"
1661 << "};"
1662 << "uniform S s[3];"
1663 << ""
1664 << "void main (void)"
1665 << "{"
1666 << " mediump float rgb[3];"
1667 << " int alpha = 0;"
1668 << " for (int i = 0; i < ui_three; i++)"
1669 << " {"
1670 << " rgb[i] = s[2-i].a;"
1671 << " alpha += s[i].b;"
1672 << " }"
1673 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1674 << " ${ASSIGN_POS}"
1675 << "}",
1676 {
1677 setUniform(gl, programID, "s[0].a", constCoords.x());
1678 setUniform(gl, programID, "s[0].b", 0);
1679 setUniform(gl, programID, "s[1].a", constCoords.y());
1680 setUniform(gl, programID, "s[1].b", -1);
1681 setUniform(gl, programID, "s[2].a", constCoords.z());
1682 setUniform(gl, programID, "s[2].b", 2);
1683 },
1684 {
1685 c.color.xyz() = c.constCoords.swizzle(2,1,0);
1686 });
1687
1688 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", FLAG_REQUIRES_DYNAMIC_INDEXING|FLAG_REQUIRES_DYNAMIC_LOOPS,
1689 LineStream()
1690 << "${DECLARATIONS}"
1691 << "uniform int ui_zero;"
1692 << "uniform int ui_one;"
1693 << "uniform int ui_two;"
1694 << "uniform int ui_three;"
1695 << "uniform mediump float uf_two;"
1696 << "uniform mediump float uf_three;"
1697 << "uniform mediump float uf_four;"
1698 << "uniform mediump float uf_half;"
1699 << "uniform mediump float uf_third;"
1700 << "uniform mediump float uf_fourth;"
1701 << "uniform mediump float uf_sixth;"
1702 << ""
1703 << "struct T {"
1704 << " mediump float a;"
1705 << " mediump vec2 b[2];"
1706 << "};"
1707 << "struct S {"
1708 << " mediump float a;"
1709 << " T b[3];"
1710 << " int c;"
1711 << "};"
1712 << "uniform S s[2];"
1713 << ""
1714 << "void main (void)"
1715 << "{"
1716 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1717 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1718 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1719 << " mediump float a = 1.0;"
1720 << " for (int i = 0; i < ui_two; i++)"
1721 << " {"
1722 << " for (int j = 0; j < ui_three; j++)"
1723 << " {"
1724 << " r += s[0].b[j].b[i].y;"
1725 << " g += s[i].b[j].b[0].x;"
1726 << " b += s[i].b[j].b[1].x;"
1727 << " a *= s[i].b[j].a;"
1728 << " }"
1729 << " }"
1730 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1731 << " ${ASSIGN_POS}"
1732 << "}",
1733 {
1734 tcu::Vec2 arr[2];
1735
1736 setUniform(gl, programID, "s[0].a", constCoords.x());
1737 arr[0] = constCoords.swizzle(1,0);
1738 arr[1] = constCoords.swizzle(2,0);
1739 setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1740 setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1741 arr[0] = constCoords.swizzle(1,1);
1742 arr[1] = constCoords.swizzle(3,1);
1743 setUniform(gl, programID, "s[0].b[1].a", 1.0f/3.0f);
1744 setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1745 arr[0] = constCoords.swizzle(2,1);
1746 arr[1] = constCoords.swizzle(2,1);
1747 setUniform(gl, programID, "s[0].b[2].a", 1.0f/4.0f);
1748 setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1749 setUniform(gl, programID, "s[0].c", 0);
1750
1751 setUniform(gl, programID, "s[1].a", constCoords.w());
1752 arr[0] = constCoords.swizzle(2,0);
1753 arr[1] = constCoords.swizzle(2,1);
1754 setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1755 setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1756 arr[0] = constCoords.swizzle(2,2);
1757 arr[1] = constCoords.swizzle(3,3);
1758 setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1759 setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1760 arr[0] = constCoords.swizzle(1,0);
1761 arr[1] = constCoords.swizzle(3,2);
1762 setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1763 setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1764 setUniform(gl, programID, "s[1].c", 1);
1765 },
1766 {
1767 c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1768 });
1769
1770 UNIFORM_STRUCT_CASE(sampler, "Sampler in struct", FLAG_USES_TEXTURES,
1771 LineStream()
1772 << "${DECLARATIONS}"
1773 << "uniform int ui_one;"
1774 << ""
1775 << "struct S {"
1776 << " mediump float a;"
1777 << " mediump vec3 b;"
1778 << " sampler2D c;"
1779 << "};"
1780 << "uniform S s;"
1781 << ""
1782 << "void main (void)"
1783 << "{"
1784 << " ${DST} = vec4(texture2D(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1785 << " ${ASSIGN_POS}"
1786 << "}",
1787 {
1788 DE_UNREF(constCoords);
1789 setUniform(gl, programID, "s.a", 1.0f);
1790 setUniform(gl, programID, "s.b", tcu::Vec3(0.25f, 0.25f, 0.5f));
1791 setUniform(gl, programID, "s.c", 0);
1792 },
1793 {
1794 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1795 });
1796
1797 UNIFORM_STRUCT_CASE(sampler_nested, "Sampler in nested struct", FLAG_USES_TEXTURES,
1798 LineStream()
1799 << "${DECLARATIONS}"
1800 << "uniform int ui_zero;"
1801 << "uniform int ui_one;"
1802 << ""
1803 << "struct T {"
1804 << " sampler2D a;"
1805 << " mediump vec2 b;"
1806 << "};"
1807 << "struct S {"
1808 << " mediump float a;"
1809 << " T b;"
1810 << " int c;"
1811 << "};"
1812 << "uniform S s;"
1813 << ""
1814 << "void main (void)"
1815 << "{"
1816 << " ${DST} = vec4(texture2D(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1817 << " ${ASSIGN_POS}"
1818 << "}",
1819 {
1820 DE_UNREF(constCoords);
1821 setUniform(gl, programID, "s.a", 0.5f);
1822 setUniform(gl, programID, "s.b.a", 0);
1823 setUniform(gl, programID, "s.b.b", tcu::Vec2(0.25f, 0.25f));
1824 setUniform(gl, programID, "s.c", 1);
1825 },
1826 {
1827 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1828 });
1829
1830 UNIFORM_STRUCT_CASE(sampler_array, "Sampler in struct array", FLAG_USES_TEXTURES,
1831 LineStream()
1832 << "${DECLARATIONS}"
1833 << "uniform int ui_one;"
1834 << ""
1835 << "struct S {"
1836 << " mediump float a;"
1837 << " mediump vec3 b;"
1838 << " sampler2D c;"
1839 << "};"
1840 << "uniform S s[2];"
1841 << ""
1842 << "void main (void)"
1843 << "{"
1844 << " ${DST} = vec4(texture2D(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1845 << " ${ASSIGN_POS}"
1846 << "}",
1847 {
1848 DE_UNREF(constCoords);
1849 setUniform(gl, programID, "s[0].a", 1.0f);
1850 setUniform(gl, programID, "s[0].b", tcu::Vec3(0.25f, 0.25f, 0.25f));
1851 setUniform(gl, programID, "s[0].c", 1);
1852 setUniform(gl, programID, "s[1].a", 0.0f);
1853 setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.5f));
1854 setUniform(gl, programID, "s[1].c", 0);
1855 },
1856 {
1857 c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1858 });
1859
1860 UNIFORM_STRUCT_CASE(equal, "Struct equality", 0,
1861 LineStream()
1862 << "${DECLARATIONS}"
1863 << "uniform mediump float uf_one;"
1864 << "uniform int ui_two;"
1865 << ""
1866 << "struct S {"
1867 << " mediump float a;"
1868 << " mediump vec3 b;"
1869 << " int c;"
1870 << "};"
1871 << "uniform S a;"
1872 << "uniform S b;"
1873 << "uniform S c;"
1874 << ""
1875 << "void main (void)"
1876 << "{"
1877 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1878 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1879 << " if (a == b) ${DST}.x = 1.0;"
1880 << " if (a == c) ${DST}.y = 1.0;"
1881 << " if (a == d) ${DST}.z = 1.0;"
1882 << " ${ASSIGN_POS}"
1883 << "}",
1884 {
1885 DE_UNREF(constCoords);
1886 setUniform(gl, programID, "a.a", 1.0f);
1887 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1888 setUniform(gl, programID, "a.c", 2);
1889 setUniform(gl, programID, "b.a", 1.0f);
1890 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1891 setUniform(gl, programID, "b.c", 2);
1892 setUniform(gl, programID, "c.a", 1.0f);
1893 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1894 setUniform(gl, programID, "c.c", 2);
1895 },
1896 {
1897 c.color.xy() = tcu::Vec2(1.0f, 0.0f);
1898 if (deFloatFloor(c.coords[1]+1.0f) == deFloatFloor(1.1f))
1899 c.color.z() = 1.0f;
1900 });
1901
1902 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", 0,
1903 LineStream()
1904 << "${DECLARATIONS}"
1905 << "uniform mediump float uf_one;"
1906 << "uniform int ui_two;"
1907 << ""
1908 << "struct S {"
1909 << " mediump float a;"
1910 << " mediump vec3 b;"
1911 << " int c;"
1912 << "};"
1913 << "uniform S a;"
1914 << "uniform S b;"
1915 << "uniform S c;"
1916 << ""
1917 << "void main (void)"
1918 << "{"
1919 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1920 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1921 << " if (a != b) ${DST}.x = 1.0;"
1922 << " if (a != c) ${DST}.y = 1.0;"
1923 << " if (a != d) ${DST}.z = 1.0;"
1924 << " ${ASSIGN_POS}"
1925 << "}",
1926 {
1927 DE_UNREF(constCoords);
1928 setUniform(gl, programID, "a.a", 1.0f);
1929 setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1930 setUniform(gl, programID, "a.c", 2);
1931 setUniform(gl, programID, "b.a", 1.0f);
1932 setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1933 setUniform(gl, programID, "b.c", 2);
1934 setUniform(gl, programID, "c.a", 1.0f);
1935 setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1936 setUniform(gl, programID, "c.c", 2);
1937 },
1938 {
1939 c.color.xy() = tcu::Vec2(0.0f, 1.0f);
1940 if (deFloatFloor(c.coords[1]+1.0f) != deFloatFloor(1.1f))
1941 c.color.z() = 1.0f;
1942 });
1943 }
1944
ShaderStructTests(Context & context)1945 ShaderStructTests::ShaderStructTests (Context& context)
1946 : TestCaseGroup(context, "struct", "Struct Tests")
1947 {
1948 }
1949
~ShaderStructTests(void)1950 ShaderStructTests::~ShaderStructTests (void)
1951 {
1952 }
1953
init(void)1954 void ShaderStructTests::init (void)
1955 {
1956 addChild(new LocalStructTests(m_context));
1957 addChild(new UniformStructTests(m_context));
1958 }
1959
1960 } // Functional
1961 } // gles2
1962 } // deqp
1963