• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Logger()43 	Logger() : null_log_(0)
44 	{
45 	}
46 
Logger(const Logger & rhs)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 
~Logger()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>
operator <<(const T & t)66 	Logger& operator<<(const T& t)
67 	{
68 		if (!null_log_)
69 		{
70 			str_ << t;
71 		}
72 		return *this;
73 	}
74 
Get()75 	static tcu::TestLog* Get()
76 	{
77 		return s_tcuLog;
78 	}
79 
setOutput(tcu::TestLog & log)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 
DefOccurence(DefOccurenceEnum _occurence)106 	DefOccurence(DefOccurenceEnum _occurence) : occurence(_occurence)
107 	{
108 	}
109 
occurs(GLenum shader) const110 	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 
LayoutSpecifierBase(int _val,NumSys _numSys,DefOccurence _occurence)158 	LayoutSpecifierBase(int _val, NumSys _numSys, DefOccurence _occurence)
159 		: val(_val), numSys(_numSys), occurence(_occurence)
160 	{
161 	}
162 
isImplicit(const std::vector<GLenum> stages) const163 	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:
LayoutSpecifier(int _val,NumSys _numSys,DefOccurence _occurence)183 	LayoutSpecifier(int _val, NumSys _numSys, DefOccurence _occurence) : LayoutSpecifierBase(_val, _numSys, _occurence)
184 	{
185 	}
186 
C(int _val,NumSys _sys=Dec)187 	static LayoutSpecifier<T> C(int _val, NumSys _sys = Dec)
188 	{
189 		return LayoutSpecifier<T>(_val, _sys, DefOccurence::ALL_SH);
190 	}
191 
C(int _val,DefOccurence _occurence)192 	static LayoutSpecifier<T> C(int _val, DefOccurence _occurence)
193 	{
194 		return LayoutSpecifier<T>(_val, Dec, _occurence);
195 	}
196 
Implicit()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 <>
streamDefinition(std::ostringstream & str,GLenum shader) const209 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 <>
streamDefinition(std::ostringstream & str,GLenum shader) const229 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:
UniformStructCounter()251 	UniformStructCounter() : counter(0)
252 	{
253 	}
getNextCount()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:
UniformType(GLenum _enumType,int _arraySize=0)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 	}
UniformType(GLenum _enumType,const std::vector<int> & _arraySizesSegmented)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 	}
UniformType(UniformStructCounter & structCounter,std::vector<UniformType> _childTypes,int _arraySize=0)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 
str() const302 	inline const std::string& str() const
303 	{
304 		return strType;
305 	}
306 
refStr() const307 	inline const std::string& refStr() const
308 	{
309 		return refStrType;
310 	}
311 
isStruct() const312 	bool isStruct() const
313 	{
314 		return (baseType == 0);
315 	}
316 
isSigned() const317 	bool isSigned() const
318 	{
319 		return signedType;
320 	}
321 
abs() const322 	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 
getSize() const339 	std::pair<int, int> getSize() const
340 	{
341 		return size;
342 	}
343 
getBaseType() const344 	GLenum getBaseType() const
345 	{
346 		return baseType;
347 	}
348 
streamArrayStr(std::ostringstream & _str,int arrayElem=-1) const349 	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:
fill()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:
UniformValueGenerator()516 	UniformValueGenerator() : fValue(0.0f), iValue(0)
517 	{
518 	}
genF()519 	GLfloat genF()
520 	{
521 		if (fValue > 99999.0f)
522 		{
523 			fValue = 0.0f;
524 		}
525 		return (fValue += 1.0f);
526 	}
genI()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:
streamValue(std::ostringstream & str,int arrayElement=0,int column=0) const541 	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 
getPtr(int arrayElement) const580 	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 
UniformValue(const UniformType & _type,UniformValueGenerator & generator)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:
Uniform(UniformValueGenerator & generator,UniformType _type,Loc _location,DefOccurence _declOccurence=DefOccurence::ALL_SH,DefOccurence _usageOccurence=DefOccurence::ALL_SH)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 
setName(const std::string & parentName,const std::string & _name)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 	}
getName() const718 	const std::string& getName() const
719 	{
720 		return name;
721 	}
722 
streamDefinition(std::ostringstream & str) const723 	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:
SubroutineFunction(UniformValueGenerator & generator,Index _index=Index::Implicit ())741 	SubroutineFunction(UniformValueGenerator& generator, Index _index = Index::Implicit())
742 		: index(_index), embeddedRetVal(GL_FLOAT_VEC4, generator)
743 	{
744 	}
getRetVal() const745 	const UniformValue& getRetVal() const
746 	{
747 		return embeddedRetVal;
748 	}
749 
getName() const750 	inline const std::string& getName() const
751 	{
752 		return name;
753 	}
754 
setName(int _name)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:
SubroutineFunctionSet(UniformValueGenerator & generator,size_t count=0)772 	SubroutineFunctionSet(UniformValueGenerator& generator, size_t count = 0) : fn(count, SubroutineFunction(generator))
773 	{
774 	}
775 
push_back(const SubroutineFunction & _fn)776 	void push_back(const SubroutineFunction& _fn)
777 	{
778 		fn.push_back(_fn);
779 	}
780 
getTypeName() const781 	inline const std::string& getTypeName() const
782 	{
783 		return typeName;
784 	}
785 
setTypeName(int _name)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:
SubroutineUniform(UniformValueGenerator & generator,SubroutineFunctionSet & _functions,Loc _location,int _arraySize=0,DefOccurence _defOccurence=DefOccurence::ALL_SH,bool _used=true)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 
SubroutineUniform(UniformValueGenerator & generator,SubroutineFunctionSet & _functions,Loc _location,std::vector<int> _arraySizesSegmented,DefOccurence _defOccurence=DefOccurence::ALL_SH,bool _used=true)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 	}
setName(const std::string & _name)856 	void setName(const std::string& _name)
857 	{
858 		name = _name;
859 	}
860 
getName() const861 	const std::string& getName() const
862 	{
863 		return name;
864 	}
865 
streamArrayStr(std::ostringstream & str,int arrayElem=-1) const866 	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 
getSelectedFunction(int arrayElem) const891 	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:
ShaderKey()914 	ShaderKey()
915 	{
916 	}
ShaderKey(GLenum _stage,const std::string & _input,const std::string & _output)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 
operator <(const ShaderKey & rhs) const924 	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 
streamUniformDefinitions(const std::vector<Uniform> & uniforms,GLenum shader,std::ostringstream & ret)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 
streamSubroutineDefinitions(const std::vector<SubroutineUniform> & subroutineUniforms,GLenum shader,std::ostringstream & ret)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 
streamUniformValidator(std::ostringstream & ret,const Uniform & uniform,GLenum shader,const char * outTemporary)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 
streamUniformValidators(std::ostringstream & ret,const std::vector<Uniform> & uniforms,GLenum shader,const char * outTemporary)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 
streamSubroutineValidator(std::ostringstream & ret,const SubroutineUniform & subroutineUniform,GLenum shader,const char * outTemporary)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 
streamSubroutineValidators(std::ostringstream & ret,const std::vector<SubroutineUniform> & subroutineUniforms,GLenum shader,const char * outTemporary)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 
streamShaderHeader(std::ostringstream & str,const glu::ContextType type)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 
generateFragmentShader(const ShaderKey & key,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef,const glu::ContextType type)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 
generateVertexShader(const ShaderKey & key,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef,const glu::ContextType type)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 
generateComputeShader(const ShaderKey &,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef,const glu::ContextType type)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:
generateShader(const ShaderKey & key,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef,const glu::ContextType type)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 		case GL_COMPUTE_SHADER:
1200 			return generateComputeShader(key, uniforms, subroutineUniforms, additionalDef, type);
1201 		default:
1202 			assert(0);
1203 			return "";
1204 		}
1205 	}
1206 };
1207 
1208 class ExplicitUniformLocationCaseBase : public glcts::SubcaseBase
1209 {
Title()1210 	virtual std::string Title()
1211 	{
1212 		return "";
1213 	}
Purpose()1214 	virtual std::string Purpose()
1215 	{
1216 		return "";
1217 	}
Method()1218 	virtual std::string Method()
1219 	{
1220 		return "";
1221 	}
PassCriteria()1222 	virtual std::string PassCriteria()
1223 	{
1224 		return "";
1225 	}
1226 
getWindowWidth()1227 	int getWindowWidth()
1228 	{
1229 		return m_context.getRenderContext().getRenderTarget().getWidth();
1230 	}
1231 
getWindowHeight()1232 	int getWindowHeight()
1233 	{
1234 		return m_context.getRenderContext().getRenderTarget().getHeight();
1235 	}
1236 
CreateShaders(const std::vector<std::vector<ShaderKey>> & programConfigs,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef)1237 	std::map<ShaderKey, GLuint> CreateShaders(const std::vector<std::vector<ShaderKey> >& programConfigs,
1238 											  const std::vector<Uniform>&			uniforms,
1239 											  const std::vector<SubroutineUniform>& subroutineUniforms,
1240 											  const std::string&					additionalDef)
1241 	{
1242 		std::map<ShaderKey, GLuint> ret;
1243 
1244 		//create shaders
1245 		for (size_t config = 0; config < programConfigs.size(); config++)
1246 		{
1247 			for (size_t target = 0; target < programConfigs[config].size(); target++)
1248 			{
1249 
1250 				if (ret.find(programConfigs[config][target]) == ret.end())
1251 				{
1252 					GLuint shader = glCreateShader(programConfigs[config][target].stage);
1253 
1254 					std::string source = ShaderSourceFactory::generateShader(programConfigs[config][target], uniforms,
1255 																			 subroutineUniforms, additionalDef,
1256 																			 m_context.getRenderContext().getType());
1257 					const char* cSource[] = { source.c_str() };
1258 					glShaderSource(shader, 1, cSource, NULL);
1259 					ret[programConfigs[config][target]] = shader;
1260 				}
1261 			}
1262 		}
1263 
1264 		//compile shaders
1265 		for (std::map<ShaderKey, GLuint>::iterator i = ret.begin(); i != ret.end(); i++)
1266 		{
1267 			glCompileShader(i->second);
1268 		}
1269 
1270 		return ret;
1271 	}
1272 
CreatePrograms(std::vector<CompiledProgram> & programs,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms,const std::string & additionalDef,bool negativeCompile,bool negativeLink)1273 	long CreatePrograms(std::vector<CompiledProgram>& programs, const std::vector<Uniform>& uniforms,
1274 						const std::vector<SubroutineUniform>& subroutineUniforms, const std::string& additionalDef,
1275 						bool negativeCompile, bool negativeLink)
1276 	{
1277 
1278 		long ret = NO_ERROR;
1279 
1280 		std::vector<std::vector<ShaderKey> > programConfigs;
1281 		{
1282 			std::vector<ShaderKey> vsh_fsh(2);
1283 			vsh_fsh[0] = ShaderKey(GL_VERTEX_SHADER, "", "vs_ValidationResult");
1284 			vsh_fsh[1] = ShaderKey(GL_FRAGMENT_SHADER, "vs_ValidationResult", "");
1285 			programConfigs.push_back(vsh_fsh);
1286 		}
1287 		{
1288 			std::vector<ShaderKey> csh(1);
1289 			csh[0] = ShaderKey(GL_COMPUTE_SHADER, "", "");
1290 			programConfigs.push_back(csh);
1291 		}
1292 
1293 		std::map<ShaderKey, GLuint> shaders =
1294 			CreateShaders(programConfigs, uniforms, subroutineUniforms, additionalDef);
1295 
1296 		//query compilation results
1297 		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1298 		{
1299 			GLint status;
1300 			glGetShaderiv(it->second, GL_COMPILE_STATUS, &status);
1301 			GLchar infoLog[1000], source[4000];
1302 			glGetShaderSource(it->second, 4000, NULL, source);
1303 			glGetShaderInfoLog(it->second, 1000, NULL, infoLog);
1304 			Logger::Get()->writeKernelSource(source);
1305 			Logger::Get()->writeCompileInfo("shader", "", status == GL_TRUE, infoLog);
1306 
1307 			if (!negativeLink)
1308 			{
1309 				if (!negativeCompile)
1310 				{
1311 					if (status != GL_TRUE)
1312 					{
1313 						Logger() << "Shader compilation failed";
1314 						ret |= ERROR;
1315 					}
1316 				}
1317 				else
1318 				{
1319 					if (status)
1320 					{
1321 						Logger() << "Negative compilation case failed: shader shoult not compile, but "
1322 									"GL_COMPILE_STATUS != 0";
1323 						ret |= ERROR;
1324 					}
1325 				}
1326 			}
1327 		}
1328 
1329 		if (negativeCompile)
1330 		{
1331 
1332 			//delete shaders
1333 			for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1334 			{
1335 				glDeleteShader(it->second);
1336 			}
1337 
1338 			return ret;
1339 		}
1340 
1341 		//assemble programs and link
1342 		for (size_t config = 0; config < programConfigs.size(); config++)
1343 		{
1344 			CompiledProgram program;
1345 			program.name = glCreateProgram();
1346 
1347 			for (size_t target = 0; target < programConfigs[config].size(); target++)
1348 			{
1349 
1350 				GLuint shader = shaders.find(programConfigs[config][target])->second;
1351 
1352 				glAttachShader(program.name, shader);
1353 
1354 				program.stages.push_back(programConfigs[config][target].stage);
1355 			}
1356 			programs.push_back(program);
1357 			glLinkProgram(programs[config].name);
1358 		}
1359 		for (size_t config = 0; config < programConfigs.size(); config++)
1360 		{
1361 			glLinkProgram(programs[config].name);
1362 		}
1363 
1364 		//delete shaders
1365 		for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++)
1366 		{
1367 			glDeleteShader(it->second);
1368 		}
1369 
1370 		//query link status:
1371 		for (size_t config = 0; config < programConfigs.size(); config++)
1372 		{
1373 			GLint status;
1374 
1375 			glGetProgramiv(programs[config].name, GL_LINK_STATUS, &status);
1376 			GLchar infoLog[1000];
1377 			glGetProgramInfoLog(programs[config].name, 1000, NULL, infoLog);
1378 			Logger::Get()->writeCompileInfo("program", "", status == GL_TRUE, infoLog);
1379 
1380 			if (!negativeLink)
1381 			{
1382 				if (status != GL_TRUE)
1383 				{
1384 					Logger() << "Shader link failed";
1385 					ret |= ERROR;
1386 				}
1387 			}
1388 			else
1389 			{
1390 				if (status)
1391 				{
1392 					Logger() << "Negative link case failed: program should not link, but GL_LINK_STATUS != 0";
1393 					ret |= ERROR;
1394 				}
1395 			}
1396 		}
1397 		return ret;
1398 	}
1399 
DeletePrograms(std::vector<CompiledProgram> & programs)1400 	long DeletePrograms(std::vector<CompiledProgram>& programs)
1401 	{
1402 		for (size_t i = 0; i < programs.size(); i++)
1403 		{
1404 			glDeleteProgram(programs[i].name);
1405 		}
1406 		programs.resize(0);
1407 		return NO_ERROR;
1408 	}
1409 
setUniform(const Uniform & uniform,const CompiledProgram & program)1410 	void setUniform(const Uniform& uniform, const CompiledProgram& program)
1411 	{
1412 
1413 		bool used = false;
1414 		for (size_t i = 0; i < program.stages.size(); i++)
1415 		{
1416 			used |= uniform.declOccurence.occurs(program.stages[i]) && uniform.usageOccurence.occurs(program.stages[i]);
1417 		}
1418 		if (!used)
1419 			return;
1420 
1421 		if (uniform.type.isStruct())
1422 		{
1423 			for (size_t j = 0; j < uniform.childUniforms.size(); j++)
1424 			{
1425 				setUniform(uniform.childUniforms[j], program);
1426 			}
1427 		}
1428 		else
1429 		{
1430 			GLint loc;
1431 			if (uniform.location.isImplicit(program.stages))
1432 			{
1433 				std::ostringstream name;
1434 				name << uniform.getName();
1435 				uniform.type.streamArrayStr(name, 0);
1436 				loc = glGetUniformLocation(program.name, name.str().c_str());
1437 			}
1438 			else
1439 			{
1440 				loc = uniform.location.val;
1441 			}
1442 
1443 			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
1444 			{
1445 				switch (uniform.type.enumType)
1446 				{
1447 				case GL_FLOAT:
1448 					glUniform1f(loc, *(GLfloat*)uniform.value.getPtr(arrayElem));
1449 					break;
1450 				case GL_FLOAT_VEC2:
1451 					glUniform2fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1452 					break;
1453 				case GL_FLOAT_VEC3:
1454 					glUniform3fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1455 					break;
1456 				case GL_FLOAT_VEC4:
1457 					glUniform4fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem));
1458 					break;
1459 				case GL_FLOAT_MAT2:
1460 					glUniformMatrix2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1461 					break;
1462 				case GL_FLOAT_MAT3:
1463 					glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1464 					break;
1465 				case GL_FLOAT_MAT4:
1466 					glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1467 					break;
1468 				case GL_FLOAT_MAT2x3:
1469 					glUniformMatrix2x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1470 					break;
1471 				case GL_FLOAT_MAT4x3:
1472 					glUniformMatrix4x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1473 					break;
1474 				case GL_FLOAT_MAT2x4:
1475 					glUniformMatrix2x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1476 					break;
1477 				case GL_FLOAT_MAT3x4:
1478 					glUniformMatrix3x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1479 					break;
1480 				case GL_FLOAT_MAT3x2:
1481 					glUniformMatrix3x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1482 					break;
1483 				case GL_FLOAT_MAT4x2:
1484 					glUniformMatrix4x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem));
1485 					break;
1486 				case GL_INT:
1487 				case GL_SAMPLER_2D:
1488 					glUniform1i(loc, *(GLint*)uniform.value.getPtr(arrayElem));
1489 					break;
1490 				case GL_INT_VEC2:
1491 					glUniform2iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1492 					break;
1493 				case GL_INT_VEC3:
1494 					glUniform3iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1495 					break;
1496 				case GL_INT_VEC4:
1497 					glUniform4iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem));
1498 					break;
1499 				case GL_UNSIGNED_INT:
1500 					glUniform1ui(loc, *(GLuint*)uniform.value.getPtr(arrayElem));
1501 					break;
1502 				default:
1503 					assert(0);
1504 				}
1505 				loc++;
1506 			}
1507 		}
1508 	}
1509 
setSubroutineUniform(const SubroutineUniform & subroutineUniform,const CompiledProgram & program,GLenum stage,std::vector<glw::GLuint> & indicesOut)1510 	void setSubroutineUniform(const SubroutineUniform& subroutineUniform, const CompiledProgram& program, GLenum stage,
1511 							  std::vector<glw::GLuint>& indicesOut)
1512 	{
1513 		bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
1514 		if (used)
1515 		{
1516 
1517 			for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
1518 			{
1519 				GLint loc = -1;
1520 				if (subroutineUniform.location.isImplicit(program.stages))
1521 				{
1522 					std::ostringstream name;
1523 					name << subroutineUniform.getName();
1524 					subroutineUniform.streamArrayStr(name, arrayElem);
1525 					loc = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
1526 				}
1527 				else
1528 				{
1529 					loc = subroutineUniform.location.val + arrayElem;
1530 				}
1531 
1532 				if (loc >= 0)
1533 				{
1534 					const SubroutineFunction& selectedFunction = subroutineUniform.getSelectedFunction(arrayElem);
1535 
1536 					int index = -1;
1537 					if (selectedFunction.index.isImplicit(std::vector<GLenum>(1, stage)))
1538 					{
1539 						index = glGetSubroutineIndex(program.name, stage, selectedFunction.getName().c_str());
1540 					}
1541 					else
1542 					{
1543 						index = selectedFunction.index.val;
1544 					}
1545 
1546 					if (loc < (int)indicesOut.size())
1547 					{
1548 						indicesOut[loc] = index;
1549 					}
1550 					else
1551 					{
1552 						assert(0);
1553 					}
1554 				}
1555 				else
1556 				{
1557 					assert(0);
1558 				}
1559 			}
1560 		}
1561 	}
1562 
runExecuteProgram(const CompiledProgram & program,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms)1563 	long runExecuteProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
1564 						   const std::vector<SubroutineUniform>& subroutineUniforms)
1565 	{
1566 		long ret = NO_ERROR;
1567 
1568 		glUseProgram(program.name);
1569 
1570 		for (size_t i = 0; i < uniforms.size(); i++)
1571 		{
1572 			setUniform(uniforms[i], program);
1573 		}
1574 
1575 		for (size_t stage = 0; stage < program.stages.size() && subroutineUniforms.size(); stage++)
1576 		{
1577 
1578 			glw::GLint numactive;
1579 			glGetProgramStageiv(program.name, program.stages[stage], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
1580 								&numactive);
1581 			if (numactive)
1582 			{
1583 				std::vector<glw::GLuint> indices(numactive, 0);
1584 
1585 				for (size_t i = 0; i < subroutineUniforms.size(); i++)
1586 				{
1587 					setSubroutineUniform(subroutineUniforms[i], program, program.stages[stage], indices);
1588 				}
1589 				glUniformSubroutinesuiv(program.stages[stage], numactive, &indices[0]);
1590 			}
1591 		}
1592 
1593 		if (program.stages[0] != GL_COMPUTE_SHADER)
1594 		{
1595 			glClear(GL_COLOR_BUFFER_BIT);
1596 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1597 
1598 			std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
1599 
1600 			glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
1601 			for (size_t i = 0; i < pixels.size(); i += 4)
1602 			{
1603 				if (pixels[i] != 0 || pixels[i + 1] != 255 || pixels[i + 2] != 0)
1604 				{
1605 					ret |= ERROR;
1606 					Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)pixels[i]
1607 							 << ", " << (int)pixels[i + 1] << ", " << (int)pixels[i + 2] << ", " << (int)pixels[i + 3]
1608 							 << ").";
1609 					break;
1610 				}
1611 			}
1612 			Logger().Get()->writeImage("rendered image", "", QP_IMAGE_COMPRESSION_MODE_BEST, QP_IMAGE_FORMAT_RGBA8888,
1613 									   getWindowWidth(), getWindowHeight(), 0, &pixels[0]);
1614 		}
1615 		else
1616 		{
1617 			GLuint buffer;
1618 			glGenBuffers(1, &buffer);
1619 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1620 			glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLfloat), NULL, GL_DYNAMIC_READ);
1621 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
1622 
1623 			glDispatchCompute(1, 1, 1);
1624 			glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
1625 
1626 			GLfloat* color = reinterpret_cast<GLfloat*>(
1627 				glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(GLfloat), GL_MAP_READ_BIT));
1628 
1629 			if (color[0] != 0 || color[1] != 1.0 || color[2] != 0)
1630 			{
1631 				ret |= ERROR;
1632 				Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)color[0]
1633 						 << ", " << (int)color[1] << ", " << (int)color[2] << ", " << (int)color[3] << ").";
1634 			}
1635 
1636 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1637 
1638 			glDeleteBuffers(1, &buffer);
1639 		}
1640 
1641 		return ret;
1642 	}
1643 
runQueryUniform(const CompiledProgram & program,const Uniform & uniform,std::set<GLuint> & usedLocations,GLint max)1644 	long runQueryUniform(const CompiledProgram& program, const Uniform& uniform, std::set<GLuint>& usedLocations,
1645 						 GLint max)
1646 	{
1647 		long ret = NO_ERROR;
1648 
1649 		/*
1650 		 glGetUniformLocation(program, name);
1651 		 Query passes if returned value is unique in current program, matches
1652 		 explicit location (if passed in GLSL code) and is less than value of
1653 		 GL_MAX_UNIFORM_LOCATIONS.
1654 
1655 		 glGetProgramResourceLocation(program, GL_UNIFIORM, name);
1656 		 Query passes if returned value matches value returned from
1657 		 glGetUniformLocation().
1658 		 */
1659 
1660 		if (uniform.type.isStruct())
1661 		{
1662 			for (size_t i = 0; i < uniform.childUniforms.size(); i++)
1663 			{
1664 				ret |= runQueryUniform(program, uniform.childUniforms[i], usedLocations, max);
1665 			}
1666 		}
1667 		else
1668 		{
1669 			for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++)
1670 			{
1671 
1672 				/* Location that is taken by this uniform (even if not used).*/
1673 				GLint reservedLocation = -1;
1674 				if (!uniform.location.isImplicit(program.stages))
1675 				{
1676 					reservedLocation = uniform.location.val + arrayElem;
1677 				}
1678 
1679 				//optimization: for continuous arrays run queries at the beging and end only.
1680 				bool runQueries = uniform.location.isImplicit(program.stages) ||
1681 								  (arrayElem < 1000 || arrayElem > uniform.type.arraySize - 1000);
1682 
1683 				if (runQueries)
1684 				{
1685 					std::ostringstream name;
1686 					name << uniform.getName();
1687 					uniform.type.streamArrayStr(name, arrayElem);
1688 					GLint returned = glGetUniformLocation(program.name, name.str().c_str());
1689 
1690 					GLint returnedPIQ = glGetProgramResourceLocation(program.name, GL_UNIFORM, name.str().c_str());
1691 
1692 					if (returned != returnedPIQ)
1693 					{
1694 						ret |= ERROR;
1695 						Logger()
1696 							<< "Locations of  uniform \"" << name.str()
1697 							<< "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
1698 							<< returned << " != " << returnedPIQ << ".";
1699 					}
1700 
1701 					bool used = false;
1702 					for (size_t i = 0; i < program.stages.size(); i++)
1703 					{
1704 						used |= uniform.declOccurence.occurs(program.stages[i]) &&
1705 								uniform.usageOccurence.occurs(program.stages[i]);
1706 					}
1707 
1708 					if (!uniform.location.isImplicit(program.stages))
1709 					{
1710 						//Validate uniform location against explicit value
1711 						GLint expected = reservedLocation;
1712 						if (!(expected == returned || (!used && returned == -1)))
1713 						{
1714 							ret |= ERROR;
1715 							Logger() << "Unexpected uniform \"" << name.str() << "\" location: expected " << expected
1716 									 << ", got " << returned << ".";
1717 						}
1718 					}
1719 					else
1720 					{
1721 						//Check if location > 0 if used;
1722 						if (used)
1723 						{
1724 							if (returned < 0)
1725 							{
1726 								ret |= ERROR;
1727 								Logger() << "Unexpected uniform \"" << name.str()
1728 										 << "\" location: expected positive value, got " << returned << ".";
1729 							}
1730 							else
1731 							{
1732 								reservedLocation = returned;
1733 							}
1734 						}
1735 					}
1736 
1737 					if (returned >= 0)
1738 					{
1739 						//check if location is less than max
1740 
1741 						if (returned >= max)
1742 						{
1743 							ret |= ERROR;
1744 							Logger() << "Uniform \"" << name.str() << "\" returned location (" << returned
1745 									 << ") is greater than implementation dependent limit (" << max << ").";
1746 						}
1747 					}
1748 				} //if (runQueries)
1749 
1750 				//usedLocations is always checked (even if queries were not run.
1751 				if (reservedLocation >= 0)
1752 				{
1753 					//check if location is unique
1754 					if (usedLocations.find(reservedLocation) != usedLocations.end())
1755 					{
1756 						ret |= ERROR;
1757 						Logger() << "Uniform location (" << reservedLocation << ") is not unique.";
1758 					}
1759 					usedLocations.insert(reservedLocation);
1760 				}
1761 			}
1762 		}
1763 		return ret;
1764 	}
1765 
runQueryUniformSubroutine(const CompiledProgram & program,GLenum stage,const SubroutineUniform & subroutineUniform,std::set<GLuint> & usedLocations,GLint max)1766 	long runQueryUniformSubroutine(const CompiledProgram& program, GLenum stage,
1767 								   const SubroutineUniform& subroutineUniform, std::set<GLuint>& usedLocations,
1768 								   GLint max)
1769 	{
1770 		long ret = NO_ERROR;
1771 		/*
1772 		 glGetSubroutineUniformLocation(program, shaderType, name)
1773 		 Query passes if returned value is unique in current program stage,
1774 		 matches explicit location (if passed in GLSL code) and is less than
1775 		 value of GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS.
1776 
1777 		 glGetProgramResourceLocation(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
1778 		 ..._SUBROUTINE_UNIFORM, name)
1779 		 Query passes if returned value matches value returned from
1780 		 glGetUniformLocation().
1781 		 */
1782 
1783 		for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++)
1784 		{
1785 			std::ostringstream name;
1786 			name << subroutineUniform.getName();
1787 
1788 			subroutineUniform.streamArrayStr(name, arrayElem);
1789 
1790 			GLint returned = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str());
1791 
1792 			glw::GLenum piqStage = 0;
1793 			switch (stage)
1794 			{
1795 			case GL_VERTEX_SHADER:
1796 				piqStage = GL_VERTEX_SUBROUTINE_UNIFORM;
1797 				break;
1798 			case GL_FRAGMENT_SHADER:
1799 				piqStage = GL_FRAGMENT_SUBROUTINE_UNIFORM;
1800 				break;
1801 			case GL_COMPUTE_SHADER:
1802 				piqStage = GL_COMPUTE_SUBROUTINE_UNIFORM;
1803 				break;
1804 			default:
1805 				assert(0);
1806 			}
1807 
1808 			GLint returnedPIQ = glGetProgramResourceLocation(program.name, piqStage, name.str().c_str());
1809 
1810 			if (returned != returnedPIQ)
1811 			{
1812 				ret |= ERROR;
1813 				Logger() << "Locations of subrutine uniform \"" << name.str()
1814 						 << "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: "
1815 						 << returned << " != " << returnedPIQ << ".";
1816 			}
1817 
1818 			bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used;
1819 
1820 			GLint reservedLocation = -1;
1821 
1822 			if (!subroutineUniform.location.isImplicit(std::vector<glw::GLenum>(1, stage)))
1823 			{
1824 				//Validate uniform location against explicit value
1825 				GLint expected = subroutineUniform.location.val + arrayElem;
1826 				if (!(expected == returned || (!used && returned == -1)))
1827 				{
1828 					ret |= ERROR;
1829 					Logger() << "Unexpected subroutine uniform \"" << name.str() << "\" location: expected " << expected
1830 							 << ", got " << returned << ".";
1831 				}
1832 
1833 				reservedLocation = expected;
1834 			}
1835 			else
1836 			{
1837 				//Check if location > 0 if used;
1838 				if (used)
1839 				{
1840 					if (returned < 0)
1841 					{
1842 						ret |= ERROR;
1843 						Logger() << "Unexpected subroutine uniform \"" << name.str()
1844 								 << "\" location: expected positive value, got " << returned << ".";
1845 					}
1846 					else
1847 					{
1848 						reservedLocation = returned;
1849 					}
1850 				}
1851 			}
1852 
1853 			if (reservedLocation >= 0)
1854 			{
1855 				//check if location is unique
1856 				if (usedLocations.find(reservedLocation) != usedLocations.end())
1857 				{
1858 					ret |= ERROR;
1859 					Logger() << "Subroutine uniform \"" << name.str() << "\" location (" << reservedLocation
1860 							 << ") is not unique.";
1861 				}
1862 				usedLocations.insert(reservedLocation);
1863 			}
1864 
1865 			if (returned >= 0)
1866 			{
1867 				//check if location is less than max
1868 
1869 				if (returned >= max)
1870 				{
1871 					ret |= ERROR;
1872 					Logger() << "Subroutine uniform \"" << name.str() << "\" returned location (" << returned
1873 							 << ") is greater than implementation dependent limit (" << max << ").";
1874 				}
1875 			}
1876 		}
1877 		return ret;
1878 	}
1879 
runQueryUniformSubroutineFunction(const CompiledProgram & program,GLenum stage,const SubroutineFunction & subroutineFunction,std::set<GLuint> & usedIndices,GLint max,bool used)1880 	long runQueryUniformSubroutineFunction(const CompiledProgram& program, GLenum stage,
1881 										   const SubroutineFunction& subroutineFunction, std::set<GLuint>& usedIndices,
1882 										   GLint max, bool used)
1883 	{
1884 		long ret = NO_ERROR;
1885 		/*
1886 		 glGetSubroutineIndex(program, shaderType, name)
1887 		 Query passes if returned value is unique in current program stage,
1888 		 matches explicit index (if passed in GLSL code) and is less than value
1889 		 of GL_MAX_SUBROUTINES.
1890 
1891 		 glGetProgramResourceIndex(program, GL_(VERTEX|FRAGMENT|COMPUTE|...
1892 		 ..._SUBROUTINE, name)
1893 		 Query passes if returned value matches value returned from
1894 		 glGetSubroutineIndex().
1895 		 */
1896 
1897 		std::string name = subroutineFunction.getName();
1898 
1899 		GLint returned = glGetSubroutineIndex(program.name, stage, name.c_str());
1900 
1901 		glw::GLenum piqStage = 0;
1902 		switch (stage)
1903 		{
1904 		case GL_VERTEX_SHADER:
1905 			piqStage = GL_VERTEX_SUBROUTINE;
1906 			break;
1907 		case GL_FRAGMENT_SHADER:
1908 			piqStage = GL_FRAGMENT_SUBROUTINE;
1909 			break;
1910 		case GL_COMPUTE_SHADER:
1911 			piqStage = GL_COMPUTE_SUBROUTINE;
1912 			break;
1913 		default:
1914 			assert(0);
1915 		}
1916 
1917 		GLint returnedPIQ = glGetProgramResourceIndex(program.name, piqStage, name.c_str());
1918 
1919 		if (returned != returnedPIQ)
1920 		{
1921 			ret |= ERROR;
1922 			Logger() << "Indices of subroutine function \"" << name
1923 					 << "\" returned by glGetSubroutineIndex and differ glGetProgramResourceIndex differ: " << returned
1924 					 << " != " << returnedPIQ << ".";
1925 		}
1926 
1927 		GLint reservedIndex = -1;
1928 
1929 		if (!subroutineFunction.index.isImplicit(std::vector<glw::GLenum>(1, stage)))
1930 		{
1931 			//Validate uniform location against explicit value
1932 			GLint expected = subroutineFunction.index.val;
1933 			if (!(expected == returned || (!used && returned == -1)))
1934 			{
1935 				ret |= ERROR;
1936 				Logger() << "Unexpected subroutine function \"" << name << "\" index: expected " << expected << ", got "
1937 						 << returned << ".";
1938 			}
1939 
1940 			reservedIndex = expected;
1941 		}
1942 		else
1943 		{
1944 			//Check if location > 0 if used;
1945 			if (used)
1946 			{
1947 				if (returned < 0)
1948 				{
1949 					ret |= ERROR;
1950 					Logger() << "Unexpected subroutine function \"" << name << "\" index: expected positive value, got "
1951 							 << returned << ".";
1952 				}
1953 				else
1954 				{
1955 					reservedIndex = returned;
1956 				}
1957 			}
1958 		}
1959 
1960 		if (reservedIndex >= 0)
1961 		{
1962 			//check if location is unique
1963 			if (usedIndices.find(reservedIndex) != usedIndices.end())
1964 			{
1965 				ret |= ERROR;
1966 				Logger() << "Subroutine function \"" << name << "\" index (" << reservedIndex << ") is not unique.";
1967 			}
1968 			usedIndices.insert(reservedIndex);
1969 		}
1970 
1971 		if (returned >= 0)
1972 		{
1973 			//check if location is less than max
1974 
1975 			if (returned >= max)
1976 			{
1977 				ret |= ERROR;
1978 				Logger() << "Subroutine function \"" << name << "\" returned index (" << returned
1979 						 << ") is greater than implementation dependent limit (" << max << ").";
1980 			}
1981 		}
1982 
1983 		return ret;
1984 	}
1985 
runQueryProgram(const CompiledProgram & program,const std::vector<Uniform> & uniforms,const std::vector<SubroutineUniform> & subroutineUniforms)1986 	long runQueryProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms,
1987 						 const std::vector<SubroutineUniform>& subroutineUniforms)
1988 	{
1989 		long ret = NO_ERROR;
1990 
1991 		{
1992 			std::set<GLuint> usedLocations;
1993 
1994 			GLint max;
1995 			glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
1996 
1997 			for (size_t i = 0; i < uniforms.size(); i++)
1998 			{
1999 				ret |= runQueryUniform(program, uniforms[i], usedLocations, max);
2000 			}
2001 		}
2002 
2003 		if (subroutineUniforms.size())
2004 		{
2005 			GLint maxLocation, maxIndex;
2006 			glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &maxLocation);
2007 			glGetIntegerv(GL_MAX_SUBROUTINES, &maxIndex);
2008 
2009 			for (size_t stage = 0; stage < program.stages.size(); stage++)
2010 			{
2011 				std::set<GLuint> usedLocations;
2012 				std::set<GLuint> usedIndices;
2013 				for (size_t i = 0; i < subroutineUniforms.size(); i++)
2014 				{
2015 					ret |= runQueryUniformSubroutine(program, program.stages[stage], subroutineUniforms[i],
2016 													 usedLocations, maxLocation);
2017 					for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
2018 					{
2019 						ret |= runQueryUniformSubroutineFunction(
2020 							program, program.stages[stage], subroutineUniforms[i].functions.fn[fn], usedIndices,
2021 							maxIndex,
2022 							subroutineUniforms[i].defOccurence.occurs(program.stages[stage]) &&
2023 								subroutineUniforms[i].used);
2024 					}
2025 				}
2026 			}
2027 		}
2028 
2029 		return ret;
2030 	}
2031 
2032 protected:
2033 	UniformValueGenerator uniformValueGenerator;
2034 	UniformStructCounter  uniformStructCounter;
2035 
doRun(std::vector<SubroutineUniform> & subroutineUniforms)2036 	long doRun(std::vector<SubroutineUniform>& subroutineUniforms)
2037 	{
2038 		assert(subroutineUniforms.size());
2039 		std::vector<Uniform> noUniforms;
2040 		return doRun(noUniforms, subroutineUniforms);
2041 	}
2042 
doRun(std::vector<Uniform> & uniforms)2043 	long doRun(std::vector<Uniform>& uniforms)
2044 	{
2045 		assert(uniforms.size());
2046 		std::vector<SubroutineUniform> noSubroutineUniforms;
2047 		return doRun(uniforms, noSubroutineUniforms);
2048 	}
2049 
doRunNegativeCompile(const std::string additionalDef)2050 	long doRunNegativeCompile(const std::string additionalDef)
2051 	{
2052 		std::vector<Uniform>		   noUniforms;
2053 		std::vector<SubroutineUniform> noSubroutineUniforms;
2054 		return doRun(noUniforms, noSubroutineUniforms, additionalDef, true);
2055 	}
2056 
doRunNegativeLink(std::vector<Uniform> & uniforms)2057 	long doRunNegativeLink(std::vector<Uniform>& uniforms)
2058 	{
2059 		std::vector<SubroutineUniform> noSubroutineUniforms;
2060 		return doRun(uniforms, noSubroutineUniforms, "", false, true);
2061 	}
2062 
doRunNegativeLink(std::vector<SubroutineUniform> & subroutineUniforms)2063 	long doRunNegativeLink(std::vector<SubroutineUniform>& subroutineUniforms)
2064 	{
2065 		std::vector<Uniform> noUniforms;
2066 		return doRun(noUniforms, subroutineUniforms, "", false, true);
2067 	}
2068 
doRun(std::vector<Uniform> & uniforms,std::vector<SubroutineUniform> & subroutineUniforms,std::string additionalDef="",bool negativeCompile=false,bool negativeLink=false)2069 	long doRun(std::vector<Uniform>& uniforms, std::vector<SubroutineUniform>& subroutineUniforms,
2070 			   std::string additionalDef = "", bool negativeCompile = false, bool negativeLink = false)
2071 	{
2072 		long		ret				  = NO_ERROR;
2073 		std::string parentUniformName = "";
2074 		for (size_t i = 0; i < uniforms.size(); i++)
2075 		{
2076 			std::ostringstream name;
2077 			name << "u" << i;
2078 			uniforms[i].setName(parentUniformName, name.str());
2079 		}
2080 		int subroutineTypeCounter	 = 0;
2081 		int subroutineFunctionCounter = 0;
2082 		for (size_t i = 0; i < subroutineUniforms.size(); i++)
2083 		{
2084 			std::ostringstream name;
2085 			name << "u" << i + uniforms.size();
2086 			subroutineUniforms[i].setName(name.str());
2087 			if (!subroutineUniforms[i].functions.getTypeName().size())
2088 			{
2089 				subroutineUniforms[i].functions.setTypeName(subroutineTypeCounter++);
2090 				for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++)
2091 				{
2092 					subroutineUniforms[i].functions.fn[fn].setName(subroutineFunctionCounter++);
2093 				}
2094 			}
2095 		}
2096 
2097 		GLfloat coords[] = {
2098 			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,
2099 		};
2100 
2101 		GLuint vbo, vao;
2102 		glGenBuffers(1, &vbo);
2103 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
2104 		glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
2105 
2106 		glGenVertexArrays(1, &vao);
2107 		glBindVertexArray(vao);
2108 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
2109 		glEnableVertexAttribArray(0);
2110 
2111 		std::vector<CompiledProgram> programs;
2112 		ret |= CreatePrograms(programs, uniforms, subroutineUniforms, additionalDef, negativeCompile, negativeLink);
2113 
2114 		for (size_t i = 0; i < programs.size() && ret == NO_ERROR && !negativeCompile && !negativeLink; i++)
2115 		{
2116 			ret |= runExecuteProgram(programs[i], uniforms, subroutineUniforms);
2117 			ret |= runQueryProgram(programs[i], uniforms, subroutineUniforms);
2118 		}
2119 
2120 		glUseProgram(0);
2121 
2122 		DeletePrograms(programs);
2123 
2124 		glDeleteBuffers(1, &vbo);
2125 		glDeleteVertexArrays(1, &vao);
2126 
2127 		return ret;
2128 	}
2129 };
2130 
2131 class UniformLoc : public ExplicitUniformLocationCaseBase
2132 {
Run()2133 	virtual long Run()
2134 	{
2135 		//layout (location = 2) uniform vec4 u0;
2136 		std::vector<Uniform> uniforms;
2137 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2138 		return doRun(uniforms);
2139 	}
2140 };
2141 
2142 class UniformLocNonDec : public ExplicitUniformLocationCaseBase
2143 {
Run()2144 	virtual long Run()
2145 	{
2146 		//layout (location = 0x0a) uniform vec4 u0;
2147 		//layout (location = 010) uniform vec4  u1;
2148 		std::vector<Uniform> uniforms;
2149 		uniforms.push_back(
2150 			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(0x0a, Loc::Hex), DefOccurence::FSH_OR_CSH));
2151 		uniforms.push_back(
2152 			Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(010, Loc::Oct), DefOccurence::FSH_OR_CSH));
2153 		return doRun(uniforms);
2154 	}
2155 };
2156 
2157 class UniformLocMultipleStages : public ExplicitUniformLocationCaseBase
2158 {
Run()2159 	virtual long Run()
2160 	{
2161 		//layout (location = 2) uniform vec4 u0;
2162 		std::vector<Uniform> uniforms;
2163 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
2164 		return doRun(uniforms);
2165 	}
2166 };
2167 
2168 class UniformLocMultipleUniforms : public ExplicitUniformLocationCaseBase
2169 {
Run()2170 	virtual long Run()
2171 	{
2172 		//layout (location = 2) uniform vec4 u0;
2173 		//layout (location = 3) uniform vec4 u1;
2174 		//layout (location = 5) uniform vec4 u2;
2175 		std::vector<Uniform> uniforms;
2176 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2)));
2177 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(3)));
2178 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(5)));
2179 		return doRun(uniforms);
2180 	}
2181 };
2182 
2183 class UniformLocTypesMix : public ExplicitUniformLocationCaseBase
2184 {
Run()2185 	virtual long Run()
2186 	{
2187 		//layout (location = 2) uniform float u0;
2188 		//layout (location = 3) uniform vec3  u1;
2189 		//layout (location = 0) uniform uint  u2;
2190 		//layout (location = 1) uniform ivec3 u3;
2191 		//layout (location = 4) uniform mat2  u4;
2192 		//layout (location = 7) uniform mat2  u5;
2193 		//layout (location = 5) uniform mat2  u6;
2194 		//layout (location = 6) uniform mat3  u7;
2195 		std::vector<Uniform> uniforms;
2196 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
2197 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(3)));
2198 		uniforms.push_back(Uniform(uniformValueGenerator, GL_UNSIGNED_INT, Loc::C(0)));
2199 		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC3, Loc::C(1)));
2200 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(4)));
2201 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(7)));
2202 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(5)));
2203 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3, Loc::C(6)));
2204 		return doRun(uniforms);
2205 	}
2206 };
2207 
2208 class UniformLocTypesMat : public ExplicitUniformLocationCaseBase
2209 {
Run()2210 	virtual long Run()
2211 	{
2212 		std::vector<Uniform> uniforms;
2213 		//layout (location = 1) uniform mat2x3   u0;
2214 		//layout (location = 2) uniform mat3x2   u1;
2215 		//layout (location = 0) uniform mat2     u2;
2216 		//layout (location = 3) uniform imat3x4  u3;
2217 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2x3, Loc::C(1)));
2218 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3x2, Loc::C(2)));
2219 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(0)));
2220 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT4x3, Loc::C(3)));
2221 		return doRun(uniforms);
2222 	}
2223 };
2224 
2225 class UniformLocTypesSamplers : public ExplicitUniformLocationCaseBase
2226 {
Run()2227 	virtual long Run()
2228 	{
2229 		//layout (location = 1) uniform sampler2D s0[3];
2230 		//layout (location = 13) uniform sampler2D s1;
2231 		std::vector<Uniform> uniforms;
2232 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_SAMPLER_2D, 3), Loc::C(1)));
2233 		uniforms.push_back(Uniform(uniformValueGenerator, GL_SAMPLER_2D, Loc::C(13)));
2234 
2235 		std::vector<GLuint>				   texUnits;
2236 		std::vector<std::vector<GLubyte> > colors;
2237 
2238 		for (size_t i = 0; i < uniforms.size(); i++)
2239 		{
2240 			for (int elem = 0; elem < uniforms[i].type.arraySize; elem++)
2241 			{
2242 				texUnits.push_back(uniforms[i].value.iValues[elem]);
2243 
2244 				std::vector<GLubyte> color(4);
2245 				color[0] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 0] + 0.5);
2246 				color[1] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 1] + 0.5);
2247 				color[2] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 2] + 0.5);
2248 				color[3] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 3] + 0.5);
2249 				colors.push_back(color);
2250 			}
2251 		}
2252 
2253 		std::vector<GLuint> textures(texUnits.size());
2254 		glGenTextures((GLsizei)(textures.size()), &textures[0]);
2255 
2256 		for (size_t i = 0; i < textures.size(); i++)
2257 		{
2258 			glActiveTexture(GL_TEXTURE0 + texUnits[i]);
2259 			glBindTexture(GL_TEXTURE_2D, textures[i]);
2260 			glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2261 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &colors[i][0]);
2262 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2263 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2264 		}
2265 		glActiveTexture(GL_TEXTURE0);
2266 		long ret = doRun(uniforms);
2267 		glDeleteTextures((GLsizei)(textures.size()), &textures[0]);
2268 		return ret;
2269 	}
2270 };
2271 
2272 class UniformLocTypesStructs : public ExplicitUniformLocationCaseBase
2273 {
Run()2274 	virtual long Run()
2275 	{
2276 
2277 		/**
2278 		 * This test case uses following uniform declarations:
2279 		 *
2280 		 * struct S {
2281 		 *   vec4  u0;
2282 		 *   float u1[2];
2283 		 *   mat2  u2;
2284 		 * };
2285 		 * layout (location = 1) uniform S s0[3];
2286 		 * layout (location = 13) uniform S s1;
2287 		 */
2288 
2289 		std::vector<UniformType> members;
2290 		members.push_back(GL_FLOAT_VEC4);
2291 		members.push_back(UniformType(GL_FLOAT, 2));
2292 		members.push_back(GL_FLOAT_MAT2);
2293 		std::vector<Uniform> uniforms;
2294 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members, 3), Loc::C(1)));
2295 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members), Loc::C(13)));
2296 		return doRun(uniforms);
2297 	}
2298 };
2299 
2300 class UniformLocArraysNonSpaced : public ExplicitUniformLocationCaseBase
2301 {
Run()2302 	virtual long Run()
2303 	{
2304 		//layout (location = 2) uniform float[3] u0;
2305 		//layout (location = 5) uniform vec3[2]  u1;
2306 		//layout (location = 7) uniform int[3]   u2;
2307 		//layout (location = 10) uniform ivec4   u3;
2308 		std::vector<Uniform> uniforms;
2309 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(2)));
2310 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
2311 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(7)));
2312 		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC4, Loc::C(10)));
2313 		return doRun(uniforms);
2314 	}
2315 };
2316 
2317 class UniformLocArraySpaced : public ExplicitUniformLocationCaseBase
2318 {
Run()2319 	virtual long Run()
2320 	{
2321 		//layout (location = 2) uniform float     u0;
2322 		//layout (location = 5) uniform vec3[2]   u1;
2323 		//layout (location = 8) uniform int[3]    u2;
2324 		//layout (location = 12) uniform ivec4[1] u3;
2325 		std::vector<Uniform> uniforms;
2326 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2)));
2327 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5)));
2328 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(8)));
2329 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 1), Loc::C(12)));
2330 		return doRun(uniforms);
2331 	}
2332 };
2333 
2334 class UniformLocArrayofArrays : public ExplicitUniformLocationCaseBase
2335 {
Run()2336 	virtual long Run()
2337 	{
2338 		//layout (location = 2) uniform float[2][3]  u0;
2339 		//layout (location = 8) uniform vec3[2][2]   u1;
2340 		//layout (location = 12) uniform float       u2;
2341 		std::vector<Uniform> uniforms;
2342 		{
2343 			std::vector<int> arraySizesSegmented(2);
2344 			arraySizesSegmented[0] = 2;
2345 			arraySizesSegmented[1] = 3;
2346 			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, arraySizesSegmented), Loc::C(2)));
2347 		}
2348 		{
2349 			std::vector<int> arraySizesSegmented(2);
2350 			arraySizesSegmented[0] = arraySizesSegmented[1] = 2;
2351 			uniforms.push_back(
2352 				Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, arraySizesSegmented), Loc::C(8)));
2353 		}
2354 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(12)));
2355 		return doRun(uniforms);
2356 	}
2357 };
2358 
2359 class UniformLocMixWithImplicit : public ExplicitUniformLocationCaseBase
2360 {
Run()2361 	virtual long Run()
2362 	{
2363 		//layout (location = 0) uniform float     u0;
2364 		//layout (location = 2) uniform vec3      u1;
2365 		//layout (location = 3) uniform int       u2;
2366 
2367 		//uniform float     u0;
2368 		//uniform vec3      u1;
2369 		//uniform int       u2;
2370 		std::vector<Uniform> uniforms;
2371 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::FSH_OR_CSH)));
2372 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2, DefOccurence::FSH_OR_CSH)));
2373 		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
2374 		return doRun(uniforms);
2375 	}
2376 };
2377 
2378 class UniformLocMixWithImplicit2 : public ExplicitUniformLocationCaseBase
2379 {
Run()2380 	virtual long Run()
2381 	{
2382 		//uniform float[3] u0;
2383 		//layout (location = 3) uniform vec3[2]  u1;
2384 		//uniform int[3]   u2;
2385 		//layout (location = 8) uniform ivec4   u3;
2386 		std::vector<Uniform> uniforms;
2387 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::Implicit()));
2388 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(3)));
2389 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::Implicit()));
2390 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 2), Loc::C(8)));
2391 		return doRun(uniforms);
2392 	}
2393 };
2394 
2395 class UniformLocMixWithImplicit3 : public ExplicitUniformLocationCaseBase
2396 {
Run()2397 	virtual long Run()
2398 	{
2399 		//layout (location = 0) uniform float     u0; //unused
2400 		//layout (location = 2) uniform vec3      u1; //unused
2401 		//layout (location = 3) uniform int       u2; //unused
2402 
2403 		//uniform float     u3;
2404 		//uniform vec3      u4;
2405 		//uniform int       u5;
2406 		std::vector<Uniform> uniforms;
2407 		uniforms.push_back(
2408 			Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2409 		uniforms.push_back(
2410 			Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2411 		uniforms.push_back(
2412 			Uniform(uniformValueGenerator, GL_INT, Loc::C(3), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2413 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
2414 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::Implicit()));
2415 		uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::Implicit()));
2416 		return doRun(uniforms);
2417 	}
2418 };
2419 
2420 class UniformLocMixWithImplicitMax : public ExplicitUniformLocationCaseBase
2421 {
Run()2422 	virtual long Run()
2423 	{
2424 		long ret = NO_ERROR;
2425 
2426 		GLint max;
2427 		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2428 
2429 		const int implicitCount = 1;
2430 
2431 		int tests[3] = { 0, 3, max - implicitCount };
2432 
2433 		for (int test = 0; test < 3; test++)
2434 		{
2435 			std::vector<Uniform> uniforms;
2436 
2437 			//for performance reasons fill-up all avaliable locations with an unused arrays.
2438 			if (tests[test] > 0)
2439 			{
2440 				//[0..test - 1]
2441 				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
2442 										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2443 				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2444 					   tests[test]);
2445 			}
2446 
2447 			if (tests[test] < max - implicitCount)
2448 			{
2449 				//[test + 1..max]
2450 				uniforms.push_back(
2451 					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
2452 							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2453 				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2454 					   max);
2455 			}
2456 
2457 			uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit()));
2458 			ret |= doRun(uniforms);
2459 		}
2460 		return ret;
2461 	}
2462 };
2463 
2464 class UniformLocMixWithImplicitMaxArray : public ExplicitUniformLocationCaseBase
2465 {
Run()2466 	virtual long Run()
2467 	{
2468 		long ret = NO_ERROR;
2469 
2470 		GLint max;
2471 		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2472 
2473 		const int implicitCount = 3;
2474 
2475 		int tests[3] = { 0, 3, max - 4 };
2476 
2477 		for (int test = 0; test < 3; test++)
2478 		{
2479 			std::vector<Uniform> uniforms;
2480 
2481 			//for performance reasons fill-up all avaliable locations with an unused arrays.
2482 			if (tests[test] > 0)
2483 			{
2484 				//[0..test - 1]
2485 				uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0),
2486 										   DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2487 				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2488 					   tests[test]);
2489 			}
2490 
2491 			if (tests[test] < max - implicitCount)
2492 			{
2493 				//[test + 3 ..max]
2494 				uniforms.push_back(
2495 					Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]),
2496 							Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH));
2497 				assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize ==
2498 					   max);
2499 			}
2500 			uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, implicitCount), Loc::Implicit()));
2501 			ret |= doRun(uniforms);
2502 		}
2503 		return ret;
2504 	}
2505 };
2506 
2507 class UniformLocImplicitInSomeStages : public ExplicitUniformLocationCaseBase
2508 {
Run()2509 	virtual long Run()
2510 	{
2511 		//One shader: uniform float u0;
2512 		//Another shader: layout (location = 3) uniform float  u0;
2513 		std::vector<Uniform> uniforms;
2514 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH)));
2515 		return doRun(uniforms);
2516 	}
2517 };
2518 
2519 class UniformLocImplicitInSomeStages2 : public ExplicitUniformLocationCaseBase
2520 {
Run()2521 	virtual long Run()
2522 	{
2523 		//One shader: uniform float u0;
2524 		//Another shader: layout (location = 3) uniform float  u0; //not used!
2525 		std::vector<Uniform> uniforms;
2526 
2527 		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2528 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
2529 								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2530 		return doRun(uniforms);
2531 	}
2532 };
2533 
2534 class UniformLocImplicitInSomeStages3 : public ExplicitUniformLocationCaseBase
2535 {
Run()2536 	virtual long Run()
2537 	{
2538 		std::vector<Uniform> uniforms;
2539 
2540 		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2541 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH),
2542 								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2543 
2544 		//location in all but fsh, declaration in all shaders, usage in fsh.
2545 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2, DefOccurence::ALL_BUT_FSH),
2546 								   DefOccurence::ALL_SH, DefOccurence::FSH_OR_CSH));
2547 
2548 		//location only in fsh, declaration in all shaders, usage in all shaders but fsh.
2549 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(7, DefOccurence::FSH_OR_CSH),
2550 								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH));
2551 
2552 		//location in all but fsh, declaration in all shaders, usage in fsh.
2553 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3),
2554 								   Loc::C(4, DefOccurence::ALL_BUT_FSH), DefOccurence::ALL_SH,
2555 								   DefOccurence::FSH_OR_CSH));
2556 
2557 		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
2558 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::VSH), DefOccurence::ALL_SH,
2559 								   DefOccurence::ALL_BUT_VSH));
2560 
2561 		//location only in vsh, declaration in all shaders, usage in all shaders but vsh.
2562 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(1, DefOccurence::ALL_BUT_FSH),
2563 								   DefOccurence::ALL_SH, DefOccurence::ALL_BUT_VSH));
2564 
2565 		return doRun(uniforms);
2566 	}
2567 };
2568 
2569 class UniformLocNegativeCompileNonNumberLiteral : public ExplicitUniformLocationCaseBase
2570 {
Run()2571 	virtual long Run()
2572 	{
2573 		std::string def = "layout (location = x) uniform float u0;";
2574 		return doRunNegativeCompile(def);
2575 	}
2576 };
2577 
2578 class UniformLocNegativeCompileNonConstLoc : public ExplicitUniformLocationCaseBase
2579 {
Run()2580 	virtual long Run()
2581 	{
2582 		std::string def = NL "const int i = 1;" NL "layout (location = i) uniform float u0;";
2583 		return doRunNegativeCompile(def);
2584 	}
2585 };
2586 
2587 class UniformLocNegativeLinkLocationReused1 : public ExplicitUniformLocationCaseBase
2588 {
Run()2589 	virtual long Run()
2590 	{
2591 		//layout (location = 2) uniform float u0;
2592 		//layout (location = 2) uniform float u1;
2593 		std::vector<Uniform> uniforms;
2594 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2595 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2596 		return doRunNegativeLink(uniforms);
2597 	}
2598 };
2599 
2600 class UniformLocNegativeLinkLocationReused2 : public ExplicitUniformLocationCaseBase
2601 {
Run()2602 	virtual long Run()
2603 	{
2604 		///layout (location = 2) uniform float u0;
2605 		//layout (location = 2) uniform float u1;
2606 		std::vector<Uniform> uniforms;
2607 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH));
2608 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::ALL_BUT_FSH));
2609 		return doRunNegativeLink(uniforms);
2610 	}
2611 };
2612 
2613 class UniformLocNegativeLinkMaxLocation : public ExplicitUniformLocationCaseBase
2614 {
Run()2615 	virtual long Run()
2616 	{
2617 		//layout (location = X) uniform float u0;
2618 		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
2619 
2620 		GLint max;
2621 		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2622 
2623 		std::vector<Uniform> uniforms;
2624 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(max), DefOccurence::FSH_OR_CSH));
2625 
2626 		return doRunNegativeLink(uniforms);
2627 	}
2628 };
2629 
2630 class UniformLocNegativeLinkMaxMaxNumOfLocation : public ExplicitUniformLocationCaseBase
2631 {
Run()2632 	virtual long Run()
2633 	{
2634 
2635 		GLint max;
2636 		glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max);
2637 		std::vector<Uniform> uniforms;
2638 		uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max), Loc::C(0),
2639 								   DefOccurence::FSH_OR_CSH, DefOccurence::NONE_SH));
2640 		uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit(), DefOccurence::ALL_BUT_FSH));
2641 		return doRunNegativeLink(uniforms);
2642 	}
2643 };
2644 
2645 class SubRoutineLoc : public ExplicitUniformLocationCaseBase
2646 {
Run()2647 	virtual long Run()
2648 	{
2649 
2650 		//one shader:
2651 		//subroutine vec4 st0(float param);
2652 		//subroutine(st0) vec4 sf0(float param) { .... };
2653 		//subroutine(st0) vec4 sf1(float param) { .... };
2654 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2655 
2656 		std::vector<SubroutineUniform> subroutineUniforms;
2657 
2658 		//layout(location = 2) subroutine uniform st0 u0;
2659 		subroutineUniforms.push_back(
2660 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2661 		return doRun(subroutineUniforms);
2662 	}
2663 };
2664 
2665 class SubRoutineLocNonDecimal : public ExplicitUniformLocationCaseBase
2666 {
Run()2667 	virtual long Run()
2668 	{
2669 		//one shader:
2670 		//subroutine vec4 st0(float param);
2671 		//subroutine(st0) vec4 sf0(float param) { .... };
2672 		//subroutine(st0) vec4 sf1(float param) { .... };
2673 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2674 
2675 		std::vector<SubroutineUniform> subroutineUniforms;
2676 
2677 		//layout(location = 0x0a) subroutine uniform st0 u0;
2678 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0x0a, Loc::Hex), 0,
2679 													   DefOccurence::FSH_OR_CSH));
2680 		//layout(location = 010 ) subroutine uniform st0 u1;
2681 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(010, Loc::Oct), 0,
2682 													   DefOccurence::FSH_OR_CSH));
2683 		return doRun(subroutineUniforms);
2684 	}
2685 };
2686 
2687 class SubRoutineLocAllStages : public ExplicitUniformLocationCaseBase
2688 {
Run()2689 	virtual long Run()
2690 	{
2691 		//subroutine vec4 st0(float param);
2692 		//subroutine(st0) vec4 sf0(float param) { .... };
2693 		//subroutine(st0) vec4 sf1(float param) { .... };
2694 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2695 
2696 		std::vector<SubroutineUniform> subroutineUniforms;
2697 
2698 		//layout(location = 2) subroutine uniform st0 u0;
2699 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2)));
2700 		return doRun(subroutineUniforms);
2701 	}
2702 };
2703 
2704 class SubRoutineLocArrays : public ExplicitUniformLocationCaseBase
2705 {
Run()2706 	virtual long Run()
2707 	{
2708 
2709 		//subroutine vec4 st0(float param);
2710 		//subroutine(st0) vec4 sf0(float param) { .... };
2711 		//subroutine(st0) vec4 sf1(float param) { .... };
2712 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2713 
2714 		std::vector<SubroutineUniform> subroutineUniforms;
2715 
2716 		//layout(location = 1) subroutine uniform st0 u0[2];
2717 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
2718 		return doRun(subroutineUniforms);
2719 	}
2720 };
2721 
2722 class SubRoutineLocArraysMix : public ExplicitUniformLocationCaseBase
2723 {
Run()2724 	virtual long Run()
2725 	{
2726 		//subroutine vec4 st0(float param);
2727 		//subroutine(st0) vec4 sf0(float param) { .... };
2728 		//subroutine(st0) vec4 sf1(float param) { .... };
2729 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2730 
2731 		//subroutine vec4 st1(float param);
2732 		//subroutine(st1) vec4 sf2(float param) { .... };
2733 		//subroutine(st1) vec4 sf3(float param) { .... };
2734 		SubroutineFunctionSet functions_st1(uniformValueGenerator, 2);
2735 
2736 		std::vector<SubroutineUniform> subroutineUniforms;
2737 
2738 		//layout(location = 1) subroutine uniform st0 u0[2];
2739 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2));
2740 
2741 		////layout(location = 3) subroutine uniform st0 u1[2][3];
2742 		std::vector<int> arraySizesSegmented(2);
2743 		arraySizesSegmented[0] = 2;
2744 		arraySizesSegmented[1] = 3;
2745 		subroutineUniforms.push_back(
2746 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), arraySizesSegmented));
2747 
2748 		//layout(location = 9) subroutine uniform st1 u2;
2749 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9)));
2750 
2751 		return doRun(subroutineUniforms);
2752 	}
2753 };
2754 
2755 class SubRoutineLocMixWithImplicit : public ExplicitUniformLocationCaseBase
2756 {
Run()2757 	virtual long Run()
2758 	{
2759 		//subroutine vec4 st0(float param);
2760 		//subroutine(st0) vec4 sf0(float param) { .... };
2761 		//subroutine(st0) vec4 sf1(float param) { .... };
2762 		SubroutineFunctionSet functions_st0(uniformValueGenerator, 2);
2763 
2764 		std::vector<SubroutineUniform> subroutineUniforms;
2765 		//subroutine uniform st0 u0;
2766 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit()));
2767 		//layout(location = 1 ) subroutine uniform st0 u1;
2768 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0)));
2769 		//layout(location = 0 ) subroutine uniform st0 u2;
2770 		subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1)));
2771 
2772 		return doRun(subroutineUniforms);
2773 	}
2774 };
2775 
2776 class SubRoutineLocCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
2777 {
Run()2778 	virtual long Run()
2779 	{
2780 
2781 		std::string def =
2782 			NL "subroutine vec4 st0(float param);" NL "subroutine(st0) vec4 sf0(float param) { return param; }" NL
2783 			   "layout(location = x ) subroutine uniform st0 u0;";
2784 
2785 		return doRunNegativeCompile(def);
2786 	}
2787 };
2788 
2789 class SubRoutineLocCompilationNonConstLoc : public ExplicitUniformLocationCaseBase
2790 {
Run()2791 	virtual long Run()
2792 	{
2793 		std::string def = NL "const int i = 1;" NL "subroutine vec4 st0(float param);" NL
2794 							 "subroutine(st0) vec4 sf0(float param) { return param; }" NL
2795 							 "layout(location = i ) subroutine uniform st0 u0;";
2796 		return doRunNegativeCompile(def);
2797 	}
2798 };
2799 
2800 class SubRoutineLocLinkLocationReused1 : public ExplicitUniformLocationCaseBase
2801 {
Run()2802 	virtual long Run()
2803 	{
2804 		//layout(location = 1) subroutine uniform st0 u0;
2805 		//layout(location = 1) subroutine uniform st0 u0;
2806 		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2807 		std::vector<SubroutineUniform> subroutineUniforms;
2808 		subroutineUniforms.push_back(
2809 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2810 		subroutineUniforms.push_back(
2811 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2812 		return doRunNegativeLink(subroutineUniforms);
2813 	}
2814 };
2815 
2816 class SubRoutineLocLinkLocationMaxLocation : public ExplicitUniformLocationCaseBase
2817 {
Run()2818 	virtual long Run()
2819 	{
2820 		//layout(location = N) subroutine uniform st0 u0;
2821 		//Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS.
2822 
2823 		GLint max;
2824 		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
2825 		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2826 		std::vector<SubroutineUniform> subroutineUniforms;
2827 		subroutineUniforms.push_back(
2828 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(max), 0, DefOccurence::FSH_OR_CSH));
2829 		return doRunNegativeLink(subroutineUniforms);
2830 	}
2831 };
2832 
2833 class SubRoutineLocLinkMaxNumOfLocations : public ExplicitUniformLocationCaseBase
2834 {
Run()2835 	virtual long Run()
2836 	{
2837 
2838 		GLint max;
2839 		glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max);
2840 		SubroutineFunctionSet		   functions_st0(uniformValueGenerator, 2);
2841 		std::vector<SubroutineUniform> subroutineUniforms;
2842 		subroutineUniforms.push_back(
2843 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0), max, DefOccurence::FSH_OR_CSH, false));
2844 		subroutineUniforms.push_back(
2845 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2846 		return doRunNegativeLink(subroutineUniforms);
2847 	}
2848 };
2849 
2850 class SubroutineIndex : public ExplicitUniformLocationCaseBase
2851 {
Run()2852 	virtual long Run()
2853 	{
2854 		//one shader:
2855 
2856 		//subroutine vec4 st0(float param);
2857 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2858 		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2859 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2860 		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2861 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2862 
2863 		std::vector<SubroutineUniform> subroutineUniforms;
2864 
2865 		//subroutine uniform st0 u0;
2866 		subroutineUniforms.push_back(
2867 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2868 		return doRun(subroutineUniforms);
2869 	}
2870 };
2871 
2872 class SubroutineIndexNonDecimal : public ExplicitUniformLocationCaseBase
2873 {
Run()2874 	virtual long Run()
2875 	{
2876 		//one shader:
2877 
2878 		//subroutine vec4 st0(float param);
2879 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2880 		//layout(index = 0x0a) subroutine(st0) vec4 sf0(float param) { .... };
2881 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0x0a, Index::Hex)));
2882 		//layout(index = 010 ) subroutine(st0) vec4 sf1(float param) { .... };
2883 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(010, Index::Oct)));
2884 
2885 		std::vector<SubroutineUniform> subroutineUniforms;
2886 
2887 		//subroutine uniform st0 u0;
2888 		subroutineUniforms.push_back(
2889 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
2890 
2891 		return doRun(subroutineUniforms);
2892 	}
2893 };
2894 
2895 class SubroutineIndexLoc : public ExplicitUniformLocationCaseBase
2896 {
Run()2897 	virtual long Run()
2898 	{
2899 
2900 		//one shader:
2901 
2902 		//subroutine vec4 st0(float param);
2903 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2904 		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2905 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2906 		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2907 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2908 
2909 		std::vector<SubroutineUniform> subroutineUniforms;
2910 
2911 		//layout(location = 3) subroutine uniform st0 u0;
2912 		subroutineUniforms.push_back(
2913 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), 0, DefOccurence::FSH_OR_CSH));
2914 		return doRun(subroutineUniforms);
2915 	}
2916 };
2917 
2918 class SubroutineIndexNonCont : public ExplicitUniformLocationCaseBase
2919 {
Run()2920 	virtual long Run()
2921 	{
2922 		//one shader:
2923 
2924 		//subroutine vec4 st0(float param);
2925 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2926 		//layout(index = 0) subroutine(st0) vec4 sf0(float param) { .... };
2927 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
2928 		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2929 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2930 
2931 		std::vector<SubroutineUniform> subroutineUniforms;
2932 
2933 		//layout(location = 2) subroutine uniform st0 u0;
2934 		subroutineUniforms.push_back(
2935 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
2936 		return doRun(subroutineUniforms);
2937 	}
2938 };
2939 
2940 class SubroutineIndexMultUniforms : public ExplicitUniformLocationCaseBase
2941 {
Run()2942 	virtual long Run()
2943 	{
2944 
2945 		//one shader:
2946 
2947 		//subroutine vec4 st0(float param);
2948 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2949 		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2950 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2951 		//layout(index = 3) subroutine(st0) vec4 sf1(float param) { .... };
2952 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(3)));
2953 
2954 		//subroutine vec4 st1(float param);
2955 		SubroutineFunctionSet functions_st1(uniformValueGenerator);
2956 		//layout(index = 2) subroutine(st1) vec4 sf2(float param) { .... };
2957 		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2958 		//layout(index = 0) subroutine(st1) vec4 sf3(float param) { .... };
2959 		functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
2960 
2961 		std::vector<SubroutineUniform> subroutineUniforms;
2962 		//layout(location = 1) subroutine uniform st0 u0;
2963 		subroutineUniforms.push_back(
2964 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 0, DefOccurence::FSH_OR_CSH));
2965 		//layout(location = 9) subroutine uniform st1 u1;
2966 		subroutineUniforms.push_back(
2967 			SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9), 0, DefOccurence::FSH_OR_CSH));
2968 
2969 		return doRun(subroutineUniforms);
2970 	}
2971 };
2972 
2973 class SubroutineIndexAllstages : public ExplicitUniformLocationCaseBase
2974 {
Run()2975 	virtual long Run()
2976 	{
2977 
2978 		//subroutine vec4 st0(float param);
2979 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
2980 		//layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... };
2981 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
2982 		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
2983 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
2984 
2985 		std::vector<SubroutineUniform> subroutineUniforms;
2986 
2987 		//subroutine uniform st0 u0;
2988 		subroutineUniforms.push_back(
2989 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::ALL_SH));
2990 		return doRun(subroutineUniforms);
2991 	}
2992 };
2993 
2994 class SubroutineIndexMixImplicit : public ExplicitUniformLocationCaseBase
2995 {
Run()2996 	virtual long Run()
2997 	{
2998 
2999 		//subroutine vec4 st0(float param);
3000 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3001 		//subroutine(st0) vec4 sf0(float param) { .... };
3002 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
3003 		//layout(index = 1) subroutine(st0) vec4 sf1(float param) { .... };
3004 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1)));
3005 		//layout(index = 0) subroutine(st0) vec4 sf1(float param) { .... };
3006 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0)));
3007 
3008 		std::vector<SubroutineUniform> subroutineUniforms;
3009 
3010 		//layout(location = 2) subroutine uniform st0 u0;
3011 		subroutineUniforms.push_back(
3012 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH));
3013 		return doRun(subroutineUniforms);
3014 	}
3015 };
3016 
3017 class SubroutineIndexNegativeCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase
3018 {
Run()3019 	virtual long Run()
3020 	{
3021 		std::string def = NL "subroutine vec4 st0(float param);" NL
3022 							 "layout(index = x) subroutine(st0) vec4 sf1(float param) { return param; };";
3023 		return doRunNegativeCompile(def);
3024 	}
3025 };
3026 
3027 class SubroutineIndexNegativeCompilationNonConstIndex : public ExplicitUniformLocationCaseBase
3028 {
Run()3029 	virtual long Run()
3030 	{
3031 		std::string def =
3032 			NL "const int i = 1;" NL "layout(index = i) subroutine(st0) vec4 sf1(float param) { return param; };";
3033 		return doRunNegativeCompile(def);
3034 	}
3035 };
3036 
3037 class SubroutineIndexNegativeLinkIndexReused : public ExplicitUniformLocationCaseBase
3038 {
Run()3039 	virtual long Run()
3040 	{
3041 		//subroutine vec4 st0(float param);
3042 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3043 		//layout(index = 2) subroutine(st0) vec4 sf0(float param) { .... };
3044 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
3045 		//layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... };
3046 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2)));
3047 
3048 		std::vector<SubroutineUniform> subroutineUniforms;
3049 
3050 		//subroutine uniform st0 u0;
3051 		subroutineUniforms.push_back(
3052 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3053 		return doRunNegativeLink(subroutineUniforms);
3054 	}
3055 };
3056 
3057 class SubroutineIndexNegativeLinkMaxIndex : public ExplicitUniformLocationCaseBase
3058 {
Run()3059 	virtual long Run()
3060 	{
3061 
3062 		GLint max;
3063 		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
3064 
3065 		//subroutine vec4 st0(float param);
3066 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3067 		//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
3068 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(max)));
3069 
3070 		std::vector<SubroutineUniform> subroutineUniforms;
3071 
3072 		//subroutine uniform st0 u0;
3073 		subroutineUniforms.push_back(
3074 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3075 		return doRunNegativeLink(subroutineUniforms);
3076 	}
3077 };
3078 
3079 class SubroutineIndexNegativeLinkMaxNumOfIndices : public ExplicitUniformLocationCaseBase
3080 {
Run()3081 	virtual long Run()
3082 	{
3083 		//subroutine vec4 st0(float param);
3084 		SubroutineFunctionSet functions_st0(uniformValueGenerator);
3085 
3086 		glw::GLint max;
3087 		glGetIntegerv(GL_MAX_SUBROUTINES, &max);
3088 
3089 		for (int i = 0; i < max; i++)
3090 		{
3091 			//layout(index = N) subroutine(st0) vec4 sf0(float param) { .... };
3092 			functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(i)));
3093 		}
3094 		functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit()));
3095 
3096 		std::vector<SubroutineUniform> subroutineUniforms;
3097 
3098 		//subroutine uniform st0 u0;
3099 		subroutineUniforms.push_back(
3100 			SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH));
3101 		return doRunNegativeLink(subroutineUniforms);
3102 	}
3103 };
3104 }
3105 
ExplicitUniformLocationGLTests(glcts::Context & context)3106 ExplicitUniformLocationGLTests::ExplicitUniformLocationGLTests(glcts::Context& context)
3107 	: TestCaseGroup(context, "explicit_uniform_location", "")
3108 {
3109 }
3110 
~ExplicitUniformLocationGLTests(void)3111 ExplicitUniformLocationGLTests::~ExplicitUniformLocationGLTests(void)
3112 {
3113 }
3114 
init()3115 void ExplicitUniformLocationGLTests::init()
3116 {
3117 	using namespace glcts;
3118 
3119 	Logger::setOutput(m_context.getTestContext().getLog());
3120 	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
3121 	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
3122 	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
3123 	addChild(
3124 		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
3125 	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
3126 	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
3127 	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
3128 	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
3129 	addChild(
3130 		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
3131 	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
3132 
3133 	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
3134 
3135 	addChild(
3136 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
3137 	addChild(
3138 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
3139 	addChild(
3140 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
3141 	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
3142 							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
3143 	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
3144 							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
3145 
3146 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
3147 							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
3148 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
3149 							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
3150 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
3151 							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
3152 
3153 	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
3154 							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
3155 	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
3156 							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
3157 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
3158 							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
3159 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
3160 							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
3161 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
3162 							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
3163 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
3164 							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
3165 
3166 	addChild(new TestSubcase(m_context, "subroutine-loc", TestSubcase::Create<SubRoutineLoc>));
3167 	addChild(new TestSubcase(m_context, "subroutine-loc-nondecimal", TestSubcase::Create<SubRoutineLocNonDecimal>));
3168 	addChild(new TestSubcase(m_context, "subroutine-loc-all-stages", TestSubcase::Create<SubRoutineLocAllStages>));
3169 	addChild(new TestSubcase(m_context, "subroutine-loc-arrays", TestSubcase::Create<SubRoutineLocArrays>));
3170 	addChild(new TestSubcase(m_context, "subroutine-loc-arrays-mix", TestSubcase::Create<SubRoutineLocArraysMix>));
3171 	addChild(new TestSubcase(m_context, "subroutine-loc-mix-with-implicit",
3172 							 TestSubcase::Create<SubRoutineLocMixWithImplicit>));
3173 	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-non-number-literal",
3174 							 TestSubcase::Create<SubRoutineLocCompilationNonNumberLiteral>));
3175 	addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-nonconst-loc",
3176 							 TestSubcase::Create<SubRoutineLocCompilationNonConstLoc>));
3177 	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-reused1",
3178 							 TestSubcase::Create<SubRoutineLocLinkLocationReused1>));
3179 	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-max-location",
3180 							 TestSubcase::Create<SubRoutineLocLinkLocationMaxLocation>));
3181 	addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-max-num-of-locations",
3182 							 TestSubcase::Create<SubRoutineLocLinkMaxNumOfLocations>));
3183 	addChild(new TestSubcase(m_context, "subroutine-index", TestSubcase::Create<SubroutineIndex>));
3184 	addChild(new TestSubcase(m_context, "subroutine-index-nondecimal", TestSubcase::Create<SubroutineIndexNonDecimal>));
3185 	addChild(new TestSubcase(m_context, "subroutine-index-loc", TestSubcase::Create<SubroutineIndexLoc>));
3186 	addChild(
3187 		new TestSubcase(m_context, "subroutine-index-non-continuous", TestSubcase::Create<SubroutineIndexNonCont>));
3188 	addChild(new TestSubcase(m_context, "subroutine-index-multiple-uniforms",
3189 							 TestSubcase::Create<SubroutineIndexMultUniforms>));
3190 	addChild(new TestSubcase(m_context, "subroutine-index-all-stages", TestSubcase::Create<SubroutineIndexAllstages>));
3191 	addChild(
3192 		new TestSubcase(m_context, "subroutine-index-mix-implicit", TestSubcase::Create<SubroutineIndexMixImplicit>));
3193 	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-non-number-literal",
3194 							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonNumberLiteral>));
3195 	addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-nonconst-index",
3196 							 TestSubcase::Create<SubroutineIndexNegativeCompilationNonConstIndex>));
3197 	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-index-reused",
3198 							 TestSubcase::Create<SubroutineIndexNegativeLinkIndexReused>));
3199 	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-location-maxindex",
3200 							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxIndex>));
3201 	addChild(new TestSubcase(m_context, "subroutine-index-negative-link-max-num-of-indices",
3202 							 TestSubcase::Create<SubroutineIndexNegativeLinkMaxNumOfIndices>));
3203 }
3204 
ExplicitUniformLocationES31Tests(glcts::Context & context)3205 ExplicitUniformLocationES31Tests::ExplicitUniformLocationES31Tests(glcts::Context& context)
3206 	: TestCaseGroup(context, "explicit_uniform_location", "")
3207 {
3208 }
3209 
~ExplicitUniformLocationES31Tests(void)3210 ExplicitUniformLocationES31Tests::~ExplicitUniformLocationES31Tests(void)
3211 {
3212 }
3213 
init()3214 void ExplicitUniformLocationES31Tests::init()
3215 {
3216 	using namespace glcts;
3217 	Logger::setOutput(m_context.getTestContext().getLog());
3218 	addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>));
3219 	addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>));
3220 	addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>));
3221 	addChild(
3222 		new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>));
3223 	addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>));
3224 	addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>));
3225 	addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>));
3226 	addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>));
3227 	addChild(
3228 		new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>));
3229 	addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>));
3230 	addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>));
3231 	addChild(
3232 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>));
3233 	addChild(
3234 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>));
3235 	addChild(
3236 		new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>));
3237 	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max",
3238 							 TestSubcase::Create<UniformLocMixWithImplicitMax>));
3239 	addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array",
3240 							 TestSubcase::Create<UniformLocMixWithImplicitMaxArray>));
3241 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages",
3242 							 TestSubcase::Create<UniformLocImplicitInSomeStages>));
3243 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2",
3244 							 TestSubcase::Create<UniformLocImplicitInSomeStages2>));
3245 	addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3",
3246 							 TestSubcase::Create<UniformLocImplicitInSomeStages3>));
3247 	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal",
3248 							 TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>));
3249 	addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc",
3250 							 TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>));
3251 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1",
3252 							 TestSubcase::Create<UniformLocNegativeLinkLocationReused1>));
3253 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2",
3254 							 TestSubcase::Create<UniformLocNegativeLinkLocationReused2>));
3255 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location",
3256 							 TestSubcase::Create<UniformLocNegativeLinkMaxLocation>));
3257 	addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations",
3258 							 TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>));
3259 }
3260 }
3261