1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 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 Vertex array object tests
22 *//*--------------------------------------------------------------------*/
23 #include "es3fVertexArrayObjectTests.hpp"
24
25 #include "gluShaderProgram.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluRenderContext.hpp"
28
29 #include "tcuTestLog.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuSurface.hpp"
32 #include "tcuRenderTarget.hpp"
33
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "deMemory.h"
37
38 #include <vector>
39 #include <string>
40 #include <memory>
41
42 #include "glw.h"
43
44 using std::vector;
45 using std::string;
46
47 namespace deqp
48 {
49 namespace gles3
50 {
51 namespace Functional
52 {
53
54 namespace
55 {
56 struct Attribute
57 {
58 Attribute (void);
59 GLboolean enabled;
60 GLint size;
61 GLint stride;
62 GLenum type;
63 GLboolean integer;
64 GLint divisor;
65 GLint offset;
66 GLboolean normalized;
67
68 int bufferNdx;
69 };
70
71 struct VertexArrayState
72 {
73 VertexArrayState (void);
74
75 vector<Attribute> attributes;
76 int elementArrayBuffer;
77 };
78
VertexArrayState(void)79 VertexArrayState::VertexArrayState (void)
80 : elementArrayBuffer(-1)
81 {
82 }
83
Attribute(void)84 Attribute::Attribute (void)
85 : enabled (GL_FALSE)
86 , size (1)
87 , stride (0)
88 , type (GL_FLOAT)
89 , integer (GL_FALSE)
90 , divisor (0)
91 , offset (0)
92 , normalized (GL_FALSE)
93 , bufferNdx (0)
94 {
95 }
96
97 struct BufferSpec
98 {
99 int count;
100 int size;
101 int componentCount;
102 int stride;
103 int offset;
104
105 GLenum type;
106
107 int intRangeMin;
108 int intRangeMax;
109
110 float floatRangeMin;
111 float floatRangeMax;
112 };
113
114 struct Spec
115 {
116 Spec (void);
117
118 int count;
119 int instances;
120 bool useDrawElements;
121 GLenum indexType;
122 int indexOffset;
123 int indexRangeMin;
124 int indexRangeMax;
125 int indexCount;
126 VertexArrayState state;
127 VertexArrayState vao;
128 vector<BufferSpec> buffers;
129 };
130
Spec(void)131 Spec::Spec (void)
132 : count (-1)
133 , instances (-1)
134 , useDrawElements (false)
135 , indexType (GL_NONE)
136 , indexOffset (-1)
137 , indexRangeMin (-1)
138 , indexRangeMax (-1)
139 , indexCount (-1)
140 {
141 }
142
143 } // anonymous
144
145 class VertexArrayObjectTest : public TestCase
146 {
147 public:
148
149 VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description);
150 ~VertexArrayObjectTest (void);
151 virtual void init (void);
152 virtual void deinit (void);
153 virtual IterateResult iterate (void);
154
155 private:
156 Spec m_spec;
157 tcu::TestLog& m_log;
158 vector<GLuint> m_buffers;
159 glu::ShaderProgram* m_vaoProgram;
160 glu::ShaderProgram* m_stateProgram;
161 de::Random m_random;
162 deUint8* m_indices;
163
164 void logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
165 deUint8* createRandomBufferData (const BufferSpec& buffer);
166 deUint8* generateIndices (void);
167 glu::ShaderProgram* createProgram (const VertexArrayState& state);
168 void setState (const VertexArrayState& state);
169 void render (tcu::Surface& vaoResult, tcu::Surface& defaultResult);
170 void makeDrawCall (const VertexArrayState& state);
171 void genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef);
172
173 VertexArrayObjectTest (const VertexArrayObjectTest&);
174 VertexArrayObjectTest& operator= (const VertexArrayObjectTest&);
175 };
176
VertexArrayObjectTest(Context & context,const Spec & spec,const char * name,const char * description)177 VertexArrayObjectTest::VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description)
178 : TestCase (context, name, description)
179 , m_spec (spec)
180 , m_log (context.getTestContext().getLog())
181 , m_vaoProgram (NULL)
182 , m_stateProgram (NULL)
183 , m_random (deStringHash(name))
184 , m_indices (NULL)
185 {
186 // Makes zero to zero mapping for buffers
187 m_buffers.push_back(0);
188 }
189
~VertexArrayObjectTest(void)190 VertexArrayObjectTest::~VertexArrayObjectTest (void)
191 {
192 }
193
logVertexArrayState(tcu::TestLog & log,const VertexArrayState & state,const std::string & msg)194 void VertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
195 {
196 std::stringstream message;
197
198 message << msg << "\n";
199 message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
200
201 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
202 {
203 message
204 << "attribute : " << attribNdx << "\n"
205 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") << "\n"
206 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size << "\n"
207 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride << "\n"
208 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type << "\n"
209 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") << "\n"
210 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") << "\n"
211 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor << "\n"
212 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset << "\n"
213 << "\tGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] << "\n";
214 }
215 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
216 }
217
218
init(void)219 void VertexArrayObjectTest::init (void)
220 {
221 // \note [mika] Index 0 is reserved for 0 buffer
222 for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
223 {
224 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
225
226 try
227 {
228 GLuint buffer;
229 GLU_CHECK_CALL(glGenBuffers(1, &buffer));
230 m_buffers.push_back(buffer);
231
232 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
233 GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
234 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
235
236 } catch (...) {
237 delete[] data;
238 throw;
239 }
240
241 delete[] data;
242 }
243
244 m_vaoProgram = createProgram(m_spec.vao);
245 m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
246 m_log << *m_vaoProgram;
247 m_stateProgram = createProgram(m_spec.state);
248 m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
249 m_log << *m_stateProgram;
250
251 if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
252 TCU_FAIL("Failed to compile shaders");
253
254 if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
255 m_indices = generateIndices();
256 }
257
deinit(void)258 void VertexArrayObjectTest::deinit (void)
259 {
260 GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
261 m_buffers.clear();
262 delete m_vaoProgram;
263 delete m_stateProgram;
264 delete[] m_indices;
265 }
266
generateIndices(void)267 deUint8* VertexArrayObjectTest::generateIndices (void)
268 {
269 int typeSize = 0;
270 switch (m_spec.indexType)
271 {
272 case GL_UNSIGNED_INT: typeSize = sizeof(GLuint); break;
273 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort); break;
274 case GL_UNSIGNED_BYTE: typeSize = sizeof(GLubyte); break;
275 default:
276 DE_ASSERT(false);
277 }
278
279 deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
280
281 for (int i = 0; i < m_spec.indexCount; i++)
282 {
283 deUint8* pos = indices + typeSize * i;
284
285 switch (m_spec.indexType)
286 {
287 case GL_UNSIGNED_INT:
288 {
289 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
290 deMemcpy(pos, &v, sizeof(v));
291 break;
292 }
293
294 case GL_UNSIGNED_SHORT:
295 {
296 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
297 deMemcpy(pos, &v, sizeof(v));
298 break;
299 }
300
301 case GL_UNSIGNED_BYTE:
302 {
303 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
304 deMemcpy(pos, &v, sizeof(v));
305 break;
306 }
307
308 default:
309 DE_ASSERT(false);
310 }
311 }
312
313 return indices;
314 }
315
createRandomBufferData(const BufferSpec & buffer)316 deUint8* VertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
317 {
318 deUint8* data = new deUint8[buffer.size];
319
320 int stride;
321
322 if (buffer.stride != 0)
323 {
324 stride = buffer.stride;
325 }
326 else
327 {
328 switch (buffer.type)
329 {
330 case GL_FLOAT: stride = buffer.componentCount * (int)sizeof(GLfloat); break;
331 case GL_INT: stride = buffer.componentCount * (int)sizeof(GLint); break;
332 case GL_UNSIGNED_INT: stride = buffer.componentCount * (int)sizeof(GLuint); break;
333 case GL_SHORT: stride = buffer.componentCount * (int)sizeof(GLshort); break;
334 case GL_UNSIGNED_SHORT: stride = buffer.componentCount * (int)sizeof(GLushort); break;
335 case GL_BYTE: stride = buffer.componentCount * (int)sizeof(GLbyte); break;
336 case GL_UNSIGNED_BYTE: stride = buffer.componentCount * (int)sizeof(GLubyte); break;
337
338 default:
339 stride = 0;
340 DE_ASSERT(DE_FALSE);
341 }
342 }
343
344 deUint8* itr = data;
345
346 for (int pos = 0; pos < buffer.count; pos++)
347 {
348 deUint8* componentItr = itr;
349 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
350 {
351 switch (buffer.type)
352 {
353 case GL_FLOAT:
354 {
355 float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
356 deMemcpy(componentItr, &v, sizeof(v));
357 componentItr += sizeof(v);
358 break;
359 }
360
361 case GL_INT:
362 {
363 GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
364 deMemcpy(componentItr, &v, sizeof(v));
365 componentItr += sizeof(v);
366 break;
367 }
368
369 case GL_UNSIGNED_INT:
370 {
371 GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
372 deMemcpy(componentItr, &v, sizeof(v));
373 componentItr += sizeof(v);
374 break;
375 }
376
377 case GL_SHORT:
378 {
379 GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
380 deMemcpy(componentItr, &v, sizeof(v));
381 componentItr += sizeof(v);
382 break;
383 }
384
385 case GL_UNSIGNED_SHORT:
386 {
387 GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
388 deMemcpy(componentItr, &v, sizeof(v));
389 componentItr += sizeof(v);
390 break;
391 }
392
393 case GL_BYTE:
394 {
395 GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
396 deMemcpy(componentItr, &v, sizeof(v));
397 componentItr += sizeof(v);
398 break;
399 }
400
401 case GL_UNSIGNED_BYTE:
402 {
403 GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
404 deMemcpy(componentItr, &v, sizeof(v));
405 componentItr += sizeof(v);
406 break;
407 }
408
409 default:
410 DE_ASSERT(false);
411 }
412 }
413
414 itr += stride;
415 }
416
417 return data;
418 }
419
createProgram(const VertexArrayState & state)420 glu::ShaderProgram* VertexArrayObjectTest::createProgram (const VertexArrayState& state)
421 {
422 std::stringstream vertexShaderStream;
423 std::stringstream value;
424
425 vertexShaderStream << "#version 300 es\n";
426
427 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
428 {
429 if (state.attributes[attribNdx].integer)
430 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
431 else
432 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
433
434 if (state.attributes[attribNdx].integer)
435 {
436 float scale = 0.0f;
437
438 switch (state.attributes[0].type)
439 {
440 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
441 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
442 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
443 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
444 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
445 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
446
447 default:
448 DE_ASSERT(DE_FALSE);
449 }
450 value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
451 }
452 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
453 {
454 float scale = 0.0f;
455
456 switch (state.attributes[0].type)
457 {
458 case GL_SHORT: scale = (0.5f/float((1u<<14)-1u)); break;
459 case GL_UNSIGNED_SHORT: scale = (0.5f/float((1u<<15)-1u)); break;
460 case GL_INT: scale = (0.5f/float((1u<<30)-1u)); break;
461 case GL_UNSIGNED_INT: scale = (0.5f/float((1u<<31)-1u)); break;
462 case GL_BYTE: scale = (0.5f/float((1u<<6)-1u)); break;
463 case GL_UNSIGNED_BYTE: scale = (0.5f/float((1u<<7)-1u)); break;
464
465 default:
466 DE_ASSERT(DE_FALSE);
467 }
468 value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
469 }
470 else
471 value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
472 }
473
474 vertexShaderStream
475 << "out mediump vec4 v_value;\n"
476 << "void main (void)\n"
477 << "{\n"
478 << "\tv_value = " << value.str() << ";\n";
479
480 if (state.attributes[0].integer)
481 {
482 float scale = 0.0f;
483
484 switch (state.attributes[0].type)
485 {
486 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
487 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
488 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
489 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
490 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
491 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
492
493 default:
494 DE_ASSERT(DE_FALSE);
495 }
496
497 vertexShaderStream
498 << "\tgl_Position = vec4(" << scale << " * " << "vec3(a_attrib0.xyz), 1.0);\n"
499 << "}";
500 }
501 else
502 {
503 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
504 {
505 vertexShaderStream
506 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
507 << "}";
508 }
509 else
510 {
511 float scale = 0.0f;
512
513 switch (state.attributes[0].type)
514 {
515 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
516 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
517 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
518 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
519 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
520 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
521
522 default:
523 DE_ASSERT(DE_FALSE);
524 }
525
526 scale *= 0.5f;
527
528 vertexShaderStream
529 << "\tgl_Position = vec4(" << scale << " * " << "a_attrib0.xyz, 1.0);\n"
530 << "}";
531 }
532 }
533
534 const char* fragmentShader =
535 "#version 300 es\n"
536 "in mediump vec4 v_value;\n"
537 "layout(location = 0) out mediump vec4 fragColor;\n"
538 "void main (void)\n"
539 "{\n"
540 "\tfragColor = vec4(v_value.xyz, 1.0);\n"
541 "}";
542
543 return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
544 }
545
setState(const VertexArrayState & state)546 void VertexArrayObjectTest::setState (const VertexArrayState& state)
547 {
548 GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
549
550 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
551 {
552 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
553 if (state.attributes[attribNdx].enabled)
554 GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
555 else
556 GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
557
558 if (state.attributes[attribNdx].integer)
559 GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
560 else
561 GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
562
563 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
564 }
565 }
566
makeDrawCall(const VertexArrayState & state)567 void VertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
568 {
569 GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
570 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
571
572 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
573 {
574 if (state.attributes[attribNdx].integer)
575 glVertexAttribI4i(attribNdx, 0, 0, 0, 1);
576 else
577 glVertexAttrib4f(attribNdx, 0.0f, 0.0f, 0.0f, 1.0f);
578 }
579
580 if (m_spec.useDrawElements)
581 {
582 if (state.elementArrayBuffer == 0)
583 {
584 if (m_spec.instances == 0)
585 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
586 else
587 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
588 }
589 else
590 {
591 if (m_spec.instances == 0)
592 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
593 else
594 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
595 }
596 }
597 else
598 {
599 if (m_spec.instances == 0)
600 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
601 else
602 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
603 }
604 }
605
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)606 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
607 {
608 GLuint vao = 0;
609
610 GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
611 GLU_CHECK_CALL(glBindVertexArray(vao));
612 setState(m_spec.vao);
613 GLU_CHECK_CALL(glBindVertexArray(0));
614
615 setState(m_spec.state);
616
617 GLU_CHECK_CALL(glBindVertexArray(vao));
618 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
619 makeDrawCall(m_spec.vao);
620 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
621 setState(m_spec.vao);
622 GLU_CHECK_CALL(glBindVertexArray(0));
623
624 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
625 makeDrawCall(m_spec.state);
626 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
627 }
628
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)629 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
630 {
631 setState(m_spec.vao);
632 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
633 makeDrawCall(m_spec.vao);
634 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
635
636 setState(m_spec.state);
637 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
638 makeDrawCall(m_spec.state);
639 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
640 }
641
iterate(void)642 TestCase::IterateResult VertexArrayObjectTest::iterate (void)
643 {
644 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
645 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
646
647 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
648 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
649
650 bool isOk;
651
652 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
653 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
654 genReferences(stateReference, vaoReference);
655 render(stateResult, vaoResult);
656
657 isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
658 isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
659
660 if (isOk)
661 {
662 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
663 return STOP;
664 }
665 else
666 {
667 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
668 return STOP;
669 }
670 }
671
672 class MultiVertexArrayObjectTest : public TestCase
673 {
674 public:
675
676 MultiVertexArrayObjectTest (Context& context, const char* name, const char* description);
677 ~MultiVertexArrayObjectTest (void);
678 virtual void init (void);
679 virtual void deinit (void);
680 virtual IterateResult iterate (void);
681
682 private:
683 Spec m_spec;
684 tcu::TestLog& m_log;
685 vector<GLuint> m_buffers;
686 glu::ShaderProgram* m_vaoProgram;
687 glu::ShaderProgram* m_stateProgram;
688 de::Random m_random;
689 deUint8* m_indices;
690
691 void logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
692 deUint8* createRandomBufferData (const BufferSpec& buffer);
693 deUint8* generateIndices (void);
694 glu::ShaderProgram* createProgram (const VertexArrayState& state);
695 void setState (const VertexArrayState& state);
696 void render (tcu::Surface& vaoResult, tcu::Surface& defaultResult);
697 void makeDrawCall (const VertexArrayState& state);
698 void genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef);
699
700 MultiVertexArrayObjectTest (const MultiVertexArrayObjectTest&);
701 MultiVertexArrayObjectTest& operator= (const MultiVertexArrayObjectTest&);
702 };
703
MultiVertexArrayObjectTest(Context & context,const char * name,const char * description)704 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description)
705 : TestCase (context, name, description)
706 , m_log (context.getTestContext().getLog())
707 , m_vaoProgram (NULL)
708 , m_stateProgram (NULL)
709 , m_random (deStringHash(name))
710 , m_indices (NULL)
711 {
712 // Makes zero to zero mapping for buffers
713 m_buffers.push_back(0);
714 }
715
~MultiVertexArrayObjectTest(void)716 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void)
717 {
718 }
719
logVertexArrayState(tcu::TestLog & log,const VertexArrayState & state,const std::string & msg)720 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
721 {
722 std::stringstream message;
723
724 message << msg << "\n";
725 message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
726
727 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
728 {
729 message
730 << "attribute : " << attribNdx << "\n"
731 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") << "\n"
732 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size << "\n"
733 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride << "\n"
734 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type << "\n"
735 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") << "\n"
736 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") << "\n"
737 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor << "\n"
738 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset << "\n"
739 << "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] << "\n";
740 }
741 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
742 }
743
744
init(void)745 void MultiVertexArrayObjectTest::init (void)
746 {
747 GLint attribCount;
748
749 GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount));
750
751 m_spec.useDrawElements = false;
752 m_spec.instances = 0;
753 m_spec.count = 24;
754 m_spec.indexOffset = 0;
755 m_spec.indexRangeMin = 0;
756 m_spec.indexRangeMax = 0;
757 m_spec.indexType = GL_NONE;
758 m_spec.indexCount = 0;
759 m_spec.vao.elementArrayBuffer = 0;
760 m_spec.state.elementArrayBuffer = 0;
761
762 for (int attribNdx = 0; attribNdx < attribCount; attribNdx++)
763 {
764 BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
765 m_spec.buffers.push_back(shortCoordBuffer48);
766
767 m_spec.state.attributes.push_back(Attribute());
768 m_spec.state.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
769 m_spec.state.attributes[attribNdx].size = m_random.getInt(2,4);
770 m_spec.state.attributes[attribNdx].stride = 2*m_random.getInt(1, 3);
771 m_spec.state.attributes[attribNdx].type = GL_SHORT;
772 m_spec.state.attributes[attribNdx].integer = m_random.getBool();
773 m_spec.state.attributes[attribNdx].divisor = m_random.getInt(0, 1);
774 m_spec.state.attributes[attribNdx].offset = 2*m_random.getInt(0, 2);
775 m_spec.state.attributes[attribNdx].normalized = m_random.getBool();
776 m_spec.state.attributes[attribNdx].bufferNdx = attribNdx+1;
777
778 if (attribNdx == 0)
779 {
780 m_spec.state.attributes[attribNdx].divisor = 0;
781 m_spec.state.attributes[attribNdx].enabled = GL_TRUE;
782 m_spec.state.attributes[attribNdx].size = 2;
783 }
784
785 m_spec.vao.attributes.push_back(Attribute());
786 m_spec.vao.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
787 m_spec.vao.attributes[attribNdx].size = m_random.getInt(2,4);
788 m_spec.vao.attributes[attribNdx].stride = 2*m_random.getInt(1, 3);
789 m_spec.vao.attributes[attribNdx].type = GL_SHORT;
790 m_spec.vao.attributes[attribNdx].integer = m_random.getBool();
791 m_spec.vao.attributes[attribNdx].divisor = m_random.getInt(0, 1);
792 m_spec.vao.attributes[attribNdx].offset = 2*m_random.getInt(0, 2);
793 m_spec.vao.attributes[attribNdx].normalized = m_random.getBool();
794 m_spec.vao.attributes[attribNdx].bufferNdx = attribCount - attribNdx;
795
796 if (attribNdx == 0)
797 {
798 m_spec.vao.attributes[attribNdx].divisor = 0;
799 m_spec.vao.attributes[attribNdx].enabled = GL_TRUE;
800 m_spec.vao.attributes[attribNdx].size = 2;
801 }
802
803 }
804
805 // \note [mika] Index 0 is reserved for 0 buffer
806 for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
807 {
808 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
809
810 try
811 {
812 GLuint buffer;
813 GLU_CHECK_CALL(glGenBuffers(1, &buffer));
814 m_buffers.push_back(buffer);
815
816 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
817 GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
818 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
819
820 } catch (...) {
821 delete[] data;
822 throw;
823 }
824
825 delete[] data;
826 }
827
828 m_vaoProgram = createProgram(m_spec.vao);
829 m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
830 m_log << *m_vaoProgram;
831 m_stateProgram = createProgram(m_spec.state);
832 m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
833 m_log << *m_stateProgram;
834
835 if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
836 TCU_FAIL("Failed to compile shaders");
837
838 if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
839 m_indices = generateIndices();
840 }
841
deinit(void)842 void MultiVertexArrayObjectTest::deinit (void)
843 {
844 GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
845 m_buffers.clear();
846 delete m_vaoProgram;
847 delete m_stateProgram;
848 delete[] m_indices;
849 }
850
generateIndices(void)851 deUint8* MultiVertexArrayObjectTest::generateIndices (void)
852 {
853 int typeSize = 0;
854 switch (m_spec.indexType)
855 {
856 case GL_UNSIGNED_INT: typeSize = sizeof(GLuint); break;
857 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort); break;
858 case GL_UNSIGNED_BYTE: typeSize = sizeof(GLubyte); break;
859 default:
860 DE_ASSERT(false);
861 }
862
863 deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
864
865 for (int i = 0; i < m_spec.indexCount; i++)
866 {
867 deUint8* pos = indices + typeSize * i;
868
869 switch (m_spec.indexType)
870 {
871 case GL_UNSIGNED_INT:
872 {
873 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
874 deMemcpy(pos, &v, sizeof(v));
875 break;
876 }
877
878 case GL_UNSIGNED_SHORT:
879 {
880 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
881 deMemcpy(pos, &v, sizeof(v));
882 break;
883 }
884
885 case GL_UNSIGNED_BYTE:
886 {
887 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
888 deMemcpy(pos, &v, sizeof(v));
889 break;
890 }
891
892 default:
893 DE_ASSERT(false);
894 }
895 }
896
897 return indices;
898 }
899
createRandomBufferData(const BufferSpec & buffer)900 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
901 {
902 deUint8* data = new deUint8[buffer.size];
903
904 int stride;
905
906 if (buffer.stride != 0)
907 {
908 stride = buffer.stride;
909 }
910 else
911 {
912 switch (buffer.type)
913 {
914 case GL_FLOAT: stride = buffer.componentCount * (int)sizeof(GLfloat); break;
915 case GL_INT: stride = buffer.componentCount * (int)sizeof(GLint); break;
916 case GL_UNSIGNED_INT: stride = buffer.componentCount * (int)sizeof(GLuint); break;
917 case GL_SHORT: stride = buffer.componentCount * (int)sizeof(GLshort); break;
918 case GL_UNSIGNED_SHORT: stride = buffer.componentCount * (int)sizeof(GLushort); break;
919 case GL_BYTE: stride = buffer.componentCount * (int)sizeof(GLbyte); break;
920 case GL_UNSIGNED_BYTE: stride = buffer.componentCount * (int)sizeof(GLubyte); break;
921
922 default:
923 stride = 0;
924 DE_ASSERT(DE_FALSE);
925 }
926 }
927
928 deUint8* itr = data;
929
930 for (int pos = 0; pos < buffer.count; pos++)
931 {
932 deUint8* componentItr = itr;
933 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
934 {
935 switch (buffer.type)
936 {
937 case GL_FLOAT:
938 {
939 float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
940 deMemcpy(componentItr, &v, sizeof(v));
941 componentItr += sizeof(v);
942 break;
943 }
944
945 case GL_INT:
946 {
947 GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
948 deMemcpy(componentItr, &v, sizeof(v));
949 componentItr += sizeof(v);
950 break;
951 }
952
953 case GL_UNSIGNED_INT:
954 {
955 GLuint v = (GLuint)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
956 deMemcpy(componentItr, &v, sizeof(v));
957 componentItr += sizeof(v);
958 break;
959 }
960
961 case GL_SHORT:
962 {
963 GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
964 deMemcpy(componentItr, &v, sizeof(v));
965 componentItr += sizeof(v);
966 break;
967 }
968
969 case GL_UNSIGNED_SHORT:
970 {
971 GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
972 deMemcpy(componentItr, &v, sizeof(v));
973 componentItr += sizeof(v);
974 break;
975 }
976
977 case GL_BYTE:
978 {
979 GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
980 deMemcpy(componentItr, &v, sizeof(v));
981 componentItr += sizeof(v);
982 break;
983 }
984
985 case GL_UNSIGNED_BYTE:
986 {
987 GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
988 deMemcpy(componentItr, &v, sizeof(v));
989 componentItr += sizeof(v);
990 break;
991 }
992
993 default:
994 DE_ASSERT(false);
995 }
996 }
997
998 itr += stride;
999 }
1000
1001 return data;
1002 }
1003
createProgram(const VertexArrayState & state)1004 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state)
1005 {
1006 std::stringstream vertexShaderStream;
1007 std::stringstream value;
1008
1009 vertexShaderStream << "#version 300 es\n";
1010
1011 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1012 {
1013 if (state.attributes[attribNdx].integer)
1014 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
1015 else
1016 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
1017
1018 if (state.attributes[attribNdx].integer)
1019 {
1020 float scale = 0.0f;
1021
1022 switch (state.attributes[0].type)
1023 {
1024 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1025 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1026 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1027 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1028 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1029 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1030
1031 default:
1032 DE_ASSERT(DE_FALSE);
1033 }
1034 value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
1035 }
1036 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
1037 {
1038 float scale = 0.0f;
1039
1040 switch (state.attributes[0].type)
1041 {
1042 case GL_SHORT: scale = (0.5f/float((1u<<14)-1u)); break;
1043 case GL_UNSIGNED_SHORT: scale = (0.5f/float((1u<<15)-1u)); break;
1044 case GL_INT: scale = (0.5f/float((1u<<30)-1u)); break;
1045 case GL_UNSIGNED_INT: scale = (0.5f/float((1u<<31)-1u)); break;
1046 case GL_BYTE: scale = (0.5f/float((1u<<6)-1u)); break;
1047 case GL_UNSIGNED_BYTE: scale = (0.5f/float((1u<<7)-1u)); break;
1048
1049 default:
1050 DE_ASSERT(DE_FALSE);
1051 }
1052 value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
1053 }
1054 else
1055 value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
1056 }
1057
1058 vertexShaderStream
1059 << "out mediump vec4 v_value;\n"
1060 << "void main (void)\n"
1061 << "{\n"
1062 << "\tv_value = " << value.str() << ";\n";
1063
1064 if (state.attributes[0].integer)
1065 {
1066 float scale = 0.0f;
1067
1068 switch (state.attributes[0].type)
1069 {
1070 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1071 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1072 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1073 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1074 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1075 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1076
1077
1078 default:
1079 DE_ASSERT(DE_FALSE);
1080 }
1081
1082 vertexShaderStream
1083 << "\tgl_Position = vec4(" << scale << " * " << "a_attrib0.xyz, 1.0);\n"
1084 << "}";
1085 }
1086 else
1087 {
1088 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
1089 {
1090 vertexShaderStream
1091 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
1092 << "}";
1093 }
1094 else
1095 {
1096 float scale = 0.0f;
1097
1098 switch (state.attributes[0].type)
1099 {
1100 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1101 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1102 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1103 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1104 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1105 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1106
1107 default:
1108 DE_ASSERT(DE_FALSE);
1109 }
1110
1111 scale *= 0.5f;
1112
1113 vertexShaderStream
1114 << "\tgl_Position = vec4(" << scale << " * " << "vec3(a_attrib0.xyz), 1.0);\n"
1115 << "}";
1116 }
1117 }
1118
1119 const char* fragmentShader =
1120 "#version 300 es\n"
1121 "in mediump vec4 v_value;\n"
1122 "layout(location = 0) out mediump vec4 fragColor;\n"
1123 "void main (void)\n"
1124 "{\n"
1125 "\tfragColor = vec4(v_value.xyz, 1.0);\n"
1126 "}";
1127
1128 return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
1129 }
1130
setState(const VertexArrayState & state)1131 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state)
1132 {
1133 GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
1134
1135 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1136 {
1137 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
1138 if (state.attributes[attribNdx].enabled)
1139 GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
1140 else
1141 GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
1142
1143 if (state.attributes[attribNdx].integer)
1144 GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1145 else
1146 GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1147
1148 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
1149 }
1150 }
1151
makeDrawCall(const VertexArrayState & state)1152 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
1153 {
1154 GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
1155 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1156
1157 if (m_spec.useDrawElements)
1158 {
1159 if (state.elementArrayBuffer == 0)
1160 {
1161 if (m_spec.instances == 0)
1162 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
1163 else
1164 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
1165 }
1166 else
1167 {
1168 if (m_spec.instances == 0)
1169 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
1170 else
1171 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
1172 }
1173 }
1174 else
1175 {
1176 if (m_spec.instances == 0)
1177 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
1178 else
1179 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
1180 }
1181 }
1182
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)1183 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
1184 {
1185 GLuint vao = 0;
1186
1187 GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
1188 GLU_CHECK_CALL(glBindVertexArray(vao));
1189 setState(m_spec.vao);
1190 GLU_CHECK_CALL(glBindVertexArray(0));
1191
1192 setState(m_spec.state);
1193
1194 GLU_CHECK_CALL(glBindVertexArray(vao));
1195 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1196 makeDrawCall(m_spec.vao);
1197 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
1198 setState(m_spec.vao);
1199 GLU_CHECK_CALL(glBindVertexArray(0));
1200
1201 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1202 makeDrawCall(m_spec.state);
1203 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
1204 }
1205
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)1206 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
1207 {
1208 setState(m_spec.vao);
1209 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1210 makeDrawCall(m_spec.vao);
1211 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
1212
1213 setState(m_spec.state);
1214 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1215 makeDrawCall(m_spec.state);
1216 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
1217 }
1218
iterate(void)1219 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void)
1220 {
1221 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1222 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1223
1224 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1225 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1226
1227 bool isOk;
1228
1229 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
1230 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
1231 genReferences(stateReference, vaoReference);
1232 render(stateResult, vaoResult);
1233
1234 isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1235 isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1236
1237 if (isOk)
1238 {
1239 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1240 return STOP;
1241 }
1242 else
1243 {
1244 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1245 return STOP;
1246 }
1247 }
1248
VertexArrayObjectTestGroup(Context & context)1249 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context)
1250 : TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases")
1251 {
1252 }
1253
~VertexArrayObjectTestGroup(void)1254 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void)
1255 {
1256 }
1257
init(void)1258 void VertexArrayObjectTestGroup::init (void)
1259 {
1260 BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1261 BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1262
1263 BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
1264
1265 // Different buffer
1266 {
1267 Spec spec;
1268
1269 VertexArrayState state;
1270
1271 state.attributes.push_back(Attribute());
1272
1273 state.attributes[0].enabled = true;
1274 state.attributes[0].size = 2;
1275 state.attributes[0].stride = 0;
1276 state.attributes[0].type = GL_FLOAT;
1277 state.attributes[0].integer = GL_FALSE;
1278 state.attributes[0].divisor = 0;
1279 state.attributes[0].offset = 0;
1280 state.attributes[0].normalized = GL_FALSE;
1281
1282 state.elementArrayBuffer = 0;
1283
1284 spec.buffers.push_back(floatCoordBuffer48_1);
1285 spec.buffers.push_back(floatCoordBuffer48_2);
1286
1287 spec.useDrawElements = false;
1288 spec.instances = 0;
1289 spec.count = 48;
1290 spec.vao = state;
1291 spec.state = state;
1292 spec.indexOffset = 0;
1293 spec.indexRangeMin = 0;
1294 spec.indexRangeMax = 0;
1295 spec.indexType = GL_NONE;
1296 spec.indexCount = 0;
1297
1298 spec.state.attributes[0].bufferNdx = 1;
1299 spec.vao.attributes[0].bufferNdx = 2;
1300 addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer"));
1301 }
1302 // Different size
1303 {
1304 Spec spec;
1305
1306 VertexArrayState state;
1307
1308 state.attributes.push_back(Attribute());
1309
1310 state.attributes[0].enabled = true;
1311 state.attributes[0].size = 2;
1312 state.attributes[0].stride = 0;
1313 state.attributes[0].type = GL_FLOAT;
1314 state.attributes[0].integer = GL_FALSE;
1315 state.attributes[0].divisor = 0;
1316 state.attributes[0].offset = 0;
1317 state.attributes[0].normalized = GL_FALSE;
1318 state.attributes[0].bufferNdx = 1;
1319
1320 state.elementArrayBuffer = 0;
1321
1322 spec.buffers.push_back(floatCoordBuffer48_1);
1323
1324 spec.useDrawElements = false;
1325 spec.instances = 0;
1326 spec.count = 24;
1327 spec.vao = state;
1328 spec.state = state;
1329 spec.indexOffset = 0;
1330 spec.indexRangeMin = 0;
1331 spec.indexRangeMax = 0;
1332 spec.indexType = GL_NONE;
1333 spec.indexCount = 0;
1334
1335 spec.state.attributes[0].size = 2;
1336 spec.vao.attributes[0].size = 3;
1337 addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size"));
1338 }
1339
1340 // Different stride
1341 {
1342 Spec spec;
1343
1344 VertexArrayState state;
1345
1346 state.attributes.push_back(Attribute());
1347
1348 state.attributes[0].enabled = true;
1349 state.attributes[0].size = 2;
1350 state.attributes[0].stride = 0;
1351 state.attributes[0].type = GL_SHORT;
1352 state.attributes[0].integer = GL_FALSE;
1353 state.attributes[0].divisor = 0;
1354 state.attributes[0].offset = 0;
1355 state.attributes[0].normalized = GL_TRUE;
1356 state.attributes[0].bufferNdx = 1;
1357
1358 state.elementArrayBuffer = 0;
1359
1360 spec.buffers.push_back(shortCoordBuffer48);
1361
1362 spec.useDrawElements = false;
1363 spec.instances = 0;
1364 spec.count = 24;
1365 spec.vao = state;
1366 spec.state = state;
1367 spec.indexOffset = 0;
1368 spec.indexRangeMin = 0;
1369 spec.indexRangeMax = 0;
1370 spec.indexType = GL_NONE;
1371 spec.indexCount = 0;
1372
1373 spec.vao.attributes[0].stride = 2;
1374 spec.state.attributes[0].stride = 4;
1375 addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride"));
1376 }
1377
1378 // Different types
1379 {
1380 Spec spec;
1381
1382 VertexArrayState state;
1383
1384 state.attributes.push_back(Attribute());
1385
1386 state.attributes[0].enabled = true;
1387 state.attributes[0].size = 2;
1388 state.attributes[0].stride = 0;
1389 state.attributes[0].type = GL_SHORT;
1390 state.attributes[0].integer = GL_FALSE;
1391 state.attributes[0].divisor = 0;
1392 state.attributes[0].offset = 0;
1393 state.attributes[0].normalized = GL_TRUE;
1394 state.attributes[0].bufferNdx = 1;
1395
1396 state.elementArrayBuffer = 0;
1397
1398 spec.buffers.push_back(shortCoordBuffer48);
1399
1400 spec.useDrawElements = false;
1401 spec.instances = 0;
1402 spec.count = 24;
1403 spec.vao = state;
1404 spec.state = state;
1405 spec.indexOffset = 0;
1406 spec.indexRangeMin = 0;
1407 spec.indexRangeMax = 0;
1408 spec.indexType = GL_NONE;
1409 spec.indexCount = 0;
1410
1411 spec.vao.attributes[0].type = GL_SHORT;
1412 spec.state.attributes[0].type = GL_BYTE;
1413 addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type"));
1414 }
1415 // Different "integer"
1416 {
1417 Spec spec;
1418
1419 VertexArrayState state;
1420
1421 state.attributes.push_back(Attribute());
1422
1423 state.attributes[0].enabled = true;
1424 state.attributes[0].size = 2;
1425 state.attributes[0].stride = 0;
1426 state.attributes[0].type = GL_BYTE;
1427 state.attributes[0].integer = GL_TRUE;
1428 state.attributes[0].divisor = 0;
1429 state.attributes[0].offset = 0;
1430 state.attributes[0].normalized = GL_FALSE;
1431 state.attributes[0].bufferNdx = 1;
1432
1433 state.elementArrayBuffer = 0;
1434
1435 spec.buffers.push_back(shortCoordBuffer48);
1436
1437 spec.useDrawElements = false;
1438 spec.count = 24;
1439 spec.vao = state;
1440 spec.state = state;
1441 spec.instances = 0;
1442 spec.indexOffset = 0;
1443 spec.indexRangeMin = 0;
1444 spec.indexRangeMax = 0;
1445 spec.indexType = GL_NONE;
1446 spec.indexCount = 0;
1447
1448 spec.state.attributes[0].integer = GL_FALSE;
1449 spec.vao.attributes[0].integer = GL_TRUE;
1450 addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer"));
1451 }
1452 // Different divisor
1453 {
1454 Spec spec;
1455
1456 VertexArrayState state;
1457
1458 state.attributes.push_back(Attribute());
1459 state.attributes.push_back(Attribute());
1460
1461 state.attributes[0].enabled = true;
1462 state.attributes[0].size = 2;
1463 state.attributes[0].stride = 0;
1464 state.attributes[0].type = GL_SHORT;
1465 state.attributes[0].integer = GL_FALSE;
1466 state.attributes[0].divisor = 0;
1467 state.attributes[0].offset = 0;
1468 state.attributes[0].normalized = GL_TRUE;
1469 state.attributes[0].bufferNdx = 1;
1470
1471 state.attributes[1].enabled = true;
1472 state.attributes[1].size = 4;
1473 state.attributes[1].stride = 0;
1474 state.attributes[1].type = GL_FLOAT;
1475 state.attributes[1].integer = GL_FALSE;
1476 state.attributes[1].divisor = 0;
1477 state.attributes[1].offset = 0;
1478 state.attributes[1].normalized = GL_FALSE;
1479 state.attributes[1].bufferNdx = 2;
1480
1481 state.elementArrayBuffer = 0;
1482
1483 spec.buffers.push_back(shortCoordBuffer48);
1484 spec.buffers.push_back(floatCoordBuffer48_1);
1485
1486 spec.useDrawElements = false;
1487 spec.instances = 10;
1488 spec.count = 12;
1489 spec.vao = state;
1490 spec.state = state;
1491 spec.indexOffset = 0;
1492 spec.indexRangeMin = 0;
1493 spec.indexRangeMax = 0;
1494 spec.indexType = GL_NONE;
1495 spec.indexCount = 0;
1496
1497 spec.vao.attributes[1].divisor = 3;
1498 spec.state.attributes[1].divisor = 2;
1499
1500 addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor"));
1501 }
1502 // Different offset
1503 {
1504 Spec spec;
1505
1506 VertexArrayState state;
1507
1508 state.attributes.push_back(Attribute());
1509
1510 state.attributes[0].enabled = true;
1511 state.attributes[0].size = 2;
1512 state.attributes[0].stride = 0;
1513 state.attributes[0].type = GL_SHORT;
1514 state.attributes[0].integer = GL_FALSE;
1515 state.attributes[0].divisor = 0;
1516 state.attributes[0].offset = 0;
1517 state.attributes[0].normalized = GL_TRUE;
1518 state.attributes[0].bufferNdx = 1;
1519
1520 state.elementArrayBuffer = 0;
1521
1522 spec.buffers.push_back(shortCoordBuffer48);
1523
1524 spec.useDrawElements = false;
1525 spec.instances = 0;
1526 spec.count = 24;
1527 spec.vao = state;
1528 spec.state = state;
1529 spec.indexOffset = 0;
1530 spec.indexRangeMin = 0;
1531 spec.indexRangeMax = 0;
1532 spec.indexType = GL_NONE;
1533 spec.indexCount = 0;
1534
1535 spec.vao.attributes[0].offset = 2;
1536 spec.state.attributes[0].offset = 4;
1537 addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset"));
1538 }
1539 // Different normalize
1540 {
1541 Spec spec;
1542
1543 VertexArrayState state;
1544
1545 state.attributes.push_back(Attribute());
1546
1547 state.attributes[0].enabled = true;
1548 state.attributes[0].size = 2;
1549 state.attributes[0].stride = 0;
1550 state.attributes[0].type = GL_SHORT;
1551 state.attributes[0].integer = GL_FALSE;
1552 state.attributes[0].divisor = 0;
1553 state.attributes[0].offset = 0;
1554 state.attributes[0].normalized = GL_TRUE;
1555 state.attributes[0].bufferNdx = 1;
1556
1557 state.elementArrayBuffer = 0;
1558
1559 spec.buffers.push_back(shortCoordBuffer48);
1560
1561 spec.useDrawElements = false;
1562 spec.instances = 0;
1563 spec.count = 48;
1564 spec.vao = state;
1565 spec.state = state;
1566 spec.indexOffset = 0;
1567 spec.indexRangeMin = 0;
1568 spec.indexRangeMax = 0;
1569 spec.indexType = GL_NONE;
1570 spec.indexCount = 0;
1571
1572 spec.vao.attributes[0].normalized = GL_TRUE;
1573 spec.state.attributes[0].normalized = GL_FALSE;
1574 addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize"));
1575 }
1576 // DrawElements with buffer / Pointer
1577 {
1578 Spec spec;
1579
1580 VertexArrayState state;
1581
1582 state.attributes.push_back(Attribute());
1583
1584 state.attributes[0].enabled = true;
1585 state.attributes[0].size = 2;
1586 state.attributes[0].stride = 0;
1587 state.attributes[0].type = GL_FLOAT;
1588 state.attributes[0].integer = GL_FALSE;
1589 state.attributes[0].divisor = 0;
1590 state.attributes[0].offset = 0;
1591 state.attributes[0].normalized = GL_TRUE;
1592 state.attributes[0].bufferNdx = 1;
1593
1594 state.elementArrayBuffer = 0;
1595
1596 spec.buffers.push_back(floatCoordBuffer48_1);
1597
1598 BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f };
1599 spec.buffers.push_back(indexBuffer);
1600
1601 spec.useDrawElements = true;
1602 spec.count = 24;
1603 spec.vao = state;
1604 spec.state = state;
1605 spec.instances = 0;
1606 spec.indexOffset = 0;
1607 spec.indexRangeMin = 0;
1608 spec.indexRangeMax = 48;
1609 spec.indexType = GL_UNSIGNED_SHORT;
1610 spec.indexCount = 24;
1611
1612 spec.state.elementArrayBuffer = 0;
1613 spec.vao.elementArrayBuffer = 2;
1614 addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices"));
1615 }
1616 // Use all attributes
1617
1618 addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes"));
1619 }
1620
1621 } // Functional
1622 } // gles3
1623 } // deqp
1624