Home | History | Annotate | Download | only in gles31
      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 
     34 namespace glcts
     35 {
     36 using namespace glw;
     37 namespace
     38 {
     39 
     40 class Logger
     41 {
     42 public:
     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 
     85 private:
     86 	void				 operator=(const Logger&);
     87 	bool				 null_log_;
     88 	std::ostringstream   str_;
     89 	static tcu::TestLog* s_tcuLog;
     90 };
     91 tcu::TestLog* Logger::s_tcuLog = NULL;
     92 
     93 class DefOccurence
     94 {
     95 public:
     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 
    141 class LocationSpecifier
    142 {
    143 };
    144 class IndexSpecifier
    145 {
    146 };
    147 
    148 class LayoutSpecifierBase
    149 {
    150 public:
    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 
    179 template <class T>
    180 class LayoutSpecifier : public LayoutSpecifierBase
    181 {
    182 public:
    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 
    205 typedef LayoutSpecifier<LocationSpecifier> Loc;
    206 typedef LayoutSpecifier<IndexSpecifier>	Index;
    207 
    208 template <>
    209 void 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 
    228 template <>
    229 void 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 
    248 class UniformStructCounter
    249 {
    250 public:
    251 	UniformStructCounter() : counter(0)
    252 	{
    253 	}
    254 	GLint getNextCount()
    255 	{
    256 		return counter++;
    257 	}
    258 
    259 private:
    260 	UniformStructCounter(const UniformStructCounter&);
    261 	GLint counter;
    262 };
    263 
    264 class UniformType
    265 {
    266 public:
    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 
    385 private:
    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 
    513 class UniformValueGenerator
    514 {
    515 public:
    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 
    532 private:
    533 	UniformValueGenerator(const UniformValueGenerator&);
    534 	GLfloat fValue;
    535 	GLint   iValue;
    536 };
    537 
    538 class UniformValue
    539 {
    540 public:
    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 
    660 private:
    661 	UniformType type;
    662 };
    663 
    664 class Uniform
    665 {
    666 public:
    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 
    738 class SubroutineFunction
    739 {
    740 public:
    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 
    764 private:
    765 	UniformValue embeddedRetVal;
    766 	std::string  name;
    767 };
    768 
    769 class SubroutineFunctionSet
    770 {
    771 public:
    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 
    797 class SubroutineUniform
    798 {
    799 public:
    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 
    903 private:
    904 	std::vector<int> arraySizesSegmented;
    905 	bool			 isArray;
    906 	UniformValue	 embeddedUIntUniform;
    907 
    908 	std::string name;
    909 };
    910 
    911 class ShaderKey
    912 {
    913 public:
    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 
    938 class CompiledProgram
    939 {
    940 public:
    941 	GLuint				name;
    942 	std::vector<GLenum> stages;
    943 };
    944 
    945 class 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 
   1187 public:
   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 
   1210 class 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 
   2034 protected:
   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 
   2133 class 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 
   2144 class 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 
   2159 class 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 
   2170 class 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 
   2185 class 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 
   2210 class 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 
   2227 class 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 
   2274 class 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 
   2302 class 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 
   2319 class 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 
   2336 class 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 
   2361 class 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 
   2380 class 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 
   2397 class 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 
   2422 class 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 
   2466 class 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 
   2509 class 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 
   2521 class 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 
   2536 class 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 
   2571 class 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 
   2580 class 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 
   2589 class 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 
   2602 class 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 
   2615 class 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 
   2632 class 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 
   2647 class 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 
   2667 class 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 
   2689 class 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 
   2706 class 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 
   2724 class 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 
   2757 class 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 
   2778 class 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 
   2791 class 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 
   2802 class 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 
   2818 class 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 
   2835 class 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 
   2852 class 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 
   2874 class 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 
   2897 class 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 
   2920 class 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 
   2942 class 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 
   2975 class 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 
   2996 class 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 
   3019 class 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 
   3029 class 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 
   3039 class 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 
   3059 class 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 
   3081 class 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 
   3108 ExplicitUniformLocationGLTests::ExplicitUniformLocationGLTests(glcts::Context& context)
   3109 	: TestCaseGroup(context, "explicit_uniform_location", "")
   3110 {
   3111 }
   3112 
   3113 ExplicitUniformLocationGLTests::~ExplicitUniformLocationGLTests(void)
   3114 {
   3115 }
   3116 
   3117 void 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 
   3207 ExplicitUniformLocationES31Tests::ExplicitUniformLocationES31Tests(glcts::Context& context)
   3208 	: TestCaseGroup(context, "explicit_uniform_location", "")
   3209 {
   3210 }
   3211 
   3212 ExplicitUniformLocationES31Tests::~ExplicitUniformLocationES31Tests(void)
   3213 {
   3214 }
   3215 
   3216 void 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