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