| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL (ES) Module |
| * ----------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * 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 Attribute location tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "glsAttributeLocationTests.hpp" |
| |
| #include "tcuStringTemplate.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include "gluDefs.hpp" |
| #include "gluRenderContext.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "gluShaderUtil.hpp" |
| #include "gluStrUtil.hpp" |
| |
| #include "glwFunctions.hpp" |
| |
| #include "deStringUtil.hpp" |
| |
| #include <map> |
| #include <set> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include <cstring> |
| |
| #include "glw.h" |
| |
| using tcu::TestLog; |
| |
| using std::string; |
| using std::vector; |
| using std::set; |
| using std::map; |
| using std::pair; |
| |
| using namespace deqp::gls::AttributeLocationTestUtil; |
| |
| namespace deqp |
| { |
| namespace gls |
| { |
| namespace |
| { |
| |
| deInt32 getBoundLocation (const map<string, deUint32>& bindings, const string& attrib) |
| { |
| std::map<string, deUint32>::const_iterator iter = bindings.find(attrib); |
| |
| return (iter == bindings.end() ? (deInt32)Attribute::LOC_UNDEF : iter->second); |
| } |
| |
| bool hasAttributeAliasing (const vector<Attribute>& attributes, const map<string, deUint32>& bindings) |
| { |
| vector<bool> reservedSpaces; |
| |
| for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++) |
| { |
| const deInt32 location = getBoundLocation(bindings, attributes[attribNdx].getName()); |
| const deUint32 size = attributes[attribNdx].getType().getLocationSize(); |
| |
| if (location != Attribute::LOC_UNDEF) |
| { |
| if (reservedSpaces.size() < location + size) |
| reservedSpaces.resize(location + size, false); |
| |
| for (int i = 0; i < (int)size; i++) |
| { |
| if (reservedSpaces[location + i]) |
| return true; |
| |
| reservedSpaces[location + i] = true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| deInt32 getMaxAttributeLocations (glu::RenderContext& renderCtx) |
| { |
| const glw::Functions& gl = renderCtx.getFunctions(); |
| deInt32 maxAttribs; |
| |
| gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()"); |
| |
| return maxAttribs; |
| } |
| |
| string generateAttributeDefinitions (const vector<Attribute>& attributes) |
| { |
| std::ostringstream src; |
| |
| for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) |
| { |
| if (iter->getLayoutLocation() != Attribute::LOC_UNDEF) |
| src << "layout(location = " << iter->getLayoutLocation() << ") "; |
| |
| src << "${VTX_INPUT} mediump " |
| << iter->getType().getName() << " " |
| << iter->getName() |
| << (iter->getArraySize() != Attribute::NOT_ARRAY ? "[" + de::toString(iter->getArraySize()) + "]" : "") << ";\n"; |
| } |
| |
| return src.str(); |
| } |
| |
| string generateConditionUniformDefinitions (const vector<Attribute>& attributes) |
| { |
| std::ostringstream src; |
| set<string> conditions; |
| |
| for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) |
| { |
| if (iter->getCondition() != Cond::COND_NEVER && iter->getCondition() != Cond::COND_ALWAYS) |
| conditions.insert(iter->getCondition().getName()); |
| } |
| |
| for (set<string>::const_iterator iter = conditions.begin(); iter != conditions.end(); ++iter) |
| src << "uniform mediump float u_" << (*iter) << ";\n"; |
| |
| return src.str(); |
| } |
| |
| string generateToVec4Expression (const Attribute& attrib, int id=-1) |
| { |
| const string variableName(attrib.getName() + (attrib.getArraySize() != Attribute::NOT_ARRAY ? "[" + de::toString(id) + "]" : "")); |
| std::ostringstream src; |
| |
| switch (attrib.getType().getGLTypeEnum()) |
| { |
| case GL_INT_VEC2: |
| case GL_UNSIGNED_INT_VEC2: |
| case GL_FLOAT_VEC2: |
| src << "vec4(" << variableName << ".xy, " << variableName << ".yx)"; |
| break; |
| |
| case GL_INT_VEC3: |
| case GL_UNSIGNED_INT_VEC3: |
| case GL_FLOAT_VEC3: |
| src << "vec4(" << variableName << ".xyz, " << variableName << ".x)"; |
| break; |
| |
| default: |
| src << "vec4(" << variableName << ")"; |
| break; |
| } |
| |
| return src.str(); |
| } |
| |
| string generateOutputCode (const vector<Attribute>& attributes) |
| { |
| std::ostringstream src; |
| |
| for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) |
| { |
| if (iter->getCondition() == Cond::COND_NEVER) |
| { |
| src << |
| "\tif (0 != 0)\n" |
| "\t{\n"; |
| |
| if (iter->getArraySize() == Attribute::NOT_ARRAY) |
| src << "\t\tcolor += " << generateToVec4Expression(*iter) << ";\n"; |
| else |
| { |
| for (int i = 0; i < iter->getArraySize(); i++) |
| src << "\t\tcolor += " << generateToVec4Expression(*iter, i) << ";\n"; |
| } |
| |
| src << "\t}\n"; |
| } |
| else if (iter->getCondition() == Cond::COND_ALWAYS) |
| { |
| if (iter->getArraySize() == Attribute::NOT_ARRAY) |
| src << "\tcolor += " << generateToVec4Expression(*iter) << ";\n"; |
| else |
| { |
| for (int i = 0; i < iter->getArraySize(); i++) |
| src << "\tcolor += " << generateToVec4Expression(*iter, i) << ";\n"; |
| } |
| } |
| else |
| { |
| src << |
| "\tif (u_" << iter->getCondition().getName() << (iter->getCondition().getNegate() ? " != " : " == ") << "0.0)\n" |
| "\t{\n"; |
| |
| if (iter->getArraySize() == Attribute::NOT_ARRAY) |
| src << "\t\tcolor += " << generateToVec4Expression(*iter) << ";\n"; |
| else |
| { |
| for (int i = 0; i < iter->getArraySize(); i++) |
| src << "\t\tcolor += " << generateToVec4Expression(*iter, i) << ";\n"; |
| } |
| |
| src << |
| "\t}\n"; |
| } |
| } |
| |
| return src.str(); |
| } |
| |
| string generateVertexShaderTemplate (const vector<Attribute>& attributes) |
| { |
| std::ostringstream src; |
| |
| src << "${VERSION}\n" |
| "${VTX_OUTPUT} mediump vec4 v_color;\n"; |
| |
| src << generateAttributeDefinitions(attributes) |
| << "\n" |
| << generateConditionUniformDefinitions(attributes) |
| << "\n"; |
| |
| src << "void main (void)\n" |
| "{\n" |
| "\tmediump vec4 color = vec4(0.0);\n" |
| "\n"; |
| |
| src << generateOutputCode(attributes); |
| |
| src << "\n" |
| "\tv_color = color;\n" |
| "\tgl_Position = color;\n" |
| "}\n"; |
| |
| return src.str(); |
| } |
| |
| string createVertexShaderSource (glu::RenderContext& renderCtx, const vector<Attribute>& attributes, bool attributeAliasing) |
| { |
| // \note On GLES only GLSL #version 100 supports aliasing |
| const glu::GLSLVersion contextGLSLVersion = glu::getContextTypeGLSLVersion(renderCtx.getType()); |
| const glu::GLSLVersion glslVersion = (attributeAliasing && glu::glslVersionIsES(contextGLSLVersion) ? glu::GLSL_VERSION_100_ES : contextGLSLVersion); |
| const bool usesInOutQualifiers = glu::glslVersionUsesInOutQualifiers(glslVersion); |
| const tcu::StringTemplate vertexShaderTemplate(generateVertexShaderTemplate(attributes)); |
| |
| map<string, string> parameters; |
| |
| parameters["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); |
| parameters["VTX_OUTPUT"] = (usesInOutQualifiers ? "out" : "varying"); |
| parameters["VTX_INPUT"] = (usesInOutQualifiers ? "in" : "attribute"); |
| parameters["FRAG_INPUT"] = (usesInOutQualifiers ? "in" : "varying"); |
| parameters["FRAG_OUTPUT_VAR"] = (usesInOutQualifiers ? "dEQP_FragColor" : "gl_FragColor"); |
| parameters["FRAG_OUTPUT_DECLARATION"] = (usesInOutQualifiers |
| ? "layout(location=0) out mediump vec4 dEQP_FragColor;" |
| : ""); |
| |
| return vertexShaderTemplate.specialize(parameters); |
| } |
| |
| string createFragmentShaderSource (glu::RenderContext& renderCtx, bool attributeAliasing) |
| { |
| const char* const fragmentShaderSource = |
| "${VERSION}\n" |
| "${FRAG_OUTPUT_DECLARATION}\n" |
| "${FRAG_INPUT} mediump vec4 v_color;\n" |
| "void main (void)\n" |
| "{\n" |
| "\t${FRAG_OUTPUT_VAR} = v_color;\n" |
| "}\n"; |
| |
| // \note On GLES only GLSL #version 100 supports aliasing |
| const glu::GLSLVersion contextGLSLVersion = glu::getContextTypeGLSLVersion(renderCtx.getType()); |
| const glu::GLSLVersion glslVersion = (attributeAliasing && glu::glslVersionIsES(contextGLSLVersion) ? glu::GLSL_VERSION_100_ES : contextGLSLVersion); |
| const tcu::StringTemplate fragmentShaderTemplate(fragmentShaderSource); |
| const bool usesInOutQualifiers = glu::glslVersionUsesInOutQualifiers(glslVersion); |
| |
| map<string, string> parameters; |
| |
| parameters["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); |
| parameters["VTX_OUTPUT"] = (usesInOutQualifiers ? "out" : "varying"); |
| parameters["VTX_INPUT"] = (usesInOutQualifiers ? "in" : "attribute"); |
| parameters["FRAG_INPUT"] = (usesInOutQualifiers ? "in" : "varying"); |
| parameters["FRAG_OUTPUT_VAR"] = (usesInOutQualifiers ? "dEQP_FragColor" : "gl_FragColor"); |
| parameters["FRAG_OUTPUT_DECLARATION"] = (usesInOutQualifiers |
| ? "layout(location=0) out mediump vec4 dEQP_FragColor;" |
| : ""); |
| |
| return fragmentShaderTemplate.specialize(parameters); |
| } |
| |
| string getShaderInfoLog (const glw::Functions& gl, deUint32 shader) |
| { |
| deInt32 length = 0; |
| string infoLog; |
| |
| gl.getShaderiv(shader, GL_INFO_LOG_LENGTH, &length); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); |
| |
| infoLog.resize(length, '\0'); |
| |
| gl.getShaderInfoLog(shader, (glw::GLsizei)infoLog.length(), DE_NULL, &(infoLog[0])); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()"); |
| |
| return infoLog; |
| } |
| |
| bool getShaderCompileStatus (const glw::Functions& gl, deUint32 shader) |
| { |
| deInt32 status; |
| |
| gl.getShaderiv(shader, GL_COMPILE_STATUS, &status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); |
| |
| return status == GL_TRUE; |
| } |
| |
| string getProgramInfoLog (const glw::Functions& gl, deUint32 program) |
| { |
| deInt32 length = 0; |
| string infoLog; |
| |
| gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &length); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); |
| |
| infoLog.resize(length, '\0'); |
| |
| gl.getProgramInfoLog(program, (glw::GLsizei)infoLog.length(), DE_NULL, &(infoLog[0])); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()"); |
| |
| return infoLog; |
| } |
| |
| bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program) |
| { |
| deInt32 status; |
| |
| gl.getProgramiv(program, GL_LINK_STATUS, &status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); |
| |
| return status == GL_TRUE; |
| } |
| |
| void logProgram (TestLog& log, const glw::Functions& gl, deUint32 program) |
| { |
| const bool programLinkOk = getProgramLinkStatus(gl, program); |
| const string programInfoLog = getProgramInfoLog(gl, program); |
| tcu::ScopedLogSection linkInfo (log, "Program Link Info", "Program Link Info"); |
| |
| { |
| tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log"); |
| |
| log << TestLog::Message << programInfoLog << TestLog::EndMessage; |
| } |
| |
| log << TestLog::Message << "Link result: " << (programLinkOk ? "Ok" : "Fail") << TestLog::EndMessage; |
| } |
| |
| void logShaders (TestLog& log, |
| const string& vertexShaderSource, |
| const string& vertexShaderInfoLog, |
| bool vertexCompileOk, |
| const string& fragmentShaderSource, |
| const string& fragmentShaderInfoLog, |
| bool fragmentCompileOk) |
| { |
| // \todo [mika] Log as real shader elements. Currently not supported by TestLog. |
| { |
| tcu::ScopedLogSection shaderSection(log, "Vertex Shader Info", "Vertex Shader Info"); |
| |
| log << TestLog::KernelSource(vertexShaderSource); |
| |
| { |
| tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log"); |
| |
| log << TestLog::Message << vertexShaderInfoLog << TestLog::EndMessage; |
| } |
| |
| log << TestLog::Message << "Compilation result: " << (vertexCompileOk ? "Ok" : "Failed") << TestLog::EndMessage; |
| } |
| |
| { |
| tcu::ScopedLogSection shaderSection(log, "Fragment Shader Info", "Fragment Shader Info"); |
| |
| log << TestLog::KernelSource(fragmentShaderSource); |
| |
| { |
| tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log"); |
| |
| log << TestLog::Message << fragmentShaderInfoLog << TestLog::EndMessage; |
| } |
| |
| log << TestLog::Message << "Compilation result: " << (fragmentCompileOk ? "Ok" : "Failed") << TestLog::EndMessage; |
| } |
| } |
| |
| pair<deUint32, deUint32> createAndAttachShaders (TestLog& log, glu::RenderContext& renderCtx, deUint32 program, const vector<Attribute>& attributes, bool attributeAliasing) |
| { |
| const glw::Functions& gl = renderCtx.getFunctions(); |
| const string vertexShaderSource = createVertexShaderSource(renderCtx, attributes, attributeAliasing); |
| const string fragmentShaderSource = createFragmentShaderSource(renderCtx, attributeAliasing); |
| |
| const deUint32 vertexShader = gl.createShader(GL_VERTEX_SHADER); |
| const deUint32 fragmentShader = gl.createShader(GL_FRAGMENT_SHADER); |
| |
| try |
| { |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader()"); |
| |
| { |
| const char* const vertexShaderString = vertexShaderSource.c_str(); |
| const char* const fragmentShaderString = fragmentShaderSource.c_str(); |
| |
| gl.shaderSource(vertexShader, 1, &vertexShaderString, DE_NULL); |
| gl.shaderSource(fragmentShader, 1, &fragmentShaderString, DE_NULL); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); |
| } |
| |
| gl.compileShader(vertexShader); |
| gl.compileShader(fragmentShader); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()"); |
| |
| gl.attachShader(program, vertexShader); |
| gl.attachShader(program, fragmentShader); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()"); |
| |
| { |
| const bool vertexCompileOk = getShaderCompileStatus(gl, vertexShader); |
| const bool fragmentCompileOk = getShaderCompileStatus(gl, fragmentShader); |
| |
| const string vertexShaderInfoLog = getShaderInfoLog(gl, vertexShader); |
| const string fragmentShaderInfoLog = getShaderInfoLog(gl, fragmentShader); |
| |
| logShaders(log, vertexShaderSource, vertexShaderInfoLog, vertexCompileOk, fragmentShaderSource, fragmentShaderInfoLog, fragmentCompileOk); |
| |
| TCU_CHECK_MSG(vertexCompileOk, "Vertex shader compilation failed"); |
| TCU_CHECK_MSG(fragmentCompileOk, "Fragment shader compilation failed"); |
| } |
| |
| gl.deleteShader(vertexShader); |
| gl.deleteShader(fragmentShader); |
| |
| return pair<deUint32, deUint32>(vertexShader, fragmentShader); |
| } |
| catch (...) |
| { |
| if (vertexShader != 0) |
| gl.deleteShader(vertexShader); |
| |
| if (fragmentShader != 0) |
| gl.deleteShader(fragmentShader); |
| |
| throw; |
| } |
| } |
| |
| void bindAttributes (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Bind>& binds) |
| { |
| for (vector<Bind>::const_iterator iter = binds.begin(); iter != binds.end(); ++iter) |
| { |
| log << TestLog::Message << "Bind attribute: '" << iter->getAttributeName() << "' to " << iter->getLocation() << TestLog::EndMessage; |
| gl.bindAttribLocation(program, iter->getLocation(), iter->getAttributeName().c_str()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation()"); |
| } |
| } |
| |
| void logAttributes (TestLog& log, const vector<Attribute>& attributes) |
| { |
| for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++) |
| { |
| const Attribute& attrib = attributes[attribNdx]; |
| |
| log << TestLog::Message |
| << "Type: " << attrib.getType().getName() |
| << ", Name: " << attrib.getName() |
| << (attrib.getLayoutLocation() != Attribute::LOC_UNDEF ? ", Layout location " + de::toString(attrib.getLayoutLocation()) : "") |
| << TestLog::EndMessage; |
| } |
| } |
| |
| bool checkActiveAttribQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes) |
| { |
| deInt32 activeAttribCount = 0; |
| set<string> activeAttributes; |
| bool isOk = true; |
| |
| gl.getProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount)"); |
| |
| for (int activeAttribNdx = 0; activeAttribNdx < activeAttribCount; activeAttribNdx++) |
| { |
| char name[128]; |
| const size_t maxNameSize = DE_LENGTH_OF_ARRAY(name) - 1; |
| deInt32 length = 0; |
| deInt32 size = 0; |
| deUint32 type = 0; |
| |
| std::memset(name, 0, sizeof(name)); |
| |
| gl.getActiveAttrib(program, activeAttribNdx, maxNameSize, &length, &size, &type, name); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveAttrib()"); |
| |
| log << TestLog::Message |
| << "glGetActiveAttrib(program" |
| << ", index=" << activeAttribNdx |
| << ", bufSize=" << maxNameSize |
| << ", length=" << length |
| << ", size=" << size |
| << ", type=" << glu::getShaderVarTypeStr(type) |
| << ", name='" << name << "')" << TestLog::EndMessage; |
| |
| { |
| bool found = false; |
| |
| for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++) |
| { |
| const Attribute& attrib = attributes[attribNdx]; |
| |
| if (attrib.getName() == name) |
| { |
| if (type != attrib.getType().getGLTypeEnum()) |
| { |
| log << TestLog::Message |
| << "Error: Wrong type " << glu::getShaderVarTypeStr(type) |
| << " expected " << glu::getShaderVarTypeStr(attrib.getType().getGLTypeEnum()) |
| << TestLog::EndMessage; |
| |
| isOk = false; |
| } |
| |
| if (attrib.getArraySize() == Attribute::NOT_ARRAY) |
| { |
| if (size != 1) |
| { |
| log << TestLog::Message << "Error: Wrong size " << size << " expected " << 1 << TestLog::EndMessage; |
| isOk = false; |
| } |
| } |
| else |
| { |
| if (size != attrib.getArraySize()) |
| { |
| log << TestLog::Message << "Error: Wrong size " << size << " expected " << attrib.getArraySize() << TestLog::EndMessage; |
| isOk = false; |
| } |
| } |
| |
| found = true; |
| break; |
| } |
| } |
| |
| if (!found) |
| { |
| log << TestLog::Message << "Error: Unknown attribute '" << name << "' returned by glGetActiveAttrib()." << TestLog::EndMessage; |
| isOk = false; |
| } |
| } |
| |
| activeAttributes.insert(name); |
| } |
| |
| for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++) |
| { |
| const Attribute& attrib = attributes[attribNdx]; |
| const bool isActive = attrib.getCondition() != Cond::COND_NEVER; |
| |
| if (isActive) |
| { |
| if (activeAttributes.find(attrib.getName()) == activeAttributes.end()) |
| { |
| log << TestLog::Message << "Error: Active attribute " << attrib.getName() << " wasn't returned by glGetActiveAttrib()." << TestLog::EndMessage; |
| isOk = false; |
| } |
| } |
| else |
| { |
| if (activeAttributes.find(attrib.getName()) != activeAttributes.end()) |
| log << TestLog::Message << "Note: Inactive attribute " << attrib.getName() << " was returned by glGetActiveAttrib()." << TestLog::EndMessage; |
| } |
| } |
| |
| return isOk; |
| } |
| |
| bool checkAttribLocationQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes, const map<string, deUint32>& bindings) |
| { |
| bool isOk = true; |
| |
| for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++) |
| { |
| const Attribute& attrib = attributes[attribNdx]; |
| const deInt32 expectedLocation = (attrib.getLayoutLocation() != Attribute::LOC_UNDEF ? attrib.getLayoutLocation() : getBoundLocation(bindings, attrib.getName())); |
| const deInt32 location = gl.getAttribLocation(program, attrib.getName().c_str()); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation()"); |
| |
| log << TestLog::Message |
| << location << " = glGetAttribLocation(program, \"" << attrib.getName() << "\")" |
| << (attrib.getCondition() != Cond::COND_NEVER && expectedLocation != Attribute::LOC_UNDEF ? ", expected " + de::toString(expectedLocation) : "") |
| << "." << TestLog::EndMessage; |
| |
| if (attrib.getCondition() == Cond::COND_NEVER && location != -1) |
| log << TestLog::Message << "\tNote: Inactive attribute with location." << TestLog::EndMessage; |
| |
| if (attrib.getCondition() != Cond::COND_NEVER && expectedLocation != Attribute::LOC_UNDEF && expectedLocation != location) |
| log << TestLog::Message << "\tError: Invalid attribute location." << TestLog::EndMessage; |
| |
| isOk &= (attrib.getCondition() == Cond::COND_NEVER || expectedLocation == Attribute::LOC_UNDEF || expectedLocation == location); |
| } |
| |
| return isOk; |
| } |
| |
| bool checkQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes, const map<string, deUint32>& bindings) |
| { |
| bool isOk = checkActiveAttribQuery(log, gl, program, attributes); |
| |
| if (!checkAttribLocationQuery(log, gl, program, attributes, bindings)) |
| isOk = false; |
| |
| return isOk; |
| } |
| |
| string generateTestName (const AttribType& type, int arraySize) |
| { |
| return type.getName() + (arraySize != Attribute::NOT_ARRAY ? "_array_" + de::toString(arraySize) : ""); |
| } |
| |
| } // anonymous |
| |
| namespace AttributeLocationTestUtil |
| { |
| |
| AttribType::AttribType (const string& name, deUint32 localSize, deUint32 typeEnum) |
| : m_name (name) |
| , m_locationSize (localSize) |
| , m_glTypeEnum (typeEnum) |
| { |
| } |
| |
| Cond::Cond (const string& name, bool negate) |
| : m_negate (negate) |
| , m_name (name) |
| { |
| } |
| |
| Cond::Cond (ConstCond cond) |
| : m_negate (cond != COND_NEVER) |
| , m_name ("__always__") |
| { |
| DE_ASSERT(cond == COND_ALWAYS || cond == COND_NEVER); |
| } |
| |
| Attribute::Attribute (const AttribType& type, const string& name, deInt32 layoutLocation, const Cond& cond, int arraySize) |
| : m_type (type) |
| , m_name (name) |
| , m_layoutLocation (layoutLocation) |
| , m_cond (cond) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| Bind::Bind (const std::string& attribute, deUint32 location) |
| : m_attribute (attribute) |
| , m_location (location) |
| { |
| } |
| |
| void runTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const vector<Attribute>& attributes, |
| const vector<Bind>& preAttachBind, |
| const vector<Bind>& preLinkBind, |
| const vector<Bind>& postLinkBind, |
| bool relink, |
| bool reattach = false, |
| const vector<Attribute>& reattachAttributes = vector<Attribute>()) |
| { |
| TestLog& log = testCtx.getLog(); |
| const glw::Functions& gl = renderCtx.getFunctions(); |
| deUint32 program = 0; |
| pair<deUint32, deUint32> shaders; |
| |
| try |
| { |
| bool isOk = true; |
| map<string, deUint32> activeBindings; |
| |
| for (int bindNdx = 0; bindNdx < (int)preAttachBind.size(); bindNdx++) |
| activeBindings[preAttachBind[bindNdx].getAttributeName()] = preAttachBind[bindNdx].getLocation(); |
| |
| for (int bindNdx = 0; bindNdx < (int)preLinkBind.size(); bindNdx++) |
| activeBindings[preLinkBind[bindNdx].getAttributeName()] = preLinkBind[bindNdx].getLocation(); |
| |
| { |
| tcu::ScopedLogSection section(log, "Attributes", "Attribute information"); |
| logAttributes(testCtx.getLog(), attributes); |
| } |
| |
| log << TestLog::Message << "Create program." << TestLog::EndMessage; |
| program = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram()"); |
| |
| if (!preAttachBind.empty()) |
| bindAttributes(log, gl, program, preAttachBind); |
| |
| log << TestLog::Message << "Create and attach shaders to program." << TestLog::EndMessage; |
| shaders = createAndAttachShaders(log, renderCtx, program, attributes, hasAttributeAliasing(attributes, activeBindings)); |
| |
| if (!preLinkBind.empty()) |
| bindAttributes(log, gl, program, preLinkBind); |
| |
| log << TestLog::Message << "Link program." << TestLog::EndMessage; |
| |
| gl.linkProgram(program); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()"); |
| |
| logProgram(log, gl, program); |
| TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed"); |
| |
| if (!checkQuery(log, gl, program, attributes, activeBindings)) |
| isOk = false; |
| |
| if (!postLinkBind.empty()) |
| { |
| bindAttributes(log, gl, program, postLinkBind); |
| |
| if (!checkQuery(log, gl, program, attributes, activeBindings)) |
| isOk = false; |
| } |
| |
| if (relink) |
| { |
| log << TestLog::Message << "Relink program." << TestLog::EndMessage; |
| gl.linkProgram(program); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()"); |
| |
| logProgram(log, gl, program); |
| TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed"); |
| |
| for (int bindNdx = 0; bindNdx < (int)postLinkBind.size(); bindNdx++) |
| activeBindings[postLinkBind[bindNdx].getAttributeName()] = postLinkBind[bindNdx].getLocation(); |
| |
| if (!checkQuery(log, gl, program, attributes, activeBindings)) |
| isOk = false; |
| } |
| |
| if (reattach) |
| { |
| gl.detachShader(program, shaders.first); |
| gl.detachShader(program, shaders.second); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader()"); |
| |
| log << TestLog::Message << "Create and attach shaders to program." << TestLog::EndMessage; |
| createAndAttachShaders(log, renderCtx, program, reattachAttributes, hasAttributeAliasing(reattachAttributes, activeBindings)); |
| |
| log << TestLog::Message << "Relink program." << TestLog::EndMessage; |
| gl.linkProgram(program); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()"); |
| |
| logProgram(log, gl, program); |
| TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed"); |
| |
| if (!checkQuery(log, gl, program, reattachAttributes, activeBindings)) |
| isOk = false; |
| } |
| |
| gl.deleteProgram(program); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()"); |
| |
| if (isOk) |
| testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| catch (...) |
| { |
| if (program) |
| gl.deleteProgram(program); |
| |
| throw; |
| } |
| } |
| |
| } // AttributeLocationTestUtil |
| |
| BindAttributeTest::BindAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(m_type, "a_0", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindMaxAttributesTest::BindMaxAttributesTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindMaxAttributesTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| int ndx = 0; |
| |
| m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage; |
| |
| for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize())) |
| { |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindAliasingAttributeTest::BindAliasingAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int offset, |
| int arraySize) |
| : TestCase (testCtx, ("cond_" + generateTestName(type, arraySize) + (offset != 0 ? "_offset_" + de::toString(offset) : "")).c_str(), |
| ("cond_" + generateTestName(type, arraySize) + (offset != 0 ? "_offset_" + de::toString(offset) : "")).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_offset (offset) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindAliasingAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(m_type, "a_0", Attribute::LOC_UNDEF, Cond("A", true), m_arraySize)); |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_1", Attribute::LOC_UNDEF, Cond("A", false))); |
| bindings.push_back(Bind("a_0", 1)); |
| bindings.push_back(Bind("a_1", 1 + m_offset)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindMaxAliasingAttributeTest::BindMaxAliasingAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, ("max_cond_" + generateTestName(type, arraySize)).c_str(), ("max_cond_" + generateTestName(type, arraySize)).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindMaxAliasingAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| int ndx = 0; |
| |
| m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage; |
| |
| for (int loc = maxAttributes - arrayElementCount * m_type.getLocationSize(); loc >= 0; loc -= m_type.getLocationSize() * arrayElementCount) |
| { |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond("A", true))); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx + maxAttributes), Attribute::LOC_UNDEF, Cond("A", false))); |
| bindings.push_back(Bind("a_" + de::toString(ndx + maxAttributes), loc)); |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindHoleAttributeTest::BindHoleAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindHoleAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| int ndx; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| bindings.push_back(Bind("a_0", 0)); |
| |
| attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| |
| ndx = 2; |
| for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) |
| { |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx))); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindInactiveAliasingAttributeTest::BindInactiveAliasingAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, ("max_inactive_" + generateTestName(type, arraySize)).c_str(), |
| ("max_inactive_" + generateTestName(type, arraySize)).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindInactiveAliasingAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| int ndx = 0; |
| |
| m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage; |
| |
| for (int loc = maxAttributes - arrayElementCount * m_type.getLocationSize(); loc >= 0; loc -= m_type.getLocationSize() * arrayElementCount) |
| { |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond("A"))); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx + maxAttributes), Attribute::LOC_UNDEF, Cond::COND_NEVER)); |
| bindings.push_back(Bind("a_" + de::toString(ndx + maxAttributes), loc)); |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| PreAttachBindAttributeTest::PreAttachBindAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "pre_attach", "pre_attach") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PreAttachBindAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0")); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, bindings, noBindings, noBindings, false); |
| return STOP; |
| } |
| |
| PreLinkBindAttributeTest::PreLinkBindAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "pre_link", "pre_link") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PreLinkBindAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0")); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| PostLinkBindAttributeTest::PostLinkBindAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "post_link", "post_link") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PostLinkBindAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0")); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, bindings, false); |
| return STOP; |
| } |
| |
| LocationAttributeTest::LocationAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult LocationAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| |
| attributes.push_back(Attribute(m_type, "a_0", 3, Cond::COND_ALWAYS, m_arraySize)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false); |
| return STOP; |
| } |
| |
| LocationMaxAttributesTest::LocationMaxAttributesTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult LocationMaxAttributesTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| int ndx = 0; |
| |
| m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage; |
| |
| for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize())) |
| { |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), loc, Cond::COND_ALWAYS, m_arraySize)); |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false); |
| return STOP; |
| } |
| |
| LocationHoleAttributeTest::LocationHoleAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult LocationHoleAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| int ndx; |
| |
| attributes.push_back(Attribute(vec4, "a_0", 0)); |
| |
| attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| |
| ndx = 2; |
| for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) |
| { |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc)); |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false); |
| return STOP; |
| } |
| |
| MixedAttributeTest::MixedAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Bind> bindings; |
| vector<Attribute> attributes; |
| |
| attributes.push_back(Attribute(m_type, "a_0", 3, Cond::COND_ALWAYS, m_arraySize)); |
| bindings.push_back(Bind("a_0", 4)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| MixedMaxAttributesTest::MixedMaxAttributesTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedMaxAttributesTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Bind> bindings; |
| vector<Attribute> attributes; |
| int ndx = 0; |
| |
| m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage; |
| |
| for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize())) |
| { |
| if ((ndx % 2) != 0) |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), loc, Cond::COND_ALWAYS, m_arraySize)); |
| else |
| { |
| attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| } |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| MixedHoleAttributeTest::MixedHoleAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedHoleAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Bind> bindings; |
| vector<Attribute> attributes; |
| int ndx; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| bindings.push_back(Bind("a_0", 0)); |
| |
| attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| |
| ndx = 2; |
| for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) |
| { |
| if ((ndx % 2) != 0) |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc)); |
| else |
| { |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc)); |
| bindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| } |
| ndx++; |
| } |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| BindRelinkAttributeTest::BindRelinkAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "relink", "relink") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindRelinkAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| |
| vector<Attribute> attributes; |
| vector<Bind> preLinkBindings; |
| vector<Bind> postLinkBindings; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| attributes.push_back(Attribute(vec4, "a_1")); |
| |
| preLinkBindings.push_back(Bind("a_0", 3)); |
| preLinkBindings.push_back(Bind("a_0", 5)); |
| |
| postLinkBindings.push_back(Bind("a_0", 6)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true); |
| return STOP; |
| } |
| |
| BindRelinkHoleAttributeTest::BindRelinkHoleAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindRelinkHoleAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const AttribType vec4 ("vec4", 1, GL_FLOAT_VEC4); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Attribute> attributes; |
| vector<Bind> preLinkBindings; |
| vector<Bind> postLinkBindings; |
| int ndx; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| preLinkBindings.push_back(Bind("a_0", 0)); |
| |
| attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| |
| ndx = 2; |
| for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) |
| { |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx))); |
| preLinkBindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| ndx++; |
| } |
| |
| postLinkBindings.push_back(Bind("a_2", 1)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true); |
| return STOP; |
| } |
| |
| MixedRelinkHoleAttributeTest::MixedRelinkHoleAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx, |
| const AttribType& type, |
| int arraySize) |
| : TestCase (testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str()) |
| , m_renderCtx (renderCtx) |
| , m_type (type) |
| , m_arraySize (arraySize) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedRelinkHoleAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const deInt32 maxAttributes = getMaxAttributeLocations(m_renderCtx); |
| const AttribType vec4 ("vec4", 1, GL_FLOAT_VEC4); |
| const int arrayElementCount = (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1); |
| |
| vector<Bind> preLinkBindings; |
| vector<Bind> postLinkBindings; |
| vector<Attribute> attributes; |
| int ndx; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| preLinkBindings.push_back(Bind("a_0", 0)); |
| |
| attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize)); |
| |
| ndx = 2; |
| for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) |
| { |
| if ((ndx % 2) != 0) |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc)); |
| else |
| { |
| attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx))); |
| preLinkBindings.push_back(Bind("a_" + de::toString(ndx), loc)); |
| |
| } |
| ndx++; |
| } |
| |
| postLinkBindings.push_back(Bind("a_2", 1)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true); |
| return STOP; |
| } |
| |
| BindReattachAttributeTest::BindReattachAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "reattach", "reattach") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult BindReattachAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| const AttribType vec2("vec2", 1, GL_FLOAT_VEC2); |
| |
| vector<Bind> bindings; |
| vector<Attribute> attributes; |
| vector<Attribute> reattachAttributes; |
| |
| attributes.push_back(Attribute(vec4, "a_0")); |
| bindings.push_back(Bind("a_0", 1)); |
| bindings.push_back(Bind("a_1", 1)); |
| |
| reattachAttributes.push_back(Attribute(vec2, "a_1")); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false, true, reattachAttributes); |
| return STOP; |
| } |
| |
| PreAttachMixedAttributeTest::PreAttachMixedAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "pre_attach", "pre_attach") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PreAttachMixedAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1)); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, bindings, noBindings, noBindings, false); |
| return STOP; |
| } |
| |
| PreLinkMixedAttributeTest::PreLinkMixedAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "pre_link", "pre_link") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PreLinkMixedAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1)); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false); |
| return STOP; |
| } |
| |
| PostLinkMixedAttributeTest::PostLinkMixedAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "post_link", "post_link") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult PostLinkMixedAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| |
| vector<Attribute> attributes; |
| vector<Bind> bindings; |
| |
| attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1)); |
| bindings.push_back(Bind("a_0", 3)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, bindings, false); |
| return STOP; |
| } |
| |
| MixedReattachAttributeTest::MixedReattachAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "reattach", "reattach") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedReattachAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| const AttribType vec2("vec2", 1, GL_FLOAT_VEC2); |
| |
| vector<Bind> bindings; |
| vector<Attribute> attributes; |
| vector<Attribute> reattachAttributes; |
| |
| attributes.push_back(Attribute(vec4, "a_0", 2)); |
| bindings.push_back(Bind("a_0", 1)); |
| bindings.push_back(Bind("a_1", 1)); |
| |
| reattachAttributes.push_back(Attribute(vec2, "a_1")); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false, true, reattachAttributes); |
| return STOP; |
| } |
| |
| MixedRelinkAttributeTest::MixedRelinkAttributeTest (tcu::TestContext& testCtx, |
| glu::RenderContext& renderCtx) |
| : TestCase (testCtx, "relink", "relink") |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| tcu::TestCase::IterateResult MixedRelinkAttributeTest::iterate (void) |
| { |
| const vector<Bind> noBindings; |
| const AttribType vec4("vec4", 1, GL_FLOAT_VEC4); |
| |
| vector<Attribute> attributes; |
| vector<Bind> preLinkBindings; |
| vector<Bind> postLinkBindings; |
| |
| attributes.push_back(Attribute(vec4, "a_0", 1)); |
| attributes.push_back(Attribute(vec4, "a_1")); |
| |
| preLinkBindings.push_back(Bind("a_0", 3)); |
| preLinkBindings.push_back(Bind("a_0", 5)); |
| |
| postLinkBindings.push_back(Bind("a_0", 6)); |
| |
| runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true); |
| return STOP; |
| } |
| |
| } // gls |
| } // deqp |