| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2014-2016 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ /*! |
| * \file |
| * \brief |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "glwEnums.hpp" |
| |
| #include "gluContextInfo.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include <assert.h> |
| #include <map> |
| |
| #include "es31cExplicitUniformLocationTest.hpp" |
| |
| namespace glcts |
| { |
| using namespace glw; |
| namespace |
| { |
| |
| class Logger |
| { |
| public: |
| Logger() : null_log_(0) |
| { |
| } |
| |
| Logger(const Logger& rhs) |
| { |
| null_log_ = rhs.null_log_; |
| if (!null_log_) |
| { |
| str_ << rhs.str_.str(); |
| } |
| } |
| |
| ~Logger() |
| { |
| s_tcuLog->writeMessage(str_.str().c_str()); |
| if (!str_.str().empty()) |
| { |
| s_tcuLog->writeMessage(NL); |
| } |
| } |
| |
| template <class T> |
| Logger& operator<<(const T& t) |
| { |
| if (!null_log_) |
| { |
| str_ << t; |
| } |
| return *this; |
| } |
| |
| static tcu::TestLog* Get() |
| { |
| return s_tcuLog; |
| } |
| |
| static void setOutput(tcu::TestLog& log) |
| { |
| s_tcuLog = &log; |
| } |
| |
| private: |
| void operator=(const Logger&); |
| bool null_log_; |
| std::ostringstream str_; |
| static tcu::TestLog* s_tcuLog; |
| }; |
| tcu::TestLog* Logger::s_tcuLog = NULL; |
| |
| class DefOccurence |
| { |
| public: |
| enum DefOccurenceEnum |
| { |
| ALL_SH, |
| VSH, |
| FSH_OR_CSH, //"one shader" |
| ALL_BUT_FSH, |
| ALL_BUT_VSH, |
| NONE_SH, |
| } occurence; |
| |
| DefOccurence(DefOccurenceEnum _occurence) : occurence(_occurence) |
| { |
| } |
| |
| bool occurs(GLenum shader) const |
| { |
| if (occurence == NONE_SH) |
| { |
| return false; |
| } |
| if (occurence == ALL_SH) |
| { |
| return true; |
| } |
| if (occurence == FSH_OR_CSH) |
| { |
| return shader == GL_FRAGMENT_SHADER || shader == GL_COMPUTE_SHADER; |
| } |
| if (occurence == VSH) |
| { |
| return shader == GL_VERTEX_SHADER; |
| } |
| if (occurence == ALL_BUT_FSH) |
| { |
| return shader != GL_FRAGMENT_SHADER; |
| } |
| if (occurence == ALL_BUT_VSH) |
| { |
| return shader != GL_VERTEX_SHADER; |
| } |
| assert(0); |
| return false; |
| } |
| }; |
| |
| class LocationSpecifier |
| { |
| }; |
| class IndexSpecifier |
| { |
| }; |
| |
| class LayoutSpecifierBase |
| { |
| public: |
| enum NumSys |
| { |
| Dec, |
| Oct, |
| Hex, |
| }; |
| |
| LayoutSpecifierBase(int _val, NumSys _numSys, DefOccurence _occurence) |
| : val(_val), numSys(_numSys), occurence(_occurence) |
| { |
| } |
| |
| bool isImplicit(const std::vector<GLenum> stages) const |
| { |
| bool implicit = true; |
| for (size_t i = 0; i < stages.size(); i++) |
| { |
| implicit &= !occurence.occurs(stages[i]); |
| } |
| |
| return implicit; |
| } |
| |
| int val; |
| NumSys numSys; |
| DefOccurence occurence; |
| }; |
| |
| template <class T> |
| class LayoutSpecifier : public LayoutSpecifierBase |
| { |
| public: |
| LayoutSpecifier(int _val, NumSys _numSys, DefOccurence _occurence) : LayoutSpecifierBase(_val, _numSys, _occurence) |
| { |
| } |
| |
| static LayoutSpecifier<T> C(int _val, NumSys _sys = Dec) |
| { |
| return LayoutSpecifier<T>(_val, _sys, DefOccurence::ALL_SH); |
| } |
| |
| static LayoutSpecifier<T> C(int _val, DefOccurence _occurence) |
| { |
| return LayoutSpecifier<T>(_val, Dec, _occurence); |
| } |
| |
| static LayoutSpecifier<T> Implicit() |
| { |
| return LayoutSpecifier<T>(1999999, Dec, DefOccurence::NONE_SH); |
| } |
| |
| void streamDefinition(std::ostringstream& str, GLenum shader) const; |
| }; |
| |
| typedef LayoutSpecifier<LocationSpecifier> Loc; |
| typedef LayoutSpecifier<IndexSpecifier> Index; |
| |
| template <> |
| void LayoutSpecifier<LocationSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const |
| { |
| if (val < 0 || !occurence.occurs(shader)) |
| { |
| return; |
| } |
| |
| str << "layout(location = "; |
| if (numSys == Loc::Oct) |
| { |
| str << std::oct << "0"; |
| } |
| else if (numSys == Loc::Hex) |
| { |
| str << std::hex << "0x"; |
| } |
| str << val << std::dec << ") "; |
| } |
| |
| template <> |
| void LayoutSpecifier<IndexSpecifier>::streamDefinition(std::ostringstream& str, GLenum shader) const |
| { |
| if (val < 0 || !occurence.occurs(shader)) |
| { |
| return; |
| } |
| |
| str << "layout(index = "; |
| if (numSys == Loc::Oct) |
| { |
| str << std::oct << "0"; |
| } |
| else if (numSys == Loc::Hex) |
| { |
| str << std::hex << "0x"; |
| } |
| str << val << std::dec << ") "; |
| } |
| |
| class UniformStructCounter |
| { |
| public: |
| UniformStructCounter() : counter(0) |
| { |
| } |
| GLint getNextCount() |
| { |
| return counter++; |
| } |
| |
| private: |
| UniformStructCounter(const UniformStructCounter&); |
| GLint counter; |
| }; |
| |
| class UniformType |
| { |
| public: |
| UniformType(GLenum _enumType, int _arraySize = 0) |
| : enumType(_enumType), arraySize(_arraySize), isArray(_arraySize > 0), signedType(true) |
| { |
| if (!arraySize) |
| { |
| arraySize = 1; |
| } |
| arraySizesSegmented.push_back(arraySize); |
| fill(); |
| } |
| UniformType(GLenum _enumType, const std::vector<int>& _arraySizesSegmented) |
| : enumType(_enumType), arraySizesSegmented(_arraySizesSegmented), isArray(true), signedType(true) |
| { |
| arraySize = 1; |
| for (size_t i = 0; i < arraySizesSegmented.size(); i++) |
| { |
| assert(arraySizesSegmented[i] > 0); |
| arraySize *= arraySizesSegmented[i]; |
| } |
| fill(); |
| } |
| UniformType(UniformStructCounter& structCounter, std::vector<UniformType> _childTypes, int _arraySize = 0) |
| : enumType(0), arraySize(_arraySize), childTypes(_childTypes), isArray(_arraySize > 0), signedType(true) |
| { |
| baseType = 0; |
| std::ostringstream _str; |
| _str << "S" << structCounter.getNextCount(); |
| strType = _str.str(); |
| if (!arraySize) |
| { |
| arraySize = 1; |
| } |
| arraySizesSegmented.push_back(arraySize); |
| } |
| |
| inline const std::string& str() const |
| { |
| return strType; |
| } |
| |
| inline const std::string& refStr() const |
| { |
| return refStrType; |
| } |
| |
| bool isStruct() const |
| { |
| return (baseType == 0); |
| } |
| |
| bool isSigned() const |
| { |
| return signedType; |
| } |
| |
| const char* abs() const |
| { |
| switch (baseType) |
| { |
| case GL_FLOAT: |
| case GL_SAMPLER: |
| return "0.1"; |
| case GL_UNSIGNED_INT: |
| return "0u"; |
| case GL_INT: |
| return "0"; |
| default: |
| assert(0); |
| return ""; |
| } |
| } |
| |
| std::pair<int, int> getSize() const |
| { |
| return size; |
| } |
| |
| GLenum getBaseType() const |
| { |
| return baseType; |
| } |
| |
| void streamArrayStr(std::ostringstream& _str, int arrayElem = -1) const |
| { |
| if (!isArray) |
| { |
| return; |
| } |
| if (arrayElem < 0) |
| { |
| for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++) |
| { |
| _str << "[" << arraySizesSegmented[segment] << "]"; |
| } |
| } |
| else |
| { |
| int tailSize = arraySize; |
| for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++) |
| { |
| tailSize /= arraySizesSegmented[segment]; |
| _str << "[" << arrayElem / tailSize << "]"; |
| arrayElem %= tailSize; |
| } |
| } |
| } |
| |
| GLenum enumType; |
| |
| //arrays-of-arrays size |
| std::vector<int> arraySizesSegmented; |
| |
| //premultiplied array size |
| int arraySize; |
| |
| //child types for nested (struct) types; |
| std::vector<UniformType> childTypes; |
| |
| private: |
| void fill() |
| { |
| |
| size = std::pair<int, int>(1, 1); |
| |
| switch (enumType) |
| { |
| case GL_SAMPLER_2D: |
| refStrType = "vec4"; |
| strType = "sampler2D"; |
| baseType = GL_SAMPLER; |
| break; |
| case GL_FLOAT: |
| refStrType = strType = "float"; |
| baseType = GL_FLOAT; |
| break; |
| case GL_INT: |
| refStrType = strType = "int"; |
| baseType = GL_INT; |
| break; |
| case GL_UNSIGNED_INT: |
| refStrType = strType = "uint"; |
| baseType = GL_UNSIGNED_INT; |
| signedType = false; |
| break; |
| case GL_FLOAT_VEC2: |
| refStrType = strType = "vec2"; |
| baseType = GL_FLOAT; |
| size.first = 2; |
| break; |
| case GL_FLOAT_VEC3: |
| refStrType = strType = "vec3"; |
| baseType = GL_FLOAT; |
| size.first = 3; |
| break; |
| case GL_FLOAT_VEC4: |
| refStrType = strType = "vec4"; |
| baseType = GL_FLOAT; |
| size.first = 4; |
| break; |
| case GL_FLOAT_MAT2: |
| strType = "mat2"; |
| refStrType = "vec2"; |
| baseType = GL_FLOAT; |
| size.first = size.second = 2; |
| break; |
| case GL_FLOAT_MAT3: |
| strType = "mat3"; |
| refStrType = "vec3"; |
| baseType = GL_FLOAT; |
| size.first = size.second = 3; |
| break; |
| case GL_FLOAT_MAT4: |
| strType = "mat4"; |
| refStrType = "vec4"; |
| baseType = GL_FLOAT; |
| size.first = size.second = 4; |
| break; |
| case GL_FLOAT_MAT2x3: |
| strType = "mat2x3"; |
| refStrType = "vec3"; |
| baseType = GL_FLOAT; |
| size.first = 3; |
| size.second = 2; |
| break; |
| case GL_FLOAT_MAT4x3: |
| strType = "mat4x3"; |
| refStrType = "vec3"; |
| baseType = GL_FLOAT; |
| size.first = 3; |
| size.second = 4; |
| break; |
| case GL_FLOAT_MAT2x4: |
| strType = "mat2x4"; |
| refStrType = "vec4"; |
| baseType = GL_FLOAT; |
| size.first = 4; |
| size.second = 2; |
| break; |
| case GL_FLOAT_MAT3x4: |
| strType = "mat3x4"; |
| refStrType = "vec4"; |
| baseType = GL_FLOAT; |
| size.first = 4; |
| size.second = 3; |
| break; |
| case GL_FLOAT_MAT3x2: |
| strType = "mat3x2"; |
| refStrType = "vec2"; |
| baseType = GL_FLOAT; |
| size.first = 2; |
| size.second = 3; |
| break; |
| case GL_FLOAT_MAT4x2: |
| strType = "mat4x2"; |
| refStrType = "vec2"; |
| baseType = GL_FLOAT; |
| size.first = 2; |
| size.second = 4; |
| break; |
| case GL_INT_VEC2: |
| refStrType = strType = "ivec2"; |
| baseType = GL_INT; |
| size.first = 2; |
| break; |
| case GL_INT_VEC3: |
| refStrType = strType = "ivec3"; |
| baseType = GL_INT; |
| size.first = 3; |
| break; |
| case GL_INT_VEC4: |
| refStrType = strType = "ivec4"; |
| baseType = GL_INT; |
| size.first = 4; |
| break; |
| default: |
| assert(0); |
| } |
| } |
| |
| std::string strType, refStrType; |
| std::pair<int, int> size; |
| GLenum baseType; |
| bool isArray; |
| bool signedType; |
| }; |
| |
| class UniformValueGenerator |
| { |
| public: |
| UniformValueGenerator() : fValue(0.0f), iValue(0) |
| { |
| } |
| GLfloat genF() |
| { |
| if (fValue > 99999.0f) |
| { |
| fValue = 0.0f; |
| } |
| return (fValue += 1.0f); |
| } |
| GLint genI() |
| { |
| return (iValue += 1); |
| } |
| |
| private: |
| UniformValueGenerator(const UniformValueGenerator&); |
| GLfloat fValue; |
| GLint iValue; |
| }; |
| |
| class UniformValue |
| { |
| public: |
| void streamValue(std::ostringstream& str, int arrayElement = 0, int column = 0) const |
| { |
| int arrayElementSize = type.getSize().first * type.getSize().second; |
| |
| str << type.refStr() << "("; |
| |
| if (type.getBaseType() == GL_SAMPLER) |
| { |
| for (size_t elem = 0; elem < 4; elem++) |
| { |
| if (elem) |
| str << ", "; |
| str << fValues[arrayElement * 4 + elem]; |
| } |
| str << ")"; |
| return; |
| } |
| |
| for (int elem = 0; fValues.size() && elem < type.getSize().first; elem++) |
| { |
| if (elem) |
| str << ", "; |
| str << fValues[arrayElement * arrayElementSize + column * type.getSize().first + elem] << ".0"; |
| } |
| for (int elem = 0; iValues.size() && elem < type.getSize().first; elem++) |
| { |
| if (elem) |
| str << ", "; |
| str << iValues[arrayElement * arrayElementSize + elem]; |
| } |
| for (int elem = 0; uValues.size() && elem < type.getSize().first; elem++) |
| { |
| if (elem) |
| str << ", "; |
| str << uValues[arrayElement * arrayElementSize + elem] << "u"; |
| } |
| str << ")"; |
| } |
| |
| const void* getPtr(int arrayElement) const |
| { |
| int arrayElementSize = type.getSize().first * type.getSize().second; |
| if (type.getBaseType() == GL_INT || type.getBaseType() == GL_SAMPLER) |
| { |
| return &iValues[arrayElement * arrayElementSize]; |
| } |
| else if (type.getBaseType() == GL_UNSIGNED_INT) |
| { |
| return &uValues[arrayElement * arrayElementSize]; |
| } |
| else if (type.getBaseType() == GL_FLOAT) |
| { |
| return &fValues[arrayElement * arrayElementSize]; |
| } |
| assert(0); |
| return NULL; |
| } |
| |
| UniformValue(const UniformType& _type, UniformValueGenerator& generator) : type(_type) |
| { |
| const int sizeRow = type.getSize().first; |
| const int sizeColumn = type.getSize().second; |
| |
| if (type.isStruct()) |
| { |
| return; |
| } |
| |
| if (type.getBaseType() == GL_INT) |
| { |
| assert(sizeColumn == 1); |
| iValues.resize(sizeRow * type.arraySize); |
| for (size_t elem = 0; elem < iValues.size(); elem++) |
| { |
| iValues[elem] = generator.genI(); |
| } |
| } |
| else if (type.getBaseType() == GL_UNSIGNED_INT) |
| { |
| assert(sizeColumn == 1); |
| uValues.resize(sizeRow * type.arraySize); |
| for (size_t elem = 0; elem < uValues.size(); elem++) |
| { |
| uValues[elem] = static_cast<GLuint>(generator.genI()); |
| } |
| } |
| else if (type.getBaseType() == GL_FLOAT) |
| { |
| fValues.resize(sizeColumn * sizeRow * type.arraySize); |
| for (size_t elem = 0; elem < fValues.size(); elem++) |
| { |
| fValues[elem] = generator.genF(); |
| } |
| } |
| else if (type.getBaseType() == GL_SAMPLER) |
| { |
| //color ref value |
| fValues.resize(4 * type.arraySize); |
| for (size_t elem = 0; elem < fValues.size(); elem++) |
| { |
| fValues[elem] = float(elem) / float(fValues.size()); |
| } |
| //uniform value |
| iValues.resize(type.arraySize); |
| for (size_t elem = 0; elem < iValues.size(); elem++) |
| { |
| iValues[elem] = generator.genI() % 16; |
| } |
| } |
| else |
| { |
| assert(0); |
| } |
| } |
| |
| std::vector<GLfloat> fValues; |
| std::vector<GLint> iValues; |
| std::vector<GLint> uValues; |
| |
| private: |
| UniformType type; |
| }; |
| |
| class Uniform |
| { |
| public: |
| Uniform(UniformValueGenerator& generator, UniformType _type, Loc _location, |
| DefOccurence _declOccurence = DefOccurence::ALL_SH, DefOccurence _usageOccurence = DefOccurence::ALL_SH) |
| : type(_type) |
| , location(_location) |
| , declOccurence(_declOccurence) |
| , usageOccurence(_usageOccurence) |
| , value(_type, generator) |
| { |
| |
| if (type.isStruct()) |
| { |
| int currentLocation = location.val; |
| for (int arrayElem = 0; arrayElem < type.arraySize; arrayElem++) |
| { |
| for (size_t child = 0; child < type.childTypes.size(); child++) |
| { |
| Loc childLocation = Loc::Implicit(); |
| if (currentLocation > 0) |
| { |
| childLocation = Loc::C(currentLocation); |
| } |
| childUniforms.push_back( |
| Uniform(generator, type.childTypes[child], childLocation, declOccurence, usageOccurence)); |
| currentLocation += type.childTypes[child].arraySize; |
| } |
| } |
| } |
| } |
| |
| void setName(const std::string& parentName, const std::string& _name) |
| { |
| shortName = _name; |
| { |
| std::ostringstream __name; |
| __name << parentName << _name; |
| name = __name.str(); |
| } |
| if (type.isStruct()) |
| { |
| for (size_t i = 0; i < childUniforms.size(); i++) |
| { |
| std::ostringstream childName; |
| childName << "m" << (i % (childUniforms.size() / type.arraySize)); |
| std::ostringstream childParentName; |
| childParentName << name; |
| type.streamArrayStr(childParentName, (int)(i / type.arraySize)); |
| childParentName << "."; |
| childUniforms[i].setName(childParentName.str(), childName.str()); |
| } |
| } |
| } |
| const std::string& getName() const |
| { |
| return name; |
| } |
| |
| void streamDefinition(std::ostringstream& str) const |
| { |
| str << type.str() << " " << shortName; |
| type.streamArrayStr(str); |
| } |
| |
| UniformType type; |
| Loc location; |
| DefOccurence declOccurence, usageOccurence; |
| UniformValue value; |
| |
| std::vector<Uniform> childUniforms; |
| std::string name, shortName; |
| }; |
| |
| class SubroutineFunction |
| { |
| public: |
| SubroutineFunction(UniformValueGenerator& generator, Index _index = Index::Implicit()) |
| : index(_index), embeddedRetVal(GL_FLOAT_VEC4, generator) |
| { |
| } |
| const UniformValue& getRetVal() const |
| { |
| return embeddedRetVal; |
| } |
| |
| inline const std::string& getName() const |
| { |
| return name; |
| } |
| |
| void setName(int _name) |
| { |
| std::ostringstream __name; |
| __name << "sf" << _name; |
| name = __name.str(); |
| } |
| |
| Index index; |
| |
| private: |
| UniformValue embeddedRetVal; |
| std::string name; |
| }; |
| |
| class SubroutineFunctionSet |
| { |
| public: |
| SubroutineFunctionSet(UniformValueGenerator& generator, size_t count = 0) : fn(count, SubroutineFunction(generator)) |
| { |
| } |
| |
| void push_back(const SubroutineFunction& _fn) |
| { |
| fn.push_back(_fn); |
| } |
| |
| inline const std::string& getTypeName() const |
| { |
| return typeName; |
| } |
| |
| void setTypeName(int _name) |
| { |
| std::ostringstream __name; |
| __name << "st" << _name; |
| typeName = __name.str(); |
| } |
| |
| std::vector<SubroutineFunction> fn; |
| std::string typeName; |
| }; |
| |
| class SubroutineUniform |
| { |
| public: |
| SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location, |
| int _arraySize = 0, DefOccurence _defOccurence = DefOccurence::ALL_SH, bool _used = true) |
| : functions(_functions) |
| , location(_location) |
| , arraySize(_arraySize) |
| , defOccurence(_defOccurence) |
| , used(_used) |
| , embeddedUIntUniform(GL_UNSIGNED_INT, generator) |
| { |
| |
| assert(arraySize >= 0); |
| |
| if (!arraySize) |
| { |
| arraySize = 1; |
| isArray = false; |
| } |
| else |
| { |
| isArray = true; |
| } |
| |
| arraySizesSegmented.push_back(arraySize); |
| |
| embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator); |
| for (int i = 0; i < arraySize; i++) |
| { |
| embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size()); |
| } |
| } |
| |
| SubroutineUniform(UniformValueGenerator& generator, SubroutineFunctionSet& _functions, Loc _location, |
| std::vector<int> _arraySizesSegmented, DefOccurence _defOccurence = DefOccurence::ALL_SH, |
| bool _used = true) |
| : functions(_functions) |
| , location(_location) |
| , defOccurence(_defOccurence) |
| , used(_used) |
| , arraySizesSegmented(_arraySizesSegmented) |
| , isArray(true) |
| , embeddedUIntUniform(GL_UNSIGNED_INT, generator) |
| { |
| |
| arraySize = 1; |
| for (size_t i = 0; i < arraySizesSegmented.size(); i++) |
| { |
| assert(arraySizesSegmented[i] > 0); |
| arraySize *= arraySizesSegmented[i]; |
| } |
| |
| embeddedUIntUniform = UniformValue(UniformType(GL_UNSIGNED_INT, arraySize), generator); |
| for (int i = 0; i < arraySize; i++) |
| { |
| embeddedUIntUniform.uValues[i] = static_cast<GLint>(embeddedUIntUniform.uValues[i] % functions.fn.size()); |
| } |
| } |
| void setName(const std::string& _name) |
| { |
| name = _name; |
| } |
| |
| const std::string& getName() const |
| { |
| return name; |
| } |
| |
| void streamArrayStr(std::ostringstream& str, int arrayElem = -1) const |
| { |
| if (!isArray) |
| { |
| return; |
| } |
| if (arrayElem < 0) |
| { |
| for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++) |
| { |
| str << "[" << arraySizesSegmented[segment] << "]"; |
| } |
| } |
| else |
| { |
| int tailSize = arraySize; |
| for (size_t segment = 0; segment < arraySizesSegmented.size(); segment++) |
| { |
| tailSize /= arraySizesSegmented[segment]; |
| str << "[" << arrayElem / tailSize << "]"; |
| arrayElem %= tailSize; |
| } |
| } |
| } |
| |
| const SubroutineFunction& getSelectedFunction(int arrayElem) const |
| { |
| assert(arrayElem < arraySize); |
| return functions.fn[embeddedUIntUniform.uValues[arrayElem]]; |
| } |
| |
| SubroutineFunctionSet functions; |
| Loc location; |
| int arraySize; |
| DefOccurence defOccurence; |
| bool used; |
| |
| private: |
| std::vector<int> arraySizesSegmented; |
| bool isArray; |
| UniformValue embeddedUIntUniform; |
| |
| std::string name; |
| }; |
| |
| class ShaderKey |
| { |
| public: |
| ShaderKey() |
| { |
| } |
| ShaderKey(GLenum _stage, const std::string& _input, const std::string& _output) |
| : stage(_stage), input(_input), output(_output) |
| { |
| } |
| GLenum stage; |
| std::string input, output; |
| |
| bool operator<(const ShaderKey& rhs) const |
| { |
| if (stage == rhs.stage) |
| { |
| if (input == rhs.input) |
| { |
| return (output < rhs.output); |
| } |
| return input < rhs.input; |
| } |
| return stage < rhs.stage; |
| } |
| }; |
| |
| class CompiledProgram |
| { |
| public: |
| GLuint name; |
| std::vector<GLenum> stages; |
| }; |
| |
| class ShaderSourceFactory |
| { |
| |
| static void streamUniformDefinitions(const std::vector<Uniform>& uniforms, GLenum shader, std::ostringstream& ret) |
| { |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| if (uniforms[i].declOccurence.occurs(shader)) |
| { |
| if (uniforms[i].type.isStruct()) |
| { |
| ret << "struct " << uniforms[i].type.str() << " {" << std::endl; |
| for (size_t child = 0; child < uniforms[i].childUniforms.size() / uniforms[i].type.arraySize; |
| child++) |
| { |
| ret << " "; |
| uniforms[i].childUniforms[child].streamDefinition(ret); |
| ret << ";" << std::endl; |
| } |
| ret << "};" << std::endl; |
| } |
| uniforms[i].location.streamDefinition(ret, shader); |
| ret << "uniform "; |
| uniforms[i].streamDefinition(ret); |
| ret << ";" << std::endl; |
| } |
| } |
| } |
| |
| static void streamSubroutineDefinitions(const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader, |
| std::ostringstream& ret) |
| { |
| if (subroutineUniforms.size()) |
| { |
| //add a "zero" uniform; |
| ret << "uniform float zero;" << std::endl; |
| } |
| |
| for (size_t i = 0; i < subroutineUniforms.size(); i++) |
| { |
| if (subroutineUniforms[i].defOccurence.occurs(shader)) |
| { |
| |
| //subroutine vec4 st0(float param); |
| ret << "subroutine vec4 " << subroutineUniforms[i].functions.getTypeName() << "(float param);" |
| << std::endl; |
| |
| for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++) |
| { |
| //layout(index = X) subroutine(st0) vec4 sf0(float param) { .... }; |
| subroutineUniforms[i].functions.fn[fn].index.streamDefinition(ret, shader); |
| ret << "subroutine(" << subroutineUniforms[i].functions.getTypeName() << ") vec4 " |
| << subroutineUniforms[i].functions.fn[fn].getName() << "(float param) { return zero + "; |
| subroutineUniforms[i].functions.fn[fn].getRetVal().streamValue(ret); |
| ret << "; }" << std::endl; |
| } |
| |
| //layout(location = X) subroutine uniform stX uX[...]; |
| subroutineUniforms[i].location.streamDefinition(ret, shader); |
| ret << "subroutine uniform " << subroutineUniforms[i].functions.getTypeName() << " " |
| << subroutineUniforms[i].getName(); |
| subroutineUniforms[i].streamArrayStr(ret); |
| ret << ";" << std::endl; |
| } |
| } |
| } |
| |
| static void streamUniformValidator(std::ostringstream& ret, const Uniform& uniform, GLenum shader, |
| const char* outTemporary) |
| { |
| if (uniform.declOccurence.occurs(shader) && uniform.usageOccurence.occurs(shader)) |
| { |
| if (uniform.type.isStruct()) |
| { |
| for (size_t child = 0; child < uniform.childUniforms.size(); child++) |
| { |
| streamUniformValidator(ret, uniform.childUniforms[child], shader, outTemporary); |
| } |
| } |
| else |
| { |
| for (int arrayElement = 0; arrayElement < uniform.type.arraySize; arrayElement++) |
| { |
| for (int column = 0; column < uniform.type.getSize().second; column++) |
| { |
| std::string columnIndex; |
| if (uniform.type.getSize().second > 1) |
| { |
| std::ostringstream str; |
| str << "[" << column << "]"; |
| columnIndex = str.str(); |
| } |
| std::string absoluteF; |
| if (uniform.type.isSigned()) |
| { |
| absoluteF = "abs"; |
| } |
| |
| if (uniform.type.getBaseType() == GL_SAMPLER) |
| { |
| ret << NL " if (any(greaterThan(" << absoluteF << "(texture(" << uniform.getName(); |
| uniform.type.streamArrayStr(ret, arrayElement); |
| ret << columnIndex << ", vec2(0.5)) - "; |
| uniform.value.streamValue(ret, arrayElement, column); |
| ret << " ), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {"; |
| } |
| else if (uniform.type.getSize().first > 1) |
| { |
| ret << NL " if (any(greaterThan(" << absoluteF << "(" << uniform.getName(); |
| uniform.type.streamArrayStr(ret, arrayElement); |
| ret << columnIndex << " - "; |
| uniform.value.streamValue(ret, arrayElement, column); |
| ret << "), " << uniform.type.refStr() << "(" << uniform.type.abs() << ")))) {"; |
| } |
| else |
| { |
| ret << NL " if (" << absoluteF << "(" << uniform.getName(); |
| uniform.type.streamArrayStr(ret, arrayElement); |
| ret << " - "; |
| uniform.value.streamValue(ret, arrayElement); |
| ret << ") >" << uniform.type.refStr() << "(" << uniform.type.abs() << ")) {"; |
| } |
| ret << NL " " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);"; |
| ret << NL " }"; |
| } |
| } |
| } |
| } |
| } |
| |
| static void streamUniformValidators(std::ostringstream& ret, const std::vector<Uniform>& uniforms, GLenum shader, |
| const char* outTemporary) |
| { |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| streamUniformValidator(ret, uniforms[i], shader, outTemporary); |
| } |
| } |
| |
| static void streamSubroutineValidator(std::ostringstream& ret, const SubroutineUniform& subroutineUniform, |
| GLenum shader, const char* outTemporary) |
| { |
| if (subroutineUniform.defOccurence.occurs(shader) && subroutineUniform.used) |
| { |
| for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++) |
| { |
| ret << NL " if (any(greaterThan(abs(" << subroutineUniform.getName(); |
| subroutineUniform.streamArrayStr(ret, arrayElem); |
| ret << "(zero) - "; |
| subroutineUniform.getSelectedFunction(arrayElem).getRetVal().streamValue(ret); |
| ret << "), vec4(0.1)))) {"; |
| ret << NL " " << outTemporary << " = vec4 (1.0, 0.0, 0.0, 1.0);"; |
| ret << NL " }"; |
| } |
| } |
| } |
| |
| static void streamSubroutineValidators(std::ostringstream& ret, |
| const std::vector<SubroutineUniform>& subroutineUniforms, GLenum shader, |
| const char* outTemporary) |
| { |
| for (size_t i = 0; i < subroutineUniforms.size(); i++) |
| { |
| streamSubroutineValidator(ret, subroutineUniforms[i], shader, outTemporary); |
| } |
| } |
| |
| static void streamShaderHeader(std::ostringstream& str, const glu::ContextType type) |
| { |
| if (glu::isContextTypeES(type)) |
| { |
| str << "#version 310 es" NL "precision highp float;" NL "precision highp int;"; |
| } |
| else |
| { |
| str << "#version 430 core" NL; |
| } |
| } |
| |
| static std::string generateFragmentShader(const ShaderKey& key, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, |
| const std::string& additionalDef, const glu::ContextType type) |
| { |
| |
| std::ostringstream ret; |
| streamShaderHeader(ret, type); |
| ret << NL; |
| streamUniformDefinitions(uniforms, GL_FRAGMENT_SHADER, ret); |
| ret << NL; |
| streamSubroutineDefinitions(subroutineUniforms, GL_FRAGMENT_SHADER, ret); |
| ret << NL << additionalDef << NL "in vec4 " << key.input << ";" << NL "out vec4 out_FragColor;" |
| << NL "void main() {" << NL " vec4 validationResult = " << key.input << ";" << NL; |
| streamUniformValidators(ret, uniforms, GL_FRAGMENT_SHADER, "validationResult"); |
| ret << NL; |
| streamSubroutineValidators(ret, subroutineUniforms, GL_FRAGMENT_SHADER, "validationResult"); |
| ret << NL " out_FragColor = validationResult;" << NL "}"; |
| |
| return ret.str(); |
| } |
| |
| static std::string generateVertexShader(const ShaderKey& key, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, |
| const std::string& additionalDef, const glu::ContextType type) |
| { |
| |
| std::ostringstream ret; |
| streamShaderHeader(ret, type); |
| ret << NL; |
| streamUniformDefinitions(uniforms, GL_VERTEX_SHADER, ret); |
| ret << NL; |
| streamSubroutineDefinitions(subroutineUniforms, GL_VERTEX_SHADER, ret); |
| ret << NL << additionalDef << NL "in vec4 in_Position;" << NL "out vec4 " << key.output << ";" |
| << NL "void main() {" << NL " vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);" << NL; |
| streamUniformValidators(ret, uniforms, GL_VERTEX_SHADER, "validationResult"); |
| ret << NL; |
| streamSubroutineValidators(ret, subroutineUniforms, GL_VERTEX_SHADER, "validationResult"); |
| ret << NL " " << key.output << " = validationResult;" << NL " gl_Position = in_Position;" << NL "}"; |
| return ret.str(); |
| } |
| |
| static std::string generateComputeShader(const ShaderKey&, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, |
| const std::string& additionalDef, const glu::ContextType type) |
| { |
| |
| std::ostringstream ret; |
| streamShaderHeader(ret, type); |
| ret << NL "layout (local_size_x = 1, local_size_y = 1) in;" |
| << NL "layout (std430, binding = 1) buffer ResultBuffer {" << NL " vec4 cs_ValidationResult;" << NL "};" |
| << NL; |
| streamUniformDefinitions(uniforms, GL_COMPUTE_SHADER, ret); |
| ret << NL; |
| streamSubroutineDefinitions(subroutineUniforms, GL_COMPUTE_SHADER, ret); |
| ret << NL << additionalDef << NL "void main() {" << NL " vec4 validationResult = vec4(0.0, 1.0, 0.0, 1.0);" |
| << NL; |
| streamUniformValidators(ret, uniforms, GL_COMPUTE_SHADER, "validationResult"); |
| ret << NL; |
| streamSubroutineValidators(ret, subroutineUniforms, GL_COMPUTE_SHADER, "validationResult"); |
| ret << NL " cs_ValidationResult = validationResult;" << NL "}"; |
| return ret.str(); |
| } |
| |
| public: |
| static std::string generateShader(const ShaderKey& key, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, |
| const std::string& additionalDef, const glu::ContextType type) |
| { |
| |
| switch (key.stage) |
| { |
| case GL_VERTEX_SHADER: |
| return generateVertexShader(key, uniforms, subroutineUniforms, additionalDef, type); |
| case GL_FRAGMENT_SHADER: |
| return generateFragmentShader(key, uniforms, subroutineUniforms, additionalDef, type); |
| case GL_COMPUTE_SHADER: |
| return generateComputeShader(key, uniforms, subroutineUniforms, additionalDef, type); |
| default: |
| assert(0); |
| return ""; |
| } |
| } |
| }; |
| |
| class ExplicitUniformLocationCaseBase : public glcts::SubcaseBase |
| { |
| virtual std::string Title() |
| { |
| return ""; |
| } |
| virtual std::string Purpose() |
| { |
| return ""; |
| } |
| virtual std::string Method() |
| { |
| return ""; |
| } |
| virtual std::string PassCriteria() |
| { |
| return ""; |
| } |
| |
| int getWindowWidth() |
| { |
| return m_context.getRenderContext().getRenderTarget().getWidth(); |
| } |
| |
| int getWindowHeight() |
| { |
| return m_context.getRenderContext().getRenderTarget().getHeight(); |
| } |
| |
| std::map<ShaderKey, GLuint> CreateShaders(const std::vector<std::vector<ShaderKey> >& programConfigs, |
| const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, |
| const std::string& additionalDef) |
| { |
| std::map<ShaderKey, GLuint> ret; |
| |
| //create shaders |
| for (size_t config = 0; config < programConfigs.size(); config++) |
| { |
| for (size_t target = 0; target < programConfigs[config].size(); target++) |
| { |
| |
| if (ret.find(programConfigs[config][target]) == ret.end()) |
| { |
| GLuint shader = glCreateShader(programConfigs[config][target].stage); |
| |
| std::string source = ShaderSourceFactory::generateShader(programConfigs[config][target], uniforms, |
| subroutineUniforms, additionalDef, |
| m_context.getRenderContext().getType()); |
| const char* cSource[] = { source.c_str() }; |
| glShaderSource(shader, 1, cSource, NULL); |
| ret[programConfigs[config][target]] = shader; |
| } |
| } |
| } |
| |
| //compile shaders |
| for (std::map<ShaderKey, GLuint>::iterator i = ret.begin(); i != ret.end(); i++) |
| { |
| glCompileShader(i->second); |
| } |
| |
| return ret; |
| } |
| |
| long CreatePrograms(std::vector<CompiledProgram>& programs, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms, const std::string& additionalDef, |
| bool negativeCompile, bool negativeLink) |
| { |
| |
| long ret = NO_ERROR; |
| |
| std::vector<std::vector<ShaderKey> > programConfigs; |
| { |
| std::vector<ShaderKey> vsh_fsh(2); |
| vsh_fsh[0] = ShaderKey(GL_VERTEX_SHADER, "", "vs_ValidationResult"); |
| vsh_fsh[1] = ShaderKey(GL_FRAGMENT_SHADER, "vs_ValidationResult", ""); |
| programConfigs.push_back(vsh_fsh); |
| } |
| { |
| std::vector<ShaderKey> csh(1); |
| csh[0] = ShaderKey(GL_COMPUTE_SHADER, "", ""); |
| programConfigs.push_back(csh); |
| } |
| |
| std::map<ShaderKey, GLuint> shaders = |
| CreateShaders(programConfigs, uniforms, subroutineUniforms, additionalDef); |
| |
| //query compilation results |
| for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++) |
| { |
| GLint status; |
| glGetShaderiv(it->second, GL_COMPILE_STATUS, &status); |
| GLchar infoLog[1000], source[4000]; |
| glGetShaderSource(it->second, 4000, NULL, source); |
| glGetShaderInfoLog(it->second, 1000, NULL, infoLog); |
| Logger::Get()->writeKernelSource(source); |
| Logger::Get()->writeCompileInfo("shader", "", status == GL_TRUE, infoLog); |
| |
| if (!negativeLink) |
| { |
| if (!negativeCompile) |
| { |
| if (status != GL_TRUE) |
| { |
| Logger() << "Shader compilation failed"; |
| ret |= ERROR; |
| } |
| } |
| else |
| { |
| if (status) |
| { |
| Logger() << "Negative compilation case failed: shader shoult not compile, but " |
| "GL_COMPILE_STATUS != 0"; |
| ret |= ERROR; |
| } |
| } |
| } |
| } |
| |
| if (negativeCompile) |
| { |
| |
| //delete shaders |
| for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++) |
| { |
| glDeleteShader(it->second); |
| } |
| |
| return ret; |
| } |
| |
| //assemble programs and link |
| for (size_t config = 0; config < programConfigs.size(); config++) |
| { |
| CompiledProgram program; |
| program.name = glCreateProgram(); |
| |
| for (size_t target = 0; target < programConfigs[config].size(); target++) |
| { |
| |
| GLuint shader = shaders.find(programConfigs[config][target])->second; |
| |
| glAttachShader(program.name, shader); |
| |
| program.stages.push_back(programConfigs[config][target].stage); |
| } |
| programs.push_back(program); |
| glLinkProgram(programs[config].name); |
| } |
| for (size_t config = 0; config < programConfigs.size(); config++) |
| { |
| glLinkProgram(programs[config].name); |
| } |
| |
| //delete shaders |
| for (std::map<ShaderKey, GLuint>::iterator it = shaders.begin(); it != shaders.end(); it++) |
| { |
| glDeleteShader(it->second); |
| } |
| |
| //query link status: |
| for (size_t config = 0; config < programConfigs.size(); config++) |
| { |
| GLint status; |
| |
| glGetProgramiv(programs[config].name, GL_LINK_STATUS, &status); |
| GLchar infoLog[1000]; |
| glGetProgramInfoLog(programs[config].name, 1000, NULL, infoLog); |
| Logger::Get()->writeCompileInfo("program", "", status == GL_TRUE, infoLog); |
| |
| if (!negativeLink) |
| { |
| if (status != GL_TRUE) |
| { |
| Logger() << "Shader link failed"; |
| ret |= ERROR; |
| } |
| } |
| else |
| { |
| if (status) |
| { |
| Logger() << "Negative link case failed: program should not link, but GL_LINK_STATUS != 0"; |
| ret |= ERROR; |
| } |
| } |
| } |
| return ret; |
| } |
| |
| long DeletePrograms(std::vector<CompiledProgram>& programs) |
| { |
| for (size_t i = 0; i < programs.size(); i++) |
| { |
| glDeleteProgram(programs[i].name); |
| } |
| programs.resize(0); |
| return NO_ERROR; |
| } |
| |
| void setUniform(const Uniform& uniform, const CompiledProgram& program) |
| { |
| |
| bool used = false; |
| for (size_t i = 0; i < program.stages.size(); i++) |
| { |
| used |= uniform.declOccurence.occurs(program.stages[i]) && uniform.usageOccurence.occurs(program.stages[i]); |
| } |
| if (!used) |
| return; |
| |
| if (uniform.type.isStruct()) |
| { |
| for (size_t j = 0; j < uniform.childUniforms.size(); j++) |
| { |
| setUniform(uniform.childUniforms[j], program); |
| } |
| } |
| else |
| { |
| GLint loc; |
| if (uniform.location.isImplicit(program.stages)) |
| { |
| std::ostringstream name; |
| name << uniform.getName(); |
| uniform.type.streamArrayStr(name, 0); |
| loc = glGetUniformLocation(program.name, name.str().c_str()); |
| } |
| else |
| { |
| loc = uniform.location.val; |
| } |
| |
| for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++) |
| { |
| switch (uniform.type.enumType) |
| { |
| case GL_FLOAT: |
| glUniform1f(loc, *(GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_VEC2: |
| glUniform2fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_VEC3: |
| glUniform3fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_VEC4: |
| glUniform4fv(loc, 1, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT2: |
| glUniformMatrix2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT3: |
| glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT4: |
| glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT2x3: |
| glUniformMatrix2x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT4x3: |
| glUniformMatrix4x3fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT2x4: |
| glUniformMatrix2x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT3x4: |
| glUniformMatrix3x4fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT3x2: |
| glUniformMatrix3x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_FLOAT_MAT4x2: |
| glUniformMatrix4x2fv(loc, 1, GL_FALSE, (GLfloat*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_INT: |
| case GL_SAMPLER_2D: |
| glUniform1i(loc, *(GLint*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_INT_VEC2: |
| glUniform2iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_INT_VEC3: |
| glUniform3iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_INT_VEC4: |
| glUniform4iv(loc, 1, (GLint*)uniform.value.getPtr(arrayElem)); |
| break; |
| case GL_UNSIGNED_INT: |
| glUniform1ui(loc, *(GLuint*)uniform.value.getPtr(arrayElem)); |
| break; |
| default: |
| assert(0); |
| } |
| loc++; |
| } |
| } |
| } |
| |
| void setSubroutineUniform(const SubroutineUniform& subroutineUniform, const CompiledProgram& program, GLenum stage, |
| std::vector<glw::GLuint>& indicesOut) |
| { |
| bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used; |
| if (used) |
| { |
| |
| for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++) |
| { |
| GLint loc = -1; |
| if (subroutineUniform.location.isImplicit(program.stages)) |
| { |
| std::ostringstream name; |
| name << subroutineUniform.getName(); |
| subroutineUniform.streamArrayStr(name, arrayElem); |
| loc = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str()); |
| } |
| else |
| { |
| loc = subroutineUniform.location.val + arrayElem; |
| } |
| |
| if (loc >= 0) |
| { |
| const SubroutineFunction& selectedFunction = subroutineUniform.getSelectedFunction(arrayElem); |
| |
| int index = -1; |
| if (selectedFunction.index.isImplicit(std::vector<GLenum>(1, stage))) |
| { |
| index = glGetSubroutineIndex(program.name, stage, selectedFunction.getName().c_str()); |
| } |
| else |
| { |
| index = selectedFunction.index.val; |
| } |
| |
| if (loc < (int)indicesOut.size()) |
| { |
| indicesOut[loc] = index; |
| } |
| else |
| { |
| assert(0); |
| } |
| } |
| else |
| { |
| assert(0); |
| } |
| } |
| } |
| } |
| |
| long runExecuteProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms) |
| { |
| long ret = NO_ERROR; |
| |
| glUseProgram(program.name); |
| |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| setUniform(uniforms[i], program); |
| } |
| |
| for (size_t stage = 0; stage < program.stages.size() && subroutineUniforms.size(); stage++) |
| { |
| |
| glw::GLint numactive; |
| glGetProgramStageiv(program.name, program.stages[stage], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, |
| &numactive); |
| if (numactive) |
| { |
| std::vector<glw::GLuint> indices(numactive, 0); |
| |
| for (size_t i = 0; i < subroutineUniforms.size(); i++) |
| { |
| setSubroutineUniform(subroutineUniforms[i], program, program.stages[stage], indices); |
| } |
| glUniformSubroutinesuiv(program.stages[stage], numactive, &indices[0]); |
| } |
| } |
| |
| if (program.stages[0] != GL_COMPUTE_SHADER) |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| |
| std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4); |
| |
| glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); |
| for (size_t i = 0; i < pixels.size(); i += 4) |
| { |
| if (pixels[i] != 0 || pixels[i + 1] != 255 || pixels[i + 2] != 0) |
| { |
| ret |= ERROR; |
| Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)pixels[i] |
| << ", " << (int)pixels[i + 1] << ", " << (int)pixels[i + 2] << ", " << (int)pixels[i + 3] |
| << ")."; |
| break; |
| } |
| } |
| Logger().Get()->writeImage("rendered image", "", QP_IMAGE_COMPRESSION_MODE_BEST, QP_IMAGE_FORMAT_RGBA8888, |
| getWindowWidth(), getWindowHeight(), 0, &pixels[0]); |
| } |
| else |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLfloat), NULL, GL_DYNAMIC_READ); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer); |
| |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| GLfloat* color = reinterpret_cast<GLfloat*>( |
| glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(GLfloat), GL_MAP_READ_BIT)); |
| |
| if (color[0] != 0 || color[1] != 1.0 || color[2] != 0) |
| { |
| ret |= ERROR; |
| Logger() << "Program " << program.name << ": Wrong color. Expected green, got (" << (int)color[0] |
| << ", " << (int)color[1] << ", " << (int)color[2] << ", " << (int)color[3] << ")."; |
| } |
| |
| glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); |
| |
| glDeleteBuffers(1, &buffer); |
| } |
| |
| return ret; |
| } |
| |
| long runQueryUniform(const CompiledProgram& program, const Uniform& uniform, std::set<GLuint>& usedLocations, |
| GLint max) |
| { |
| long ret = NO_ERROR; |
| |
| /* |
| glGetUniformLocation(program, name); |
| Query passes if returned value is unique in current program, matches |
| explicit location (if passed in GLSL code) and is less than value of |
| GL_MAX_UNIFORM_LOCATIONS. |
| |
| glGetProgramResourceLocation(program, GL_UNIFIORM, name); |
| Query passes if returned value matches value returned from |
| glGetUniformLocation(). |
| */ |
| |
| if (uniform.type.isStruct()) |
| { |
| for (size_t i = 0; i < uniform.childUniforms.size(); i++) |
| { |
| ret |= runQueryUniform(program, uniform.childUniforms[i], usedLocations, max); |
| } |
| } |
| else |
| { |
| for (int arrayElem = 0; arrayElem < uniform.type.arraySize; arrayElem++) |
| { |
| |
| /* Location that is taken by this uniform (even if not used).*/ |
| GLint reservedLocation = -1; |
| if (!uniform.location.isImplicit(program.stages)) |
| { |
| reservedLocation = uniform.location.val + arrayElem; |
| } |
| |
| //optimization: for continuous arrays run queries at the beging and end only. |
| bool runQueries = uniform.location.isImplicit(program.stages) || |
| (arrayElem < 1000 || arrayElem > uniform.type.arraySize - 1000); |
| |
| if (runQueries) |
| { |
| std::ostringstream name; |
| name << uniform.getName(); |
| uniform.type.streamArrayStr(name, arrayElem); |
| GLint returned = glGetUniformLocation(program.name, name.str().c_str()); |
| |
| GLint returnedPIQ = glGetProgramResourceLocation(program.name, GL_UNIFORM, name.str().c_str()); |
| |
| if (returned != returnedPIQ) |
| { |
| ret |= ERROR; |
| Logger() |
| << "Locations of uniform \"" << name.str() |
| << "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: " |
| << returned << " != " << returnedPIQ << "."; |
| } |
| |
| bool used = false; |
| for (size_t i = 0; i < program.stages.size(); i++) |
| { |
| used |= uniform.declOccurence.occurs(program.stages[i]) && |
| uniform.usageOccurence.occurs(program.stages[i]); |
| } |
| |
| if (!uniform.location.isImplicit(program.stages)) |
| { |
| //Validate uniform location against explicit value |
| GLint expected = reservedLocation; |
| if (!(expected == returned || (!used && returned == -1))) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected uniform \"" << name.str() << "\" location: expected " << expected |
| << ", got " << returned << "."; |
| } |
| } |
| else |
| { |
| //Check if location > 0 if used; |
| if (used) |
| { |
| if (returned < 0) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected uniform \"" << name.str() |
| << "\" location: expected positive value, got " << returned << "."; |
| } |
| else |
| { |
| reservedLocation = returned; |
| } |
| } |
| } |
| |
| if (returned >= 0) |
| { |
| //check if location is less than max |
| |
| if (returned >= max) |
| { |
| ret |= ERROR; |
| Logger() << "Uniform \"" << name.str() << "\" returned location (" << returned |
| << ") is greater than implementation dependent limit (" << max << ")."; |
| } |
| } |
| } //if (runQueries) |
| |
| //usedLocations is always checked (even if queries were not run. |
| if (reservedLocation >= 0) |
| { |
| //check if location is unique |
| if (usedLocations.find(reservedLocation) != usedLocations.end()) |
| { |
| ret |= ERROR; |
| Logger() << "Uniform location (" << reservedLocation << ") is not unique."; |
| } |
| usedLocations.insert(reservedLocation); |
| } |
| } |
| } |
| return ret; |
| } |
| |
| long runQueryUniformSubroutine(const CompiledProgram& program, GLenum stage, |
| const SubroutineUniform& subroutineUniform, std::set<GLuint>& usedLocations, |
| GLint max) |
| { |
| long ret = NO_ERROR; |
| /* |
| glGetSubroutineUniformLocation(program, shaderType, name) |
| Query passes if returned value is unique in current program stage, |
| matches explicit location (if passed in GLSL code) and is less than |
| value of GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS. |
| |
| glGetProgramResourceLocation(program, GL_(VERTEX|FRAGMENT|COMPUTE|... |
| ..._SUBROUTINE_UNIFORM, name) |
| Query passes if returned value matches value returned from |
| glGetUniformLocation(). |
| */ |
| |
| for (int arrayElem = 0; arrayElem < subroutineUniform.arraySize; arrayElem++) |
| { |
| std::ostringstream name; |
| name << subroutineUniform.getName(); |
| |
| subroutineUniform.streamArrayStr(name, arrayElem); |
| |
| GLint returned = glGetSubroutineUniformLocation(program.name, stage, name.str().c_str()); |
| |
| glw::GLenum piqStage = 0; |
| switch (stage) |
| { |
| case GL_VERTEX_SHADER: |
| piqStage = GL_VERTEX_SUBROUTINE_UNIFORM; |
| break; |
| case GL_FRAGMENT_SHADER: |
| piqStage = GL_FRAGMENT_SUBROUTINE_UNIFORM; |
| break; |
| case GL_COMPUTE_SHADER: |
| piqStage = GL_COMPUTE_SUBROUTINE_UNIFORM; |
| break; |
| default: |
| assert(0); |
| } |
| |
| GLint returnedPIQ = glGetProgramResourceLocation(program.name, piqStage, name.str().c_str()); |
| |
| if (returned != returnedPIQ) |
| { |
| ret |= ERROR; |
| Logger() << "Locations of subrutine uniform \"" << name.str() |
| << "\" returned by glGetUniformLocation and differ glGetProgramResourceLocation differ: " |
| << returned << " != " << returnedPIQ << "."; |
| } |
| |
| bool used = subroutineUniform.defOccurence.occurs(stage) && subroutineUniform.used; |
| |
| GLint reservedLocation = -1; |
| |
| if (!subroutineUniform.location.isImplicit(std::vector<glw::GLenum>(1, stage))) |
| { |
| //Validate uniform location against explicit value |
| GLint expected = subroutineUniform.location.val + arrayElem; |
| if (!(expected == returned || (!used && returned == -1))) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected subroutine uniform \"" << name.str() << "\" location: expected " << expected |
| << ", got " << returned << "."; |
| } |
| |
| reservedLocation = expected; |
| } |
| else |
| { |
| //Check if location > 0 if used; |
| if (used) |
| { |
| if (returned < 0) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected subroutine uniform \"" << name.str() |
| << "\" location: expected positive value, got " << returned << "."; |
| } |
| else |
| { |
| reservedLocation = returned; |
| } |
| } |
| } |
| |
| if (reservedLocation >= 0) |
| { |
| //check if location is unique |
| if (usedLocations.find(reservedLocation) != usedLocations.end()) |
| { |
| ret |= ERROR; |
| Logger() << "Subroutine uniform \"" << name.str() << "\" location (" << reservedLocation |
| << ") is not unique."; |
| } |
| usedLocations.insert(reservedLocation); |
| } |
| |
| if (returned >= 0) |
| { |
| //check if location is less than max |
| |
| if (returned >= max) |
| { |
| ret |= ERROR; |
| Logger() << "Subroutine uniform \"" << name.str() << "\" returned location (" << returned |
| << ") is greater than implementation dependent limit (" << max << ")."; |
| } |
| } |
| } |
| return ret; |
| } |
| |
| long runQueryUniformSubroutineFunction(const CompiledProgram& program, GLenum stage, |
| const SubroutineFunction& subroutineFunction, std::set<GLuint>& usedIndices, |
| GLint max, bool used) |
| { |
| long ret = NO_ERROR; |
| /* |
| glGetSubroutineIndex(program, shaderType, name) |
| Query passes if returned value is unique in current program stage, |
| matches explicit index (if passed in GLSL code) and is less than value |
| of GL_MAX_SUBROUTINES. |
| |
| glGetProgramResourceIndex(program, GL_(VERTEX|FRAGMENT|COMPUTE|... |
| ..._SUBROUTINE, name) |
| Query passes if returned value matches value returned from |
| glGetSubroutineIndex(). |
| */ |
| |
| std::string name = subroutineFunction.getName(); |
| |
| GLint returned = glGetSubroutineIndex(program.name, stage, name.c_str()); |
| |
| glw::GLenum piqStage = 0; |
| switch (stage) |
| { |
| case GL_VERTEX_SHADER: |
| piqStage = GL_VERTEX_SUBROUTINE; |
| break; |
| case GL_FRAGMENT_SHADER: |
| piqStage = GL_FRAGMENT_SUBROUTINE; |
| break; |
| case GL_COMPUTE_SHADER: |
| piqStage = GL_COMPUTE_SUBROUTINE; |
| break; |
| default: |
| assert(0); |
| } |
| |
| GLint returnedPIQ = glGetProgramResourceIndex(program.name, piqStage, name.c_str()); |
| |
| if (returned != returnedPIQ) |
| { |
| ret |= ERROR; |
| Logger() << "Indices of subroutine function \"" << name |
| << "\" returned by glGetSubroutineIndex and differ glGetProgramResourceIndex differ: " << returned |
| << " != " << returnedPIQ << "."; |
| } |
| |
| GLint reservedIndex = -1; |
| |
| if (!subroutineFunction.index.isImplicit(std::vector<glw::GLenum>(1, stage))) |
| { |
| //Validate uniform location against explicit value |
| GLint expected = subroutineFunction.index.val; |
| if (!(expected == returned || (!used && returned == -1))) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected subroutine function \"" << name << "\" index: expected " << expected << ", got " |
| << returned << "."; |
| } |
| |
| reservedIndex = expected; |
| } |
| else |
| { |
| //Check if location > 0 if used; |
| if (used) |
| { |
| if (returned < 0) |
| { |
| ret |= ERROR; |
| Logger() << "Unexpected subroutine function \"" << name << "\" index: expected positive value, got " |
| << returned << "."; |
| } |
| else |
| { |
| reservedIndex = returned; |
| } |
| } |
| } |
| |
| if (reservedIndex >= 0) |
| { |
| //check if location is unique |
| if (usedIndices.find(reservedIndex) != usedIndices.end()) |
| { |
| ret |= ERROR; |
| Logger() << "Subroutine function \"" << name << "\" index (" << reservedIndex << ") is not unique."; |
| } |
| usedIndices.insert(reservedIndex); |
| } |
| |
| if (returned >= 0) |
| { |
| //check if location is less than max |
| |
| if (returned >= max) |
| { |
| ret |= ERROR; |
| Logger() << "Subroutine function \"" << name << "\" returned index (" << returned |
| << ") is greater than implementation dependent limit (" << max << ")."; |
| } |
| } |
| |
| return ret; |
| } |
| |
| long runQueryProgram(const CompiledProgram& program, const std::vector<Uniform>& uniforms, |
| const std::vector<SubroutineUniform>& subroutineUniforms) |
| { |
| long ret = NO_ERROR; |
| |
| { |
| std::set<GLuint> usedLocations; |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max); |
| |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| ret |= runQueryUniform(program, uniforms[i], usedLocations, max); |
| } |
| } |
| |
| if (subroutineUniforms.size()) |
| { |
| GLint maxLocation, maxIndex; |
| glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &maxLocation); |
| glGetIntegerv(GL_MAX_SUBROUTINES, &maxIndex); |
| |
| for (size_t stage = 0; stage < program.stages.size(); stage++) |
| { |
| std::set<GLuint> usedLocations; |
| std::set<GLuint> usedIndices; |
| for (size_t i = 0; i < subroutineUniforms.size(); i++) |
| { |
| ret |= runQueryUniformSubroutine(program, program.stages[stage], subroutineUniforms[i], |
| usedLocations, maxLocation); |
| for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++) |
| { |
| ret |= runQueryUniformSubroutineFunction( |
| program, program.stages[stage], subroutineUniforms[i].functions.fn[fn], usedIndices, |
| maxIndex, |
| subroutineUniforms[i].defOccurence.occurs(program.stages[stage]) && |
| subroutineUniforms[i].used); |
| } |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| protected: |
| UniformValueGenerator uniformValueGenerator; |
| UniformStructCounter uniformStructCounter; |
| |
| long doRun(std::vector<SubroutineUniform>& subroutineUniforms) |
| { |
| assert(subroutineUniforms.size()); |
| std::vector<Uniform> noUniforms; |
| return doRun(noUniforms, subroutineUniforms); |
| } |
| |
| long doRun(std::vector<Uniform>& uniforms) |
| { |
| assert(uniforms.size()); |
| std::vector<SubroutineUniform> noSubroutineUniforms; |
| return doRun(uniforms, noSubroutineUniforms); |
| } |
| |
| long doRunNegativeCompile(const std::string additionalDef) |
| { |
| std::vector<Uniform> noUniforms; |
| std::vector<SubroutineUniform> noSubroutineUniforms; |
| return doRun(noUniforms, noSubroutineUniforms, additionalDef, true); |
| } |
| |
| long doRunNegativeLink(std::vector<Uniform>& uniforms) |
| { |
| std::vector<SubroutineUniform> noSubroutineUniforms; |
| return doRun(uniforms, noSubroutineUniforms, "", false, true); |
| } |
| |
| long doRunNegativeLink(std::vector<SubroutineUniform>& subroutineUniforms) |
| { |
| std::vector<Uniform> noUniforms; |
| return doRun(noUniforms, subroutineUniforms, "", false, true); |
| } |
| |
| long doRun(std::vector<Uniform>& uniforms, std::vector<SubroutineUniform>& subroutineUniforms, |
| std::string additionalDef = "", bool negativeCompile = false, bool negativeLink = false) |
| { |
| long ret = NO_ERROR; |
| std::string parentUniformName = ""; |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| std::ostringstream name; |
| name << "u" << i; |
| uniforms[i].setName(parentUniformName, name.str()); |
| } |
| int subroutineTypeCounter = 0; |
| int subroutineFunctionCounter = 0; |
| for (size_t i = 0; i < subroutineUniforms.size(); i++) |
| { |
| std::ostringstream name; |
| name << "u" << i + uniforms.size(); |
| subroutineUniforms[i].setName(name.str()); |
| if (!subroutineUniforms[i].functions.getTypeName().size()) |
| { |
| subroutineUniforms[i].functions.setTypeName(subroutineTypeCounter++); |
| for (size_t fn = 0; fn < subroutineUniforms[i].functions.fn.size(); fn++) |
| { |
| subroutineUniforms[i].functions.fn[fn].setName(subroutineFunctionCounter++); |
| } |
| } |
| } |
| |
| GLfloat coords[] = { |
| 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, |
| }; |
| |
| GLuint vbo, vao; |
| glGenBuffers(1, &vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, vbo); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW); |
| |
| glGenVertexArrays(1, &vao); |
| glBindVertexArray(vao); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); |
| glEnableVertexAttribArray(0); |
| |
| std::vector<CompiledProgram> programs; |
| ret |= CreatePrograms(programs, uniforms, subroutineUniforms, additionalDef, negativeCompile, negativeLink); |
| |
| for (size_t i = 0; i < programs.size() && ret == NO_ERROR && !negativeCompile && !negativeLink; i++) |
| { |
| ret |= runExecuteProgram(programs[i], uniforms, subroutineUniforms); |
| ret |= runQueryProgram(programs[i], uniforms, subroutineUniforms); |
| } |
| |
| glUseProgram(0); |
| |
| DeletePrograms(programs); |
| |
| glDeleteBuffers(1, &vbo); |
| glDeleteVertexArrays(1, &vao); |
| |
| return ret; |
| } |
| }; |
| |
| class UniformLoc : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform vec4 u0; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH)); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocNonDec : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 0x0a) uniform vec4 u0; |
| //layout (location = 010) uniform vec4 u1; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(0x0a, Loc::Hex), DefOccurence::FSH_OR_CSH)); |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(010, Loc::Oct), DefOccurence::FSH_OR_CSH)); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMultipleStages : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform vec4 u0; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMultipleUniforms : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform vec4 u0; |
| //layout (location = 3) uniform vec4 u1; |
| //layout (location = 5) uniform vec4 u2; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(3))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(5))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocTypesMix : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform float u0; |
| //layout (location = 3) uniform vec3 u1; |
| //layout (location = 0) uniform uint u2; |
| //layout (location = 1) uniform ivec3 u3; |
| //layout (location = 4) uniform mat2 u4; |
| //layout (location = 7) uniform mat2 u5; |
| //layout (location = 5) uniform mat2 u6; |
| //layout (location = 6) uniform mat3 u7; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(3))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_UNSIGNED_INT, Loc::C(0))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC3, Loc::C(1))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(4))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(7))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(5))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3, Loc::C(6))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocTypesMat : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::vector<Uniform> uniforms; |
| //layout (location = 1) uniform mat2x3 u0; |
| //layout (location = 2) uniform mat3x2 u1; |
| //layout (location = 0) uniform mat2 u2; |
| //layout (location = 3) uniform imat3x4 u3; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2x3, Loc::C(1))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT3x2, Loc::C(2))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT2, Loc::C(0))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_MAT4x3, Loc::C(3))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocTypesSamplers : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 1) uniform sampler2D s0[3]; |
| //layout (location = 13) uniform sampler2D s1; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_SAMPLER_2D, 3), Loc::C(1))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_SAMPLER_2D, Loc::C(13))); |
| |
| std::vector<GLuint> texUnits; |
| std::vector<std::vector<GLubyte> > colors; |
| |
| for (size_t i = 0; i < uniforms.size(); i++) |
| { |
| for (int elem = 0; elem < uniforms[i].type.arraySize; elem++) |
| { |
| texUnits.push_back(uniforms[i].value.iValues[elem]); |
| |
| std::vector<GLubyte> color(4); |
| color[0] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 0] + 0.5); |
| color[1] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 1] + 0.5); |
| color[2] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 2] + 0.5); |
| color[3] = static_cast<GLubyte>(255. * uniforms[i].value.fValues[4 * elem + 3] + 0.5); |
| colors.push_back(color); |
| } |
| } |
| |
| std::vector<GLuint> textures(texUnits.size()); |
| glGenTextures((GLsizei)(textures.size()), &textures[0]); |
| |
| for (size_t i = 0; i < textures.size(); i++) |
| { |
| glActiveTexture(GL_TEXTURE0 + texUnits[i]); |
| glBindTexture(GL_TEXTURE_2D, textures[i]); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &colors[i][0]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| } |
| glActiveTexture(GL_TEXTURE0); |
| long ret = doRun(uniforms); |
| glDeleteTextures((GLsizei)(textures.size()), &textures[0]); |
| return ret; |
| } |
| }; |
| |
| class UniformLocTypesStructs : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| /** |
| * This test case uses following uniform declarations: |
| * |
| * struct S { |
| * vec4 u0; |
| * float u1[2]; |
| * mat2 u2; |
| * }; |
| * layout (location = 1) uniform S s0[3]; |
| * layout (location = 13) uniform S s1; |
| */ |
| |
| std::vector<UniformType> members; |
| members.push_back(GL_FLOAT_VEC4); |
| members.push_back(UniformType(GL_FLOAT, 2)); |
| members.push_back(GL_FLOAT_MAT2); |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members, 3), Loc::C(1))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(uniformStructCounter, members), Loc::C(13))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocArraysNonSpaced : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform float[3] u0; |
| //layout (location = 5) uniform vec3[2] u1; |
| //layout (location = 7) uniform int[3] u2; |
| //layout (location = 10) uniform ivec4 u3; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(2))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(7))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_INT_VEC4, Loc::C(10))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocArraySpaced : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform float u0; |
| //layout (location = 5) uniform vec3[2] u1; |
| //layout (location = 8) uniform int[3] u2; |
| //layout (location = 12) uniform ivec4[1] u3; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(5))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::C(8))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 1), Loc::C(12))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocArrayofArrays : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform float[2][3] u0; |
| //layout (location = 8) uniform vec3[2][2] u1; |
| //layout (location = 12) uniform float u2; |
| std::vector<Uniform> uniforms; |
| { |
| std::vector<int> arraySizesSegmented(2); |
| arraySizesSegmented[0] = 2; |
| arraySizesSegmented[1] = 3; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, arraySizesSegmented), Loc::C(2))); |
| } |
| { |
| std::vector<int> arraySizesSegmented(2); |
| arraySizesSegmented[0] = arraySizesSegmented[1] = 2; |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, arraySizesSegmented), Loc::C(8))); |
| } |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(12))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMixWithImplicit : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 0) uniform float u0; |
| //layout (location = 2) uniform vec3 u1; |
| //layout (location = 3) uniform int u2; |
| |
| //uniform float u0; |
| //uniform vec3 u1; |
| //uniform int u2; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::FSH_OR_CSH))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2, DefOccurence::FSH_OR_CSH))); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::C(3, DefOccurence::FSH_OR_CSH))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMixWithImplicit2 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //uniform float[3] u0; |
| //layout (location = 3) uniform vec3[2] u1; |
| //uniform int[3] u2; |
| //layout (location = 8) uniform ivec4 u3; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::Implicit())); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT_VEC3, 2), Loc::C(3))); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT, 3), Loc::Implicit())); |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_INT_VEC4, 2), Loc::C(8))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMixWithImplicit3 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 0) uniform float u0; //unused |
| //layout (location = 2) uniform vec3 u1; //unused |
| //layout (location = 3) uniform int u2; //unused |
| |
| //uniform float u3; |
| //uniform vec3 u4; |
| //uniform int u5; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0), DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::C(2), DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, GL_INT, Loc::C(3), DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit())); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC3, Loc::Implicit())); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_INT, Loc::Implicit())); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocMixWithImplicitMax : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| long ret = NO_ERROR; |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max); |
| |
| const int implicitCount = 1; |
| |
| int tests[3] = { 0, 3, max - implicitCount }; |
| |
| for (int test = 0; test < 3; test++) |
| { |
| std::vector<Uniform> uniforms; |
| |
| //for performance reasons fill-up all avaliable locations with an unused arrays. |
| if (tests[test] > 0) |
| { |
| //[0..test - 1] |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0), |
| DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize == |
| tests[test]); |
| } |
| |
| if (tests[test] < max - implicitCount) |
| { |
| //[test + 1..max] |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]), |
| Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize == |
| max); |
| } |
| |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit())); |
| ret |= doRun(uniforms); |
| } |
| return ret; |
| } |
| }; |
| |
| class UniformLocMixWithImplicitMaxArray : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| long ret = NO_ERROR; |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max); |
| |
| const int implicitCount = 3; |
| |
| int tests[3] = { 0, 3, max - 4 }; |
| |
| for (int test = 0; test < 3; test++) |
| { |
| std::vector<Uniform> uniforms; |
| |
| //for performance reasons fill-up all avaliable locations with an unused arrays. |
| if (tests[test] > 0) |
| { |
| //[0..test - 1] |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, tests[test]), Loc::C(0), |
| DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize == |
| tests[test]); |
| } |
| |
| if (tests[test] < max - implicitCount) |
| { |
| //[test + 3 ..max] |
| uniforms.push_back( |
| Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max - implicitCount - tests[test]), |
| Loc::C(tests[test] + implicitCount), DefOccurence::ALL_SH, DefOccurence::NONE_SH)); |
| assert(uniforms[uniforms.size() - 1].location.val + uniforms[uniforms.size() - 1].type.arraySize == |
| max); |
| } |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, implicitCount), Loc::Implicit())); |
| ret |= doRun(uniforms); |
| } |
| return ret; |
| } |
| }; |
| |
| class UniformLocImplicitInSomeStages : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //One shader: uniform float u0; |
| //Another shader: layout (location = 3) uniform float u0; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH))); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocImplicitInSomeStages2 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //One shader: uniform float u0; |
| //Another shader: layout (location = 3) uniform float u0; //not used! |
| std::vector<Uniform> uniforms; |
| |
| //location only in fsh, declaration in all shaders, usage in all shaders but fsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH), |
| DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH)); |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocImplicitInSomeStages3 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::vector<Uniform> uniforms; |
| |
| //location only in fsh, declaration in all shaders, usage in all shaders but fsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(3, DefOccurence::FSH_OR_CSH), |
| DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH)); |
| |
| //location in all but fsh, declaration in all shaders, usage in fsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(2, DefOccurence::ALL_BUT_FSH), |
| DefOccurence::ALL_SH, DefOccurence::FSH_OR_CSH)); |
| |
| //location only in fsh, declaration in all shaders, usage in all shaders but fsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), Loc::C(7, DefOccurence::FSH_OR_CSH), |
| DefOccurence::ALL_SH, DefOccurence::ALL_BUT_FSH)); |
| |
| //location in all but fsh, declaration in all shaders, usage in fsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, 3), |
| Loc::C(4, DefOccurence::ALL_BUT_FSH), DefOccurence::ALL_SH, |
| DefOccurence::FSH_OR_CSH)); |
| |
| //location only in vsh, declaration in all shaders, usage in all shaders but vsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(0, DefOccurence::VSH), DefOccurence::ALL_SH, |
| DefOccurence::ALL_BUT_VSH)); |
| |
| //location only in vsh, declaration in all shaders, usage in all shaders but vsh. |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::C(1, DefOccurence::ALL_BUT_FSH), |
| DefOccurence::ALL_SH, DefOccurence::ALL_BUT_VSH)); |
| |
| return doRun(uniforms); |
| } |
| }; |
| |
| class UniformLocNegativeCompileNonNumberLiteral : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::string def = "layout (location = x) uniform float u0;"; |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class UniformLocNegativeCompileNonConstLoc : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::string def = NL "const int i = 1;" NL "layout (location = i) uniform float u0;"; |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class UniformLocNegativeLinkLocationReused1 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = 2) uniform float u0; |
| //layout (location = 2) uniform float u1; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH)); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(uniforms); |
| } |
| }; |
| |
| class UniformLocNegativeLinkLocationReused2 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| ///layout (location = 2) uniform float u0; |
| //layout (location = 2) uniform float u1; |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::FSH_OR_CSH)); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(2), DefOccurence::ALL_BUT_FSH)); |
| return doRunNegativeLink(uniforms); |
| } |
| }; |
| |
| class UniformLocNegativeLinkMaxLocation : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout (location = X) uniform float u0; |
| //Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS. |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max); |
| |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT_VEC4, Loc::C(max), DefOccurence::FSH_OR_CSH)); |
| |
| return doRunNegativeLink(uniforms); |
| } |
| }; |
| |
| class UniformLocNegativeLinkMaxMaxNumOfLocation : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max); |
| std::vector<Uniform> uniforms; |
| uniforms.push_back(Uniform(uniformValueGenerator, UniformType(GL_FLOAT, max), Loc::C(0), |
| DefOccurence::FSH_OR_CSH, DefOccurence::NONE_SH)); |
| uniforms.push_back(Uniform(uniformValueGenerator, GL_FLOAT, Loc::Implicit(), DefOccurence::ALL_BUT_FSH)); |
| return doRunNegativeLink(uniforms); |
| } |
| }; |
| |
| class SubRoutineLoc : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //one shader: |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 2) subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocNonDecimal : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //one shader: |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 0x0a) subroutine uniform st0 u0; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0x0a, Loc::Hex), 0, |
| DefOccurence::FSH_OR_CSH)); |
| //layout(location = 010 ) subroutine uniform st0 u1; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(010, Loc::Oct), 0, |
| DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocAllStages : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 2) subroutine uniform st0 u0; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2))); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocArrays : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 1) subroutine uniform st0 u0[2]; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocArraysMix : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| //subroutine vec4 st1(float param); |
| //subroutine(st1) vec4 sf2(float param) { .... }; |
| //subroutine(st1) vec4 sf3(float param) { .... }; |
| SubroutineFunctionSet functions_st1(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 1) subroutine uniform st0 u0[2]; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 2)); |
| |
| ////layout(location = 3) subroutine uniform st0 u1[2][3]; |
| std::vector<int> arraySizesSegmented(2); |
| arraySizesSegmented[0] = 2; |
| arraySizesSegmented[1] = 3; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), arraySizesSegmented)); |
| |
| //layout(location = 9) subroutine uniform st1 u2; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9))); |
| |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocMixWithImplicit : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //subroutine vec4 st0(float param); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| //subroutine(st0) vec4 sf1(float param) { .... }; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit())); |
| //layout(location = 1 ) subroutine uniform st0 u1; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0))); |
| //layout(location = 0 ) subroutine uniform st0 u2; |
| subroutineUniforms.push_back(SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1))); |
| |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| std::string def = |
| NL "subroutine vec4 st0(float param);" NL "subroutine(st0) vec4 sf0(float param) { return param; }" NL |
| "layout(location = x ) subroutine uniform st0 u0;"; |
| |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class SubRoutineLocCompilationNonConstLoc : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::string def = NL "const int i = 1;" NL "subroutine vec4 st0(float param);" NL |
| "subroutine(st0) vec4 sf0(float param) { return param; }" NL |
| "layout(location = i ) subroutine uniform st0 u0;"; |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class SubRoutineLocLinkLocationReused1 : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout(location = 1) subroutine uniform st0 u0; |
| //layout(location = 1) subroutine uniform st0 u0; |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| std::vector<SubroutineUniform> subroutineUniforms; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH)); |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocLinkLocationMaxLocation : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //layout(location = N) subroutine uniform st0 u0; |
| //Where X is substituted with value of GL_MAX_UNIFORM_LOCATIONS. |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| std::vector<SubroutineUniform> subroutineUniforms; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(max), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| |
| class SubRoutineLocLinkMaxNumOfLocations : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, &max); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator, 2); |
| std::vector<SubroutineUniform> subroutineUniforms; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(0), max, DefOccurence::FSH_OR_CSH, false)); |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndex : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //one shader: |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1))); |
| //layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexNonDecimal : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //one shader: |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 0x0a) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0x0a, Index::Hex))); |
| //layout(index = 010 ) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(010, Index::Oct))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexLoc : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //one shader: |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1))); |
| //layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 3) subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(3), 0, DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexNonCont : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //one shader: |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 0) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0))); |
| //layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 2) subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexMultUniforms : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //one shader: |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1))); |
| //layout(index = 3) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(3))); |
| |
| //subroutine vec4 st1(float param); |
| SubroutineFunctionSet functions_st1(uniformValueGenerator); |
| //layout(index = 2) subroutine(st1) vec4 sf2(float param) { .... }; |
| functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| //layout(index = 0) subroutine(st1) vec4 sf3(float param) { .... }; |
| functions_st1.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| //layout(location = 1) subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(1), 0, DefOccurence::FSH_OR_CSH)); |
| //layout(location = 9) subroutine uniform st1 u1; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st1, Loc::C(9), 0, DefOccurence::FSH_OR_CSH)); |
| |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexAllstages : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 1) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1))); |
| //layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::ALL_SH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexMixImplicit : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit())); |
| //layout(index = 1) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(1))); |
| //layout(index = 0) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(0))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //layout(location = 2) subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::C(2), 0, DefOccurence::FSH_OR_CSH)); |
| return doRun(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexNegativeCompilationNonNumberLiteral : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::string def = NL "subroutine vec4 st0(float param);" NL |
| "layout(index = x) subroutine(st0) vec4 sf1(float param) { return param; };"; |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class SubroutineIndexNegativeCompilationNonConstIndex : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| std::string def = |
| NL "const int i = 1;" NL "layout(index = i) subroutine(st0) vec4 sf1(float param) { return param; };"; |
| return doRunNegativeCompile(def); |
| } |
| }; |
| |
| class SubroutineIndexNegativeLinkIndexReused : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = 2) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| //layout(index = 2) subroutine(st0) vec4 sf1(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(2))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexNegativeLinkMaxIndex : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| |
| GLint max; |
| glGetIntegerv(GL_MAX_SUBROUTINES, &max); |
| |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| //layout(index = N) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(max))); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| |
| class SubroutineIndexNegativeLinkMaxNumOfIndices : public ExplicitUniformLocationCaseBase |
| { |
| virtual long Run() |
| { |
| //subroutine vec4 st0(float param); |
| SubroutineFunctionSet functions_st0(uniformValueGenerator); |
| |
| glw::GLint max; |
| glGetIntegerv(GL_MAX_SUBROUTINES, &max); |
| |
| for (int i = 0; i < max; i++) |
| { |
| //layout(index = N) subroutine(st0) vec4 sf0(float param) { .... }; |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::C(i))); |
| } |
| functions_st0.push_back(SubroutineFunction(uniformValueGenerator, Index::Implicit())); |
| |
| std::vector<SubroutineUniform> subroutineUniforms; |
| |
| //subroutine uniform st0 u0; |
| subroutineUniforms.push_back( |
| SubroutineUniform(uniformValueGenerator, functions_st0, Loc::Implicit(), 0, DefOccurence::FSH_OR_CSH)); |
| return doRunNegativeLink(subroutineUniforms); |
| } |
| }; |
| } |
| |
| ExplicitUniformLocationGLTests::ExplicitUniformLocationGLTests(glcts::Context& context) |
| : TestCaseGroup(context, "explicit_uniform_location", "") |
| { |
| } |
| |
| ExplicitUniformLocationGLTests::~ExplicitUniformLocationGLTests(void) |
| { |
| } |
| |
| void ExplicitUniformLocationGLTests::init() |
| { |
| using namespace glcts; |
| |
| Logger::setOutput(m_context.getTestContext().getLog()); |
| addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>)); |
| |
| addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>)); |
| |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max", |
| TestSubcase::Create<UniformLocMixWithImplicitMax>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array", |
| TestSubcase::Create<UniformLocMixWithImplicitMaxArray>)); |
| |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages", |
| TestSubcase::Create<UniformLocImplicitInSomeStages>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2", |
| TestSubcase::Create<UniformLocImplicitInSomeStages2>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3", |
| TestSubcase::Create<UniformLocImplicitInSomeStages3>)); |
| |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal", |
| TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc", |
| TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1", |
| TestSubcase::Create<UniformLocNegativeLinkLocationReused1>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2", |
| TestSubcase::Create<UniformLocNegativeLinkLocationReused2>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location", |
| TestSubcase::Create<UniformLocNegativeLinkMaxLocation>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations", |
| TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>)); |
| |
| addChild(new TestSubcase(m_context, "subroutine-loc", TestSubcase::Create<SubRoutineLoc>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-nondecimal", TestSubcase::Create<SubRoutineLocNonDecimal>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-all-stages", TestSubcase::Create<SubRoutineLocAllStages>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-arrays", TestSubcase::Create<SubRoutineLocArrays>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-arrays-mix", TestSubcase::Create<SubRoutineLocArraysMix>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-mix-with-implicit", |
| TestSubcase::Create<SubRoutineLocMixWithImplicit>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-non-number-literal", |
| TestSubcase::Create<SubRoutineLocCompilationNonNumberLiteral>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-negative-compilation-nonconst-loc", |
| TestSubcase::Create<SubRoutineLocCompilationNonConstLoc>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-reused1", |
| TestSubcase::Create<SubRoutineLocLinkLocationReused1>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-location-max-location", |
| TestSubcase::Create<SubRoutineLocLinkLocationMaxLocation>)); |
| addChild(new TestSubcase(m_context, "subroutine-loc-negative-link-max-num-of-locations", |
| TestSubcase::Create<SubRoutineLocLinkMaxNumOfLocations>)); |
| addChild(new TestSubcase(m_context, "subroutine-index", TestSubcase::Create<SubroutineIndex>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-nondecimal", TestSubcase::Create<SubroutineIndexNonDecimal>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-loc", TestSubcase::Create<SubroutineIndexLoc>)); |
| addChild( |
| new TestSubcase(m_context, "subroutine-index-non-continuous", TestSubcase::Create<SubroutineIndexNonCont>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-multiple-uniforms", |
| TestSubcase::Create<SubroutineIndexMultUniforms>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-all-stages", TestSubcase::Create<SubroutineIndexAllstages>)); |
| addChild( |
| new TestSubcase(m_context, "subroutine-index-mix-implicit", TestSubcase::Create<SubroutineIndexMixImplicit>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-non-number-literal", |
| TestSubcase::Create<SubroutineIndexNegativeCompilationNonNumberLiteral>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-negative-compilation-nonconst-index", |
| TestSubcase::Create<SubroutineIndexNegativeCompilationNonConstIndex>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-negative-link-index-reused", |
| TestSubcase::Create<SubroutineIndexNegativeLinkIndexReused>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-negative-link-location-maxindex", |
| TestSubcase::Create<SubroutineIndexNegativeLinkMaxIndex>)); |
| addChild(new TestSubcase(m_context, "subroutine-index-negative-link-max-num-of-indices", |
| TestSubcase::Create<SubroutineIndexNegativeLinkMaxNumOfIndices>)); |
| } |
| |
| ExplicitUniformLocationES31Tests::ExplicitUniformLocationES31Tests(glcts::Context& context) |
| : TestCaseGroup(context, "explicit_uniform_location", "") |
| { |
| } |
| |
| ExplicitUniformLocationES31Tests::~ExplicitUniformLocationES31Tests(void) |
| { |
| } |
| |
| void ExplicitUniformLocationES31Tests::init() |
| { |
| using namespace glcts; |
| Logger::setOutput(m_context.getTestContext().getLog()); |
| addChild(new TestSubcase(m_context, "uniform-loc", TestSubcase::Create<UniformLoc>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-nondecimal", TestSubcase::Create<UniformLocNonDec>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-all-stages", TestSubcase::Create<UniformLocMultipleStages>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-multiple-uniforms", TestSubcase::Create<UniformLocMultipleUniforms>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-mix", TestSubcase::Create<UniformLocTypesMix>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-mat", TestSubcase::Create<UniformLocTypesMat>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-structs", TestSubcase::Create<UniformLocTypesStructs>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-types-samplers", TestSubcase::Create<UniformLocTypesSamplers>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-arrays-nonspaced", TestSubcase::Create<UniformLocArraysNonSpaced>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-arrays-spaced", TestSubcase::Create<UniformLocArraySpaced>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-arrays-of-arrays", TestSubcase::Create<UniformLocArrayofArrays>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit", TestSubcase::Create<UniformLocMixWithImplicit>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit2", TestSubcase::Create<UniformLocMixWithImplicit2>)); |
| addChild( |
| new TestSubcase(m_context, "uniform-loc-mix-with-implicit3", TestSubcase::Create<UniformLocMixWithImplicit3>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max", |
| TestSubcase::Create<UniformLocMixWithImplicitMax>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-mix-with-implicit-max-array", |
| TestSubcase::Create<UniformLocMixWithImplicitMaxArray>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages", |
| TestSubcase::Create<UniformLocImplicitInSomeStages>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages2", |
| TestSubcase::Create<UniformLocImplicitInSomeStages2>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-implicit-in-some-stages3", |
| TestSubcase::Create<UniformLocImplicitInSomeStages3>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-non-number-literal", |
| TestSubcase::Create<UniformLocNegativeCompileNonNumberLiteral>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-compile-nonconst-loc", |
| TestSubcase::Create<UniformLocNegativeCompileNonConstLoc>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused1", |
| TestSubcase::Create<UniformLocNegativeLinkLocationReused1>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-location-reused2", |
| TestSubcase::Create<UniformLocNegativeLinkLocationReused2>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-location", |
| TestSubcase::Create<UniformLocNegativeLinkMaxLocation>)); |
| addChild(new TestSubcase(m_context, "uniform-loc-negative-link-max-num-of-locations", |
| TestSubcase::Create<UniformLocNegativeLinkMaxMaxNumOfLocation>)); |
| } |
| } |