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