• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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