Do not use degenerate frames in EGL tests
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsAttributeLocationTests.cpp
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