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