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