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