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