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