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