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