Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) Module
      3  * -----------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Attribute location tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsAttributeLocationTests.hpp"
     25 
     26 #include "tcuStringTemplate.hpp"
     27 #include "tcuTestLog.hpp"
     28 
     29 #include "gluDefs.hpp"
     30 #include "gluRenderContext.hpp"
     31 #include "gluShaderProgram.hpp"
     32 #include "gluShaderUtil.hpp"
     33 #include "gluStrUtil.hpp"
     34 
     35 #include "glwFunctions.hpp"
     36 
     37 #include "deStringUtil.hpp"
     38 
     39 #include <map>
     40 #include <set>
     41 #include <sstream>
     42 #include <string>
     43 #include <vector>
     44 
     45 #include <cstring>
     46 
     47 #include "glw.h"
     48 
     49 using tcu::TestLog;
     50 
     51 using std::string;
     52 using std::vector;
     53 using std::set;
     54 using std::map;
     55 using std::pair;
     56 
     57 using namespace deqp::gls::AttributeLocationTestUtil;
     58 
     59 namespace deqp
     60 {
     61 namespace gls
     62 {
     63 namespace
     64 {
     65 
     66 deInt32 getBoundLocation (const map<string, deUint32>& bindings, const string& attrib)
     67 {
     68 	std::map<string, deUint32>::const_iterator iter = bindings.find(attrib);
     69 
     70 	return (iter == bindings.end() ? (deInt32)Attribute::LOC_UNDEF : iter->second);
     71 }
     72 
     73 bool hasAttributeAliasing (const vector<Attribute>& attributes, const map<string, deUint32>& bindings)
     74 {
     75 	vector<bool> reservedSpaces;
     76 
     77 	for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++)
     78 	{
     79 		const deInt32	location	= getBoundLocation(bindings, attributes[attribNdx].getName());
     80 		const deUint32	size		= attributes[attribNdx].getType().getLocationSize();
     81 
     82 		if (location != Attribute::LOC_UNDEF)
     83 		{
     84 			if (reservedSpaces.size() < location + size)
     85 				reservedSpaces.resize(location + size, false);
     86 
     87 			for (int i = 0; i < (int)size; i++)
     88 			{
     89 				if (reservedSpaces[location + i])
     90 					return true;
     91 
     92 				reservedSpaces[location + i] = true;
     93 			}
     94 		}
     95 	}
     96 
     97 	return false;
     98 }
     99 
    100 deInt32 getMaxAttributeLocations (glu::RenderContext& renderCtx)
    101 {
    102 	const glw::Functions& gl = renderCtx.getFunctions();
    103 	deInt32 maxAttribs;
    104 
    105 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
    106 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
    107 
    108 	return maxAttribs;
    109 }
    110 
    111 string generateAttributeDefinitions (const vector<Attribute>& attributes)
    112 {
    113 	std::ostringstream src;
    114 
    115 	for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    116 	{
    117 		if (iter->getLayoutLocation() != Attribute::LOC_UNDEF)
    118 			src << "layout(location = " << iter->getLayoutLocation() << ") ";
    119 
    120 		src << "${VTX_INPUT} mediump "
    121 			<< iter->getType().getName() << " "
    122 			<< iter->getName()
    123 			<<  (iter->getArraySize() != Attribute::NOT_ARRAY ? "[" + de::toString(iter->getArraySize()) + "]" : "") << ";\n";
    124 	}
    125 
    126 	return src.str();
    127 }
    128 
    129 string generateConditionUniformDefinitions (const vector<Attribute>& attributes)
    130 {
    131 	std::ostringstream src;
    132 	set<string> conditions;
    133 
    134 	for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    135 	{
    136 		if (iter->getCondition() != Cond::COND_NEVER && iter->getCondition() != Cond::COND_ALWAYS)
    137 			conditions.insert(iter->getCondition().getName());
    138 	}
    139 
    140 	for (set<string>::const_iterator iter = conditions.begin(); iter != conditions.end(); ++iter)
    141 			src << "uniform mediump float u_" << (*iter) << ";\n";
    142 
    143 	return src.str();
    144 }
    145 
    146 string generateToVec4Expression (const Attribute& attrib, int id=-1)
    147 {
    148 	const string		variableName(attrib.getName() + (attrib.getArraySize() != Attribute::NOT_ARRAY ? "[" + de::toString(id) + "]" : ""));
    149 	std::ostringstream	src;
    150 
    151 	switch (attrib.getType().getGLTypeEnum())
    152 	{
    153 		case GL_INT_VEC2:
    154 		case GL_UNSIGNED_INT_VEC2:
    155 		case GL_FLOAT_VEC2:
    156 			src << "vec4(" << variableName << ".xy, " << variableName << ".yx)";
    157 			break;
    158 
    159 		case GL_INT_VEC3:
    160 		case GL_UNSIGNED_INT_VEC3:
    161 		case GL_FLOAT_VEC3:
    162 			src << "vec4(" << variableName << ".xyz, " << variableName << ".x)";
    163 			break;
    164 
    165 		default:
    166 			src << "vec4(" << variableName << ")";
    167 			break;
    168 	}
    169 
    170 	return src.str();
    171 }
    172 
    173 string generateOutputCode (const vector<Attribute>& attributes)
    174 {
    175 	std::ostringstream src;
    176 
    177 	for (vector<Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    178 	{
    179 		if (iter->getCondition() == Cond::COND_NEVER)
    180 		{
    181 			src <<
    182 			"\tif (0 != 0)\n"
    183 			"\t{\n";
    184 
    185 			if (iter->getArraySize() == Attribute::NOT_ARRAY)
    186 				src << "\t\tcolor += " << generateToVec4Expression(*iter) << ";\n";
    187 			else
    188 			{
    189 				for (int i = 0; i < iter->getArraySize(); i++)
    190 					src << "\t\tcolor += " << generateToVec4Expression(*iter, i) << ";\n";
    191 			}
    192 
    193 			src << "\t}\n";
    194 		}
    195 		else if (iter->getCondition() == Cond::COND_ALWAYS)
    196 		{
    197 			if (iter->getArraySize() == Attribute::NOT_ARRAY)
    198 				src << "\tcolor += " << generateToVec4Expression(*iter) << ";\n";
    199 			else
    200 			{
    201 				for (int i = 0; i < iter->getArraySize(); i++)
    202 					src << "\tcolor += " << generateToVec4Expression(*iter, i) << ";\n";
    203 			}
    204 		}
    205 		else
    206 		{
    207 			src <<
    208 			"\tif (u_" << iter->getCondition().getName() << (iter->getCondition().getNegate() ? " != " : " == ") << "0.0)\n"
    209 			"\t{\n";
    210 
    211 			if (iter->getArraySize() == Attribute::NOT_ARRAY)
    212 				src << "\t\tcolor += " << generateToVec4Expression(*iter) << ";\n";
    213 			else
    214 			{
    215 				for (int i = 0; i < iter->getArraySize(); i++)
    216 					src << "\t\tcolor += " << generateToVec4Expression(*iter, i) << ";\n";
    217 			}
    218 
    219 			src <<
    220 			"\t}\n";
    221 		}
    222 	}
    223 
    224 	return src.str();
    225 }
    226 
    227 string generateVertexShaderTemplate (const vector<Attribute>& attributes)
    228 {
    229 	std::ostringstream src;
    230 
    231 	src <<	"${VERSION}\n"
    232 			"${VTX_OUTPUT} mediump vec4 v_color;\n";
    233 
    234 	src << generateAttributeDefinitions(attributes)
    235 		<< "\n"
    236 		<< generateConditionUniformDefinitions(attributes)
    237 		<< "\n";
    238 
    239 	src <<	"void main (void)\n"
    240 			"{\n"
    241 			"\tmediump vec4 color = vec4(0.0);\n"
    242 			"\n";
    243 
    244 	src << generateOutputCode(attributes);
    245 
    246 	src <<	"\n"
    247 			"\tv_color = color;\n"
    248 			"\tgl_Position = color;\n"
    249 			"}\n";
    250 
    251 	return src.str();
    252 }
    253 
    254 string createVertexShaderSource (glu::RenderContext& renderCtx, const vector<Attribute>& attributes, bool attributeAliasing)
    255 {
    256 	// \note On GLES only GLSL #version 100 supports aliasing
    257 	const glu::GLSLVersion		contextGLSLVersion		= glu::getContextTypeGLSLVersion(renderCtx.getType());
    258 	const glu::GLSLVersion		glslVersion				= (attributeAliasing && glu::glslVersionIsES(contextGLSLVersion) ? glu::GLSL_VERSION_100_ES : contextGLSLVersion);
    259 	const bool					usesInOutQualifiers		= glu::glslVersionUsesInOutQualifiers(glslVersion);
    260 	const tcu::StringTemplate	vertexShaderTemplate(generateVertexShaderTemplate(attributes));
    261 
    262 	map<string, string> parameters;
    263 
    264 	parameters["VERSION"]					= glu::getGLSLVersionDeclaration(glslVersion);
    265 	parameters["VTX_OUTPUT"]				= (usesInOutQualifiers ? "out"				: "varying");
    266 	parameters["VTX_INPUT"]					= (usesInOutQualifiers ? "in"				: "attribute");
    267 	parameters["FRAG_INPUT"]				= (usesInOutQualifiers ? "in"				: "varying");
    268 	parameters["FRAG_OUTPUT_VAR"]			= (usesInOutQualifiers ? "dEQP_FragColor"	: "gl_FragColor");
    269 	parameters["FRAG_OUTPUT_DECLARATION"]	= (usesInOutQualifiers
    270 													? "layout(location=0) out mediump vec4 dEQP_FragColor;"
    271 													: "");
    272 
    273 	return vertexShaderTemplate.specialize(parameters);
    274 }
    275 
    276 string createFragmentShaderSource (glu::RenderContext& renderCtx, bool attributeAliasing)
    277 {
    278 	const char* const fragmentShaderSource =
    279 		"${VERSION}\n"
    280 		"${FRAG_OUTPUT_DECLARATION}\n"
    281 		"${FRAG_INPUT} mediump vec4 v_color;\n"
    282 		"void main (void)\n"
    283 		"{\n"
    284 		"\t${FRAG_OUTPUT_VAR} = v_color;\n"
    285 		"}\n";
    286 
    287 	// \note On GLES only GLSL #version 100 supports aliasing
    288 	const glu::GLSLVersion		contextGLSLVersion		= glu::getContextTypeGLSLVersion(renderCtx.getType());
    289 	const glu::GLSLVersion		glslVersion				= (attributeAliasing && glu::glslVersionIsES(contextGLSLVersion) ? glu::GLSL_VERSION_100_ES : contextGLSLVersion);
    290 	const tcu::StringTemplate	fragmentShaderTemplate(fragmentShaderSource);
    291 	const bool					usesInOutQualifiers		= glu::glslVersionUsesInOutQualifiers(glslVersion);
    292 
    293 	map<string, string> parameters;
    294 
    295 	parameters["VERSION"]					= glu::getGLSLVersionDeclaration(glslVersion);
    296 	parameters["VTX_OUTPUT"]				= (usesInOutQualifiers ? "out"				: "varying");
    297 	parameters["VTX_INPUT"]					= (usesInOutQualifiers ? "in"				: "attribute");
    298 	parameters["FRAG_INPUT"]				= (usesInOutQualifiers ? "in"				: "varying");
    299 	parameters["FRAG_OUTPUT_VAR"]			= (usesInOutQualifiers ? "dEQP_FragColor"	: "gl_FragColor");
    300 	parameters["FRAG_OUTPUT_DECLARATION"]	= (usesInOutQualifiers
    301 													? "layout(location=0) out mediump vec4 dEQP_FragColor;"
    302 													: "");
    303 
    304 	return fragmentShaderTemplate.specialize(parameters);
    305 }
    306 
    307 string getShaderInfoLog (const glw::Functions& gl, deUint32 shader)
    308 {
    309 	deInt32	length = 0;
    310 	string	infoLog;
    311 
    312 	gl.getShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
    313 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
    314 
    315 	infoLog.resize(length, '\0');
    316 
    317 	gl.getShaderInfoLog(shader, (glw::GLsizei)infoLog.length(), DE_NULL, &(infoLog[0]));
    318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()");
    319 
    320 	return infoLog;
    321 }
    322 
    323 bool getShaderCompileStatus (const glw::Functions& gl, deUint32 shader)
    324 {
    325 	deInt32 status;
    326 
    327 	gl.getShaderiv(shader, GL_COMPILE_STATUS, &status);
    328 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
    329 
    330 	return status == GL_TRUE;
    331 }
    332 
    333 string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
    334 {
    335 	deInt32	length = 0;
    336 	string	infoLog;
    337 
    338 	gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &length);
    339 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
    340 
    341 	infoLog.resize(length, '\0');
    342 
    343 	gl.getProgramInfoLog(program, (glw::GLsizei)infoLog.length(), DE_NULL, &(infoLog[0]));
    344 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()");
    345 
    346 	return infoLog;
    347 }
    348 
    349 bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
    350 {
    351 	deInt32 status;
    352 
    353 	gl.getProgramiv(program, GL_LINK_STATUS, &status);
    354 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
    355 
    356 	return status == GL_TRUE;
    357 }
    358 
    359 void logProgram (TestLog& log, const glw::Functions& gl, deUint32 program)
    360 {
    361 	const bool				programLinkOk	= getProgramLinkStatus(gl, program);
    362 	const string			programInfoLog	= getProgramInfoLog(gl, program);
    363 	tcu::ScopedLogSection	linkInfo		(log, "Program Link Info", "Program Link Info");
    364 
    365 	{
    366 		tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log");
    367 
    368 		log << TestLog::Message << programInfoLog << TestLog::EndMessage;
    369 	}
    370 
    371 	log << TestLog::Message << "Link result: " << (programLinkOk ? "Ok" : "Fail") << TestLog::EndMessage;
    372 }
    373 
    374 void logShaders (TestLog&		log,
    375 				const string&	vertexShaderSource,
    376 				const string&	vertexShaderInfoLog,
    377 				bool			vertexCompileOk,
    378 				const string&	fragmentShaderSource,
    379 				const string&	fragmentShaderInfoLog,
    380 				bool			fragmentCompileOk)
    381 {
    382 	// \todo [mika] Log as real shader elements. Currently not supported by TestLog.
    383 	{
    384 		tcu::ScopedLogSection shaderSection(log, "Vertex Shader Info", "Vertex Shader Info");
    385 
    386 		log << TestLog::KernelSource(vertexShaderSource);
    387 
    388 		{
    389 			tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log");
    390 
    391 			log << TestLog::Message << vertexShaderInfoLog << TestLog::EndMessage;
    392 		}
    393 
    394 		log << TestLog::Message << "Compilation result: " << (vertexCompileOk ? "Ok" : "Failed") << TestLog::EndMessage;
    395 	}
    396 
    397 	{
    398 		tcu::ScopedLogSection shaderSection(log, "Fragment Shader Info", "Fragment Shader Info");
    399 
    400 		log << TestLog::KernelSource(fragmentShaderSource);
    401 
    402 		{
    403 			tcu::ScopedLogSection infoLogSection(log, "Info Log", "Info Log");
    404 
    405 			log << TestLog::Message << fragmentShaderInfoLog << TestLog::EndMessage;
    406 		}
    407 
    408 		log << TestLog::Message << "Compilation result: " << (fragmentCompileOk ? "Ok" : "Failed") << TestLog::EndMessage;
    409 	}
    410 }
    411 
    412 pair<deUint32, deUint32> createAndAttachShaders (TestLog& log, glu::RenderContext& renderCtx, deUint32 program, const vector<Attribute>& attributes, bool attributeAliasing)
    413 {
    414 	const glw::Functions&	gl						= renderCtx.getFunctions();
    415 	const string			vertexShaderSource		= createVertexShaderSource(renderCtx, attributes, attributeAliasing);
    416 	const string			fragmentShaderSource	= createFragmentShaderSource(renderCtx, attributeAliasing);
    417 
    418 	const deUint32			vertexShader			= gl.createShader(GL_VERTEX_SHADER);
    419 	const deUint32			fragmentShader			= gl.createShader(GL_FRAGMENT_SHADER);
    420 
    421 	try
    422 	{
    423 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader()");
    424 
    425 		{
    426 			const char* const vertexShaderString	= vertexShaderSource.c_str();
    427 			const char* const fragmentShaderString	= fragmentShaderSource.c_str();
    428 
    429 			gl.shaderSource(vertexShader, 1, &vertexShaderString, DE_NULL);
    430 			gl.shaderSource(fragmentShader, 1, &fragmentShaderString, DE_NULL);
    431 
    432 			GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
    433 		}
    434 
    435 		gl.compileShader(vertexShader);
    436 		gl.compileShader(fragmentShader);
    437 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
    438 
    439 		gl.attachShader(program, vertexShader);
    440 		gl.attachShader(program, fragmentShader);
    441 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
    442 
    443 		{
    444 			const bool		vertexCompileOk			= getShaderCompileStatus(gl, vertexShader);
    445 			const bool		fragmentCompileOk		= getShaderCompileStatus(gl, fragmentShader);
    446 
    447 			const string	vertexShaderInfoLog		= getShaderInfoLog(gl, vertexShader);
    448 			const string	fragmentShaderInfoLog	= getShaderInfoLog(gl, fragmentShader);
    449 
    450 			logShaders(log, vertexShaderSource, vertexShaderInfoLog, vertexCompileOk, fragmentShaderSource, fragmentShaderInfoLog, fragmentCompileOk);
    451 
    452 			TCU_CHECK_MSG(vertexCompileOk, "Vertex shader compilation failed");
    453 			TCU_CHECK_MSG(fragmentCompileOk, "Fragment shader compilation failed");
    454 		}
    455 
    456 		gl.deleteShader(vertexShader);
    457 		gl.deleteShader(fragmentShader);
    458 
    459 		return pair<deUint32, deUint32>(vertexShader, fragmentShader);
    460 	}
    461 	catch (...)
    462 	{
    463 		if (vertexShader != 0)
    464 			gl.deleteShader(vertexShader);
    465 
    466 		if (fragmentShader != 0)
    467 			gl.deleteShader(fragmentShader);
    468 
    469 		throw;
    470 	}
    471 }
    472 
    473 void bindAttributes (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Bind>& binds)
    474 {
    475 	for (vector<Bind>::const_iterator iter = binds.begin(); iter != binds.end(); ++iter)
    476 	{
    477 		log << TestLog::Message << "Bind attribute: '" << iter->getAttributeName() << "' to " << iter->getLocation() << TestLog::EndMessage;
    478 		gl.bindAttribLocation(program, iter->getLocation(), iter->getAttributeName().c_str());
    479 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation()");
    480 	}
    481 }
    482 
    483 void logAttributes (TestLog& log, const vector<Attribute>& attributes)
    484 {
    485 	for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++)
    486 	{
    487 		const Attribute& attrib = attributes[attribNdx];
    488 
    489 		log << TestLog::Message
    490 			<< "Type: " << attrib.getType().getName()
    491 			<< ", Name: " << attrib.getName()
    492 			<< (attrib.getLayoutLocation()	!= Attribute::LOC_UNDEF ? ", Layout location "	+ de::toString(attrib.getLayoutLocation()) : "")
    493 			<< TestLog::EndMessage;
    494 	}
    495 }
    496 
    497 bool checkActiveAttribQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes)
    498 {
    499 	deInt32					activeAttribCount = 0;
    500 	set<string>				activeAttributes;
    501 	bool					isOk = true;
    502 
    503 	gl.getProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount);
    504 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount)");
    505 
    506 	for (int activeAttribNdx = 0; activeAttribNdx < activeAttribCount; activeAttribNdx++)
    507 	{
    508 		char			name[128];
    509 		const size_t	maxNameSize = DE_LENGTH_OF_ARRAY(name) - 1;
    510 		deInt32			length = 0;
    511 		deInt32			size = 0;
    512 		deUint32		type = 0;
    513 
    514 		std::memset(name, 0, sizeof(name));
    515 
    516 		gl.getActiveAttrib(program, activeAttribNdx, maxNameSize, &length, &size, &type, name);
    517 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveAttrib()");
    518 
    519 		log << TestLog::Message
    520 			<< "glGetActiveAttrib(program"
    521 			<< ", index=" << activeAttribNdx
    522 			<< ", bufSize=" << maxNameSize
    523 			<< ", length=" << length
    524 			<< ", size=" << size
    525 			<< ", type=" << glu::getShaderVarTypeStr(type)
    526 			<< ", name='" << name << "')" << TestLog::EndMessage;
    527 
    528 		{
    529 			bool found = false;
    530 
    531 			for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++)
    532 			{
    533 				const Attribute& attrib = attributes[attribNdx];
    534 
    535 				if (attrib.getName() == name)
    536 				{
    537 					if (type != attrib.getType().getGLTypeEnum())
    538 					{
    539 						log << TestLog::Message
    540 							<< "Error: Wrong type " << glu::getShaderVarTypeStr(type)
    541 							<< " expected " << glu::getShaderVarTypeStr(attrib.getType().getGLTypeEnum())
    542 							<< TestLog::EndMessage;
    543 
    544 						isOk = false;
    545 					}
    546 
    547 					if (attrib.getArraySize() == Attribute::NOT_ARRAY)
    548 					{
    549 						if (size != 1)
    550 						{
    551 							log << TestLog::Message << "Error: Wrong size " << size << " expected " << 1 << TestLog::EndMessage;
    552 							isOk = false;
    553 						}
    554 					}
    555 					else
    556 					{
    557 						if (size != attrib.getArraySize())
    558 						{
    559 							log << TestLog::Message << "Error: Wrong size " << size << " expected " << attrib.getArraySize() << TestLog::EndMessage;
    560 							isOk = false;
    561 						}
    562 					}
    563 
    564 					found = true;
    565 					break;
    566 				}
    567 			}
    568 
    569 			if (!found)
    570 			{
    571 				log << TestLog::Message << "Error: Unknown attribute '" << name << "' returned by glGetActiveAttrib()." << TestLog::EndMessage;
    572 				isOk = false;
    573 			}
    574 		}
    575 
    576 		activeAttributes.insert(name);
    577 	}
    578 
    579 	for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++)
    580 	{
    581 		const Attribute&	attrib		= attributes[attribNdx];
    582 		const bool			isActive	= attrib.getCondition() != Cond::COND_NEVER;
    583 
    584 		if (isActive)
    585 		{
    586 			if (activeAttributes.find(attrib.getName()) == activeAttributes.end())
    587 			{
    588 				log << TestLog::Message << "Error: Active attribute " << attrib.getName() << " wasn't returned by glGetActiveAttrib()." << TestLog::EndMessage;
    589 				isOk = false;
    590 			}
    591 		}
    592 		else
    593 		{
    594 			if (activeAttributes.find(attrib.getName()) != activeAttributes.end())
    595 				log << TestLog::Message << "Note: Inactive attribute " << attrib.getName() << " was returned by glGetActiveAttrib()." << TestLog::EndMessage;
    596 		}
    597 	}
    598 
    599 	return isOk;
    600 }
    601 
    602 bool checkAttribLocationQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes, const map<string, deUint32>& bindings)
    603 {
    604 	bool isOk = true;
    605 
    606 	for (int attribNdx = 0; attribNdx < (int)attributes.size(); attribNdx++)
    607 	{
    608 		const Attribute&	attrib				= attributes[attribNdx];
    609 		const deInt32		expectedLocation	= (attrib.getLayoutLocation() != Attribute::LOC_UNDEF ? attrib.getLayoutLocation() : getBoundLocation(bindings, attrib.getName()));
    610 		const deInt32		location			= gl.getAttribLocation(program, attrib.getName().c_str());
    611 
    612 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation()");
    613 
    614 		log << TestLog::Message
    615 			<< location << " = glGetAttribLocation(program, \"" << attrib.getName() << "\")"
    616 			<< (attrib.getCondition() != Cond::COND_NEVER && expectedLocation != Attribute::LOC_UNDEF ? ", expected " + de::toString(expectedLocation) : "")
    617 			<< "." << TestLog::EndMessage;
    618 
    619 		if (attrib.getCondition() == Cond::COND_NEVER && location != -1)
    620 			log << TestLog::Message << "\tNote: Inactive attribute with location." << TestLog::EndMessage;
    621 
    622 		if (attrib.getCondition() != Cond::COND_NEVER && expectedLocation != Attribute::LOC_UNDEF && expectedLocation != location)
    623 			log << TestLog::Message << "\tError: Invalid attribute location." << TestLog::EndMessage;
    624 
    625 		isOk &= (attrib.getCondition() == Cond::COND_NEVER || expectedLocation == Attribute::LOC_UNDEF || expectedLocation == location);
    626 	}
    627 
    628 	return isOk;
    629 }
    630 
    631 bool checkQuery (TestLog& log, const glw::Functions& gl, deUint32 program, const vector<Attribute>& attributes, const map<string, deUint32>& bindings)
    632 {
    633 	bool isOk = checkActiveAttribQuery(log, gl, program, attributes);
    634 
    635 	if (!checkAttribLocationQuery(log, gl, program, attributes, bindings))
    636 		isOk = false;
    637 
    638 	return isOk;
    639 }
    640 
    641 string generateTestName (const AttribType& type, int arraySize)
    642 {
    643 	return type.getName() + (arraySize != Attribute::NOT_ARRAY ? "_array_" + de::toString(arraySize) : "");
    644 }
    645 
    646 } // anonymous
    647 
    648 namespace AttributeLocationTestUtil
    649 {
    650 
    651 AttribType::AttribType (const string& name, deUint32 localSize, deUint32 typeEnum)
    652 	: m_name			(name)
    653 	, m_locationSize	(localSize)
    654 	, m_glTypeEnum		(typeEnum)
    655 {
    656 }
    657 
    658 Cond::Cond (const string& name, bool negate)
    659 	: m_negate	(negate)
    660 	, m_name	(name)
    661 {
    662 }
    663 
    664 Cond::Cond (ConstCond cond)
    665 	: m_negate	(cond != COND_NEVER)
    666 	, m_name	("__always__")
    667 {
    668 	DE_ASSERT(cond == COND_ALWAYS || cond == COND_NEVER);
    669 }
    670 
    671 Attribute::Attribute (const AttribType& type, const string& name, deInt32 layoutLocation, const Cond& cond, int arraySize)
    672 	: m_type			(type)
    673 	, m_name			(name)
    674 	, m_layoutLocation	(layoutLocation)
    675 	, m_cond			(cond)
    676 	, m_arraySize		(arraySize)
    677 {
    678 }
    679 
    680 Bind::Bind (const std::string& attribute, deUint32 location)
    681 	: m_attribute	(attribute)
    682 	, m_location	(location)
    683 {
    684 }
    685 
    686 void runTest (tcu::TestContext&			testCtx,
    687 			glu::RenderContext&			renderCtx,
    688 			const vector<Attribute>&	attributes,
    689 			const vector<Bind>&			preAttachBind,
    690 			const vector<Bind>&			preLinkBind,
    691 			const vector<Bind>&			postLinkBind,
    692 			bool						relink,
    693 			bool						reattach = false,
    694 			const vector<Attribute>&	reattachAttributes = vector<Attribute>())
    695 {
    696 	TestLog&					log			= testCtx.getLog();
    697 	const glw::Functions&		gl			= renderCtx.getFunctions();
    698 	deUint32					program 	= 0;
    699 	pair<deUint32, deUint32>	shaders;
    700 
    701 	try
    702 	{
    703 		bool					isOk			= true;
    704 		map<string, deUint32>	activeBindings;
    705 
    706 		for (int bindNdx = 0; bindNdx < (int)preAttachBind.size(); bindNdx++)
    707 			activeBindings[preAttachBind[bindNdx].getAttributeName()] = preAttachBind[bindNdx].getLocation();
    708 
    709 		for (int bindNdx = 0; bindNdx < (int)preLinkBind.size(); bindNdx++)
    710 			activeBindings[preLinkBind[bindNdx].getAttributeName()] = preLinkBind[bindNdx].getLocation();
    711 
    712 		{
    713 			tcu::ScopedLogSection section(log, "Attributes", "Attribute information");
    714 			logAttributes(testCtx.getLog(), attributes);
    715 		}
    716 
    717 		log << TestLog::Message << "Create program." << TestLog::EndMessage;
    718 		program = gl.createProgram();
    719 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram()");
    720 
    721 		if (!preAttachBind.empty())
    722 			bindAttributes(log, gl, program, preAttachBind);
    723 
    724 		log << TestLog::Message << "Create and attach shaders to program." << TestLog::EndMessage;
    725 		shaders = createAndAttachShaders(log, renderCtx, program, attributes, hasAttributeAliasing(attributes, activeBindings));
    726 
    727 		if (!preLinkBind.empty())
    728 			bindAttributes(log, gl, program, preLinkBind);
    729 
    730 		log << TestLog::Message << "Link program." << TestLog::EndMessage;
    731 
    732 		gl.linkProgram(program);
    733 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
    734 
    735 		logProgram(log, gl, program);
    736 		TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed");
    737 
    738 		if (!checkQuery(log, gl, program, attributes, activeBindings))
    739 			isOk = false;
    740 
    741 		if (!postLinkBind.empty())
    742 		{
    743 			bindAttributes(log, gl, program, postLinkBind);
    744 
    745 			if (!checkQuery(log, gl, program, attributes, activeBindings))
    746 				isOk = false;
    747 		}
    748 
    749 		if (relink)
    750 		{
    751 			log << TestLog::Message << "Relink program." << TestLog::EndMessage;
    752 			gl.linkProgram(program);
    753 			GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
    754 
    755 			logProgram(log, gl, program);
    756 			TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed");
    757 
    758 			for (int bindNdx = 0; bindNdx < (int)postLinkBind.size(); bindNdx++)
    759 				activeBindings[postLinkBind[bindNdx].getAttributeName()] = postLinkBind[bindNdx].getLocation();
    760 
    761 			if (!checkQuery(log, gl, program, attributes, activeBindings))
    762 				isOk = false;
    763 		}
    764 
    765 		if (reattach)
    766 		{
    767 			gl.detachShader(program, shaders.first);
    768 			gl.detachShader(program, shaders.second);
    769 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader()");
    770 
    771 			log << TestLog::Message << "Create and attach shaders to program." << TestLog::EndMessage;
    772 			createAndAttachShaders(log, renderCtx, program, reattachAttributes, hasAttributeAliasing(reattachAttributes, activeBindings));
    773 
    774 			log << TestLog::Message << "Relink program." << TestLog::EndMessage;
    775 			gl.linkProgram(program);
    776 			GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
    777 
    778 			logProgram(log, gl, program);
    779 			TCU_CHECK_MSG(getProgramLinkStatus(gl, program), "Program link failed");
    780 
    781 			if (!checkQuery(log, gl, program, reattachAttributes, activeBindings))
    782 				isOk = false;
    783 		}
    784 
    785 		gl.deleteProgram(program);
    786 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
    787 
    788 		if (isOk)
    789 			testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    790 		else
    791 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    792 	}
    793 	catch (...)
    794 	{
    795 		if (program)
    796 			gl.deleteProgram(program);
    797 
    798 		throw;
    799 	}
    800 }
    801 
    802 } // AttributeLocationTestUtil
    803 
    804 BindAttributeTest::BindAttributeTest (tcu::TestContext&		testCtx,
    805 									  glu::RenderContext&	renderCtx,
    806 									  const AttribType&		type,
    807 									  int					arraySize)
    808 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
    809 	, m_renderCtx	(renderCtx)
    810 	, m_type		(type)
    811 	, m_arraySize	(arraySize)
    812 {
    813 }
    814 
    815 tcu::TestCase::IterateResult BindAttributeTest::iterate (void)
    816 {
    817 	const vector<Bind>	noBindings;
    818 
    819 	vector<Attribute>	attributes;
    820 	vector<Bind>		bindings;
    821 
    822 	attributes.push_back(Attribute(m_type, "a_0", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
    823 	bindings.push_back(Bind("a_0", 3));
    824 
    825 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
    826 	return STOP;
    827 }
    828 
    829 BindMaxAttributesTest::BindMaxAttributesTest (tcu::TestContext&		testCtx,
    830 											  glu::RenderContext&	renderCtx,
    831 											  const AttribType&		type,
    832 											  int					arraySize)
    833 	: TestCase		(testCtx,  generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
    834 	, m_renderCtx	(renderCtx)
    835 	, m_type		(type)
    836 	, m_arraySize	(arraySize)
    837 {
    838 }
    839 
    840 tcu::TestCase::IterateResult BindMaxAttributesTest::iterate (void)
    841 {
    842 	const vector<Bind>	noBindings;
    843 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
    844 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
    845 
    846 	vector<Attribute>	attributes;
    847 	vector<Bind>		bindings;
    848 	int					ndx = 0;
    849 
    850 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage;
    851 
    852 	for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize()))
    853 	{
    854 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
    855 		bindings.push_back(Bind("a_" + de::toString(ndx), loc));
    856 		ndx++;
    857 	}
    858 
    859 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
    860 	return STOP;
    861 }
    862 
    863 BindAliasingAttributeTest::BindAliasingAttributeTest (tcu::TestContext&		testCtx,
    864 													  glu::RenderContext&	renderCtx,
    865 													  const AttribType&		type,
    866 													  int					offset,
    867 													  int					arraySize)
    868 	: TestCase		(testCtx,	("cond_" + generateTestName(type, arraySize) + (offset != 0 ? "_offset_" + de::toString(offset) : "")).c_str(),
    869 								("cond_" + generateTestName(type, arraySize) + (offset != 0 ? "_offset_" + de::toString(offset) : "")).c_str())
    870 	, m_renderCtx	(renderCtx)
    871 	, m_type		(type)
    872 	, m_offset		(offset)
    873 	, m_arraySize	(arraySize)
    874 {
    875 }
    876 
    877 tcu::TestCase::IterateResult BindAliasingAttributeTest::iterate (void)
    878 {
    879 	const vector<Bind>	noBindings;
    880 
    881 	vector<Attribute>	attributes;
    882 	vector<Bind>		bindings;
    883 
    884 	attributes.push_back(Attribute(m_type, "a_0", Attribute::LOC_UNDEF, Cond("A", true), m_arraySize));
    885 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_1", Attribute::LOC_UNDEF, Cond("A", false)));
    886 	bindings.push_back(Bind("a_0", 1));
    887 	bindings.push_back(Bind("a_1", 1 + m_offset));
    888 
    889 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
    890 	return STOP;
    891 }
    892 
    893 BindMaxAliasingAttributeTest::BindMaxAliasingAttributeTest (tcu::TestContext&	testCtx,
    894 															glu::RenderContext&	renderCtx,
    895 															const AttribType&	type,
    896 															int					arraySize)
    897 	: TestCase		(testCtx, ("max_cond_" + generateTestName(type, arraySize)).c_str(), ("max_cond_" + generateTestName(type, arraySize)).c_str())
    898 	, m_renderCtx	(renderCtx)
    899 	, m_type		(type)
    900 	, m_arraySize	(arraySize)
    901 {
    902 }
    903 
    904 tcu::TestCase::IterateResult BindMaxAliasingAttributeTest::iterate (void)
    905 {
    906 	const vector<Bind>	noBindings;
    907 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
    908 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
    909 
    910 	vector<Attribute>	attributes;
    911 	vector<Bind>		bindings;
    912 	int					ndx = 0;
    913 
    914 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage;
    915 
    916 	for (int loc = maxAttributes - arrayElementCount * m_type.getLocationSize(); loc >= 0; loc -= m_type.getLocationSize() * arrayElementCount)
    917 	{
    918 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond("A", true)));
    919 		bindings.push_back(Bind("a_" + de::toString(ndx), loc));
    920 
    921 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx + maxAttributes), Attribute::LOC_UNDEF, Cond("A", false)));
    922 		bindings.push_back(Bind("a_" + de::toString(ndx + maxAttributes), loc));
    923 		ndx++;
    924 	}
    925 
    926 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
    927 	return STOP;
    928 }
    929 
    930 BindHoleAttributeTest::BindHoleAttributeTest (tcu::TestContext&		testCtx,
    931 											  glu::RenderContext&	renderCtx,
    932 											  const AttribType&		type,
    933 											  int					arraySize)
    934 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
    935 	, m_renderCtx	(renderCtx)
    936 	, m_type		(type)
    937 	, m_arraySize	(arraySize)
    938 {
    939 }
    940 
    941 tcu::TestCase::IterateResult BindHoleAttributeTest::iterate (void)
    942 {
    943 	const vector<Bind>	noBindings;
    944 	const deInt32		maxAttributes = getMaxAttributeLocations(m_renderCtx);
    945 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
    946 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
    947 
    948 	vector<Attribute>	attributes;
    949 	vector<Bind>		bindings;
    950 	int					ndx;
    951 
    952 	attributes.push_back(Attribute(vec4, "a_0"));
    953 	bindings.push_back(Bind("a_0", 0));
    954 
    955 	attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
    956 
    957 	ndx = 2;
    958 	for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++)
    959 	{
    960 		attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx)));
    961 		bindings.push_back(Bind("a_" + de::toString(ndx), loc));
    962 
    963 		ndx++;
    964 	}
    965 
    966 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
    967 	return STOP;
    968 }
    969 
    970 BindInactiveAliasingAttributeTest::BindInactiveAliasingAttributeTest (tcu::TestContext&		testCtx,
    971 																	  glu::RenderContext&	renderCtx,
    972 																	  const AttribType&		type,
    973 																	  int					arraySize)
    974 	: TestCase		(testCtx,	("max_inactive_" + generateTestName(type, arraySize)).c_str(),
    975 								("max_inactive_" + generateTestName(type, arraySize)).c_str())
    976 	, m_renderCtx	(renderCtx)
    977 	, m_type		(type)
    978 	, m_arraySize	(arraySize)
    979 {
    980 }
    981 
    982 tcu::TestCase::IterateResult BindInactiveAliasingAttributeTest::iterate (void)
    983 {
    984 	const vector<Bind>	noBindings;
    985 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
    986 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
    987 
    988 	vector<Attribute>	attributes;
    989 	vector<Bind>		bindings;
    990 	int					ndx = 0;
    991 
    992 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage;
    993 
    994 	for (int loc = maxAttributes - arrayElementCount * m_type.getLocationSize(); loc >= 0; loc -= m_type.getLocationSize() * arrayElementCount)
    995 	{
    996 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond("A")));
    997 		bindings.push_back(Bind("a_" + de::toString(ndx), loc));
    998 
    999 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx + maxAttributes), Attribute::LOC_UNDEF, Cond::COND_NEVER));
   1000 		bindings.push_back(Bind("a_" + de::toString(ndx + maxAttributes), loc));
   1001 		ndx++;
   1002 	}
   1003 
   1004 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1005 	return STOP;
   1006 }
   1007 
   1008 PreAttachBindAttributeTest::PreAttachBindAttributeTest (tcu::TestContext&	testCtx,
   1009 														glu::RenderContext&	renderCtx)
   1010 	: TestCase		(testCtx, "pre_attach", "pre_attach")
   1011 	, m_renderCtx	(renderCtx)
   1012 {
   1013 }
   1014 
   1015 tcu::TestCase::IterateResult PreAttachBindAttributeTest::iterate (void)
   1016 {
   1017 	const vector<Bind>	noBindings;
   1018 
   1019 	vector<Attribute>	attributes;
   1020 	vector<Bind>		bindings;
   1021 
   1022 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0"));
   1023 	bindings.push_back(Bind("a_0", 3));
   1024 
   1025 	runTest(m_testCtx, m_renderCtx, attributes, bindings, noBindings, noBindings, false);
   1026 	return STOP;
   1027 }
   1028 
   1029 PreLinkBindAttributeTest::PreLinkBindAttributeTest (tcu::TestContext&	testCtx,
   1030 													glu::RenderContext&	renderCtx)
   1031 	: TestCase		(testCtx, "pre_link", "pre_link")
   1032 	, m_renderCtx	(renderCtx)
   1033 {
   1034 }
   1035 
   1036 tcu::TestCase::IterateResult PreLinkBindAttributeTest::iterate (void)
   1037 {
   1038 	const vector<Bind>	noBindings;
   1039 
   1040 	vector<Attribute>	attributes;
   1041 	vector<Bind>		bindings;
   1042 
   1043 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0"));
   1044 	bindings.push_back(Bind("a_0", 3));
   1045 
   1046 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1047 	return STOP;
   1048 }
   1049 
   1050 PostLinkBindAttributeTest::PostLinkBindAttributeTest (tcu::TestContext&		testCtx,
   1051 													  glu::RenderContext&	renderCtx)
   1052 	: TestCase		(testCtx, "post_link", "post_link")
   1053 	, m_renderCtx	(renderCtx)
   1054 {
   1055 }
   1056 
   1057 tcu::TestCase::IterateResult PostLinkBindAttributeTest::iterate (void)
   1058 {
   1059 	const vector<Bind>	noBindings;
   1060 
   1061 	vector<Attribute>	attributes;
   1062 	vector<Bind>		bindings;
   1063 
   1064 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0"));
   1065 	bindings.push_back(Bind("a_0", 3));
   1066 
   1067 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, bindings, false);
   1068 	return STOP;
   1069 }
   1070 
   1071 LocationAttributeTest::LocationAttributeTest (tcu::TestContext&		testCtx,
   1072 											  glu::RenderContext&	renderCtx,
   1073 											  const AttribType&		type,
   1074 											  int					arraySize)
   1075 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1076 	, m_renderCtx	(renderCtx)
   1077 	, m_type		(type)
   1078 	, m_arraySize	(arraySize)
   1079 {
   1080 }
   1081 
   1082 tcu::TestCase::IterateResult LocationAttributeTest::iterate (void)
   1083 {
   1084 	const vector<Bind>	noBindings;
   1085 
   1086 	vector<Attribute>	attributes;
   1087 
   1088 	attributes.push_back(Attribute(m_type, "a_0", 3, Cond::COND_ALWAYS, m_arraySize));
   1089 
   1090 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false);
   1091 	return STOP;
   1092 }
   1093 
   1094 LocationMaxAttributesTest::LocationMaxAttributesTest (tcu::TestContext&		testCtx,
   1095 													  glu::RenderContext&	renderCtx,
   1096 													  const AttribType&		type,
   1097 													  int					arraySize)
   1098 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1099 	, m_renderCtx	(renderCtx)
   1100 	, m_type		(type)
   1101 	, m_arraySize	(arraySize)
   1102 {
   1103 }
   1104 
   1105 tcu::TestCase::IterateResult LocationMaxAttributesTest::iterate (void)
   1106 {
   1107 	const vector<Bind>	noBindings;
   1108 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
   1109 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1110 
   1111 	vector<Attribute>	attributes;
   1112 	int					ndx = 0;
   1113 
   1114 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage;
   1115 
   1116 	for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize()))
   1117 	{
   1118 		attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), loc, Cond::COND_ALWAYS, m_arraySize));
   1119 		ndx++;
   1120 	}
   1121 
   1122 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false);
   1123 	return STOP;
   1124 }
   1125 
   1126 LocationHoleAttributeTest::LocationHoleAttributeTest (tcu::TestContext&		testCtx,
   1127 													  glu::RenderContext&	renderCtx,
   1128 													  const AttribType&		type,
   1129 													  int					arraySize)
   1130 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1131 	, m_renderCtx	(renderCtx)
   1132 	, m_type		(type)
   1133 	, m_arraySize	(arraySize)
   1134 {
   1135 }
   1136 
   1137 tcu::TestCase::IterateResult LocationHoleAttributeTest::iterate (void)
   1138 {
   1139 	const vector<Bind>	noBindings;
   1140 	const deInt32		maxAttributes = getMaxAttributeLocations(m_renderCtx);
   1141 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1142 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1143 
   1144 	vector<Attribute>	attributes;
   1145 	int					ndx;
   1146 
   1147 	attributes.push_back(Attribute(vec4, "a_0", 0));
   1148 
   1149 	attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
   1150 
   1151 	ndx = 2;
   1152 	for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++)
   1153 	{
   1154 		attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc));
   1155 		ndx++;
   1156 	}
   1157 
   1158 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, noBindings, false);
   1159 	return STOP;
   1160 }
   1161 
   1162 MixedAttributeTest::MixedAttributeTest (tcu::TestContext&	testCtx,
   1163 										glu::RenderContext&	renderCtx,
   1164 										const AttribType&	type,
   1165 										int					arraySize)
   1166 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1167 	, m_renderCtx	(renderCtx)
   1168 	, m_type		(type)
   1169 	, m_arraySize	(arraySize)
   1170 {
   1171 }
   1172 
   1173 tcu::TestCase::IterateResult MixedAttributeTest::iterate (void)
   1174 {
   1175 	const vector<Bind>	noBindings;
   1176 
   1177 	vector<Bind>		bindings;
   1178 	vector<Attribute>	attributes;
   1179 
   1180 	attributes.push_back(Attribute(m_type, "a_0", 3, Cond::COND_ALWAYS, m_arraySize));
   1181 	bindings.push_back(Bind("a_0", 4));
   1182 
   1183 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1184 	return STOP;
   1185 }
   1186 
   1187 MixedMaxAttributesTest::MixedMaxAttributesTest (tcu::TestContext&	testCtx,
   1188 												glu::RenderContext&	renderCtx,
   1189 												const AttribType&	type,
   1190 												int					arraySize)
   1191 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1192 	, m_renderCtx	(renderCtx)
   1193 	, m_type		(type)
   1194 	, m_arraySize	(arraySize)
   1195 {
   1196 }
   1197 
   1198 tcu::TestCase::IterateResult MixedMaxAttributesTest::iterate (void)
   1199 {
   1200 	const vector<Bind>	noBindings;
   1201 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
   1202 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1203 
   1204 	vector<Bind>		bindings;
   1205 	vector<Attribute>	attributes;
   1206 	int					ndx = 0;
   1207 
   1208 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_VERTEX_ATTRIBS: " << maxAttributes << TestLog::EndMessage;
   1209 
   1210 	for (int loc = maxAttributes - (arrayElementCount * m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * m_type.getLocationSize()))
   1211 	{
   1212 		if ((ndx % 2) != 0)
   1213 			attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), loc, Cond::COND_ALWAYS, m_arraySize));
   1214 		else
   1215 		{
   1216 			attributes.push_back(Attribute(m_type, "a_" + de::toString(ndx), Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
   1217 			bindings.push_back(Bind("a_" + de::toString(ndx), loc));
   1218 
   1219 		}
   1220 		ndx++;
   1221 	}
   1222 
   1223 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1224 	return STOP;
   1225 }
   1226 
   1227 MixedHoleAttributeTest::MixedHoleAttributeTest (tcu::TestContext&		testCtx,
   1228 												glu::RenderContext&		renderCtx,
   1229 												const AttribType&		type,
   1230 												int						arraySize)
   1231 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1232 	, m_renderCtx	(renderCtx)
   1233 	, m_type		(type)
   1234 	, m_arraySize	(arraySize)
   1235 {
   1236 }
   1237 
   1238 tcu::TestCase::IterateResult MixedHoleAttributeTest::iterate (void)
   1239 {
   1240 	const vector<Bind>	noBindings;
   1241 	const deInt32		maxAttributes = getMaxAttributeLocations(m_renderCtx);
   1242 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1243 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1244 
   1245 	vector<Bind>		bindings;
   1246 	vector<Attribute>	attributes;
   1247 	int					ndx;
   1248 
   1249 	attributes.push_back(Attribute(vec4, "a_0"));
   1250 	bindings.push_back(Bind("a_0", 0));
   1251 
   1252 	attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
   1253 
   1254 	ndx = 2;
   1255 	for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++)
   1256 	{
   1257 		if ((ndx % 2) != 0)
   1258 			attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc));
   1259 		else
   1260 		{
   1261 			attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc));
   1262 			bindings.push_back(Bind("a_" + de::toString(ndx), loc));
   1263 
   1264 		}
   1265 		ndx++;
   1266 	}
   1267 
   1268 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1269 	return STOP;
   1270 }
   1271 
   1272 BindRelinkAttributeTest::BindRelinkAttributeTest (tcu::TestContext&		testCtx,
   1273 												  glu::RenderContext&	renderCtx)
   1274 	: TestCase		(testCtx, "relink", "relink")
   1275 	, m_renderCtx	(renderCtx)
   1276 {
   1277 }
   1278 
   1279 tcu::TestCase::IterateResult BindRelinkAttributeTest::iterate (void)
   1280 {
   1281 	const vector<Bind>	noBindings;
   1282 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1283 
   1284 	vector<Attribute>	attributes;
   1285 	vector<Bind>		preLinkBindings;
   1286 	vector<Bind>		postLinkBindings;
   1287 
   1288 	attributes.push_back(Attribute(vec4, "a_0"));
   1289 	attributes.push_back(Attribute(vec4, "a_1"));
   1290 
   1291 	preLinkBindings.push_back(Bind("a_0", 3));
   1292 	preLinkBindings.push_back(Bind("a_0", 5));
   1293 
   1294 	postLinkBindings.push_back(Bind("a_0", 6));
   1295 
   1296 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true);
   1297 	return STOP;
   1298 }
   1299 
   1300 BindRelinkHoleAttributeTest::BindRelinkHoleAttributeTest (tcu::TestContext&		testCtx,
   1301 														  glu::RenderContext&	renderCtx,
   1302 														  const AttribType&		type,
   1303 														  int					arraySize)
   1304 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1305 	, m_renderCtx	(renderCtx)
   1306 	, m_type		(type)
   1307 	, m_arraySize	(arraySize)
   1308 {
   1309 }
   1310 
   1311 tcu::TestCase::IterateResult BindRelinkHoleAttributeTest::iterate (void)
   1312 {
   1313 	const vector<Bind>	noBindings;
   1314 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
   1315 	const AttribType	vec4				("vec4", 1, GL_FLOAT_VEC4);
   1316 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1317 
   1318 	vector<Attribute>	attributes;
   1319 	vector<Bind>		preLinkBindings;
   1320 	vector<Bind>		postLinkBindings;
   1321 	int					ndx;
   1322 
   1323 	attributes.push_back(Attribute(vec4, "a_0"));
   1324 	preLinkBindings.push_back(Bind("a_0", 0));
   1325 
   1326 	attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
   1327 
   1328 	ndx = 2;
   1329 	for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++)
   1330 	{
   1331 		attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx)));
   1332 		preLinkBindings.push_back(Bind("a_" + de::toString(ndx), loc));
   1333 
   1334 		ndx++;
   1335 	}
   1336 
   1337 	postLinkBindings.push_back(Bind("a_2", 1));
   1338 
   1339 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true);
   1340 	return STOP;
   1341 }
   1342 
   1343 MixedRelinkHoleAttributeTest::MixedRelinkHoleAttributeTest (tcu::TestContext&		testCtx,
   1344 															glu::RenderContext&		renderCtx,
   1345 															const AttribType&		type,
   1346 															int						arraySize)
   1347 	: TestCase		(testCtx, generateTestName(type, arraySize).c_str(), generateTestName(type, arraySize).c_str())
   1348 	, m_renderCtx	(renderCtx)
   1349 	, m_type		(type)
   1350 	, m_arraySize	(arraySize)
   1351 {
   1352 }
   1353 
   1354 tcu::TestCase::IterateResult MixedRelinkHoleAttributeTest::iterate (void)
   1355 {
   1356 	const vector<Bind>	noBindings;
   1357 	const deInt32		maxAttributes		= getMaxAttributeLocations(m_renderCtx);
   1358 	const AttribType	vec4				("vec4", 1, GL_FLOAT_VEC4);
   1359 	const int			arrayElementCount	= (m_arraySize != Attribute::NOT_ARRAY ? m_arraySize : 1);
   1360 
   1361 	vector<Bind>		preLinkBindings;
   1362 	vector<Bind>		postLinkBindings;
   1363 	vector<Attribute>	attributes;
   1364 	int					ndx;
   1365 
   1366 	attributes.push_back(Attribute(vec4, "a_0"));
   1367 	preLinkBindings.push_back(Bind("a_0", 0));
   1368 
   1369 	attributes.push_back(Attribute(m_type, "a_1", Attribute::LOC_UNDEF, Cond::COND_ALWAYS, m_arraySize));
   1370 
   1371 	ndx = 2;
   1372 	for (int loc = 1 + m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++)
   1373 	{
   1374 		if ((ndx % 2) != 0)
   1375 			attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx), loc));
   1376 		else
   1377 		{
   1378 			attributes.push_back(Attribute(vec4, "a_" + de::toString(ndx)));
   1379 			preLinkBindings.push_back(Bind("a_" + de::toString(ndx), loc));
   1380 
   1381 		}
   1382 		ndx++;
   1383 	}
   1384 
   1385 	postLinkBindings.push_back(Bind("a_2", 1));
   1386 
   1387 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true);
   1388 	return STOP;
   1389 }
   1390 
   1391 BindReattachAttributeTest::BindReattachAttributeTest (tcu::TestContext&		testCtx,
   1392 													  glu::RenderContext&	renderCtx)
   1393 	: TestCase		(testCtx, "reattach", "reattach")
   1394 	, m_renderCtx	(renderCtx)
   1395 {
   1396 }
   1397 
   1398 tcu::TestCase::IterateResult BindReattachAttributeTest::iterate (void)
   1399 {
   1400 	const vector<Bind>	noBindings;
   1401 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1402 	const AttribType	vec2("vec2", 1, GL_FLOAT_VEC2);
   1403 
   1404 	vector<Bind>		bindings;
   1405 	vector<Attribute>	attributes;
   1406 	vector<Attribute>	reattachAttributes;
   1407 
   1408 	attributes.push_back(Attribute(vec4, "a_0"));
   1409 	bindings.push_back(Bind("a_0", 1));
   1410 	bindings.push_back(Bind("a_1", 1));
   1411 
   1412 	reattachAttributes.push_back(Attribute(vec2, "a_1"));
   1413 
   1414 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false, true, reattachAttributes);
   1415 	return STOP;
   1416 }
   1417 
   1418 PreAttachMixedAttributeTest::PreAttachMixedAttributeTest (tcu::TestContext&	testCtx,
   1419 														glu::RenderContext&	renderCtx)
   1420 	: TestCase		(testCtx, "pre_attach", "pre_attach")
   1421 	, m_renderCtx	(renderCtx)
   1422 {
   1423 }
   1424 
   1425 tcu::TestCase::IterateResult PreAttachMixedAttributeTest::iterate (void)
   1426 {
   1427 	const vector<Bind>	noBindings;
   1428 
   1429 	vector<Attribute>	attributes;
   1430 	vector<Bind>		bindings;
   1431 
   1432 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1));
   1433 	bindings.push_back(Bind("a_0", 3));
   1434 
   1435 	runTest(m_testCtx, m_renderCtx, attributes, bindings, noBindings, noBindings, false);
   1436 	return STOP;
   1437 }
   1438 
   1439 PreLinkMixedAttributeTest::PreLinkMixedAttributeTest (tcu::TestContext&	testCtx,
   1440 													glu::RenderContext&	renderCtx)
   1441 	: TestCase		(testCtx, "pre_link", "pre_link")
   1442 	, m_renderCtx	(renderCtx)
   1443 {
   1444 }
   1445 
   1446 tcu::TestCase::IterateResult PreLinkMixedAttributeTest::iterate (void)
   1447 {
   1448 	const vector<Bind>	noBindings;
   1449 
   1450 	vector<Attribute>	attributes;
   1451 	vector<Bind>		bindings;
   1452 
   1453 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1));
   1454 	bindings.push_back(Bind("a_0", 3));
   1455 
   1456 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false);
   1457 	return STOP;
   1458 }
   1459 
   1460 PostLinkMixedAttributeTest::PostLinkMixedAttributeTest (tcu::TestContext&	testCtx,
   1461 														glu::RenderContext&	renderCtx)
   1462 	: TestCase		(testCtx, "post_link", "post_link")
   1463 	, m_renderCtx	(renderCtx)
   1464 {
   1465 }
   1466 
   1467 tcu::TestCase::IterateResult PostLinkMixedAttributeTest::iterate (void)
   1468 {
   1469 	const vector<Bind>	noBindings;
   1470 
   1471 	vector<Attribute>	attributes;
   1472 	vector<Bind>		bindings;
   1473 
   1474 	attributes.push_back(Attribute(AttribType("vec4", 1, GL_FLOAT_VEC4), "a_0", 1));
   1475 	bindings.push_back(Bind("a_0", 3));
   1476 
   1477 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, noBindings, bindings, false);
   1478 	return STOP;
   1479 }
   1480 
   1481 MixedReattachAttributeTest::MixedReattachAttributeTest (tcu::TestContext&	testCtx,
   1482 														glu::RenderContext&	renderCtx)
   1483 	: TestCase		(testCtx, "reattach", "reattach")
   1484 	, m_renderCtx	(renderCtx)
   1485 {
   1486 }
   1487 
   1488 tcu::TestCase::IterateResult MixedReattachAttributeTest::iterate (void)
   1489 {
   1490 	const vector<Bind>	noBindings;
   1491 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1492 	const AttribType	vec2("vec2", 1, GL_FLOAT_VEC2);
   1493 
   1494 	vector<Bind>		bindings;
   1495 	vector<Attribute>	attributes;
   1496 	vector<Attribute>	reattachAttributes;
   1497 
   1498 	attributes.push_back(Attribute(vec4, "a_0", 2));
   1499 	bindings.push_back(Bind("a_0", 1));
   1500 	bindings.push_back(Bind("a_1", 1));
   1501 
   1502 	reattachAttributes.push_back(Attribute(vec2, "a_1"));
   1503 
   1504 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, bindings, noBindings, false, true, reattachAttributes);
   1505 	return STOP;
   1506 }
   1507 
   1508 MixedRelinkAttributeTest::MixedRelinkAttributeTest (tcu::TestContext&	testCtx,
   1509 													glu::RenderContext&	renderCtx)
   1510 	: TestCase		(testCtx, "relink", "relink")
   1511 	, m_renderCtx	(renderCtx)
   1512 {
   1513 }
   1514 
   1515 tcu::TestCase::IterateResult MixedRelinkAttributeTest::iterate (void)
   1516 {
   1517 	const vector<Bind>	noBindings;
   1518 	const AttribType	vec4("vec4", 1, GL_FLOAT_VEC4);
   1519 
   1520 	vector<Attribute>	attributes;
   1521 	vector<Bind>		preLinkBindings;
   1522 	vector<Bind>		postLinkBindings;
   1523 
   1524 	attributes.push_back(Attribute(vec4, "a_0", 1));
   1525 	attributes.push_back(Attribute(vec4, "a_1"));
   1526 
   1527 	preLinkBindings.push_back(Bind("a_0", 3));
   1528 	preLinkBindings.push_back(Bind("a_0", 5));
   1529 
   1530 	postLinkBindings.push_back(Bind("a_0", 6));
   1531 
   1532 	runTest(m_testCtx, m_renderCtx, attributes, noBindings, preLinkBindings, postLinkBindings, true);
   1533 	return STOP;
   1534 }
   1535 
   1536 } // gls
   1537 } // deqp
   1538