1538 lines
48 KiB
C++
1538 lines
48 KiB
C++
/*-------------------------------------------------------------------------
|
|
* 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
|