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