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