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