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