1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 indexing (arrays, vector, matrices) tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fShaderIndexingTests.hpp"
25 #include "glsShaderLibrary.hpp"
26 #include "glsShaderRenderCase.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "tcuStringTemplate.hpp"
29
30 #include "deInt32.h"
31
32 #include <map>
33
34 #include "glwFunctions.hpp"
35
36 using namespace std;
37 using namespace tcu;
38 using namespace glu;
39 using namespace deqp::gls;
40
41 namespace deqp
42 {
43 namespace gles3
44 {
45 namespace Functional
46 {
47
48 enum IndexAccessType
49 {
50 INDEXACCESS_STATIC = 0,
51 INDEXACCESS_DYNAMIC,
52 INDEXACCESS_STATIC_LOOP,
53 INDEXACCESS_DYNAMIC_LOOP,
54
55 INDEXACCESS_LAST
56 };
57
getIndexAccessTypeName(IndexAccessType accessType)58 static const char *getIndexAccessTypeName(IndexAccessType accessType)
59 {
60 static const char *s_names[INDEXACCESS_LAST] = {"static", "dynamic", "static_loop", "dynamic_loop"};
61
62 DE_ASSERT(deInBounds32((int)accessType, 0, INDEXACCESS_LAST));
63 return s_names[(int)accessType];
64 }
65
66 enum VectorAccessType
67 {
68 DIRECT = 0,
69 COMPONENT,
70 SUBSCRIPT_STATIC,
71 SUBSCRIPT_DYNAMIC,
72 SUBSCRIPT_STATIC_LOOP,
73 SUBSCRIPT_DYNAMIC_LOOP,
74
75 VECTORACCESS_LAST
76 };
77
getVectorAccessTypeName(VectorAccessType accessType)78 static const char *getVectorAccessTypeName(VectorAccessType accessType)
79 {
80 static const char *s_names[VECTORACCESS_LAST] = {"direct",
81 "component",
82 "static_subscript",
83 "dynamic_subscript",
84 "static_loop_subscript",
85 "dynamic_loop_subscript"};
86
87 DE_ASSERT(deInBounds32((int)accessType, 0, VECTORACCESS_LAST));
88 return s_names[(int)accessType];
89 }
90
evalArrayCoordsFloat(ShaderEvalContext & c)91 void evalArrayCoordsFloat(ShaderEvalContext &c)
92 {
93 c.color.x() = 1.875f * c.coords.x();
94 }
evalArrayCoordsVec2(ShaderEvalContext & c)95 void evalArrayCoordsVec2(ShaderEvalContext &c)
96 {
97 c.color.xy() = 1.875f * c.coords.swizzle(0, 1);
98 }
evalArrayCoordsVec3(ShaderEvalContext & c)99 void evalArrayCoordsVec3(ShaderEvalContext &c)
100 {
101 c.color.xyz() = 1.875f * c.coords.swizzle(0, 1, 2);
102 }
evalArrayCoordsVec4(ShaderEvalContext & c)103 void evalArrayCoordsVec4(ShaderEvalContext &c)
104 {
105 c.color = 1.875f * c.coords;
106 }
107
getArrayCoordsEvalFunc(DataType dataType)108 static ShaderEvalFunc getArrayCoordsEvalFunc(DataType dataType)
109 {
110 if (dataType == TYPE_FLOAT)
111 return evalArrayCoordsFloat;
112 else if (dataType == TYPE_FLOAT_VEC2)
113 return evalArrayCoordsVec2;
114 else if (dataType == TYPE_FLOAT_VEC3)
115 return evalArrayCoordsVec3;
116 else if (dataType == TYPE_FLOAT_VEC4)
117 return evalArrayCoordsVec4;
118
119 DE_FATAL("Invalid data type.");
120 return NULL;
121 }
122
evalArrayUniformFloat(ShaderEvalContext & c)123 void evalArrayUniformFloat(ShaderEvalContext &c)
124 {
125 c.color.x() = 1.875f * c.constCoords.x();
126 }
evalArrayUniformVec2(ShaderEvalContext & c)127 void evalArrayUniformVec2(ShaderEvalContext &c)
128 {
129 c.color.xy() = 1.875f * c.constCoords.swizzle(0, 1);
130 }
evalArrayUniformVec3(ShaderEvalContext & c)131 void evalArrayUniformVec3(ShaderEvalContext &c)
132 {
133 c.color.xyz() = 1.875f * c.constCoords.swizzle(0, 1, 2);
134 }
evalArrayUniformVec4(ShaderEvalContext & c)135 void evalArrayUniformVec4(ShaderEvalContext &c)
136 {
137 c.color = 1.875f * c.constCoords;
138 }
139
getArrayUniformEvalFunc(DataType dataType)140 static ShaderEvalFunc getArrayUniformEvalFunc(DataType dataType)
141 {
142 if (dataType == TYPE_FLOAT)
143 return evalArrayUniformFloat;
144 else if (dataType == TYPE_FLOAT_VEC2)
145 return evalArrayUniformVec2;
146 else if (dataType == TYPE_FLOAT_VEC3)
147 return evalArrayUniformVec3;
148 else if (dataType == TYPE_FLOAT_VEC4)
149 return evalArrayUniformVec4;
150
151 DE_FATAL("Invalid data type.");
152 return NULL;
153 }
154
155 // ShaderIndexingCase
156
157 class ShaderIndexingCase : public ShaderRenderCase
158 {
159 public:
160 ShaderIndexingCase(Context &context, const char *name, const char *description, bool isVertexCase, DataType varType,
161 ShaderEvalFunc evalFunc, const char *vertShaderSource, const char *fragShaderSource);
162 virtual ~ShaderIndexingCase(void);
163
164 private:
165 ShaderIndexingCase(const ShaderIndexingCase &); // not allowed!
166 ShaderIndexingCase &operator=(const ShaderIndexingCase &); // not allowed!
167
168 virtual void setup(int programID);
169 virtual void setupUniforms(int programID, const Vec4 &constCoords);
170
171 DataType m_varType;
172 };
173
ShaderIndexingCase(Context & context,const char * name,const char * description,bool isVertexCase,DataType varType,ShaderEvalFunc evalFunc,const char * vertShaderSource,const char * fragShaderSource)174 ShaderIndexingCase::ShaderIndexingCase(Context &context, const char *name, const char *description, bool isVertexCase,
175 DataType varType, ShaderEvalFunc evalFunc, const char *vertShaderSource,
176 const char *fragShaderSource)
177 : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
178 description, isVertexCase, evalFunc, true /*useLevel*/)
179 {
180 m_varType = varType;
181 m_vertShaderSource = vertShaderSource;
182 m_fragShaderSource = fragShaderSource;
183 }
184
~ShaderIndexingCase(void)185 ShaderIndexingCase::~ShaderIndexingCase(void)
186 {
187 }
188
setup(int programID)189 void ShaderIndexingCase::setup(int programID)
190 {
191 DE_UNREF(programID);
192 }
193
setupUniforms(int programID,const Vec4 & constCoords)194 void ShaderIndexingCase::setupUniforms(int programID, const Vec4 &constCoords)
195 {
196 const glw::Functions &gl = m_renderCtx.getFunctions();
197
198 DE_UNREF(constCoords);
199
200 int arrLoc = gl.getUniformLocation(programID, "u_arr");
201 if (arrLoc != -1)
202 {
203 //int scalarSize = getDataTypeScalarSize(m_varType);
204 if (m_varType == TYPE_FLOAT)
205 {
206 float arr[4];
207 arr[0] = constCoords.x();
208 arr[1] = constCoords.x() * 0.5f;
209 arr[2] = constCoords.x() * 0.25f;
210 arr[3] = constCoords.x() * 0.125f;
211 gl.uniform1fv(arrLoc, 4, &arr[0]);
212 }
213 else if (m_varType == TYPE_FLOAT_VEC2)
214 {
215 Vec2 arr[4];
216 arr[0] = constCoords.swizzle(0, 1);
217 arr[1] = constCoords.swizzle(0, 1) * 0.5f;
218 arr[2] = constCoords.swizzle(0, 1) * 0.25f;
219 arr[3] = constCoords.swizzle(0, 1) * 0.125f;
220 gl.uniform2fv(arrLoc, 4, arr[0].getPtr());
221 }
222 else if (m_varType == TYPE_FLOAT_VEC3)
223 {
224 Vec3 arr[4];
225 arr[0] = constCoords.swizzle(0, 1, 2);
226 arr[1] = constCoords.swizzle(0, 1, 2) * 0.5f;
227 arr[2] = constCoords.swizzle(0, 1, 2) * 0.25f;
228 arr[3] = constCoords.swizzle(0, 1, 2) * 0.125f;
229 gl.uniform3fv(arrLoc, 4, arr[0].getPtr());
230 }
231 else if (m_varType == TYPE_FLOAT_VEC4)
232 {
233 Vec4 arr[4];
234 arr[0] = constCoords.swizzle(0, 1, 2, 3);
235 arr[1] = constCoords.swizzle(0, 1, 2, 3) * 0.5f;
236 arr[2] = constCoords.swizzle(0, 1, 2, 3) * 0.25f;
237 arr[3] = constCoords.swizzle(0, 1, 2, 3) * 0.125f;
238 gl.uniform4fv(arrLoc, 4, arr[0].getPtr());
239 }
240 else
241 throw tcu::TestError("u_arr should not have location assigned in this test case");
242 }
243 }
244
245 // Helpers.
246
createVaryingArrayCase(Context & context,const char * caseName,const char * description,DataType varType,IndexAccessType vertAccess,IndexAccessType fragAccess)247 static ShaderIndexingCase *createVaryingArrayCase(Context &context, const char *caseName, const char *description,
248 DataType varType, IndexAccessType vertAccess,
249 IndexAccessType fragAccess)
250 {
251 std::ostringstream vtx;
252 vtx << "#version 300 es\n";
253 vtx << "in highp vec4 a_position;\n";
254 vtx << "in highp vec4 a_coords;\n";
255 if (vertAccess == INDEXACCESS_DYNAMIC)
256 vtx << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
257 else if (vertAccess == INDEXACCESS_DYNAMIC_LOOP)
258 vtx << "uniform mediump int ui_four;\n";
259 vtx << "out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n";
260 vtx << "\n";
261 vtx << "void main()\n";
262 vtx << "{\n";
263 vtx << " gl_Position = a_position;\n";
264 if (vertAccess == INDEXACCESS_STATIC)
265 {
266 vtx << " var[0] = ${VAR_TYPE}(a_coords);\n";
267 vtx << " var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n";
268 vtx << " var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n";
269 vtx << " var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n";
270 }
271 else if (vertAccess == INDEXACCESS_DYNAMIC)
272 {
273 vtx << " var[ui_zero] = ${VAR_TYPE}(a_coords);\n";
274 vtx << " var[ui_one] = ${VAR_TYPE}(a_coords) * 0.5;\n";
275 vtx << " var[ui_two] = ${VAR_TYPE}(a_coords) * 0.25;\n";
276 vtx << " var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n";
277 }
278 else if (vertAccess == INDEXACCESS_STATIC_LOOP)
279 {
280 vtx << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
281 vtx << " for (int i = 0; i < 4; i++)\n";
282 vtx << " {\n";
283 vtx << " var[i] = ${VAR_TYPE}(coords);\n";
284 vtx << " coords = coords * 0.5;\n";
285 vtx << " }\n";
286 }
287 else
288 {
289 DE_ASSERT(vertAccess == INDEXACCESS_DYNAMIC_LOOP);
290 vtx << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
291 vtx << " for (int i = 0; i < ui_four; i++)\n";
292 vtx << " {\n";
293 vtx << " var[i] = ${VAR_TYPE}(coords);\n";
294 vtx << " coords = coords * 0.5;\n";
295 vtx << " }\n";
296 }
297 vtx << "}\n";
298
299 std::ostringstream frag;
300 frag << "#version 300 es\n";
301 frag << "precision mediump int;\n";
302 frag << "layout(location = 0) out mediump vec4 o_color;\n";
303 if (fragAccess == INDEXACCESS_DYNAMIC)
304 frag << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
305 else if (fragAccess == INDEXACCESS_DYNAMIC_LOOP)
306 frag << "uniform int ui_four;\n";
307 frag << "in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n";
308 frag << "\n";
309 frag << "void main()\n";
310 frag << "{\n";
311 frag << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
312 if (fragAccess == INDEXACCESS_STATIC)
313 {
314 frag << " res += var[0];\n";
315 frag << " res += var[1];\n";
316 frag << " res += var[2];\n";
317 frag << " res += var[3];\n";
318 }
319 else if (fragAccess == INDEXACCESS_DYNAMIC)
320 {
321 frag << " res += var[ui_zero];\n";
322 frag << " res += var[ui_one];\n";
323 frag << " res += var[ui_two];\n";
324 frag << " res += var[ui_three];\n";
325 }
326 else if (fragAccess == INDEXACCESS_STATIC_LOOP)
327 {
328 frag << " for (int i = 0; i < 4; i++)\n";
329 frag << " res += var[i];\n";
330 }
331 else
332 {
333 DE_ASSERT(fragAccess == INDEXACCESS_DYNAMIC_LOOP);
334 frag << " for (int i = 0; i < ui_four; i++)\n";
335 frag << " res += var[i];\n";
336 }
337 frag << " o_color = vec4(res${PADDING});\n";
338 frag << "}\n";
339
340 // Fill in shader templates.
341 map<string, string> params;
342 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
343 params.insert(pair<string, string>("ARRAY_LEN", "4"));
344 params.insert(pair<string, string>("PRECISION", "mediump"));
345
346 if (varType == TYPE_FLOAT)
347 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
348 else if (varType == TYPE_FLOAT_VEC2)
349 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
350 else if (varType == TYPE_FLOAT_VEC3)
351 params.insert(pair<string, string>("PADDING", ", 1.0"));
352 else
353 params.insert(pair<string, string>("PADDING", ""));
354
355 StringTemplate vertTemplate(vtx.str().c_str());
356 StringTemplate fragTemplate(frag.str().c_str());
357 string vertexShaderSource = vertTemplate.specialize(params);
358 string fragmentShaderSource = fragTemplate.specialize(params);
359
360 ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType);
361 return new ShaderIndexingCase(context, caseName, description, true, varType, evalFunc, vertexShaderSource.c_str(),
362 fragmentShaderSource.c_str());
363 }
364
createUniformArrayCase(Context & context,const char * caseName,const char * description,bool isVertexCase,DataType varType,IndexAccessType readAccess)365 static ShaderIndexingCase *createUniformArrayCase(Context &context, const char *caseName, const char *description,
366 bool isVertexCase, DataType varType, IndexAccessType readAccess)
367 {
368 std::ostringstream vtx;
369 std::ostringstream frag;
370 std::ostringstream &op = isVertexCase ? vtx : frag;
371
372 vtx << "#version 300 es\n";
373 frag << "#version 300 es\n";
374
375 vtx << "in highp vec4 a_position;\n";
376 vtx << "in highp vec4 a_coords;\n";
377 frag << "layout(location = 0) out mediump vec4 o_color;\n";
378
379 if (isVertexCase)
380 {
381 vtx << "out mediump vec4 v_color;\n";
382 frag << "in mediump vec4 v_color;\n";
383 }
384 else
385 {
386 vtx << "out mediump vec4 v_coords;\n";
387 frag << "in mediump vec4 v_coords;\n";
388 }
389
390 if (readAccess == INDEXACCESS_DYNAMIC)
391 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
392 else if (readAccess == INDEXACCESS_DYNAMIC_LOOP)
393 op << "uniform mediump int ui_four;\n";
394
395 op << "uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n";
396
397 vtx << "\n";
398 vtx << "void main()\n";
399 vtx << "{\n";
400 vtx << " gl_Position = a_position;\n";
401
402 frag << "\n";
403 frag << "void main()\n";
404 frag << "{\n";
405
406 // Read array.
407 op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
408 if (readAccess == INDEXACCESS_STATIC)
409 {
410 op << " res += u_arr[0];\n";
411 op << " res += u_arr[1];\n";
412 op << " res += u_arr[2];\n";
413 op << " res += u_arr[3];\n";
414 }
415 else if (readAccess == INDEXACCESS_DYNAMIC)
416 {
417 op << " res += u_arr[ui_zero];\n";
418 op << " res += u_arr[ui_one];\n";
419 op << " res += u_arr[ui_two];\n";
420 op << " res += u_arr[ui_three];\n";
421 }
422 else if (readAccess == INDEXACCESS_STATIC_LOOP)
423 {
424 op << " for (int i = 0; i < 4; i++)\n";
425 op << " res += u_arr[i];\n";
426 }
427 else
428 {
429 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
430 op << " for (int i = 0; i < ui_four; i++)\n";
431 op << " res += u_arr[i];\n";
432 }
433
434 if (isVertexCase)
435 {
436 vtx << " v_color = vec4(res${PADDING});\n";
437 frag << " o_color = v_color;\n";
438 }
439 else
440 {
441 vtx << " v_coords = a_coords;\n";
442 frag << " o_color = vec4(res${PADDING});\n";
443 }
444
445 vtx << "}\n";
446 frag << "}\n";
447
448 // Fill in shader templates.
449 map<string, string> params;
450 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
451 params.insert(pair<string, string>("ARRAY_LEN", "4"));
452 params.insert(pair<string, string>("PRECISION", "mediump"));
453
454 if (varType == TYPE_FLOAT)
455 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
456 else if (varType == TYPE_FLOAT_VEC2)
457 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
458 else if (varType == TYPE_FLOAT_VEC3)
459 params.insert(pair<string, string>("PADDING", ", 1.0"));
460 else
461 params.insert(pair<string, string>("PADDING", ""));
462
463 StringTemplate vertTemplate(vtx.str().c_str());
464 StringTemplate fragTemplate(frag.str().c_str());
465 string vertexShaderSource = vertTemplate.specialize(params);
466 string fragmentShaderSource = fragTemplate.specialize(params);
467
468 ShaderEvalFunc evalFunc = getArrayUniformEvalFunc(varType);
469 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
470 vertexShaderSource.c_str(), fragmentShaderSource.c_str());
471 }
472
createTmpArrayCase(Context & context,const char * caseName,const char * description,bool isVertexCase,DataType varType,IndexAccessType writeAccess,IndexAccessType readAccess)473 static ShaderIndexingCase *createTmpArrayCase(Context &context, const char *caseName, const char *description,
474 bool isVertexCase, DataType varType, IndexAccessType writeAccess,
475 IndexAccessType readAccess)
476 {
477 std::ostringstream vtx;
478 std::ostringstream frag;
479 std::ostringstream &op = isVertexCase ? vtx : frag;
480
481 vtx << "#version 300 es\n";
482 frag << "#version 300 es\n";
483
484 vtx << "in highp vec4 a_position;\n";
485 vtx << "in highp vec4 a_coords;\n";
486 frag << "layout(location = 0) out mediump vec4 o_color;\n";
487
488 if (isVertexCase)
489 {
490 vtx << "out mediump vec4 v_color;\n";
491 frag << "in mediump vec4 v_color;\n";
492 }
493 else
494 {
495 vtx << "out mediump vec4 v_coords;\n";
496 frag << "in mediump vec4 v_coords;\n";
497 }
498
499 if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC)
500 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
501
502 if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP)
503 op << "uniform mediump int ui_four;\n";
504
505 vtx << "\n";
506 vtx << "void main()\n";
507 vtx << "{\n";
508 vtx << " gl_Position = a_position;\n";
509
510 frag << "\n";
511 frag << "void main()\n";
512 frag << "{\n";
513
514 // Write array.
515 if (isVertexCase)
516 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
517 else
518 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n";
519
520 op << " ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n";
521 if (writeAccess == INDEXACCESS_STATIC)
522 {
523 op << " arr[0] = ${VAR_TYPE}(coords);\n";
524 op << " arr[1] = ${VAR_TYPE}(coords) * 0.5;\n";
525 op << " arr[2] = ${VAR_TYPE}(coords) * 0.25;\n";
526 op << " arr[3] = ${VAR_TYPE}(coords) * 0.125;\n";
527 }
528 else if (writeAccess == INDEXACCESS_DYNAMIC)
529 {
530 op << " arr[ui_zero] = ${VAR_TYPE}(coords);\n";
531 op << " arr[ui_one] = ${VAR_TYPE}(coords) * 0.5;\n";
532 op << " arr[ui_two] = ${VAR_TYPE}(coords) * 0.25;\n";
533 op << " arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n";
534 }
535 else if (writeAccess == INDEXACCESS_STATIC_LOOP)
536 {
537 op << " for (int i = 0; i < 4; i++)\n";
538 op << " {\n";
539 op << " arr[i] = ${VAR_TYPE}(coords);\n";
540 op << " coords = coords * 0.5;\n";
541 op << " }\n";
542 }
543 else
544 {
545 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP);
546 op << " for (int i = 0; i < ui_four; i++)\n";
547 op << " {\n";
548 op << " arr[i] = ${VAR_TYPE}(coords);\n";
549 op << " coords = coords * 0.5;\n";
550 op << " }\n";
551 }
552
553 // Read array.
554 op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
555 if (readAccess == INDEXACCESS_STATIC)
556 {
557 op << " res += arr[0];\n";
558 op << " res += arr[1];\n";
559 op << " res += arr[2];\n";
560 op << " res += arr[3];\n";
561 }
562 else if (readAccess == INDEXACCESS_DYNAMIC)
563 {
564 op << " res += arr[ui_zero];\n";
565 op << " res += arr[ui_one];\n";
566 op << " res += arr[ui_two];\n";
567 op << " res += arr[ui_three];\n";
568 }
569 else if (readAccess == INDEXACCESS_STATIC_LOOP)
570 {
571 op << " for (int i = 0; i < 4; i++)\n";
572 op << " res += arr[i];\n";
573 }
574 else
575 {
576 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
577 op << " for (int i = 0; i < ui_four; i++)\n";
578 op << " res += arr[i];\n";
579 }
580
581 if (isVertexCase)
582 {
583 vtx << " v_color = vec4(res${PADDING});\n";
584 frag << " o_color = v_color;\n";
585 }
586 else
587 {
588 vtx << " v_coords = a_coords;\n";
589 frag << " o_color = vec4(res${PADDING});\n";
590 }
591
592 vtx << "}\n";
593 frag << "}\n";
594
595 // Fill in shader templates.
596 map<string, string> params;
597 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
598 params.insert(pair<string, string>("ARRAY_LEN", "4"));
599 params.insert(pair<string, string>("PRECISION", "mediump"));
600
601 if (varType == TYPE_FLOAT)
602 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
603 else if (varType == TYPE_FLOAT_VEC2)
604 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
605 else if (varType == TYPE_FLOAT_VEC3)
606 params.insert(pair<string, string>("PADDING", ", 1.0"));
607 else
608 params.insert(pair<string, string>("PADDING", ""));
609
610 StringTemplate vertTemplate(vtx.str().c_str());
611 StringTemplate fragTemplate(frag.str().c_str());
612 string vertexShaderSource = vertTemplate.specialize(params);
613 string fragmentShaderSource = fragTemplate.specialize(params);
614
615 ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType);
616 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
617 vertexShaderSource.c_str(), fragmentShaderSource.c_str());
618 }
619
620 // VECTOR SUBSCRIPT.
621
evalSubscriptVec2(ShaderEvalContext & c)622 void evalSubscriptVec2(ShaderEvalContext &c)
623 {
624 c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y());
625 }
evalSubscriptVec3(ShaderEvalContext & c)626 void evalSubscriptVec3(ShaderEvalContext &c)
627 {
628 c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y() + 0.25f * c.coords.z());
629 }
evalSubscriptVec4(ShaderEvalContext & c)630 void evalSubscriptVec4(ShaderEvalContext &c)
631 {
632 c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y() + 0.25f * c.coords.z() + 0.125f * c.coords.w());
633 }
634
getVectorSubscriptEvalFunc(DataType dataType)635 static ShaderEvalFunc getVectorSubscriptEvalFunc(DataType dataType)
636 {
637 if (dataType == TYPE_FLOAT_VEC2)
638 return evalSubscriptVec2;
639 else if (dataType == TYPE_FLOAT_VEC3)
640 return evalSubscriptVec3;
641 else if (dataType == TYPE_FLOAT_VEC4)
642 return evalSubscriptVec4;
643
644 DE_FATAL("Invalid data type.");
645 return NULL;
646 }
647
createVectorSubscriptCase(Context & context,const char * caseName,const char * description,bool isVertexCase,DataType varType,VectorAccessType writeAccess,VectorAccessType readAccess)648 static ShaderIndexingCase *createVectorSubscriptCase(Context &context, const char *caseName, const char *description,
649 bool isVertexCase, DataType varType, VectorAccessType writeAccess,
650 VectorAccessType readAccess)
651 {
652 std::ostringstream vtx;
653 std::ostringstream frag;
654 std::ostringstream &op = isVertexCase ? vtx : frag;
655
656 int vecLen = getDataTypeScalarSize(varType);
657 const char *vecLenName = getIntUniformName(vecLen);
658
659 vtx << "#version 300 es\n";
660 frag << "#version 300 es\n";
661
662 vtx << "in highp vec4 a_position;\n";
663 vtx << "in highp vec4 a_coords;\n";
664 frag << "layout(location = 0) out mediump vec4 o_color;\n";
665
666 if (isVertexCase)
667 {
668 vtx << "out mediump vec3 v_color;\n";
669 frag << "in mediump vec3 v_color;\n";
670 }
671 else
672 {
673 vtx << "out mediump vec4 v_coords;\n";
674 frag << "in mediump vec4 v_coords;\n";
675 }
676
677 if (writeAccess == SUBSCRIPT_DYNAMIC || readAccess == SUBSCRIPT_DYNAMIC)
678 {
679 op << "uniform mediump int ui_zero";
680 if (vecLen >= 2)
681 op << ", ui_one";
682 if (vecLen >= 3)
683 op << ", ui_two";
684 if (vecLen >= 4)
685 op << ", ui_three";
686 op << ";\n";
687 }
688
689 if (writeAccess == SUBSCRIPT_DYNAMIC_LOOP || readAccess == SUBSCRIPT_DYNAMIC_LOOP)
690 op << "uniform mediump int " << vecLenName << ";\n";
691
692 vtx << "\n";
693 vtx << "void main()\n";
694 vtx << "{\n";
695 vtx << " gl_Position = a_position;\n";
696
697 frag << "\n";
698 frag << "void main()\n";
699 frag << "{\n";
700
701 // Write vector.
702 if (isVertexCase)
703 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
704 else
705 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n";
706
707 op << " ${PRECISION} ${VAR_TYPE} tmp;\n";
708 if (writeAccess == DIRECT)
709 op << " tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n";
710 else if (writeAccess == COMPONENT)
711 {
712 op << " tmp.x = coords.x;\n";
713 if (vecLen >= 2)
714 op << " tmp.y = coords.y * 0.5;\n";
715 if (vecLen >= 3)
716 op << " tmp.z = coords.z * 0.25;\n";
717 if (vecLen >= 4)
718 op << " tmp.w = coords.w * 0.125;\n";
719 }
720 else if (writeAccess == SUBSCRIPT_STATIC)
721 {
722 op << " tmp[0] = coords.x;\n";
723 if (vecLen >= 2)
724 op << " tmp[1] = coords.y * 0.5;\n";
725 if (vecLen >= 3)
726 op << " tmp[2] = coords.z * 0.25;\n";
727 if (vecLen >= 4)
728 op << " tmp[3] = coords.w * 0.125;\n";
729 }
730 else if (writeAccess == SUBSCRIPT_DYNAMIC)
731 {
732 op << " tmp[ui_zero] = coords.x;\n";
733 if (vecLen >= 2)
734 op << " tmp[ui_one] = coords.y * 0.5;\n";
735 if (vecLen >= 3)
736 op << " tmp[ui_two] = coords.z * 0.25;\n";
737 if (vecLen >= 4)
738 op << " tmp[ui_three] = coords.w * 0.125;\n";
739 }
740 else if (writeAccess == SUBSCRIPT_STATIC_LOOP)
741 {
742 op << " for (int i = 0; i < " << vecLen << "; i++)\n";
743 op << " {\n";
744 op << " tmp[i] = coords.x;\n";
745 op << " coords = coords.${ROT_SWIZZLE} * 0.5;\n";
746 op << " }\n";
747 }
748 else
749 {
750 DE_ASSERT(writeAccess == SUBSCRIPT_DYNAMIC_LOOP);
751 op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
752 op << " {\n";
753 op << " tmp[i] = coords.x;\n";
754 op << " coords = coords.${ROT_SWIZZLE} * 0.5;\n";
755 op << " }\n";
756 }
757
758 // Read vector.
759 op << " ${PRECISION} float res = 0.0;\n";
760 if (readAccess == DIRECT)
761 op << " res = dot(tmp, ${VAR_TYPE}(1.0));\n";
762 else if (readAccess == COMPONENT)
763 {
764 op << " res += tmp.x;\n";
765 if (vecLen >= 2)
766 op << " res += tmp.y;\n";
767 if (vecLen >= 3)
768 op << " res += tmp.z;\n";
769 if (vecLen >= 4)
770 op << " res += tmp.w;\n";
771 }
772 else if (readAccess == SUBSCRIPT_STATIC)
773 {
774 op << " res += tmp[0];\n";
775 if (vecLen >= 2)
776 op << " res += tmp[1];\n";
777 if (vecLen >= 3)
778 op << " res += tmp[2];\n";
779 if (vecLen >= 4)
780 op << " res += tmp[3];\n";
781 }
782 else if (readAccess == SUBSCRIPT_DYNAMIC)
783 {
784 op << " res += tmp[ui_zero];\n";
785 if (vecLen >= 2)
786 op << " res += tmp[ui_one];\n";
787 if (vecLen >= 3)
788 op << " res += tmp[ui_two];\n";
789 if (vecLen >= 4)
790 op << " res += tmp[ui_three];\n";
791 }
792 else if (readAccess == SUBSCRIPT_STATIC_LOOP)
793 {
794 op << " for (int i = 0; i < " << vecLen << "; i++)\n";
795 op << " res += tmp[i];\n";
796 }
797 else
798 {
799 DE_ASSERT(readAccess == SUBSCRIPT_DYNAMIC_LOOP);
800 op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
801 op << " res += tmp[i];\n";
802 }
803
804 if (isVertexCase)
805 {
806 vtx << " v_color = vec3(res);\n";
807 frag << " o_color = vec4(v_color.rgb, 1.0);\n";
808 }
809 else
810 {
811 vtx << " v_coords = a_coords;\n";
812 frag << " o_color = vec4(vec3(res), 1.0);\n";
813 }
814
815 vtx << "}\n";
816 frag << "}\n";
817
818 // Fill in shader templates.
819 static const char *s_swizzles[5] = {"", "x", "xy", "xyz", "xyzw"};
820 static const char *s_rotSwizzles[5] = {"", "x", "yx", "yzx", "yzwx"};
821
822 map<string, string> params;
823 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
824 params.insert(pair<string, string>("PRECISION", "mediump"));
825 params.insert(pair<string, string>("SWIZZLE", s_swizzles[vecLen]));
826 params.insert(pair<string, string>("ROT_SWIZZLE", s_rotSwizzles[vecLen]));
827
828 StringTemplate vertTemplate(vtx.str().c_str());
829 StringTemplate fragTemplate(frag.str().c_str());
830 string vertexShaderSource = vertTemplate.specialize(params);
831 string fragmentShaderSource = fragTemplate.specialize(params);
832
833 ShaderEvalFunc evalFunc = getVectorSubscriptEvalFunc(varType);
834 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
835 vertexShaderSource.c_str(), fragmentShaderSource.c_str());
836 }
837
838 // MATRIX SUBSCRIPT.
839
evalSubscriptMat2(ShaderEvalContext & c)840 void evalSubscriptMat2(ShaderEvalContext &c)
841 {
842 c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2);
843 }
evalSubscriptMat2x3(ShaderEvalContext & c)844 void evalSubscriptMat2x3(ShaderEvalContext &c)
845 {
846 c.color.xyz() = c.coords.swizzle(0, 1, 2) + 0.5f * c.coords.swizzle(1, 2, 3);
847 }
evalSubscriptMat2x4(ShaderEvalContext & c)848 void evalSubscriptMat2x4(ShaderEvalContext &c)
849 {
850 c.color = c.coords.swizzle(0, 1, 2, 3) + 0.5f * c.coords.swizzle(1, 2, 3, 0);
851 }
852
evalSubscriptMat3x2(ShaderEvalContext & c)853 void evalSubscriptMat3x2(ShaderEvalContext &c)
854 {
855 c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2) + 0.25f * c.coords.swizzle(2, 3);
856 }
evalSubscriptMat3(ShaderEvalContext & c)857 void evalSubscriptMat3(ShaderEvalContext &c)
858 {
859 c.color.xyz() = c.coords.swizzle(0, 1, 2) + 0.5f * c.coords.swizzle(1, 2, 3) + 0.25f * c.coords.swizzle(2, 3, 0);
860 }
evalSubscriptMat3x4(ShaderEvalContext & c)861 void evalSubscriptMat3x4(ShaderEvalContext &c)
862 {
863 c.color = c.coords.swizzle(0, 1, 2, 3) + 0.5f * c.coords.swizzle(1, 2, 3, 0) + 0.25f * c.coords.swizzle(2, 3, 0, 1);
864 }
865
evalSubscriptMat4x2(ShaderEvalContext & c)866 void evalSubscriptMat4x2(ShaderEvalContext &c)
867 {
868 c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2) + 0.25f * c.coords.swizzle(2, 3) +
869 0.125f * c.coords.swizzle(3, 0);
870 }
evalSubscriptMat4x3(ShaderEvalContext & c)871 void evalSubscriptMat4x3(ShaderEvalContext &c)
872 {
873 c.color.xyz() = c.coords.swizzle(0, 1, 2) + 0.5f * c.coords.swizzle(1, 2, 3) + 0.25f * c.coords.swizzle(2, 3, 0) +
874 0.125f * c.coords.swizzle(3, 0, 1);
875 }
evalSubscriptMat4(ShaderEvalContext & c)876 void evalSubscriptMat4(ShaderEvalContext &c)
877 {
878 c.color = c.coords + 0.5f * c.coords.swizzle(1, 2, 3, 0) + 0.25f * c.coords.swizzle(2, 3, 0, 1) +
879 0.125f * c.coords.swizzle(3, 0, 1, 2);
880 }
881
getMatrixSubscriptEvalFunc(DataType dataType)882 static ShaderEvalFunc getMatrixSubscriptEvalFunc(DataType dataType)
883 {
884 switch (dataType)
885 {
886 case TYPE_FLOAT_MAT2:
887 return evalSubscriptMat2;
888 case TYPE_FLOAT_MAT2X3:
889 return evalSubscriptMat2x3;
890 case TYPE_FLOAT_MAT2X4:
891 return evalSubscriptMat2x4;
892 case TYPE_FLOAT_MAT3X2:
893 return evalSubscriptMat3x2;
894 case TYPE_FLOAT_MAT3:
895 return evalSubscriptMat3;
896 case TYPE_FLOAT_MAT3X4:
897 return evalSubscriptMat3x4;
898 case TYPE_FLOAT_MAT4X2:
899 return evalSubscriptMat4x2;
900 case TYPE_FLOAT_MAT4X3:
901 return evalSubscriptMat4x3;
902 case TYPE_FLOAT_MAT4:
903 return evalSubscriptMat4;
904
905 default:
906 DE_FATAL("Invalid data type.");
907 return nullptr;
908 }
909 }
910
createMatrixSubscriptCase(Context & context,const char * caseName,const char * description,bool isVertexCase,DataType varType,IndexAccessType writeAccess,IndexAccessType readAccess)911 static ShaderIndexingCase *createMatrixSubscriptCase(Context &context, const char *caseName, const char *description,
912 bool isVertexCase, DataType varType, IndexAccessType writeAccess,
913 IndexAccessType readAccess)
914 {
915 std::ostringstream vtx;
916 std::ostringstream frag;
917 std::ostringstream &op = isVertexCase ? vtx : frag;
918
919 int numCols = getDataTypeMatrixNumColumns(varType);
920 int numRows = getDataTypeMatrixNumRows(varType);
921 const char *matSizeName = getIntUniformName(numCols);
922 DataType vecType = getDataTypeFloatVec(numRows);
923
924 vtx << "#version 300 es\n";
925 frag << "#version 300 es\n";
926
927 vtx << "in highp vec4 a_position;\n";
928 vtx << "in highp vec4 a_coords;\n";
929 frag << "layout(location = 0) out mediump vec4 o_color;\n";
930
931 if (isVertexCase)
932 {
933 vtx << "out mediump vec4 v_color;\n";
934 frag << "in mediump vec4 v_color;\n";
935 }
936 else
937 {
938 vtx << "out mediump vec4 v_coords;\n";
939 frag << "in mediump vec4 v_coords;\n";
940 }
941
942 if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC)
943 {
944 op << "uniform mediump int ui_zero";
945 if (numCols >= 2)
946 op << ", ui_one";
947 if (numCols >= 3)
948 op << ", ui_two";
949 if (numCols >= 4)
950 op << ", ui_three";
951 op << ";\n";
952 }
953
954 if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP)
955 op << "uniform mediump int " << matSizeName << ";\n";
956
957 vtx << "\n";
958 vtx << "void main()\n";
959 vtx << "{\n";
960 vtx << " gl_Position = a_position;\n";
961
962 frag << "\n";
963 frag << "void main()\n";
964 frag << "{\n";
965
966 // Write matrix.
967 if (isVertexCase)
968 op << " ${PRECISION} vec4 coords = a_coords;\n";
969 else
970 op << " ${PRECISION} vec4 coords = v_coords;\n";
971
972 op << " ${PRECISION} ${MAT_TYPE} tmp;\n";
973 if (writeAccess == INDEXACCESS_STATIC)
974 {
975 op << " tmp[0] = ${VEC_TYPE}(coords);\n";
976 if (numCols >= 2)
977 op << " tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
978 if (numCols >= 3)
979 op << " tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
980 if (numCols >= 4)
981 op << " tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
982 }
983 else if (writeAccess == INDEXACCESS_DYNAMIC)
984 {
985 op << " tmp[ui_zero] = ${VEC_TYPE}(coords);\n";
986 if (numCols >= 2)
987 op << " tmp[ui_one] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
988 if (numCols >= 3)
989 op << " tmp[ui_two] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
990 if (numCols >= 4)
991 op << " tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
992 }
993 else if (writeAccess == INDEXACCESS_STATIC_LOOP)
994 {
995 op << " for (int i = 0; i < " << numCols << "; i++)\n";
996 op << " {\n";
997 op << " tmp[i] = ${VEC_TYPE}(coords);\n";
998 op << " coords = coords.yzwx * 0.5;\n";
999 op << " }\n";
1000 }
1001 else
1002 {
1003 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP);
1004 op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
1005 op << " {\n";
1006 op << " tmp[i] = ${VEC_TYPE}(coords);\n";
1007 op << " coords = coords.yzwx * 0.5;\n";
1008 op << " }\n";
1009 }
1010
1011 // Read matrix.
1012 op << " ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n";
1013 if (readAccess == INDEXACCESS_STATIC)
1014 {
1015 op << " res += tmp[0];\n";
1016 if (numCols >= 2)
1017 op << " res += tmp[1];\n";
1018 if (numCols >= 3)
1019 op << " res += tmp[2];\n";
1020 if (numCols >= 4)
1021 op << " res += tmp[3];\n";
1022 }
1023 else if (readAccess == INDEXACCESS_DYNAMIC)
1024 {
1025 op << " res += tmp[ui_zero];\n";
1026 if (numCols >= 2)
1027 op << " res += tmp[ui_one];\n";
1028 if (numCols >= 3)
1029 op << " res += tmp[ui_two];\n";
1030 if (numCols >= 4)
1031 op << " res += tmp[ui_three];\n";
1032 }
1033 else if (readAccess == INDEXACCESS_STATIC_LOOP)
1034 {
1035 op << " for (int i = 0; i < " << numCols << "; i++)\n";
1036 op << " res += tmp[i];\n";
1037 }
1038 else
1039 {
1040 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
1041 op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
1042 op << " res += tmp[i];\n";
1043 }
1044
1045 if (isVertexCase)
1046 {
1047 vtx << " v_color = vec4(res${PADDING});\n";
1048 frag << " o_color = v_color;\n";
1049 }
1050 else
1051 {
1052 vtx << " v_coords = a_coords;\n";
1053 frag << " o_color = vec4(res${PADDING});\n";
1054 }
1055
1056 vtx << "}\n";
1057 frag << "}\n";
1058
1059 // Fill in shader templates.
1060 map<string, string> params;
1061 params.insert(pair<string, string>("MAT_TYPE", getDataTypeName(varType)));
1062 params.insert(pair<string, string>("VEC_TYPE", getDataTypeName(vecType)));
1063 params.insert(pair<string, string>("PRECISION", "mediump"));
1064
1065 if (numRows == 2)
1066 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
1067 else if (numRows == 3)
1068 params.insert(pair<string, string>("PADDING", ", 1.0"));
1069 else
1070 params.insert(pair<string, string>("PADDING", ""));
1071
1072 StringTemplate vertTemplate(vtx.str().c_str());
1073 StringTemplate fragTemplate(frag.str().c_str());
1074 string vertexShaderSource = vertTemplate.specialize(params);
1075 string fragmentShaderSource = fragTemplate.specialize(params);
1076
1077 ShaderEvalFunc evalFunc = getMatrixSubscriptEvalFunc(varType);
1078 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
1079 vertexShaderSource.c_str(), fragmentShaderSource.c_str());
1080 }
1081
1082 // ShaderIndexingTests.
1083
ShaderIndexingTests(Context & context)1084 ShaderIndexingTests::ShaderIndexingTests(Context &context) : TestCaseGroup(context, "indexing", "Indexing Tests")
1085 {
1086 }
1087
~ShaderIndexingTests(void)1088 ShaderIndexingTests::~ShaderIndexingTests(void)
1089 {
1090 }
1091
init(void)1092 void ShaderIndexingTests::init(void)
1093 {
1094 static const ShaderType s_shaderTypes[] = {SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT};
1095
1096 static const DataType s_floatAndVecTypes[] = {TYPE_FLOAT, TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
1097
1098 // Varying array access cases.
1099 {
1100 TestCaseGroup *varyingGroup = new TestCaseGroup(m_context, "varying_array", "Varying array access tests.");
1101 addChild(varyingGroup);
1102
1103 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1104 {
1105 DataType varType = s_floatAndVecTypes[typeNdx];
1106 for (int vertAccess = 0; vertAccess < INDEXACCESS_LAST; vertAccess++)
1107 {
1108 for (int fragAccess = 0; fragAccess < INDEXACCESS_LAST; fragAccess++)
1109 {
1110 const char *vertAccessName = getIndexAccessTypeName((IndexAccessType)vertAccess);
1111 const char *fragAccessName = getIndexAccessTypeName((IndexAccessType)fragAccess);
1112 string name =
1113 string(getDataTypeName(varType)) + "_" + vertAccessName + "_write_" + fragAccessName + "_read";
1114 string desc = string("Varying array with ") + vertAccessName + " write in vertex shader and " +
1115 fragAccessName + " read in fragment shader.";
1116 varyingGroup->addChild(createVaryingArrayCase(m_context, name.c_str(), desc.c_str(), varType,
1117 (IndexAccessType)vertAccess,
1118 (IndexAccessType)fragAccess));
1119 }
1120 }
1121 }
1122 }
1123
1124 // Uniform array access cases.
1125 {
1126 TestCaseGroup *uniformGroup = new TestCaseGroup(m_context, "uniform_array", "Uniform array access tests.");
1127 addChild(uniformGroup);
1128
1129 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1130 {
1131 DataType varType = s_floatAndVecTypes[typeNdx];
1132 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1133 {
1134 const char *readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1135 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1136 {
1137 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1138 const char *shaderTypeName = getShaderTypeName(shaderType);
1139 string name = string(getDataTypeName(varType)) + "_" + readAccessName + "_read_" + shaderTypeName;
1140 string desc =
1141 string("Uniform array with ") + readAccessName + " read in " + shaderTypeName + " shader.";
1142 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1143 uniformGroup->addChild(createUniformArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase,
1144 varType, (IndexAccessType)readAccess));
1145 }
1146 }
1147 }
1148 }
1149
1150 // Temporary array access cases.
1151 {
1152 TestCaseGroup *tmpGroup = new TestCaseGroup(m_context, "tmp_array", "Temporary array access tests.");
1153 addChild(tmpGroup);
1154
1155 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1156 {
1157 DataType varType = s_floatAndVecTypes[typeNdx];
1158 for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++)
1159 {
1160 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1161 {
1162 const char *writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess);
1163 const char *readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1164
1165 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1166 {
1167 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1168 const char *shaderTypeName = getShaderTypeName(shaderType);
1169 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1170 readAccessName + "_read_" + shaderTypeName;
1171 string desc = string("Temporary array with ") + writeAccessName + " write and " +
1172 readAccessName + " read in " + shaderTypeName + " shader.";
1173 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1174 tmpGroup->addChild(createTmpArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase,
1175 varType, (IndexAccessType)writeAccess,
1176 (IndexAccessType)readAccess));
1177 }
1178 }
1179 }
1180 }
1181 }
1182
1183 // Vector indexing with subscripts.
1184 {
1185 TestCaseGroup *vecGroup = new TestCaseGroup(m_context, "vector_subscript", "Vector subscript indexing.");
1186 addChild(vecGroup);
1187
1188 static const DataType s_vectorTypes[] = {TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
1189
1190 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_vectorTypes); typeNdx++)
1191 {
1192 DataType varType = s_vectorTypes[typeNdx];
1193 for (int writeAccess = 0; writeAccess < VECTORACCESS_LAST; writeAccess++)
1194 {
1195 for (int readAccess = 0; readAccess < VECTORACCESS_LAST; readAccess++)
1196 {
1197 const char *writeAccessName = getVectorAccessTypeName((VectorAccessType)writeAccess);
1198 const char *readAccessName = getVectorAccessTypeName((VectorAccessType)readAccess);
1199
1200 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1201 {
1202 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1203 const char *shaderTypeName = getShaderTypeName(shaderType);
1204 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1205 readAccessName + "_read_" + shaderTypeName;
1206 string desc = string("Vector subscript access with ") + writeAccessName + " write and " +
1207 readAccessName + " read in " + shaderTypeName + " shader.";
1208 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1209 vecGroup->addChild(
1210 createVectorSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType,
1211 (VectorAccessType)writeAccess, (VectorAccessType)readAccess));
1212 }
1213 }
1214 }
1215 }
1216 }
1217
1218 // Matrix indexing with subscripts.
1219 {
1220 TestCaseGroup *matGroup = new TestCaseGroup(m_context, "matrix_subscript", "Matrix subscript indexing.");
1221 addChild(matGroup);
1222
1223 static const DataType s_matrixTypes[] = {TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X4,
1224 TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3X4,
1225 TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4};
1226
1227 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_matrixTypes); typeNdx++)
1228 {
1229 DataType varType = s_matrixTypes[typeNdx];
1230 for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++)
1231 {
1232 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1233 {
1234 const char *writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess);
1235 const char *readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1236
1237 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1238 {
1239 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1240 const char *shaderTypeName = getShaderTypeName(shaderType);
1241 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1242 readAccessName + "_read_" + shaderTypeName;
1243 string desc = string("Vector subscript access with ") + writeAccessName + " write and " +
1244 readAccessName + " read in " + shaderTypeName + " shader.";
1245 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1246 matGroup->addChild(
1247 createMatrixSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType,
1248 (IndexAccessType)writeAccess, (IndexAccessType)readAccess));
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 {
1256 const std::vector<tcu::TestNode *> children =
1257 gls::ShaderLibrary(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo())
1258 .loadShaderFile("shaders/indexing.test");
1259
1260 for (int i = 0; i < (int)children.size(); i++)
1261 addChild(children[i]);
1262 }
1263 }
1264
1265 } // namespace Functional
1266 } // namespace gles3
1267 } // namespace deqp
1268