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