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