1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24#include "glwEnums.hpp"
25
26#include "gluContextInfo.hpp"
27#include "tcuRenderTarget.hpp"
28#include "tcuVectorUtil.hpp"
29#include <assert.h>
30#include <map>
31
32#include "es31cExplicitUniformLocationTest.hpp"
33
34namespace glcts
35{
36using namespace glw;
37namespace
38{
39
40class Logger
41{
42public:
43	Logger() : null_log_(0)
44	{
45	}
46
47	Logger(const Logger& rhs)
48	{
49		null_log_ = rhs.null_log_;
50		if (!null_log_)
51		{
52			str_ << rhs.str_.str();
53		}
54	}
55
56	~Logger()
57	{
58		s_tcuLog->writeMessage(str_.str().c_str());
59		if (!str_.str().empty())
60		{
61			s_tcuLog->writeMessage(NL);
62		}
63	}
64
65	template <class T>
66	Logger& operator<<(const T& t)
67	{
68		if (!null_log_)
69		{
70			str_ << t;
71		}
72		return *this;
73	}
74
75	static tcu::TestLog* Get()
76	{
77		return s_tcuLog;
78	}
79
80	static void setOutput(tcu::TestLog& log)
81	{
82		s_tcuLog = &log;
83	}
84
85private:
86	void				 operator=(const Logger&);
87	bool				 null_log_;
88	std::ostringstream   str_;
89	static tcu::TestLog* s_tcuLog;
90};
91tcu::TestLog* Logger::s_tcuLog = NULL;
92
93class DefOccurence
94{
95public:
96	enum DefOccurenceEnum
97	{
98		ALL_SH,
99		VSH,
100		FSH_OR_CSH, //"one shader"
101		ALL_BUT_FSH,
102		ALL_BUT_VSH,
103		NONE_SH,
104	} occurence;
105
106	DefOccurence(DefOccurenceEnum _occurence) : occurence(_occurence)
107	{
108	}
109
110	bool occurs(GLenum shader) const
111	{
112		if (occurence == NONE_SH)
113		{
114			return false;
115		}
116		if (occurence == ALL_SH)
117		{
118			return true;
119		}
120		if (occurence == FSH_OR_CSH)
121		{
122			return shader == GL_FRAGMENT_SHADER || shader == GL_COMPUTE_SHADER;
123		}
124		if (occurence == VSH)
125		{
126			return shader == GL_VERTEX_SHADER;
127		}
128		if (occurence == ALL_BUT_FSH)
129		{
130			return shader != GL_FRAGMENT_SHADER;
131		}
132		if (occurence == ALL_BUT_VSH)
133		{
134			return shader != GL_VERTEX_SHADER;
135		}
136		assert(0);
137		return false;
138	}
139};
140
141class LocationSpecifier
142{
143};
144class IndexSpecifier
145{
146};
147
148class LayoutSpecifierBase
149{
150public:
151	enum NumSys
152	{
153		Dec,
154		Oct,
155		Hex,
156	};
157
158	LayoutSpecifierBase(int _val, NumSys _numSys, DefOccurence _occurence)
159		: val(_val), numSys(_numSys), occurence(_occurence)
160	{
161	}
162
163	bool isImplicit(const std::vector<GLenum> stages) const
164	{
165		bool implicit = true;
166		for (size_t i = 0; i < stages.size(); i++)
167		{
168			implicit &= !occurence.occurs(stages[i]);
169		}
170
171		return implicit;
172	}
173
174	int			 val;
175	NumSys		 numSys;
176	DefOccurence occurence;
177};
178
179template <class T>
180class LayoutSpecifier : public LayoutSpecifierBase
181{
182public:
183	LayoutSpecifier(int _val, NumSys _numSys, DefOccurence _occurence) : LayoutSpecifierBase(_val, _numSys, _occurence)
184	{
185	}
186
187	static LayoutSpecifier<T> C(int _val, NumSys _sys = Dec)
188	{
189		return LayoutSpecifier<T>(_val, _sys, DefOccurence::ALL_SH);
190	}
191
192	static LayoutSpecifier<T> C(int _val, DefOccurence _occurence)
193	{
194		return LayoutSpecifier<T>(_val, Dec, _occurence);
195	}
196
197	static LayoutSpecifier<T> Implicit()
198	{
199		return LayoutSpecifier<T>(1999999, Dec, DefOccurence::NONE_SH);
200	}
201
202	void streamDefinition(std::ostringstream& str, GLenum shader) const;
203};
204
205typedef LayoutSpecifier<LocationSpecifier> Loc;
206typedef LayoutSpecifier<IndexSpecifier>	Index;
207
208template <>
209void LayoutSpecifier<LocationSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const
210{
211	if (val < 0 || !occurence.occurs(shader))
212	{
213		return;
214	}
215
216	str << "layout(location = ";
217	if (numSys == Loc::Oct)
218	{
219		str << std::oct << "0";
220	}
221	else if (numSys == Loc::Hex)
222	{
223		str << std::hex << "0x";
224	}
225	str << val << std::dec << ") ";
226}
227
228template <>
229void LayoutSpecifier<IndexSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const
230{
231	if (val < 0 || !occurence.occurs(shader))
232	{
233		return;
234	}
235
236	str << "layout(index = ";
237	if (numSys == Loc::Oct)
238	{
239		str << std::oct << "0";
240	}
241	else if (numSys == Loc::Hex)
242	{
243		str << std::hex << "0x";
244	}
245	str << val << std::dec << ") ";
246}
247
248class UniformStructCounter
249{
250public:
251	UniformStructCounter() : counter(0)
252	{
253	}
254	GLint getNextCount()
255	{
256		return counter++;
257	}
258
259private:
260	UniformStructCounter(const UniformStructCounter&);
261	GLint counter;
262};
263
264class UniformType
265{
266public:
267	UniformType(GLenum _enumType, int _arraySize = 0)
268		: enumType(_enumType), arraySize(_arraySize), isArray(_arraySize > 0), signedType(true)
269	{
270		if (!arraySize)
271		{
272			arraySize = 1;
273		}
274		arraySizesSegmented.push_back(arraySize);
275		fill();
276	}
277	UniformType(GLenum _enumType, const std::vector<int>& _arraySizesSegmented)
278		: enumType(_enumType), arraySizesSegmented(_arraySizesSegmented), isArray(true), signedType(true)
279	{
280		arraySize = 1;
281		for (size_t i = 0; i < arraySizesSegmented.size(); i++)
282		{
283			assert(arraySizesSegmented[i] > 0);
284			arraySize *= arraySizesSegmented[i];
285		}
286		fill();
287	}
288	UniformType(UniformStructCounter& structCounter, std::vector<UniformType> _childTypes, int _arraySize = 0)
289		: enumType(0), arraySize(_arraySize), childTypes(_childTypes), isArray(_arraySize > 0), signedType(true)
290	{
291		baseType = 0;
292		std::ostringstream _str;
293		_str << "S" << structCounter.getNextCount();
294		strType = _str.str();
295		if (!arraySize)
296		{
297			arraySize = 1;
298		}
299		arraySizesSegmented.push_back(arraySize);
300	}
301
302	inline const std::string& str() const
303	{
304		return strType;
305	}
306
307	inline const std::string& refStr() const
308	{
309		return refStrType;
310	}
311
312	bool isStruct() const
313	{
314		return (baseType == 0);
315	}
316
317	bool isSigned() const
318	{
319		return signedType;
320	}
321
322	const char* abs() const
323	{
324		switch (baseType)
325		{
326		case GL_FLOAT:
327		case GL_SAMPLER:
328			return "0.1";
329		case GL_UNSIGNED_INT:
330			return "0u";
331		case GL_INT:
332			return "0";
333		default:
334			assert(0);
335			return "";
336		}
337	}
338
339	std::pair<int, int> getSize() const
340	{
341		return size;
342	}
343
344	GLenum getBaseType() const
345	{
346		return baseType;
347	}
348
349	void streamArrayStr(std::ostringstream& _str, int arrayElem = -1) const
350	{
351		if (!isArray)
352		{
353			return;
354		}
355		if (arrayElem < 0)
356		{
357			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
358			{
359				_str << "[" << arraySizesSegmented[segment] << "]";
360			}
361		}
362		else
363		{
364			int tailSize = arraySize;
365			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
366			{
367				tailSize /= arraySizesSegmented[segment];
368				_str << "[" << arrayElem / tailSize << "]";
369				arrayElem %= tailSize;
370			}
371		}
372	}
373
374	GLenum enumType;
375
376	//arrays-of-arrays size
377	std::vector<int> arraySizesSegmented;
378
379	//premultiplied array size
380	int arraySize;
381
382	//child types for nested (struct) types;
383	std::vector<UniformType> childTypes;
384
385private:
386	void fill()
387	{
388
389		size = std::pair<int, int>(1, 1);
390
391		switch (enumType)
392		{
393		case GL_SAMPLER_2D:
394			refStrType = "vec4";
395			strType	= "sampler2D";
396			baseType   = GL_SAMPLER;
397			break;
398		case GL_FLOAT:
399			refStrType = strType = "float";
400			baseType			 = GL_FLOAT;
401			break;
402		case GL_INT:
403			refStrType = strType = "int";
404			baseType			 = GL_INT;
405			break;
406		case GL_UNSIGNED_INT:
407			refStrType = strType = "uint";
408			baseType			 = GL_UNSIGNED_INT;
409			signedType			 = false;
410			break;
411		case GL_FLOAT_VEC2:
412			refStrType = strType = "vec2";
413			baseType			 = GL_FLOAT;
414			size.first			 = 2;
415			break;
416		case GL_FLOAT_VEC3:
417			refStrType = strType = "vec3";
418			baseType			 = GL_FLOAT;
419			size.first			 = 3;
420			break;
421		case GL_FLOAT_VEC4:
422			refStrType = strType = "vec4";
423			baseType			 = GL_FLOAT;
424			size.first			 = 4;
425			break;
426		case GL_FLOAT_MAT2:
427			strType	= "mat2";
428			refStrType = "vec2";
429			baseType   = GL_FLOAT;
430			size.first = size.second = 2;
431			break;
432		case GL_FLOAT_MAT3:
433			strType	= "mat3";
434			refStrType = "vec3";
435			baseType   = GL_FLOAT;
436			size.first = size.second = 3;
437			break;
438		case GL_FLOAT_MAT4:
439			strType	= "mat4";
440			refStrType = "vec4";
441			baseType   = GL_FLOAT;
442			size.first = size.second = 4;
443			break;
444		case GL_FLOAT_MAT2x3:
445			strType		= "mat2x3";
446			refStrType  = "vec3";
447			baseType	= GL_FLOAT;
448			size.first  = 3;
449			size.second = 2;
450			break;
451		case GL_FLOAT_MAT4x3:
452			strType		= "mat4x3";
453			refStrType  = "vec3";
454			baseType	= GL_FLOAT;
455			size.first  = 3;
456			size.second = 4;
457			break;
458		case GL_FLOAT_MAT2x4:
459			strType		= "mat2x4";
460			refStrType  = "vec4";
461			baseType	= GL_FLOAT;
462			size.first  = 4;
463			size.second = 2;
464			break;
465		case GL_FLOAT_MAT3x4:
466			strType		= "mat3x4";
467			refStrType  = "vec4";
468			baseType	= GL_FLOAT;
469			size.first  = 4;
470			size.second = 3;
471			break;
472		case GL_FLOAT_MAT3x2:
473			strType		= "mat3x2";
474			refStrType  = "vec2";
475			baseType	= GL_FLOAT;
476			size.first  = 2;
477			size.second = 3;
478			break;
479		case GL_FLOAT_MAT4x2:
480			strType		= "mat4x2";
481			refStrType  = "vec2";
482			baseType	= GL_FLOAT;
483			size.first  = 2;
484			size.second = 4;
485			break;
486		case GL_INT_VEC2:
487			refStrType = strType = "ivec2";
488			baseType			 = GL_INT;
489			size.first			 = 2;
490			break;
491		case GL_INT_VEC3:
492			refStrType = strType = "ivec3";
493			baseType			 = GL_INT;
494			size.first			 = 3;
495			break;
496		case GL_INT_VEC4:
497			refStrType = strType = "ivec4";
498			baseType			 = GL_INT;
499			size.first			 = 4;
500			break;
501		default:
502			assert(0);
503		}
504	}
505
506	std::string strType, refStrType;
507	std::pair<int, int> size;
508	GLenum baseType;
509	bool   isArray;
510	bool   signedType;
511};
512
513class UniformValueGenerator
514{
515public:
516	UniformValueGenerator() : fValue(0.0f), iValue(0)
517	{
518	}
519	GLfloat genF()
520	{
521		if (fValue > 99999.0f)
522		{
523			fValue = 0.0f;
524		}
525		return (fValue += 1.0f);
526	}
527	GLint genI()
528	{
529		return (iValue += 1);
530	}
531
532private:
533	UniformValueGenerator(const UniformValueGenerator&);
534	GLfloat fValue;
535	GLint   iValue;
536};
537
538class UniformValue
539{
540public:
541	void streamValue(std::ostringstream& str, int arrayElement = 0, int column = 0) const
542	{
543		int arrayElementSize = type.getSize().first * type.getSize().second;
544
545		str << type.refStr() << "(";
546
547		if (type.getBaseType() == GL_SAMPLER)
548		{
549			for (size_t elem = 0; elem < 4; elem++)
550			{
551				if (elem)
552					str << ", ";
553				str << fValues[arrayElement * 4 + elem];
554			}
555			str << ")";
556			return;
557		}
558
559		for (int elem = 0; fValues.size() && elem < type.getSize().first; elem++)
560		{
561			if (elem)
562				str << ", ";
563			str << fValues[arrayElement * arrayElementSize + column * type.getSize().first + elem] << ".0";
564		}
565		for (int elem = 0; iValues.size() && elem < type.getSize().first; elem++)
566		{
567			if (elem)
568				str << ", ";
569			str << iValues[arrayElement * arrayElementSize + elem];
570		}
571		for (int elem = 0; uValues.size() && elem < type.getSize().first; elem++)
572		{
573			if (elem)
574				str << ", ";
575			str << uValues[arrayElement * arrayElementSize + elem] << "u";
576		}
577		str << ")";
578	}
579
580	const void* getPtr(int arrayElement) const
581	{
582		int arrayElementSize = type.getSize().first * type.getSize().second;
583		if (type.getBaseType() == GL_INT || type.getBaseType() == GL_SAMPLER)
584		{
585			return &iValues[arrayElement * arrayElementSize];
586		}
587		else if (type.getBaseType() == GL_UNSIGNED_INT)
588		{
589			return &uValues[arrayElement * arrayElementSize];
590		}
591		else if (type.getBaseType() == GL_FLOAT)
592		{
593			return &fValues[arrayElement * arrayElementSize];
594		}
595		assert(0);
596		return NULL;
597	}
598
599	UniformValue(const UniformType& _type, UniformValueGenerator& generator) : type(_type)
600	{
601		const int sizeRow	= type.getSize().first;
602		const int sizeColumn = type.getSize().second;
603
604		if (type.isStruct())
605		{
606			return;
607		}
608
609		if (type.getBaseType() == GL_INT)
610		{
611			assert(sizeColumn == 1);
612			iValues.resize(sizeRow * type.arraySize);
613			for (size_t elem = 0; elem < iValues.size(); elem++)
614			{
615				iValues[elem] = generator.genI();
616			}
617		}
618		else if (type.getBaseType() == GL_UNSIGNED_INT)
619		{
620			assert(sizeColumn == 1);
621			uValues.resize(sizeRow * type.arraySize);
622			for (size_t elem = 0; elem < uValues.size(); elem++)
623			{
624				uValues[elem] = static_cast<GLuint>(generator.genI());
625			}
626		}
627		else if (type.getBaseType() == GL_FLOAT)
628		{
629			fValues.resize(sizeColumn * sizeRow * type.arraySize);
630			for (size_t elem = 0; elem < fValues.size(); elem++)
631			{
632				fValues[elem] = generator.genF();
633			}
634		}
635		else if (type.getBaseType() == GL_SAMPLER)
636		{
637			//color ref value
638			fValues.resize(4 * type.arraySize);
639			for (size_t elem = 0; elem < fValues.size(); elem++)
640			{
641				fValues[elem] = float(elem) / float(fValues.size());
642			}
643			//uniform value
644			iValues.resize(type.arraySize);
645			for (size_t elem = 0; elem < iValues.size(); elem++)
646			{
647				iValues[elem] = generator.genI() % 16;
648			}
649		}
650		else
651		{
652			assert(0);
653		}
654	}
655
656	std::vector<GLfloat> fValues;
657	std::vector<GLint>   iValues;
658	std::vector<GLint>   uValues;
659
660private:
661	UniformType type;
662};
663
664class Uniform
665{
666public:
667	Uniform(UniformValueGenerator& generator, UniformType _type, Loc _location,
668			DefOccurence _declOccurence = DefOccurence::ALL_SH, DefOccurence _usageOccurence = DefOccurence::ALL_SH)
669		: type(_type)
670		, location(_location)
671		, declOccurence(_declOccurence)
672		, usageOccurence(_usageOccurence)
673		, value(_type, generator)
674	{
675
676		if (type.isStruct())
677		{
678			int currentLocation = location.val;
679			for (int arrayElem = 0; arrayElem < type.arraySize; arrayElem++)
680			{
681				for (size_t child = 0; child < type.childTypes.size(); child++)
682				{
683					Loc childLocation = Loc::Implicit();
684					if (currentLocation > 0)
685					{
686						childLocation = Loc::C(currentLocation);
687					}
688					childUniforms.push_back(
689						Uniform(generator, type.childTypes[child], childLocation, declOccurence, usageOccurence));
690					currentLocation += type.childTypes[child].arraySize;
691				}
692			}
693		}
694	}
695
696	void setName(const std::string& parentName, const std::string& _name)
697	{
698		shortName = _name;
699		{
700			std::ostringstream __name;
701			__name << parentName << _name;
702			name = __name.str();
703		}
704		if (type.isStruct())
705		{
706			for (size_t i = 0; i < childUniforms.size(); i++)
707			{
708				std::ostringstream childName;
709				childName << "m" << (i % (childUniforms.size() / type.arraySize));
710				std::ostringstream childParentName;
711				childParentName << name;
712				type.streamArrayStr(childParentName, (int)(i / type.arraySize));
713				childParentName << ".";
714				childUniforms[i].setName(childParentName.str(), childName.str());
715			}
716		}
717	}
718	const std::string& getName() const
719	{
720		return name;
721	}
722
723	void streamDefinition(std::ostringstream& str) const
724	{
725		str << type.str() << " " << shortName;
726		type.streamArrayStr(str);
727	}
728
729	UniformType  type;
730	Loc			 location;
731	DefOccurence declOccurence, usageOccurence;
732	UniformValue value;
733
734	std::vector<Uniform> childUniforms;
735	std::string			 name, shortName;
736};
737
738class SubroutineFunction
739{
740public:
741	SubroutineFunction(UniformValueGenerator& generator, Index _index = Index::Implicit())
742		: index(_index), embeddedRetVal(GL_FLOAT_VEC4, generator)
743	{
744	}
745	const UniformValue& getRetVal() const
746	{
747		return embeddedRetVal;
748	}
749
750	inline const std::string& getName() const
751	{
752		return name;
753	}
754
755	void setName(int _name)
756	{
757		std::ostringstream __name;
758		__name << "sf" << _name;
759		name = __name.str();
760	}
761
762	Index index;
763
764private:
765	UniformValue embeddedRetVal;
766	std::string  name;
767};
768
769class SubroutineFunctionSet
770{
771public:
772	SubroutineFunctionSet(UniformValueGenerator& generator, size_t count = 0) : fn(count, SubroutineFunction(generator))
773	{
774	}
775
776	void push_back(const SubroutineFunction& _fn)
777	{
778		fn.push_back(_fn);
779	}
780
781	inline const std::string& getTypeName() const
782	{
783		return typeName;
784	}
785
786	void setTypeName(int _name)
787	{
788		std::ostringstream __name;
789		__name << "st" << _name;
790		typeName = __name.str();
791	}
792
793	std::vector<SubroutineFunction> fn;
794	std::string						typeName;
795};
796
797class SubroutineUniform
798{
799public:
800	SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location,
801					  int _arraySize = 0, DefOccurence _defOccurence = DefOccurence::ALL_SH, bool _used = true)
802		: functions(_functions)
803		, location(_location)
804		, arraySize(_arraySize)
805		, defOccurence(_defOccurence)
806		, used(_used)
807		, embeddedUIntUniform(GL_UNSIGNED_INT, generator)
808	{
809
810		assert(arraySize >= 0);
811
812		if (!arraySize)
813		{
814			arraySize = 1;
815			isArray   = false;
816		}
817		else
818		{
819			isArray = true;
820		}
821
822		arraySizesSegmented.push_back(arraySize);
823
824		embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator);
825		for (int i = 0; i < arraySize; i++)
826		{
827			embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size());
828		}
829	}
830
831	SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location,
832					  std::vector<int> _arraySizesSegmented, DefOccurence _defOccurence = DefOccurence::ALL_SH,
833					  bool _used = true)
834		: functions(_functions)
835		, location(_location)
836		, defOccurence(_defOccurence)
837		, used(_used)
838		, arraySizesSegmented(_arraySizesSegmented)
839		, isArray(true)
840		, embeddedUIntUniform(GL_UNSIGNED_INT, generator)
841	{
842
843		arraySize = 1;
844		for (size_t i = 0; i < arraySizesSegmented.size(); i++)
845		{
846			assert(arraySizesSegmented[i] > 0);
847			arraySize *= arraySizesSegmented[i];
848		}
849
850		embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator);
851		for (int i = 0; i < arraySize; i++)
852		{
853			embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size());
854		}
855	}
856	void setName(const std::string& _name)
857	{
858		name = _name;
859	}
860
861	const std::string& getName() const
862	{
863		return name;
864	}
865
866	void streamArrayStr(std::ostringstream& str, int arrayElem = -1) const
867	{
868		if (!isArray)
869		{
870			return;
871		}
872		if (arrayElem < 0)
873		{
874			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
875			{
876				str << "[" << arraySizesSegmented[segment] << "]";
877			}
878		}
879		else
880		{
881			int tailSize = arraySize;
882			for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++)
883			{
884				tailSize /= arraySizesSegmented[segment];
885				str << "[" << arrayElem / tailSize << "]";
886				arrayElem %= tailSize;
887			}
888		}
889	}
890
891	const SubroutineFunction& getSelectedFunction(int arrayElem) const
892	{
893		assert(arrayElem < arraySize);
894		return functions.fn[embeddedUIntUniform.uValues[arrayElem]];
895	}
896
897	SubroutineFunctionSet functions;
898	Loc					  location;
899	int					  arraySize;
900	DefOccurence		  defOccurence;
901	bool				  used;
902
903private:
904	std::vector<int> arraySizesSegmented;
905	bool			 isArray;
906	UniformValue	 embeddedUIntUniform;
907
908	std::string name;
909};
910
911class ShaderKey
912{
913public:
914	ShaderKey()
915	{
916	}
917	ShaderKey(GLenum _stage, const std::string& _input, const std::string& _output)
918		: stage(_stage), input(_input), output(_output)
919	{
920	}
921	GLenum		stage;
922	std::string input, output;
923
924	bool operator<(const ShaderKey& rhs) const
925	{
926		if (stage == rhs.stage)
927		{
928			if (input == rhs.input)
929			{
930				return (output < rhs.output);
931			}
932			return input < rhs.input;
933		}
934		return stage < rhs.stage;
935	}
936};
937
938class CompiledProgram
939{
940public:
941	GLuint				name;
942	std::vector<GLenum> stages;
943};
944
945class ShaderSourceFactory
946{
947
948	static void streamUniformDefinitions(const std::vector<Uniform>& uniforms, GLenum shader, std::ostringstream& ret)
949	{
950		for (size_t i = 0; i < uniforms.size(); i++)
951		{
952			if (uniforms[i].declOccurence.occurs(shader))
953			{
954				if (uniforms[i].type.isStruct())
955				{
956					ret << "struct " << uniforms[i].type.str() << " {" << std::endl;
957					for (size_t child = 0; child < uniforms[i].childUniforms.size() / uniforms[i].type.arraySize;
958						 child++)
959					{
960						ret << "    ";
961						uniforms[i].childUniforms[child].streamDefinition(ret);
962						ret << ";" << std::endl;
963					}
964					ret << "};" << std::endl;
965				}
966				uniforms[i].location.streamDefinition(ret, shader);
967				ret << "uniform ";
968				uniforms[i].streamDefinition(ret);
969				ret << ";" << std::endl;
970			}
971		}
972	}
973
974	static void streamSubroutineDefinitions(const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader,
975											std::ostringstream& ret)
976	{
977		if (subroutineUniforms.size())
978		{
979			//add a "zero" uniform;
980			ret << "uniform float zero;" << std::endl;
981		}
982
983		for (size_t i = 0; i < subroutineUniforms.size(); i++)
984		{
985			if (subroutineUniforms[i].defOccurence.occurs(shader))
986			{
987
988				//subroutine vec4 st0(float param);
989				ret << "subroutine vec4 " << subroutineUniforms[i].functions.getTypeName() << "(float param);"
990					<< std::endl;
991
992				for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
993				{
994					//layout(index = X) subroutine(st0) vec4 sf0(float param) { .... };
995					subroutineUniforms[i].functions.fn[fn].index.streamDefinition(ret, shader);
996					ret << "subroutine(" << subroutineUniforms[i].functions.getTypeName() << ") vec4 "
997						<< subroutineUniforms[i].functions.fn[fn].getName() << "(float param) { return zero + ";
998					subroutineUniforms[i].functions.fn[fn].getRetVal().streamValue(ret);
999					ret << "; }" << std::endl;
1000				}
1001
1002				//layout(location = X) subroutine uniform stX uX[...];
1003				subroutineUniforms[i].location.streamDefinition(ret, shader);
1004				ret << "subroutine uniform " << subroutineUniforms[i].functions.getTypeName() << " "
1005					<< subroutineUniforms[i].getName();
1006				subroutineUniforms[i].streamArrayStr(ret);
1007				ret << ";" << std::endl;
1008			}
1009		}
1010	}
1011
1012	static void streamUniformValidator(std::ostringstream& ret, const Uniform& uniform, GLenum shader,
1013									   const char* outTemporary)
1014	{
1015		if (uniform.declOccurence.occurs(shader) && uniform.usageOccurence.occurs(shader))
1016		{
1017			if (uniform.type.isStruct())
1018			{
1019				for (size_t child = 0; child < uniform.childUniforms.size(); child++)
1020				{
1021					streamUniformValidator(ret, uniform.childUniforms[child], shader, outTemporary);
1022				}
1023			}
1024			else
1025			{
1026				for (int arrayElement = 0; arrayElement < uniform.type.arraySize; arrayElement++)
1027				{
1028					for (int column = 0; column < uniform.type.getSize().second; column++)
1029					{
1030						std::string columnIndex;
1031						if (uniform.type.getSize().second > 1)
1032						{
1033							std::ostringstream str;
1034							str << "[" << column << "]";
1035							columnIndex = str.str();
1036						}
1037						std::string absoluteF;
1038						if (uniform.type.isSigned())
1039						{
1040							absoluteF = "abs";
1041						}
1042
1043						if (uniform.type.getBaseType() == GL_SAMPLER)
1044						{
1045							ret << NL "    if (any(greaterThan(" << absoluteF << "(texture(" << uniform.getName();
1046							uniform.type.streamArrayStr(ret, arrayElement);
1047							ret << columnIndex << ", vec2(0.5)) - ";
1048							uniform.value.streamValue(ret, arrayElement, column);
1049							ret << " ), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {";
1050						}
1051						else if (uniform.type.getSize().first > 1)
1052						{
1053							ret << NL "    if (any(greaterThan(" << absoluteF << "(" << uniform.getName();
1054							uniform.type.streamArrayStr(ret, arrayElement);
1055							ret << columnIndex << " - ";
1056							uniform.value.streamValue(ret, arrayElement, column);
1057							ret << "), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {";
1058						}
1059						else
1060						{
1061							ret << NL "    if (" << absoluteF << "(" << uniform.getName();
1062							uniform.type.streamArrayStr(ret, arrayElement);
1063							ret << " - ";
1064							uniform.value.streamValue(ret, arrayElement);
1065							ret << ") >" << uniform.type.refStr() << "(" << uniform.type.abs() << ")) {";
1066						}
1067						ret << NL "       " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);";
1068						ret << NL "    }";
1069					}
1070				}
1071			}
1072		}
1073	}
1074
1075	static void streamUniformValidators(std::ostringstream& ret, const std::vector<Uniform>& uniforms, GLenum shader,
1076										const char* outTemporary)
1077	{
1078		for (size_t i = 0; i < uniforms.size(); i++)
1079		{
1080			streamUniformValidator(ret, uniforms[i], shader, outTemporary);
1081		}
1082	}
1083
1084	static void streamSubroutineValidator(std::ostringstream& ret, const SubroutineUniform& subroutineUniform,
1085										  GLenum shader, const char* outTemporary)
1086	{
1087		if (subroutineUniform.defOccurence.occurs(shader) && subroutineUniform.used)
1088		{
1089			for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
1090			{
1091				ret << NL "    if (any(greaterThan(abs(" << subroutineUniform.getName();
1092				subroutineUniform.streamArrayStr(ret, arrayElem);
1093				ret << "(zero) - ";
1094				subroutineUniform.getSelectedFunction(arrayElem).getRetVal().streamValue(ret);
1095				ret << "), vec4(0.1)))) {";
1096				ret << NL "       " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);";
1097				ret << NL "    }";
1098			}
1099		}
1100	}
1101
1102	static void streamSubroutineValidators(std::ostringstream&					 ret,
1103										   const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader,
1104										   const char* outTemporary)
1105	{
1106		for (size_t i = 0; i < subroutineUniforms.size(); i++)
1107		{
1108			streamSubroutineValidator(ret, subroutineUniforms[i], shader, outTemporary);
1109		}
1110	}
1111
1112	static void streamShaderHeader(std::ostringstream& str, const glu::ContextType type)
1113	{
1114		if (glu::isContextTypeES(type))
1115		{
1116			str << "#version 310 es" NL "precision highp float;" NL "precision highp int;";
1117		}
1118		else
1119		{
1120			str << "#version 430 core" NL;
1121		}
1122	}
1123
1124	static std::string generateFragmentShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
1125											  const std::vector<SubroutineUniform>& subroutineUniforms,
1126											  const std::string& additionalDef, const glu::ContextType type)
1127	{
1128
1129		std::ostringstream ret;
1130		streamShaderHeader(ret, type);
1131		ret << NL;
1132		streamUniformDefinitions(uniforms, GL_FRAGMENT_SHADER, ret);
1133		ret << NL;
1134		streamSubroutineDefinitions(subroutineUniforms, GL_FRAGMENT_SHADER, ret);
1135		ret << NL << additionalDef << NL "in vec4 " << key.input << ";" << NL "out vec4 out_FragColor;"
1136			<< NL "void main() {" << NL "    vec4 validationResult = " << key.input << ";" << NL;
1137		streamUniformValidators(ret, uniforms, GL_FRAGMENT_SHADER, "validationResult");
1138		ret << NL;
1139		streamSubroutineValidators(ret, subroutineUniforms, GL_FRAGMENT_SHADER, "validationResult");
1140		ret << NL "    out_FragColor =  validationResult;" << NL "}";
1141
1142		return ret.str();
1143	}
1144
1145	static std::string generateVertexShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
1146											const std::vector<SubroutineUniform>& subroutineUniforms,
1147											const std::string& additionalDef, const glu::ContextType type)
1148	{
1149
1150		std::ostringstream ret;
1151		streamShaderHeader(ret, type);
1152		ret << NL;
1153		streamUniformDefinitions(uniforms, GL_VERTEX_SHADER, ret);
1154		ret << NL;
1155		streamSubroutineDefinitions(subroutineUniforms, GL_VERTEX_SHADER, ret);
1156		ret << NL << additionalDef << NL "in vec4 in_Position;" << NL "out vec4 " << key.output << ";"
1157			<< NL "void main() {" << NL "    vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);" << NL;
1158		streamUniformValidators(ret, uniforms, GL_VERTEX_SHADER, "validationResult");
1159		ret << NL;
1160		streamSubroutineValidators(ret, subroutineUniforms, GL_VERTEX_SHADER, "validationResult");
1161		ret << NL "    " << key.output << " = validationResult;" << NL "    gl_Position = in_Position;" << NL "}";
1162		return ret.str();
1163	}
1164
1165	static std::string generateComputeShader(const ShaderKey&, const std::vector<Uniform>& uniforms,
1166											 const std::vector<SubroutineUniform>& subroutineUniforms,
1167											 const std::string& additionalDef, const glu::ContextType type)
1168	{
1169
1170		std::ostringstream ret;
1171		streamShaderHeader(ret, type);
1172		ret << NL "layout (local_size_x = 1, local_size_y = 1) in;"
1173			<< NL "layout (std430, binding = 1) buffer ResultBuffer {" << NL "    vec4 cs_ValidationResult;" << NL "};"
1174			<< NL;
1175		streamUniformDefinitions(uniforms, GL_COMPUTE_SHADER, ret);
1176		ret << NL;
1177		streamSubroutineDefinitions(subroutineUniforms, GL_COMPUTE_SHADER, ret);
1178		ret << NL << additionalDef << NL "void main() {" << NL "    vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);"
1179			<< NL;
1180		streamUniformValidators(ret, uniforms, GL_COMPUTE_SHADER, "validationResult");
1181		ret << NL;
1182		streamSubroutineValidators(ret, subroutineUniforms, GL_COMPUTE_SHADER, "validationResult");
1183		ret << NL "    cs_ValidationResult =  validationResult;" << NL "}";
1184		return ret.str();
1185	}
1186
1187public:
1188	static std::string generateShader(const ShaderKey& key, const std::vector<Uniform>& uniforms,
1189									  const std::vector<SubroutineUniform>& subroutineUniforms,
1190									  const std::string& additionalDef, const glu::ContextType type)
1191	{
1192
1193		switch (key.stage)
1194		{
1195		case GL_VERTEX_SHADER:
1196			return generateVertexShader(key, uniforms, subroutineUniforms, additionalDef, type);
1197		case GL_FRAGMENT_SHADER:
1198			return generateFragmentShader(key, uniforms, subroutineUniforms, additionalDef, type);
1199			break;
1200		case GL_COMPUTE_SHADER:
1201			return generateComputeShader(key, uniforms, subroutineUniforms, additionalDef, type);
1202			break;
1203		default:
1204			assert(0);
1205			return "";
1206		}
1207	}
1208};
1209
1210class ExplicitUniformLocationCaseBase : public glcts::SubcaseBase
1211{
1212	virtual std::string Title()
1213	{
1214		return "";
1215	}
1216	virtual std::string Purpose()
1217	{
1218		return "";
1219	}
1220	virtual std::string Method()
1221	{
1222		return "";
1223	}
1224	virtual std::string PassCriteria()
1225	{
1226		return "";
1227	}
1228
1229	int getWindowWidth()
1230	{
1231		return m_context.getRenderContext().getRenderTarget().getWidth();
1232	}
1233
1234	int getWindowHeight()
1235	{
1236		return m_context.getRenderContext().getRenderTarget().getHeight();
1237	}
1238
1239	std::map<ShaderKey, GLuint> CreateShaders(const std::vector<std::vector<ShaderKey> >& programConfigs,
1240											  const std::vector<Uniform>&			uniforms,
1241											  const std::vector<SubroutineUniform>& subroutineUniforms,
1242											  const std::string&					additionalDef)
1243	{
1244		std::map<ShaderKey, GLuint> ret;
1245
1246		//create shaders
1247		for (size_t config = 0; config < programConfigs.size(); config++)
1248		{
1249			for (size_t target = 0; target < programConfigs[config].size(); target++)
1250			{
1251
1252				if (ret.find(programConfigs[config][target]) == ret.end())
1253				{
1254					GLuint shader = glCreateShader(programConfigs[config][target].stage);
1255
1256					std::string source = ShaderSourceFactory::generateShader(programConfigs[config][target], uniforms,
1257																			 subroutineUniforms, additionalDef,
1258																			 m_context.getRenderContext().getType());
1259					const char* cSource[] = { source.c_str() };
1260					glShaderSource(shader, 1, cSource, NULL);
1261					ret[programConfigs[config][target]] = shader;
1262				}
1263			}
1264		}
1265
1266		//compile shaders
1267		for (std::map<ShaderKey, GLuint>::iterator i = ret.begin(); i != ret.end(); i++)
1268		{
1269			glCompileShader(i->second);
1270		}
1271
1272		return ret;
1273	}
1274
1275	long CreatePrograms(std::vector<CompiledProgram>& programs, const std::vector<Uniform>& uniforms,
1276						const std::vector<SubroutineUniform>& subroutineUniforms, const std::string& additionalDef,
1277						bool negativeCompile, bool negativeLink)
1278	{
1279
1280		long ret = NO_ERROR;
1281
1282		std::vector<std::vector<ShaderKey> > programConfigs;
1283		{
1284			std::vector<ShaderKey> vsh_fsh(2);
1285			vsh_fsh[0] = ShaderKey(GL_VERTEX_SHADER, "", "vs_ValidationResult");
1286			vsh_fsh[1] = ShaderKey(GL_FRAGMENT_SHADER, "vs_ValidationResult", "");
1287			programConfigs.push_back(vsh_fsh);
1288		}
1289		{
1290			std::vector<ShaderKey> csh(1);
1291			csh[0] = ShaderKey(GL_COMPUTE_SHADER, "", "");
1292			programConfigs.push_back(csh);
1293		}
1294
1295		std::map<ShaderKey, GLuint> shaders =
1296			CreateShaders(programConfigs, uniforms, subroutineUniforms, additionalDef);
1297
1298		//query compilation results
1299		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1300		{
1301			GLint status;
1302			glGetShaderiv(it->second, GL_COMPILE_STATUS, &status);
1303			GLchar infoLog[1000], source[4000];
1304			glGetShaderSource(it->second, 4000, NULL, source);
1305			glGetShaderInfoLog(it->second, 1000, NULL, infoLog);
1306			Logger::Get()->writeKernelSource(source);
1307			Logger::Get()->writeCompileInfo("shader", "", status == GL_TRUE, infoLog);
1308
1309			if (!negativeLink)
1310			{
1311				if (!negativeCompile)
1312				{
1313					if (status != GL_TRUE)
1314					{
1315						Logger() << "Shader compilation failed";
1316						ret |= ERROR;
1317					}
1318				}
1319				else
1320				{
1321					if (status)
1322					{
1323						Logger() << "Negative compilation case failed: shader shoult not compile, but "
1324									"GL_COMPILE_STATUS != 0";
1325						ret |= ERROR;
1326					}
1327				}
1328			}
1329		}
1330
1331		if (negativeCompile)
1332		{
1333
1334			//delete shaders
1335			for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1336			{
1337				glDeleteShader(it->second);
1338			}
1339
1340			return ret;
1341		}
1342
1343		//assemble programs and link
1344		for (size_t config = 0; config < programConfigs.size(); config++)
1345		{
1346			CompiledProgram program;
1347			program.name = glCreateProgram();
1348
1349			for (size_t target = 0; target < programConfigs[config].size(); target++)
1350			{
1351
1352				GLuint shader = shaders.find(programConfigs[config][target])->second;
1353
1354				glAttachShader(program.name, shader);
1355
1356				program.stages.push_back(programConfigs[config][target].stage);
1357			}
1358			programs.push_back(program);
1359			glLinkProgram(programs[config].name);
1360		}
1361		for (size_t config = 0; config < programConfigs.size(); config++)
1362		{
1363			glLinkProgram(programs[config].name);
1364		}
1365
1366		//delete shaders
1367		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1368		{
1369			glDeleteShader(it->second);
1370		}
1371
1372		//query link status:
1373		for (size_t config = 0; config < programConfigs.size(); config++)
1374		{
1375			GLint status;
1376
1377			glGetProgramiv(programs[config].name, GL_LINK_STATUS, &status);
1378			GLchar infoLog[1000];
1379			glGetProgramInfoLog(programs[config].name, 1000, NULL, infoLog);
1380			Logger::Get()->writeCompileInfo("program", "", status == GL_TRUE, infoLog);
1381
1382			if (!negativeLink)
1383			{
1384				if (status != GL_TRUE)
1385				{
1386					Logger() << "Shader link failed";
1387					ret |= ERROR;
1388				}
1389			}
1390			else
1391			{
1392				if (status)
1393				{
1394					Logger() << "Negative link case failed: program should not link, but GL_LINK_STATUS != 0";
1395					ret |= ERROR;
1396				}
1397			}
1398		}
1399		return ret;
1400	}
1401
1402	long DeletePrograms(std::vector<CompiledProgram>& programs)
1403	{
1404		for (size_t i = 0; i < programs.size(); i++)
1405		{
1406			glDeleteProgram(programs[i].name);
1407		}
1408		programs.resize(0);
1409		return NO_ERROR;
1410	}
1411
1412	void setUniform(const Uniform& uniform, const CompiledProgram& program)
1413	{
1414
1415		bool used = false;
1416		for (size_t i = 0; i < program.stages.size(); i++)
1417		{
1418			used |= uniform.declOccurence.occurs(program.stages[i]) && uniform.usageOccurence.occurs(program.stages[i]);
1419		}
1420		if (!used)
1421			return;
1422
1423		if (uniform.type.isStruct())
1424		{
1425			for (size_t j = 0; j < uniform.childUniforms.size(); j++)
1426			{
1427				setUniform(uniform.childUniforms[j], program);
1428			}
1429		}
1430		else
1431		{
1432			GLint loc;
1433			if (uniform.location.isImplicit(program.stages))
1434			{
1435				std::ostringstream name;
1436				name << uniform.getName();
1437				uniform.type.streamArrayStr(name, 0);
1438				loc = glGetUniformLocation(program.name, name.str().c_str());
1439			}
1440			else
1441			{
1442				loc = uniform.location.val;
1443			}
1444
1445			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
1446			{
1447				switch (uniform.type.enumType)
1448				{
1449				case GL_FLOAT:
1450					glUniform1f(loc, *(GLfloat*)uniform.value.getPtr(arrayElem));
1451					break;
1452				case GL_FLOAT_VEC2:
1453					glUniform2fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1454					break;
1455				case GL_FLOAT_VEC3:
1456					glUniform3fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1457					break;
1458				case GL_FLOAT_VEC4:
1459					glUniform4fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1460					break;
1461				case GL_FLOAT_MAT2:
1462					glUniformMatrix2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1463					break;
1464				case GL_FLOAT_MAT3:
1465					glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1466					break;
1467				case GL_FLOAT_MAT4:
1468					glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1469					break;
1470				case GL_FLOAT_MAT2x3:
1471					glUniformMatrix2x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1472					break;
1473				case GL_FLOAT_MAT4x3:
1474					glUniformMatrix4x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1475					break;
1476				case GL_FLOAT_MAT2x4:
1477					glUniformMatrix2x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1478					break;
1479				case GL_FLOAT_MAT3x4:
1480					glUniformMatrix3x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1481					break;
1482				case GL_FLOAT_MAT3x2:
1483					glUniformMatrix3x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1484					break;
1485				case GL_FLOAT_MAT4x2:
1486					glUniformMatrix4x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1487					break;
1488				case GL_INT:
1489				case GL_SAMPLER_2D:
1490					glUniform1i(loc, *(GLint*)uniform.value.getPtr(arrayElem));
1491					break;
1492				case GL_INT_VEC2:
1493					glUniform2iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1494					break;
1495				case GL_INT_VEC3:
1496					glUniform3iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1497					break;
1498				case GL_INT_VEC4:
1499					glUniform4iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1500					break;
1501				case GL_UNSIGNED_INT:
1502					glUniform1ui(loc, *(GLuint*)uniform.value.getPtr(arrayElem));
1503					break;
1504				default:
1505					assert(0);
1506				}
1507				loc++;
1508			}
1509		}
1510	}
1511
1512	void setSubroutineUniform(const SubroutineUniform& subroutineUniform, const CompiledProgram& program, GLenum stage,
1513							  std::vector<glw::GLuint>& indicesOut)
1514	{
1515		bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
1516		if (used)
1517		{
1518
1519			for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
1520			{
1521				GLint loc = -1;
1522				if (subroutineUniform.location.isImplicit(program.stages))
1523				{
1524					std::ostringstream name;
1525					name << subroutineUniform.getName();
1526					subroutineUniform.streamArrayStr(name, arrayElem);
1527					loc = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
1528				}
1529				else
1530				{
1531					loc = subroutineUniform.location.val + arrayElem;
1532				}
1533
1534				if (loc >= 0)
1535				{
1536					const SubroutineFunction& selectedFunction = subroutineUniform.getSelectedFunction(arrayElem);
1537
1538					int index = -1;
1539					if (selectedFunction.index.isImplicit(std::vector<GLenum>(1, stage)))
1540					{
1541						index = glGetSubroutineIndex(program.name, stage, selectedFunction.getName().c_str());
1542					}
1543					else
1544					{
1545						index = selectedFunction.index.val;
1546					}
1547
1548					if (loc < (int)indicesOut.size())
1549					{
1550						indicesOut[loc] = index;
1551					}
1552					else
1553					{
1554						assert(0);
1555					}
1556				}
1557				else
1558				{
1559					assert(0);
1560				}
1561			}
1562		}
1563	}
1564
1565	long runExecuteProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
1566						   const std::vector<SubroutineUniform>& subroutineUniforms)
1567	{
1568		long ret = NO_ERROR;
1569
1570		glUseProgram(program.name);
1571
1572		for (size_t i = 0; i < uniforms.size(); i++)
1573		{
1574			setUniform(uniforms[i], program);
1575		}
1576
1577		for (size_t stage = 0; stage < program.stages.size() && subroutineUniforms.size(); stage++)
1578		{
1579
1580			glw::GLint numactive;
1581			glGetProgramStageiv(program.name, program.stages[stage], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
1582								&numactive);
1583			if (numactive)
1584			{
1585				std::vector<glw::GLuint> indices(numactive, 0);
1586
1587				for (size_t i = 0; i < subroutineUniforms.size(); i++)
1588				{
1589					setSubroutineUniform(subroutineUniforms[i], program, program.stages[stage], indices);
1590				}
1591				glUniformSubroutinesuiv(program.stages[stage], numactive, &indices[0]);
1592			}
1593		}
1594
1595		if (program.stages[0] != GL_COMPUTE_SHADER)
1596		{
1597			glClear(GL_COLOR_BUFFER_BIT);
1598			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1599
1600			std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
1601
1602			glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
1603			for (size_t i = 0; i < pixels.size(); i += 4)
1604			{
1605				if (pixels[i] != 0 || pixels[i + 1] != 255 || pixels[i + 2] != 0)
1606				{
1607					ret |= ERROR;
1608					Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)pixels[i]
1609							 << ", " << (int)pixels[i + 1] << ", " << (int)pixels[i + 2] << ", " << (int)pixels[i + 3]
1610							 << ").";
1611					break;
1612				}
1613			}
1614			Logger().Get()->writeImage("rendered image", "", QP_IMAGE_COMPRESSION_MODE_BEST, QP_IMAGE_FORMAT_RGBA8888,
1615									   getWindowWidth(), getWindowHeight(), 0, &pixels[0]);
1616		}
1617		else
1618		{
1619			GLuint buffer;
1620			glGenBuffers(1, &buffer);
1621			glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1622			glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLfloat), NULL, GL_DYNAMIC_READ);
1623			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
1624
1625			glDispatchCompute(1, 1, 1);
1626			glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
1627
1628			GLfloat* color = reinterpret_cast<GLfloat*>(
1629				glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(GLfloat), GL_MAP_READ_BIT));
1630
1631			if (color[0] != 0 || color[1] != 1.0 || color[2] != 0)
1632			{
1633				ret |= ERROR;
1634				Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)color[0]
1635						 << ", " << (int)color[1] << ", " << (int)color[2] << ", " << (int)color[3] << ").";
1636			}
1637
1638			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1639
1640			glDeleteBuffers(1, &buffer);
1641		}
1642
1643		return ret;
1644	}
1645
1646	long runQueryUniform(const CompiledProgram& program, const Uniform& uniform, std::set<GLuint>& usedLocations,
1647						 GLint max)
1648	{
1649		long ret = NO_ERROR;
1650
1651		/*
1652		 glGetUniformLocation(program, name);
1653		 Query passes if returned value is unique in current program, matches
1654		 explicit location (if passed in GLSL code) and is less than value of
1655		 GL_MAX_UNIFORM_LOCATIONS.
1656
1657		 glGetProgramResourceLocation(program, GL_UNIFIORM, name);
1658		 Query passes if returned value matches value returned from
1659		 glGetUniformLocation().
1660		 */
1661
1662		if (uniform.type.isStruct())
1663		{
1664			for (size_t i = 0; i < uniform.childUniforms.size(); i++)
1665			{
1666				ret |= runQueryUniform(program, uniform.childUniforms[i], usedLocations, max);
1667			}
1668		}
1669		else
1670		{
1671			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
1672			{
1673
1674				/* Location that is taken by this uniform (even if not used).*/
1675				GLint reservedLocation = -1;
1676				if (!uniform.location.isImplicit(program.stages))
1677				{
1678					reservedLocation = uniform.location.val + arrayElem;
1679				}
1680
1681				//optimization: for continuous arrays run queries at the beging and end only.
1682				bool runQueries = uniform.location.isImplicit(program.stages) ||
1683								  (arrayElem < 1000 || arrayElem > uniform.type.arraySize - 1000);
1684
1685				if (runQueries)
1686				{
1687					std::ostringstream name;
1688					name << uniform.getName();
1689					uniform.type.streamArrayStr(name, arrayElem);
1690					GLint returned = glGetUniformLocation(program.name, name.str().c_str());
1691
1692					GLint returnedPIQ = glGetProgramResourceLocation(program.name, GL_UNIFORM, name.str().c_str());
1693
1694					if (returned != returnedPIQ)
1695					{
1696						ret |= ERROR;
1697						Logger()
1698							<< "Locations of  uniform \"" << name.str()
1699							<< "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
1700							<< returned << " != " << returnedPIQ << ".";
1701					}
1702
1703					bool used = false;
1704					for (size_t i = 0; i < program.stages.size(); i++)
1705					{
1706						used |= uniform.declOccurence.occurs(program.stages[i]) &&
1707								uniform.usageOccurence.occurs(program.stages[i]);
1708					}
1709
1710					if (!uniform.location.isImplicit(program.stages))
1711					{
1712						//Validate uniform location against explicit value
1713						GLint expected = reservedLocation;
1714						if (!(expected == returned || (!used && returned == -1)))
1715						{
1716							ret |= ERROR;
1717							Logger() << "Unexpected uniform \"" << name.str() << "\" location: expected " << expected
1718									 << ", got " << returned << ".";
1719						}
1720					}
1721					else
1722					{
1723						//Check if location > 0 if used;
1724						if (used)
1725						{
1726							if (returned < 0)
1727							{
1728								ret |= ERROR;
1729								Logger() << "Unexpected uniform \"" << name.str()
1730										 << "\" location: expected positive value, got " << returned << ".";
1731							}
1732							else
1733							{
1734								reservedLocation = returned;
1735							}
1736						}
1737					}
1738
1739					if (returned >= 0)
1740					{
1741						//check if location is less than max
1742
1743						if (returned >= max)
1744						{
1745							ret |= ERROR;
1746							Logger() << "Uniform \"" << name.str() << "\" returned location (" << returned
1747									 << ") is greater than implementation dependent limit (" << max << ").";
1748						}
1749					}
1750				} //if (runQueries)
1751
1752				//usedLocations is always checked (even if queries were not run.
1753				if (reservedLocation >= 0)
1754				{
1755					//check if location is unique
1756					if (usedLocations.find(reservedLocation) != usedLocations.end())
1757					{
1758						ret |= ERROR;
1759						Logger() << "Uniform location (" << reservedLocation << ") is not unique.";
1760					}
1761					usedLocations.insert(reservedLocation);
1762				}
1763			}
1764		}
1765		return ret;
1766	}
1767
1768	long runQueryUniformSubroutine(const CompiledProgram& program, GLenum stage,
1769								   const SubroutineUniform& subroutineUniform, std::set<GLuint>& usedLocations,
1770								   GLint max)
1771	{
1772		long ret = NO_ERROR;
1773		/*
1774		 glGetSubroutineUniformLocation(program, shaderType, name)
1775		 Query passes if returned value is unique in current program stage,
1776		 matches explicit location (if passed in GLSL code) and is less than
1777		 value of GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS.
1778
1779		 glGetProgramResourceLocation(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
1780		 ..._SUBROUTINE_UNIFORM, name)
1781		 Query passes if returned value matches value returned from
1782		 glGetUniformLocation().
1783		 */
1784
1785		for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
1786		{
1787			std::ostringstream name;
1788			name << subroutineUniform.getName();
1789
1790			subroutineUniform.streamArrayStr(name, arrayElem);
1791
1792			GLint returned = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
1793
1794			glw::GLenum piqStage = 0;
1795			switch (stage)
1796			{
1797			case GL_VERTEX_SHADER:
1798				piqStage = GL_VERTEX_SUBROUTINE_UNIFORM;
1799				break;
1800			case GL_FRAGMENT_SHADER:
1801				piqStage = GL_FRAGMENT_SUBROUTINE_UNIFORM;
1802				break;
1803			case GL_COMPUTE_SHADER:
1804				piqStage = GL_COMPUTE_SUBROUTINE_UNIFORM;
1805				break;
1806			default:
1807				assert(0);
1808			}
1809
1810			GLint returnedPIQ = glGetProgramResourceLocation(program.name, piqStage, name.str().c_str());
1811
1812			if (returned != returnedPIQ)
1813			{
1814				ret |= ERROR;
1815				Logger() << "Locations of subrutine uniform \"" << name.str()
1816						 << "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
1817						 << returned << " != " << returnedPIQ << ".";
1818			}
1819
1820			bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
1821
1822			GLint reservedLocation = -1;
1823
1824			if (!subroutineUniform.location.isImplicit(std::vector<glw::GLenum>(1, stage)))
1825			{
1826				//Validate uniform location against explicit value
1827				GLint expected = subroutineUniform.location.val + arrayElem;
1828				if (!(expected == returned || (!used && returned == -1)))
1829				{
1830					ret |= ERROR;
1831					Logger() << "Unexpected subroutine uniform \"" << name.str() << "\" location: expected " << expected
1832							 << ", got " << returned << ".";
1833				}
1834
1835				reservedLocation = expected;
1836			}
1837			else
1838			{
1839				//Check if location > 0 if used;
1840				if (used)
1841				{
1842					if (returned < 0)
1843					{
1844						ret |= ERROR;
1845						Logger() << "Unexpected subroutine uniform \"" << name.str()
1846								 << "\" location: expected positive value, got " << returned << ".";
1847					}
1848					else
1849					{
1850						reservedLocation = returned;
1851					}
1852				}
1853			}
1854
1855			if (reservedLocation >= 0)
1856			{
1857				//check if location is unique
1858				if (usedLocations.find(reservedLocation) != usedLocations.end())
1859				{
1860					ret |= ERROR;
1861					Logger() << "Subroutine uniform \"" << name.str() << "\" location (" << reservedLocation
1862							 << ") is not unique.";
1863				}
1864				usedLocations.insert(reservedLocation);
1865			}
1866
1867			if (returned >= 0)
1868			{
1869				//check if location is less than max
1870
1871				if (returned >= max)
1872				{
1873					ret |= ERROR;
1874					Logger() << "Subroutine uniform \"" << name.str() << "\" returned location (" << returned
1875							 << ") is greater than implementation dependent limit (" << max << ").";
1876				}
1877			}
1878		}
1879		return ret;
1880	}
1881
1882	long runQueryUniformSubroutineFunction(const CompiledProgram& program, GLenum stage,
1883										   const SubroutineFunction& subroutineFunction, std::set<GLuint>& usedIndices,
1884										   GLint max, bool used)
1885	{
1886		long ret = NO_ERROR;
1887		/*
1888		 glGetSubroutineIndex(program, shaderType, name)
1889		 Query passes if returned value is unique in current program stage,
1890		 matches explicit index (if passed in GLSL code) and is less than value
1891		 of GL_MAX_SUBROUTINES.
1892
1893		 glGetProgramResourceIndex(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
1894		 ..._SUBROUTINE, name)
1895		 Query passes if returned value matches value returned from
1896		 glGetSubroutineIndex().
1897		 */
1898
1899		std::string name = subroutineFunction.getName();
1900
1901		GLint returned = glGetSubroutineIndex(program.name, stage, name.c_str());
1902
1903		glw::GLenum piqStage = 0;
1904		switch (stage)
1905		{
1906		case GL_VERTEX_SHADER:
1907			piqStage = GL_VERTEX_SUBROUTINE;
1908			break;
1909		case GL_FRAGMENT_SHADER:
1910			piqStage = GL_FRAGMENT_SUBROUTINE;
1911			break;
1912		case GL_COMPUTE_SHADER:
1913			piqStage = GL_COMPUTE_SUBROUTINE;
1914			break;
1915		default:
1916			assert(0);
1917		}
1918
1919		GLint returnedPIQ = glGetProgramResourceIndex(program.name, piqStage, name.c_str());
1920
1921		if (returned != returnedPIQ)
1922		{
1923			ret |= ERROR;
1924			Logger() << "Indices of subroutine function \"" << name
1925					 << "\" returned by glGetSubroutineIndex and differ glGetProgramResourceIndex differ: " << returned
1926					 << " != " << returnedPIQ << ".";
1927		}
1928
1929		GLint reservedIndex = -1;
1930
1931		if (!subroutineFunction.index.isImplicit(std::vector<glw::GLenum>(1, stage)))
1932		{
1933			//Validate uniform location against explicit value
1934			GLint expected = subroutineFunction.index.val;
1935			if (!(expected == returned || (!used && returned == -1)))
1936			{
1937				ret |= ERROR;
1938				Logger() << "Unexpected subroutine function \"" << name << "\" index: expected " << expected << ", got "
1939						 << returned << ".";
1940			}
1941
1942			reservedIndex = expected;
1943		}
1944		else
1945		{
1946			//Check if location > 0 if used;
1947			if (used)
1948			{
1949				if (returned < 0)
1950				{
1951					ret |= ERROR;
1952					Logger() << "Unexpected subroutine function \"" << name << "\" index: expected positive value, got "
1953							 << returned << ".";
1954				}
1955				else
1956				{
1957					reservedIndex = returned;
1958				}
1959			}
1960		}
1961
1962		if (reservedIndex >= 0)
1963		{
1964			//check if location is unique
1965			if (usedIndices.find(reservedIndex) != usedIndices.end())
1966			{
1967				ret |= ERROR;
1968				Logger() << "Subroutine function \"" << name << "\" index (" << reservedIndex << ") is not unique.";
1969			}
1970			usedIndices.insert(reservedIndex);
1971		}
1972
1973		if (returned >= 0)
1974		{
1975			//check if location is less than max
1976
1977			if (returned >= max)
1978			{
1979				ret |= ERROR;
1980				Logger() << "Subroutine function \"" << name << "\" returned index (" << returned
1981						 << ") is greater than implementation dependent limit (" << max << ").";
1982			}
1983		}
1984
1985		return ret;
1986	}
1987
1988	long runQueryProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
1989						 const std::vector<SubroutineUniform>& subroutineUniforms)
1990	{
1991		long ret = NO_ERROR;
1992
1993		{
1994			std::set<GLuint> usedLocations;
1995
1996			GLint max;
1997			glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
1998
1999			for (size_t i = 0; i < uniforms.size(); i++)
2000			{
2001				ret |= runQueryUniform(program, uniforms[i], usedLocations, max);
2002			}
2003		}
2004
2005		if (subroutineUniforms.size())
2006		{
2007			GLint maxLocation, maxIndex;
2008			glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &maxLocation);
2009			glGetIntegerv(GL_MAX_SUBROUTINES, &maxIndex);
2010
2011			for (size_t stage = 0; stage < program.stages.size(); stage++)
2012			{
2013				std::set<GLuint> usedLocations;
2014				std::set<GLuint> usedIndices;
2015				for (size_t i = 0; i < subroutineUniforms.size(); i++)
2016				{
2017					ret |= runQueryUniformSubroutine(program, program.stages[stage], subroutineUniforms[i],
2018													 usedLocations, maxLocation);
2019					for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
2020					{
2021						ret |= runQueryUniformSubroutineFunction(
2022							program, program.stages[stage], subroutineUniforms[i].functions.fn[fn], usedIndices,
2023							maxIndex,
2024							subroutineUniforms[i].defOccurence.occurs(program.stages[stage]) &&
2025								subroutineUniforms[i].used);
2026					}
2027				}
2028			}
2029		}
2030
2031		return ret;
2032	}
2033
2034protected:
2035	UniformValueGenerator uniformValueGenerator;
2036	UniformStructCounter  uniformStructCounter;
2037
2038	long doRun(std::vector<SubroutineUniform>& subroutineUniforms)
2039	{
2040		assert(subroutineUniforms.size());
2041		std::vector<Uniform> noUniforms;
2042		return doRun(noUniforms, subroutineUniforms);
2043	}
2044
2045	long doRun(std::vector<Uniform>& uniforms)
2046	{
2047		assert(uniforms.size());
2048		std::vector<SubroutineUniform> noSubroutineUniforms;
2049		return doRun(uniforms, noSubroutineUniforms);
2050	}
2051
2052	long doRunNegativeCompile(const std::string additionalDef)
2053	{
2054		std::vector<Uniform>		   noUniforms;
2055		std::vector<SubroutineUniform> noSubroutineUniforms;
2056		return doRun(noUniforms, noSubroutineUniforms, additionalDef, true);
2057	}
2058
2059	long doRunNegativeLink(std::vector<Uniform>& uniforms)
2060	{
2061		std::vector<SubroutineUniform> noSubroutineUniforms;
2062		return doRun(uniforms, noSubroutineUniforms, "", false, true);
2063	}
2064
2065	long doRunNegativeLink(std::vector<SubroutineUniform>& subroutineUniforms)
2066	{
2067		std::vector<Uniform> noUniforms;
2068		return doRun(noUniforms, subroutineUniforms, "", false, true);
2069	}
2070
2071	long doRun(std::vector<Uniform>& uniforms, std::vector<SubroutineUniform>& subroutineUniforms,
2072			   std::string additionalDef = "", bool negativeCompile = false, bool negativeLink = false)
2073	{
2074		long		ret				  = NO_ERROR;
2075		std::string parentUniformName = "";
2076		for (size_t i = 0; i < uniforms.size(); i++)
2077		{
2078			std::ostringstream name;
2079			name << "u" << i;
2080			uniforms[i].setName(parentUniformName, name.str());
2081		}
2082		int subroutineTypeCounter	 = 0;
2083		int subroutineFunctionCounter = 0;
2084		for (size_t i = 0; i < subroutineUniforms.size(); i++)
2085		{
2086			std::ostringstream name;
2087			name << "u" << i + uniforms.size();
2088			subroutineUniforms[i].setName(name.str());
2089			if (!subroutineUniforms[i].functions.getTypeName().size())
2090			{
2091				subroutineUniforms[i].functions.setTypeName(subroutineTypeCounter++);
2092				for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
2093				{
2094					subroutineUniforms[i].functions.fn[fn].setName(subroutineFunctionCounter++);
2095				}
2096			}
2097		}
2098
2099		GLfloat coords[] = {
2100			1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
2101		};
2102
2103		GLuint vbo, vao;
2104		glGenBuffers(1, &vbo);
2105		glBindBuffer(GL_ARRAY_BUFFER, vbo);
2106		glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
2107
2108		glGenVertexArrays(1, &vao);
2109		glBindVertexArray(vao);
2110		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
2111		glEnableVertexAttribArray(0);
2112
2113		std::vector<CompiledProgram> programs;
2114		ret |= CreatePrograms(programs, uniforms, subroutineUniforms, additionalDef, negativeCompile, negativeLink);
2115
2116		for (size_t i = 0; i < programs.size() && ret == NO_ERROR && !negativeCompile && !negativeLink; i++)
2117		{
2118			ret |= runExecuteProgram(programs[i], uniforms, subroutineUniforms);
2119			ret |= runQueryProgram(programs[i], uniforms, subroutineUniforms);
2120		}
2121
2122		glUseProgram(0);
2123
2124		DeletePrograms(programs);
2125
2126		glDeleteBuffers(1, &vbo);
2127		glDeleteVertexArrays(1, &vao);
2128
2129		return ret;
2130	}
2131};
2132
2133class UniformLoc : public ExplicitUniformLocationCaseBase
2134{
2135	virtual long Run()
2136	{
2137		//layout (location = 2) uniform vec4 u0;
2138		std::vector<Uniform> uniforms;
2139		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2140		return doRun(uniforms);
2141	}
2142};
2143
2144class UniformLocNonDec : public ExplicitUniformLocationCaseBase
2145{
2146	virtual long Run()
2147	{
2148		//layout (location = 0x0a) uniform vec4 u0;
2149		//layout (location = 010) uniform vec4  u1;
2150		std::vector<Uniform> uniforms;
2151		uniforms.push_back(
2152			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(0x0a, Loc::Hex), DefOccurence::FSH_OR_CSH));
2153		uniforms.push_back(
2154			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(010, Loc::Oct), DefOccurence::FSH_OR_CSH));
2155		return doRun(uniforms);
2156	}
2157};
2158
2159class UniformLocMultipleStages : public ExplicitUniformLocationCaseBase
2160{
2161	virtual long Run()
2162	{
2163		//layout (location = 2) uniform vec4 u0;
2164		std::vector<Uniform> uniforms;
2165		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
2166		return doRun(uniforms);
2167	}
2168};
2169
2170class UniformLocMultipleUniforms : public ExplicitUniformLocationCaseBase
2171{
2172	virtual long Run()
2173	{
2174		//layout (location = 2) uniform vec4 u0;
2175		//layout (location = 3) uniform vec4 u1;
2176		//layout (location = 5) uniform vec4 u2;
2177		std::vector<Uniform> uniforms;
2178		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
2179		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(3)));
2180		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(5)));
2181		return doRun(uniforms);
2182	}
2183};
2184
2185class UniformLocTypesMix : public ExplicitUniformLocationCaseBase
2186{
2187	virtual long Run()
2188	{
2189		//layout (location = 2) uniform float u0;
2190		//layout (location = 3) uniform vec3  u1;
2191		//layout (location = 0) uniform uint  u2;
2192		//layout (location = 1) uniform ivec3 u3;
2193		//layout (location = 4) uniform mat2  u4;
2194		//layout (location = 7) uniform mat2  u5;
2195		//layout (location = 5) uniform mat2  u6;
2196		//layout (location = 6) uniform mat3  u7;
2197		std::vector<Uniform> uniforms;
2198		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
2199		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(3)));
2200		uniforms.push_back(Uniform(uniformValueGenerator, GL_UNSIGNED_INT, Loc::C(0)));
2201		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC3, Loc::C(1)));
2202		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(4)));
2203		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(7)));
2204		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(5)));
2205		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3, Loc::C(6)));
2206		return doRun(uniforms);
2207	}
2208};
2209
2210class UniformLocTypesMat : public ExplicitUniformLocationCaseBase
2211{
2212	virtual long Run()
2213	{
2214		std::vector<Uniform> uniforms;
2215		//layout (location = 1) uniform mat2x3   u0;
2216		//layout (location = 2) uniform mat3x2   u1;
2217		//layout (location = 0) uniform mat2     u2;
2218		//layout (location = 3) uniform imat3x4  u3;
2219		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2x3, Loc::C(1)));
2220		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3x2, Loc::C(2)));
2221		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(0)));
2222		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT4x3, Loc::C(3)));
2223		return doRun(uniforms);
2224	}
2225};
2226
2227class UniformLocTypesSamplers : public ExplicitUniformLocationCaseBase
2228{
2229	virtual long Run()
2230	{
2231		//layout (location = 1) uniform sampler2D s0[3];
2232		//layout (location = 13) uniform sampler2D s1;
2233		std::vector<Uniform> uniforms;
2234		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_SAMPLER_2D, 3), Loc::C(1)));
2235		uniforms.push_back(Uniform(uniformValueGenerator, GL_SAMPLER_2D, Loc::C(13)));
2236
2237		std::vector<GLuint>				   texUnits;
2238		std::vector<std::vector<GLubyte> > colors;
2239
2240		for (size_t i = 0; i < uniforms.size(); i++)
2241		{
2242			for (int elem = 0; elem < uniforms[i].type.arraySize; elem++)
2243			{
2244				texUnits.push_back(uniforms[i].value.iValues[elem]);
2245
2246				std::vector<GLubyte> color(4);
2247				color[0] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 0] + 0.5);
2248				color[1] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 1] + 0.5);
2249				color[2] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 2] + 0.5);
2250				color[3] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 3] + 0.5);
2251				colors.push_back(color);
2252			}
2253		}
2254
2255		std::vector<GLuint> textures(texUnits.size());
2256		glGenTextures((GLsizei)(textures.size()), &textures[0]);
2257
2258		for (size_t i = 0; i < textures.size(); i++)
2259		{
2260			glActiveTexture(GL_TEXTURE0 + texUnits[i]);
2261			glBindTexture(GL_TEXTURE_2D, textures[i]);
2262			glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2263			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &colors[i][0]);
2264			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2265			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2266		}
2267		glActiveTexture(GL_TEXTURE0);
2268		long ret = doRun(uniforms);
2269		glDeleteTextures((GLsizei)(textures.size()), &textures[0]);
2270		return ret;
2271	}
2272};
2273
2274class UniformLocTypesStructs : public ExplicitUniformLocationCaseBase
2275{
2276	virtual long Run()
2277	{
2278
2279		/**
2280		 * This test case uses following uniform declarations:
2281		 *
2282		 * struct S {
2283		 *   vec4  u0;
2284		 *   float u1[2];
2285		 *   mat2  u2;
2286		 * };
2287		 * layout (location = 1) uniform S s0[3];
2288		 * layout (location = 13) uniform S s1;
2289		 */
2290
2291		std::vector<UniformType> members;
2292		members.push_back(GL_FLOAT_VEC4);
2293		members.push_back(UniformType(GL_FLOAT, 2));
2294		members.push_back(GL_FLOAT_MAT2);
2295		std::vector<Uniform> uniforms;
2296		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members, 3), Loc::C(1)));
2297		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members), Loc::C(13)));
2298		return doRun(uniforms);
2299	}
2300};
2301
2302class UniformLocArraysNonSpaced : public ExplicitUniformLocationCaseBase
2303{
2304	virtual long Run()
2305	{
2306		//layout (location = 2) uniform float[3] u0;
2307		//layout (location = 5) uniform vec3[2]  u1;
2308		//layout (location = 7) uniform int[3]   u2;
2309		//layout (location = 10) uniform ivec4   u3;
2310		std::vector<Uniform> uniforms;
2311		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(2)));
2312		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
2313		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(7)));
2314		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC4, Loc::C(10)));
2315		return doRun(uniforms);
2316	}
2317};
2318
2319class UniformLocArraySpaced : public ExplicitUniformLocationCaseBase
2320{
2321	virtual long Run()
2322	{
2323		//layout (location = 2) uniform float     u0;
2324		//layout (location = 5) uniform vec3[2]   u1;
2325		//layout (location = 8) uniform int[3]    u2;
2326		//layout (location = 12) uniform ivec4[1] u3;
2327		std::vector<Uniform> uniforms;
2328		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
2329		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
2330		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(8)));
2331		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 1), Loc::C(12)));
2332		return doRun(uniforms);
2333	}
2334};
2335
2336class UniformLocArrayofArrays : public ExplicitUniformLocationCaseBase
2337{
2338	virtual long Run()
2339	{
2340		//layout (location = 2) uniform float[2][3]  u0;
2341		//layout (location = 8) uniform vec3[2][2]   u1;
2342		//layout (location = 12) uniform float       u2;
2343		std::vector<Uniform> uniforms;
2344		{
2345			std::vector<int> arraySizesSegmented(2);
2346			arraySizesSegmented[0] = 2;
2347			arraySizesSegmented[1] = 3;
2348			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, arraySizesSegmented), Loc::C(2)));
2349		}
2350		{
2351			std::vector<int> arraySizesSegmented(2);
2352			arraySizesSegmented[0] = arraySizesSegmented[1] = 2;
2353			uniforms.push_back(
2354				Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, arraySizesSegmented), Loc::C(8)));
2355		}
2356		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(12)));
2357		return doRun(uniforms);
2358	}
2359};
2360
2361class UniformLocMixWithImplicit : public ExplicitUniformLocationCaseBase
2362{
2363	virtual long Run()
2364	{
2365		//layout (location = 0) uniform float     u0;
2366		//layout (location = 2) uniform vec3      u1;
2367		//layout (location = 3) uniform int       u2;
2368
2369		//uniform float     u0;
2370		//uniform vec3      u1;
2371		//uniform int       u2;
2372		std::vector<Uniform> uniforms;
2373		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::FSH_OR_CSH)));
2374		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2, DefOccurence::FSH_OR_CSH)));
2375		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
2376		return doRun(uniforms);
2377	}
2378};
2379
2380class UniformLocMixWithImplicit2 : public ExplicitUniformLocationCaseBase
2381{
2382	virtual long Run()
2383	{
2384		//uniform float[3] u0;
2385		//layout (location = 3) uniform vec3[2]  u1;
2386		//uniform int[3]   u2;
2387		//layout (location = 8) uniform ivec4   u3;
2388		std::vector<Uniform> uniforms;
2389		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::Implicit()));
2390		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(3)));
2391		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::Implicit()));
2392		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 2), Loc::C(8)));
2393		return doRun(uniforms);
2394	}
2395};
2396
2397class UniformLocMixWithImplicit3 : public ExplicitUniformLocationCaseBase
2398{
2399	virtual long Run()
2400	{
2401		//layout (location = 0) uniform float     u0; //unused
2402		//layout (location = 2) uniform vec3      u1; //unused
2403		//layout (location = 3) uniform int       u2; //unused
2404
2405		//uniform float     u3;
2406		//uniform vec3      u4;
2407		//uniform int       u5;
2408		std::vector<Uniform> uniforms;
2409		uniforms.push_back(
2410			Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2411		uniforms.push_back(
2412			Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2413		uniforms.push_back(
2414			Uniform(uniformValueGenerator, GL_INT, Loc::C(3), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2415		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
2416		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::Implicit()));
2417		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::Implicit()));
2418		return doRun(uniforms);
2419	}
2420};
2421
2422class UniformLocMixWithImplicitMax : public ExplicitUniformLocationCaseBase
2423{
2424	virtual long Run()
2425	{
2426		long ret = NO_ERROR;
2427
2428		GLint max;
2429		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2430
2431		const int implicitCount = 1;
2432
2433		int tests[3] = { 0, 3, max - implicitCount };
2434
2435		for (int test = 0; test < 3; test++)
2436		{
2437			std::vector<Uniform> uniforms;
2438
2439			//for performance reasons fill-up all avaliable locations with an unused arrays.
2440			if (tests[test] > 0)
2441			{
2442				//[0..test - 1]
2443				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
2444										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2445				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2446					   tests[test]);
2447			}
2448
2449			if (tests[test] < max - implicitCount)
2450			{
2451				//[test + 1..max]
2452				uniforms.push_back(
2453					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
2454							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2455				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2456					   max);
2457			}
2458
2459			uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
2460			ret |= doRun(uniforms);
2461		}
2462		return ret;
2463	}
2464};
2465
2466class UniformLocMixWithImplicitMaxArray : public ExplicitUniformLocationCaseBase
2467{
2468	virtual long Run()
2469	{
2470		long ret = NO_ERROR;
2471
2472		GLint max;
2473		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2474
2475		const int implicitCount = 3;
2476
2477		int tests[3] = { 0, 3, max - 4 };
2478
2479		for (int test = 0; test < 3; test++)
2480		{
2481			std::vector<Uniform> uniforms;
2482
2483			//for performance reasons fill-up all avaliable locations with an unused arrays.
2484			if (tests[test] > 0)
2485			{
2486				//[0..test - 1]
2487				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
2488										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2489				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2490					   tests[test]);
2491			}
2492
2493			if (tests[test] < max - implicitCount)
2494			{
2495				//[test + 3 ..max]
2496				uniforms.push_back(
2497					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
2498							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2499				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2500					   max);
2501			}
2502			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, implicitCount), Loc::Implicit()));
2503			ret |= doRun(uniforms);
2504		}
2505		return ret;
2506	}
2507};
2508
2509class UniformLocImplicitInSomeStages : public ExplicitUniformLocationCaseBase
2510{
2511	virtual long Run()
2512	{
2513		//One shader: uniform float u0;
2514		//Another shader: layout (location = 3) uniform float  u0;
2515		std::vector<Uniform> uniforms;
2516		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
2517		return doRun(uniforms);
2518	}
2519};
2520
2521class UniformLocImplicitInSomeStages2 : public ExplicitUniformLocationCaseBase
2522{
2523	virtual long Run()
2524	{
2525		//One shader: uniform float u0;
2526		//Another shader: layout (location = 3) uniform float  u0; //not used!
2527		std::vector<Uniform> uniforms;
2528
2529		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2530		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
2531								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2532		return doRun(uniforms);
2533	}
2534};
2535
2536class UniformLocImplicitInSomeStages3 : public ExplicitUniformLocationCaseBase
2537{
2538	virtual long Run()
2539	{
2540		std::vector<Uniform> uniforms;
2541
2542		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2543		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
2544								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2545
2546		//location in all but fsh, declaration in all shaders, usage in fsh.
2547		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2, DefOccurence::ALL_BUT_FSH),
2548								   DefOccurence::ALL_SH, DefOccurence::FSH_OR_CSH));
2549
2550		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2551		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(7, DefOccurence::FSH_OR_CSH),
2552								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2553
2554		//location in all but fsh, declaration in all shaders, usage in fsh.
2555		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3),
2556								   Loc::C(4, DefOccurence::ALL_BUT_FSH), DefOccurence::ALL_SH,
2557								   DefOccurence::FSH_OR_CSH));
2558
2559		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
2560		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::VSH), DefOccurence::ALL_SH,
2561								   DefOccurence::ALL_BUT_VSH));
2562
2563		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
2564		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(1, DefOccurence::ALL_BUT_FSH),
2565								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_VSH));
2566
2567		return doRun(uniforms);
2568	}
2569};
2570
2571class UniformLocNegativeCompileNonNumberLiteral : public ExplicitUniformLocationCaseBase
2572{
2573	virtual long Run()
2574	{
2575		std::string def = "layout (location = x) uniform float u0;";
2576		return doRunNegativeCompile(def);
2577	}
2578};
2579
2580class UniformLocNegativeCompileNonConstLoc : public ExplicitUniformLocationCaseBase
2581{
2582	virtual long Run()
2583	{
2584		std::string def = NL "const int i = 1;" NL "layout (location = i) uniform float u0;";
2585		return doRunNegativeCompile(def);
2586	}
2587};
2588
2589class UniformLocNegativeLinkLocationReused1 : public ExplicitUniformLocationCaseBase
2590{
2591	virtual long Run()
2592	{
2593		//layout (location = 2) uniform float u0;
2594		//layout (location = 2) uniform float u1;
2595		std::vector<Uniform> uniforms;
2596		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2597		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2598		return doRunNegativeLink(uniforms);
2599	}
2600};
2601
2602class UniformLocNegativeLinkLocationReused2 : public ExplicitUniformLocationCaseBase
2603{
2604	virtual long Run()
2605	{
2606		///layout (location = 2) uniform float u0;
2607		//layout (location = 2) uniform float u1;
2608		std::vector<Uniform> uniforms;
2609		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2610		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::ALL_BUT_FSH));
2611		return doRunNegativeLink(uniforms);
2612	}
2613};
2614
2615class UniformLocNegativeLinkMaxLocation : public ExplicitUniformLocationCaseBase
2616{
2617	virtual long Run()
2618	{
2619		//layout (location = X) uniform float u0;
2620		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
2621
2622		GLint max;
2623		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2624
2625		std::vector<Uniform> uniforms;
2626		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(max), DefOccurence::FSH_OR_CSH));
2627
2628		return doRunNegativeLink(uniforms);
2629	}
2630};
2631
2632class UniformLocNegativeLinkMaxMaxNumOfLocation : public ExplicitUniformLocationCaseBase
2633{
2634	virtual long Run()
2635	{
2636
2637		GLint max;
2638		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2639		std::vector<Uniform> uniforms;
2640		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max), Loc::C(0),
2641								   DefOccurence::FSH_OR_CSH, DefOccurence::NONE_SH));
2642		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit(), DefOccurence::ALL_BUT_FSH));
2643		return doRunNegativeLink(uniforms);
2644	}
2645};
2646
2647class SubRoutineLoc : public ExplicitUniformLocationCaseBase
2648{
2649	virtual long Run()
2650	{
2651
2652		//one shader:
2653		//subroutine vec4 st0(float param);
2654		//subroutine(st0) vec4 sf0(float param) { .... };
2655		//subroutine(st0) vec4 sf1(float param) { .... };
2656		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2657
2658		std::vector<SubroutineUniform> subroutineUniforms;
2659
2660		//layout(location = 2) subroutine uniform st0 u0;
2661		subroutineUniforms.push_back(
2662			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2663		return doRun(subroutineUniforms);
2664	}
2665};
2666
2667class SubRoutineLocNonDecimal : public ExplicitUniformLocationCaseBase
2668{
2669	virtual long Run()
2670	{
2671		//one shader:
2672		//subroutine vec4 st0(float param);
2673		//subroutine(st0) vec4 sf0(float param) { .... };
2674		//subroutine(st0) vec4 sf1(float param) { .... };
2675		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2676
2677		std::vector<SubroutineUniform> subroutineUniforms;
2678
2679		//layout(location = 0x0a) subroutine uniform st0 u0;
2680		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0x0a, Loc::Hex), 0,
2681													   DefOccurence::FSH_OR_CSH));
2682		//layout(location = 010 ) subroutine uniform st0 u1;
2683		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(010, Loc::Oct), 0,
2684													   DefOccurence::FSH_OR_CSH));
2685		return doRun(subroutineUniforms);
2686	}
2687};
2688
2689class SubRoutineLocAllStages : public ExplicitUniformLocationCaseBase
2690{
2691	virtual long Run()
2692	{
2693		//subroutine vec4 st0(float param);
2694		//subroutine(st0) vec4 sf0(float param) { .... };
2695		//subroutine(st0) vec4 sf1(float param) { .... };
2696		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2697
2698		std::vector<SubroutineUniform> subroutineUniforms;
2699
2700		//layout(location = 2) subroutine uniform st0 u0;
2701		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2)));
2702		return doRun(subroutineUniforms);
2703	}
2704};
2705
2706class SubRoutineLocArrays : public ExplicitUniformLocationCaseBase
2707{
2708	virtual long Run()
2709	{
2710
2711		//subroutine vec4 st0(float param);
2712		//subroutine(st0) vec4 sf0(float param) { .... };
2713		//subroutine(st0) vec4 sf1(float param) { .... };
2714		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2715
2716		std::vector<SubroutineUniform> subroutineUniforms;
2717
2718		//layout(location = 1) subroutine uniform st0 u0[2];
2719		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
2720		return doRun(subroutineUniforms);
2721	}
2722};
2723
2724class SubRoutineLocArraysMix : public ExplicitUniformLocationCaseBase
2725{
2726	virtual long Run()
2727	{
2728		//subroutine vec4 st0(float param);
2729		//subroutine(st0) vec4 sf0(float param) { .... };
2730		//subroutine(st0) vec4 sf1(float param) { .... };
2731		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2732
2733		//subroutine vec4 st1(float param);
2734		//subroutine(st1) vec4 sf2(float param) { .... };
2735		//subroutine(st1) vec4 sf3(float param) { .... };
2736		SubroutineFunctionSet functions_st1(uniformValueGenerator, 2);
2737
2738		std::vector<SubroutineUniform> subroutineUniforms;
2739
2740		//layout(location = 1) subroutine uniform st0 u0[2];
2741		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
2742
2743		////layout(location = 3) subroutine uniform st0 u1[2][3];
2744		std::vector<int> arraySizesSegmented(2);
2745		arraySizesSegmented[0] = 2;
2746		arraySizesSegmented[1] = 3;
2747		subroutineUniforms.push_back(
2748			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), arraySizesSegmented));
2749
2750		//layout(location = 9) subroutine uniform st1 u2;
2751		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9)));
2752
2753		return doRun(subroutineUniforms);
2754	}
2755};
2756
2757class SubRoutineLocMixWithImplicit : public ExplicitUniformLocationCaseBase
2758{
2759	virtual long Run()
2760	{
2761		//subroutine vec4 st0(float param);
2762		//subroutine(st0) vec4 sf0(float param) { .... };
2763		//subroutine(st0) vec4 sf1(float param) { .... };
2764		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2765
2766		std::vector<SubroutineUniform> subroutineUniforms;
2767		//subroutine uniform st0 u0;
2768		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit()));
2769		//layout(location = 1 ) subroutine uniform st0 u1;
2770		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0)));
2771		//layout(location = 0 ) subroutine uniform st0 u2;
2772		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1)));
2773
2774		return doRun(subroutineUniforms);
2775	}
2776};
2777
2778class SubRoutineLocCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
2779{
2780	virtual long Run()
2781	{
2782
2783		std::string def =
2784			NL "subroutine vec4 st0(float param);" NL "subroutine(st0) vec4 sf0(float param) { return param; }" NL
2785			   "layout(location = x ) subroutine uniform st0 u0;";
2786
2787		return doRunNegativeCompile(def);
2788	}
2789};
2790
2791class SubRoutineLocCompilationNonConstLoc : public ExplicitUniformLocationCaseBase
2792{
2793	virtual long Run()
2794	{
2795		std::string def = NL "const int i = 1;" NL "subroutine vec4 st0(float param);" NL
2796							 "subroutine(st0) vec4 sf0(float param) { return param; }" NL
2797							 "layout(location = i ) subroutine uniform st0 u0;";
2798		return doRunNegativeCompile(def);
2799	}
2800};
2801
2802class SubRoutineLocLinkLocationReused1 : public ExplicitUniformLocationCaseBase
2803{
2804	virtual long Run()
2805	{
2806		//layout(location = 1) subroutine uniform st0 u0;
2807		//layout(location = 1) subroutine uniform st0 u0;
2808		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2809		std::vector<SubroutineUniform> subroutineUniforms;
2810		subroutineUniforms.push_back(
2811			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2812		subroutineUniforms.push_back(
2813			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2814		return doRunNegativeLink(subroutineUniforms);
2815	}
2816};
2817
2818class SubRoutineLocLinkLocationMaxLocation : public ExplicitUniformLocationCaseBase
2819{
2820	virtual long Run()
2821	{
2822		//layout(location = N) subroutine uniform st0 u0;
2823		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
2824
2825		GLint max;
2826		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
2827		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2828		std::vector<SubroutineUniform> subroutineUniforms;
2829		subroutineUniforms.push_back(
2830			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(max), 0, DefOccurence::FSH_OR_CSH));
2831		return doRunNegativeLink(subroutineUniforms);
2832	}
2833};
2834
2835class SubRoutineLocLinkMaxNumOfLocations : public ExplicitUniformLocationCaseBase
2836{
2837	virtual long Run()
2838	{
2839
2840		GLint max;
2841		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
2842		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2843		std::vector<SubroutineUniform> subroutineUniforms;
2844		subroutineUniforms.push_back(
2845			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0), max, DefOccurence::FSH_OR_CSH, false));
2846		subroutineUniforms.push_back(
2847			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2848		return doRunNegativeLink(subroutineUniforms);
2849	}
2850};
2851
2852class SubroutineIndex : public ExplicitUniformLocationCaseBase
2853{
2854	virtual long Run()
2855	{
2856		//one shader:
2857
2858		//subroutine vec4 st0(float param);
2859		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2860		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2861		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2862		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2863		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2864
2865		std::vector<SubroutineUniform> subroutineUniforms;
2866
2867		//subroutine uniform st0 u0;
2868		subroutineUniforms.push_back(
2869			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2870		return doRun(subroutineUniforms);
2871	}
2872};
2873
2874class SubroutineIndexNonDecimal : public ExplicitUniformLocationCaseBase
2875{
2876	virtual long Run()
2877	{
2878		//one shader:
2879
2880		//subroutine vec4 st0(float param);
2881		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2882		//layout(index = 0x0a) subroutine(st0) vec4 sf0(float param) { .... };
2883		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0x0a, Index::Hex)));
2884		//layout(index = 010 ) subroutine(st0) vec4 sf1(float param) { .... };
2885		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(010, Index::Oct)));
2886
2887		std::vector<SubroutineUniform> subroutineUniforms;
2888
2889		//subroutine uniform st0 u0;
2890		subroutineUniforms.push_back(
2891			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2892
2893		return doRun(subroutineUniforms);
2894	}
2895};
2896
2897class SubroutineIndexLoc : public ExplicitUniformLocationCaseBase
2898{
2899	virtual long Run()
2900	{
2901
2902		//one shader:
2903
2904		//subroutine vec4 st0(float param);
2905		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2906		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2907		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2908		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2909		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2910
2911		std::vector<SubroutineUniform> subroutineUniforms;
2912
2913		//layout(location = 3) subroutine uniform st0 u0;
2914		subroutineUniforms.push_back(
2915			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), 0, DefOccurence::FSH_OR_CSH));
2916		return doRun(subroutineUniforms);
2917	}
2918};
2919
2920class SubroutineIndexNonCont : public ExplicitUniformLocationCaseBase
2921{
2922	virtual long Run()
2923	{
2924		//one shader:
2925
2926		//subroutine vec4 st0(float param);
2927		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2928		//layout(index = 0) subroutine(st0) vec4 sf0(float param) { .... };
2929		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
2930		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2931		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2932
2933		std::vector<SubroutineUniform> subroutineUniforms;
2934
2935		//layout(location = 2) subroutine uniform st0 u0;
2936		subroutineUniforms.push_back(
2937			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2938		return doRun(subroutineUniforms);
2939	}
2940};
2941
2942class SubroutineIndexMultUniforms : public ExplicitUniformLocationCaseBase
2943{
2944	virtual long Run()
2945	{
2946
2947		//one shader:
2948
2949		//subroutine vec4 st0(float param);
2950		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2951		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2952		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2953		//layout(index = 3) subroutine(st0) vec4 sf1(float param) { .... };
2954		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(3)));
2955
2956		//subroutine vec4 st1(float param);
2957		SubroutineFunctionSet functions_st1(uniformValueGenerator);
2958		//layout(index = 2) subroutine(st1) vec4 sf2(float param) { .... };
2959		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2960		//layout(index = 0) subroutine(st1) vec4 sf3(float param) { .... };
2961		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
2962
2963		std::vector<SubroutineUniform> subroutineUniforms;
2964		//layout(location = 1) subroutine uniform st0 u0;
2965		subroutineUniforms.push_back(
2966			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 0, DefOccurence::FSH_OR_CSH));
2967		//layout(location = 9) subroutine uniform st1 u1;
2968		subroutineUniforms.push_back(
2969			SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9), 0, DefOccurence::FSH_OR_CSH));
2970
2971		return doRun(subroutineUniforms);
2972	}
2973};
2974
2975class SubroutineIndexAllstages : public ExplicitUniformLocationCaseBase
2976{
2977	virtual long Run()
2978	{
2979
2980		//subroutine vec4 st0(float param);
2981		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2982		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2983		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2984		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2985		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2986
2987		std::vector<SubroutineUniform> subroutineUniforms;
2988
2989		//subroutine uniform st0 u0;
2990		subroutineUniforms.push_back(
2991			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::ALL_SH));
2992		return doRun(subroutineUniforms);
2993	}
2994};
2995
2996class SubroutineIndexMixImplicit : public ExplicitUniformLocationCaseBase
2997{
2998	virtual long Run()
2999	{
3000
3001		//subroutine vec4 st0(float param);
3002		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3003		//subroutine(st0) vec4 sf0(float param) { .... };
3004		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
3005		//layout(index = 1) subroutine(st0) vec4 sf1(float param) { .... };
3006		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
3007		//layout(index = 0) subroutine(st0) vec4 sf1(float param) { .... };
3008		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
3009
3010		std::vector<SubroutineUniform> subroutineUniforms;
3011
3012		//layout(location = 2) subroutine uniform st0 u0;
3013		subroutineUniforms.push_back(
3014			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
3015		return doRun(subroutineUniforms);
3016	}
3017};
3018
3019class SubroutineIndexNegativeCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
3020{
3021	virtual long Run()
3022	{
3023		std::string def = NL "subroutine vec4 st0(float param);" NL
3024							 "layout(index = x) subroutine(st0) vec4 sf1(float param) { return param; };";
3025		return doRunNegativeCompile(def);
3026	}
3027};
3028
3029class SubroutineIndexNegativeCompilationNonConstIndex : public ExplicitUniformLocationCaseBase
3030{
3031	virtual long Run()
3032	{
3033		std::string def =
3034			NL "const int i = 1;" NL "layout(index = i) subroutine(st0) vec4 sf1(float param) { return param; };";
3035		return doRunNegativeCompile(def);
3036	}
3037};
3038
3039class SubroutineIndexNegativeLinkIndexReused : public ExplicitUniformLocationCaseBase
3040{
3041	virtual long Run()
3042	{
3043		//subroutine vec4 st0(float param);
3044		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3045		//layout(index = 2) subroutine(st0) vec4 sf0(float param) { .... };
3046		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
3047		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
3048		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
3049
3050		std::vector<SubroutineUniform> subroutineUniforms;
3051
3052		//subroutine uniform st0 u0;
3053		subroutineUniforms.push_back(
3054			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3055		return doRunNegativeLink(subroutineUniforms);
3056	}
3057};
3058
3059class SubroutineIndexNegativeLinkMaxIndex : public ExplicitUniformLocationCaseBase
3060{
3061	virtual long Run()
3062	{
3063
3064		GLint max;
3065		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
3066
3067		//subroutine vec4 st0(float param);
3068		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3069		//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
3070		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(max)));
3071
3072		std::vector<SubroutineUniform> subroutineUniforms;
3073
3074		//subroutine uniform st0 u0;
3075		subroutineUniforms.push_back(
3076			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3077		return doRunNegativeLink(subroutineUniforms);
3078	}
3079};
3080
3081class SubroutineIndexNegativeLinkMaxNumOfIndices : public ExplicitUniformLocationCaseBase
3082{
3083	virtual long Run()
3084	{
3085		//subroutine vec4 st0(float param);
3086		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3087
3088		glw::GLint max;
3089		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
3090
3091		for (int i = 0; i < max; i++)
3092		{
3093			//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
3094			functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(i)));
3095		}
3096		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
3097
3098		std::vector<SubroutineUniform> subroutineUniforms;
3099
3100		//subroutine uniform st0 u0;
3101		subroutineUniforms.push_back(
3102			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3103		return doRunNegativeLink(subroutineUniforms);
3104	}
3105};
3106}
3107
3108ExplicitUniformLocationGLTests::ExplicitUniformLocationGLTests(glcts::Context& context)
3109	: TestCaseGroup(context, "explicit_uniform_location", "")
3110{
3111}
3112
3113ExplicitUniformLocationGLTests::~ExplicitUniformLocationGLTests(void)
3114{
3115}
3116
3117void ExplicitUniformLocationGLTests::init()
3118{
3119	using namespace glcts;
3120
3121	Logger::setOutput(m_context.getTestContext().getLog());
3122	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
3123	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
3124	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
3125	addChild(
3126		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
3127	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
3128	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
3129	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
3130	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
3131	addChild(
3132		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
3133	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
3134
3135	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
3136
3137	addChild(
3138		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
3139	addChild(
3140		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
3141	addChild(
3142		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
3143	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
3144							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
3145	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
3146							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
3147
3148	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
3149							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
3150	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
3151							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
3152	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
3153							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
3154
3155	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
3156							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
3157	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
3158							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
3159	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
3160							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
3161	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
3162							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
3163	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
3164							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
3165	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
3166							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
3167
3168	addChild(new TestSubcase(m_context, "subroutine-loc", TestSubcase::Create<SubRoutineLoc>));
3169	addChild(new TestSubcase(m_context, "subroutine-loc-nondecimal", TestSubcase::Create<SubRoutineLocNonDecimal>));
3170	addChild(new TestSubcase(m_context, "subroutine-loc-all-stages", TestSubcase::Create<SubRoutineLocAllStages>));
3171	addChild(new TestSubcase(m_context, "subroutine-loc-arrays", TestSubcase::Create<SubRoutineLocArrays>));
3172	addChild(new TestSubcase(m_context, "subroutine-loc-arrays-mix", TestSubcase::Create<SubRoutineLocArraysMix>));
3173	addChild(new TestSubcase(m_context, "subroutine-loc-mix-with-implicit",
3174							 TestSubcase::Create<SubRoutineLocMixWithImplicit>));
3175	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-non-number-literal",
3176							 TestSubcase::Create<SubRoutineLocCompilationNonNumberLiteral>));
3177	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-nonconst-loc",
3178							 TestSubcase::Create<SubRoutineLocCompilationNonConstLoc>));
3179	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-reused1",
3180							 TestSubcase::Create<SubRoutineLocLinkLocationReused1>));
3181	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-max-location",
3182							 TestSubcase::Create<SubRoutineLocLinkLocationMaxLocation>));
3183	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-max-num-of-locations",
3184							 TestSubcase::Create<SubRoutineLocLinkMaxNumOfLocations>));
3185	addChild(new TestSubcase(m_context, "subroutine-index", TestSubcase::Create<SubroutineIndex>));
3186	addChild(new TestSubcase(m_context, "subroutine-index-nondecimal", TestSubcase::Create<SubroutineIndexNonDecimal>));
3187	addChild(new TestSubcase(m_context, "subroutine-index-loc", TestSubcase::Create<SubroutineIndexLoc>));
3188	addChild(
3189		new TestSubcase(m_context, "subroutine-index-non-continuous", TestSubcase::Create<SubroutineIndexNonCont>));
3190	addChild(new TestSubcase(m_context, "subroutine-index-multiple-uniforms",
3191							 TestSubcase::Create<SubroutineIndexMultUniforms>));
3192	addChild(new TestSubcase(m_context, "subroutine-index-all-stages", TestSubcase::Create<SubroutineIndexAllstages>));
3193	addChild(
3194		new TestSubcase(m_context, "subroutine-index-mix-implicit", TestSubcase::Create<SubroutineIndexMixImplicit>));
3195	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-non-number-literal",
3196							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonNumberLiteral>));
3197	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-nonconst-index",
3198							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonConstIndex>));
3199	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-index-reused",
3200							 TestSubcase::Create<SubroutineIndexNegativeLinkIndexReused>));
3201	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-location-maxindex",
3202							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxIndex>));
3203	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-max-num-of-indices",
3204							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxNumOfIndices>));
3205}
3206
3207ExplicitUniformLocationES31Tests::ExplicitUniformLocationES31Tests(glcts::Context& context)
3208	: TestCaseGroup(context, "explicit_uniform_location", "")
3209{
3210}
3211
3212ExplicitUniformLocationES31Tests::~ExplicitUniformLocationES31Tests(void)
3213{
3214}
3215
3216void ExplicitUniformLocationES31Tests::init()
3217{
3218	using namespace glcts;
3219	Logger::setOutput(m_context.getTestContext().getLog());
3220	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
3221	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
3222	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
3223	addChild(
3224		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
3225	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
3226	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
3227	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
3228	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
3229	addChild(
3230		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
3231	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
3232	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
3233	addChild(
3234		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
3235	addChild(
3236		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
3237	addChild(
3238		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
3239	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
3240							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
3241	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
3242							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
3243	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
3244							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
3245	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
3246							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
3247	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
3248							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
3249	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
3250							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
3251	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
3252							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
3253	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
3254							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
3255	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
3256							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
3257	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
3258							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
3259	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
3260							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
3261}
3262}
3263