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
37using namespace std;
38using namespace tcu;
39using namespace glu;
40using namespace deqp;
41
42namespace deqp
43{
44
45enum IndexAccessType
46{
47	INDEXACCESS_STATIC = 0,
48	INDEXACCESS_DYNAMIC,
49	INDEXACCESS_STATIC_LOOP,
50	INDEXACCESS_DYNAMIC_LOOP,
51
52	INDEXACCESS_LAST
53};
54
55static 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
63enum 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
75static 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
88void evalArrayCoordsFloat(ShaderEvalContext& c)
89{
90	c.color.x() = 1.875f * c.coords.x();
91}
92void evalArrayCoordsVec2(ShaderEvalContext& c)
93{
94	c.color.xy() = 1.875f * c.coords.swizzle(0, 1);
95}
96void evalArrayCoordsVec3(ShaderEvalContext& c)
97{
98	c.color.xyz() = 1.875f * c.coords.swizzle(0, 1, 2);
99}
100void evalArrayCoordsVec4(ShaderEvalContext& c)
101{
102	c.color = 1.875f * c.coords;
103}
104
105static 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
120void evalArrayUniformFloat(ShaderEvalContext& c)
121{
122	c.color.x() = 1.875f * c.constCoords.x();
123}
124void evalArrayUniformVec2(ShaderEvalContext& c)
125{
126	c.color.xy() = 1.875f * c.constCoords.swizzle(0, 1);
127}
128void evalArrayUniformVec3(ShaderEvalContext& c)
129{
130	c.color.xyz() = 1.875f * c.constCoords.swizzle(0, 1, 2);
131}
132void evalArrayUniformVec4(ShaderEvalContext& c)
133{
134	c.color = 1.875f * c.constCoords;
135}
136
137static 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
154class ShaderIndexingCase : public ShaderRenderCase
155{
156public:
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
161private:
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
171ShaderIndexingCase::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
182ShaderIndexingCase::~ShaderIndexingCase(void)
183{
184}
185
186void ShaderIndexingCase::setup(deUint32 programID)
187{
188	DE_UNREF(programID);
189}
190
191void 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
244static 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
365static 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
477static 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
627void evalGreenColor (ShaderEvalContext& c)
628{
629    c.color = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
630}
631
632static 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
672void evalSubscriptVec2(ShaderEvalContext& c)
673{
674	c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y());
675}
676void evalSubscriptVec3(ShaderEvalContext& c)
677{
678	c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y() + 0.25f * c.coords.z());
679}
680void 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
685static 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
698static 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
890void evalSubscriptMat2(ShaderEvalContext& c)
891{
892	c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2);
893}
894void evalSubscriptMat2x3(ShaderEvalContext& c)
895{
896	c.color.xyz() = c.coords.swizzle(0, 1, 2) + 0.5f * c.coords.swizzle(1, 2, 3);
897}
898void 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
903void 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}
907void 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}
911void 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
916void 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}
921void 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}
926void 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
932static 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
961static 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
1137ShaderIndexingTests::ShaderIndexingTests(Context& context, glu::GLSLVersion glslVersion)
1138	: TestCaseGroup(context, "indexing", "Indexing Tests"), m_glslVersion(glslVersion)
1139{
1140}
1141
1142ShaderIndexingTests::~ShaderIndexingTests(void)
1143{
1144}
1145
1146void 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