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 if (m_spec.useDrawElements)
573 {
574 if (state.elementArrayBuffer == 0)
575 {
576 if (m_spec.instances == 0)
577 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
578 else
579 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
580 }
581 else
582 {
583 if (m_spec.instances == 0)
584 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
585 else
586 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
587 }
588 }
589 else
590 {
591 if (m_spec.instances == 0)
592 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
593 else
594 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
595 }
596 }
597
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)598 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
599 {
600 GLuint vao = 0;
601
602 GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
603 GLU_CHECK_CALL(glBindVertexArray(vao));
604 setState(m_spec.vao);
605 GLU_CHECK_CALL(glBindVertexArray(0));
606
607 setState(m_spec.state);
608
609 GLU_CHECK_CALL(glBindVertexArray(vao));
610 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
611 makeDrawCall(m_spec.vao);
612 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
613 setState(m_spec.vao);
614 GLU_CHECK_CALL(glBindVertexArray(0));
615
616 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
617 makeDrawCall(m_spec.state);
618 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
619 }
620
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)621 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
622 {
623 setState(m_spec.vao);
624 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
625 makeDrawCall(m_spec.vao);
626 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
627
628 setState(m_spec.state);
629 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
630 makeDrawCall(m_spec.state);
631 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
632 }
633
iterate(void)634 TestCase::IterateResult VertexArrayObjectTest::iterate (void)
635 {
636 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
637 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
638
639 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
640 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
641
642 bool isOk;
643
644 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
645 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
646 genReferences(stateReference, vaoReference);
647 render(stateResult, vaoResult);
648
649 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);
650 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);
651
652 if (isOk)
653 {
654 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
655 return STOP;
656 }
657 else
658 {
659 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
660 return STOP;
661 }
662 }
663
664 class MultiVertexArrayObjectTest : public TestCase
665 {
666 public:
667
668 MultiVertexArrayObjectTest (Context& context, const char* name, const char* description);
669 ~MultiVertexArrayObjectTest (void);
670 virtual void init (void);
671 virtual void deinit (void);
672 virtual IterateResult iterate (void);
673
674 private:
675 Spec m_spec;
676 tcu::TestLog& m_log;
677 vector<GLuint> m_buffers;
678 glu::ShaderProgram* m_vaoProgram;
679 glu::ShaderProgram* m_stateProgram;
680 de::Random m_random;
681 deUint8* m_indices;
682
683 void logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
684 deUint8* createRandomBufferData (const BufferSpec& buffer);
685 deUint8* generateIndices (void);
686 glu::ShaderProgram* createProgram (const VertexArrayState& state);
687 void setState (const VertexArrayState& state);
688 void render (tcu::Surface& vaoResult, tcu::Surface& defaultResult);
689 void makeDrawCall (const VertexArrayState& state);
690 void genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef);
691
692 MultiVertexArrayObjectTest (const MultiVertexArrayObjectTest&);
693 MultiVertexArrayObjectTest& operator= (const MultiVertexArrayObjectTest&);
694 };
695
MultiVertexArrayObjectTest(Context & context,const char * name,const char * description)696 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description)
697 : TestCase (context, name, description)
698 , m_log (context.getTestContext().getLog())
699 , m_vaoProgram (NULL)
700 , m_stateProgram (NULL)
701 , m_random (deStringHash(name))
702 , m_indices (NULL)
703 {
704 // Makes zero to zero mapping for buffers
705 m_buffers.push_back(0);
706 }
707
~MultiVertexArrayObjectTest(void)708 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void)
709 {
710 }
711
logVertexArrayState(tcu::TestLog & log,const VertexArrayState & state,const std::string & msg)712 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
713 {
714 std::stringstream message;
715
716 message << msg << "\n";
717 message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
718
719 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
720 {
721 message
722 << "attribute : " << attribNdx << "\n"
723 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") << "\n"
724 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size << "\n"
725 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride << "\n"
726 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type << "\n"
727 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") << "\n"
728 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") << "\n"
729 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor << "\n"
730 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset << "\n"
731 << "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] << "\n";
732 }
733 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
734 }
735
736
init(void)737 void MultiVertexArrayObjectTest::init (void)
738 {
739 GLint attribCount;
740
741 GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount));
742
743 m_spec.useDrawElements = false;
744 m_spec.instances = 0;
745 m_spec.count = 24;
746 m_spec.indexOffset = 0;
747 m_spec.indexRangeMin = 0;
748 m_spec.indexRangeMax = 0;
749 m_spec.indexType = GL_NONE;
750 m_spec.indexCount = 0;
751 m_spec.vao.elementArrayBuffer = 0;
752 m_spec.state.elementArrayBuffer = 0;
753
754 for (int attribNdx = 0; attribNdx < attribCount; attribNdx++)
755 {
756 BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
757 m_spec.buffers.push_back(shortCoordBuffer48);
758
759 m_spec.state.attributes.push_back(Attribute());
760 m_spec.state.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
761 m_spec.state.attributes[attribNdx].size = m_random.getInt(2,4);
762 m_spec.state.attributes[attribNdx].stride = 2*m_random.getInt(1, 3);
763 m_spec.state.attributes[attribNdx].type = GL_SHORT;
764 m_spec.state.attributes[attribNdx].integer = m_random.getBool();
765 m_spec.state.attributes[attribNdx].divisor = m_random.getInt(0, 1);
766 m_spec.state.attributes[attribNdx].offset = 2*m_random.getInt(0, 2);
767 m_spec.state.attributes[attribNdx].normalized = m_random.getBool();
768 m_spec.state.attributes[attribNdx].bufferNdx = attribNdx+1;
769
770 if (attribNdx == 0)
771 {
772 m_spec.state.attributes[attribNdx].divisor = 0;
773 m_spec.state.attributes[attribNdx].enabled = GL_TRUE;
774 m_spec.state.attributes[attribNdx].size = 2;
775 }
776
777 m_spec.vao.attributes.push_back(Attribute());
778 m_spec.vao.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
779 m_spec.vao.attributes[attribNdx].size = m_random.getInt(2,4);
780 m_spec.vao.attributes[attribNdx].stride = 2*m_random.getInt(1, 3);
781 m_spec.vao.attributes[attribNdx].type = GL_SHORT;
782 m_spec.vao.attributes[attribNdx].integer = m_random.getBool();
783 m_spec.vao.attributes[attribNdx].divisor = m_random.getInt(0, 1);
784 m_spec.vao.attributes[attribNdx].offset = 2*m_random.getInt(0, 2);
785 m_spec.vao.attributes[attribNdx].normalized = m_random.getBool();
786 m_spec.vao.attributes[attribNdx].bufferNdx = attribCount - attribNdx;
787
788 if (attribNdx == 0)
789 {
790 m_spec.vao.attributes[attribNdx].divisor = 0;
791 m_spec.vao.attributes[attribNdx].enabled = GL_TRUE;
792 m_spec.vao.attributes[attribNdx].size = 2;
793 }
794
795 }
796
797 // \note [mika] Index 0 is reserved for 0 buffer
798 for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
799 {
800 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
801
802 try
803 {
804 GLuint buffer;
805 GLU_CHECK_CALL(glGenBuffers(1, &buffer));
806 m_buffers.push_back(buffer);
807
808 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
809 GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
810 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
811
812 } catch (...) {
813 delete[] data;
814 throw;
815 }
816
817 delete[] data;
818 }
819
820 m_vaoProgram = createProgram(m_spec.vao);
821 m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
822 m_log << *m_vaoProgram;
823 m_stateProgram = createProgram(m_spec.state);
824 m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
825 m_log << *m_stateProgram;
826
827 if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
828 TCU_FAIL("Failed to compile shaders");
829
830 if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
831 m_indices = generateIndices();
832 }
833
deinit(void)834 void MultiVertexArrayObjectTest::deinit (void)
835 {
836 GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
837 m_buffers.clear();
838 delete m_vaoProgram;
839 delete m_stateProgram;
840 delete[] m_indices;
841 }
842
generateIndices(void)843 deUint8* MultiVertexArrayObjectTest::generateIndices (void)
844 {
845 int typeSize = 0;
846 switch (m_spec.indexType)
847 {
848 case GL_UNSIGNED_INT: typeSize = sizeof(GLuint); break;
849 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort); break;
850 case GL_UNSIGNED_BYTE: typeSize = sizeof(GLubyte); break;
851 default:
852 DE_ASSERT(false);
853 }
854
855 deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
856
857 for (int i = 0; i < m_spec.indexCount; i++)
858 {
859 deUint8* pos = indices + typeSize * i;
860
861 switch (m_spec.indexType)
862 {
863 case GL_UNSIGNED_INT:
864 {
865 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
866 deMemcpy(pos, &v, sizeof(v));
867 break;
868 }
869
870 case GL_UNSIGNED_SHORT:
871 {
872 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
873 deMemcpy(pos, &v, sizeof(v));
874 break;
875 }
876
877 case GL_UNSIGNED_BYTE:
878 {
879 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
880 deMemcpy(pos, &v, sizeof(v));
881 break;
882 }
883
884 default:
885 DE_ASSERT(false);
886 }
887 }
888
889 return indices;
890 }
891
createRandomBufferData(const BufferSpec & buffer)892 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
893 {
894 deUint8* data = new deUint8[buffer.size];
895
896 int stride;
897
898 if (buffer.stride != 0)
899 {
900 stride = buffer.stride;
901 }
902 else
903 {
904 switch (buffer.type)
905 {
906 case GL_FLOAT: stride = buffer.componentCount * (int)sizeof(GLfloat); break;
907 case GL_INT: stride = buffer.componentCount * (int)sizeof(GLint); break;
908 case GL_UNSIGNED_INT: stride = buffer.componentCount * (int)sizeof(GLuint); break;
909 case GL_SHORT: stride = buffer.componentCount * (int)sizeof(GLshort); break;
910 case GL_UNSIGNED_SHORT: stride = buffer.componentCount * (int)sizeof(GLushort); break;
911 case GL_BYTE: stride = buffer.componentCount * (int)sizeof(GLbyte); break;
912 case GL_UNSIGNED_BYTE: stride = buffer.componentCount * (int)sizeof(GLubyte); break;
913
914 default:
915 stride = 0;
916 DE_ASSERT(DE_FALSE);
917 }
918 }
919
920 deUint8* itr = data;
921
922 for (int pos = 0; pos < buffer.count; pos++)
923 {
924 deUint8* componentItr = itr;
925 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
926 {
927 switch (buffer.type)
928 {
929 case GL_FLOAT:
930 {
931 float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
932 deMemcpy(componentItr, &v, sizeof(v));
933 componentItr += sizeof(v);
934 break;
935 }
936
937 case GL_INT:
938 {
939 GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
940 deMemcpy(componentItr, &v, sizeof(v));
941 componentItr += sizeof(v);
942 break;
943 }
944
945 case GL_UNSIGNED_INT:
946 {
947 GLuint v = (GLuint)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
948 deMemcpy(componentItr, &v, sizeof(v));
949 componentItr += sizeof(v);
950 break;
951 }
952
953 case GL_SHORT:
954 {
955 GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
956 deMemcpy(componentItr, &v, sizeof(v));
957 componentItr += sizeof(v);
958 break;
959 }
960
961 case GL_UNSIGNED_SHORT:
962 {
963 GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
964 deMemcpy(componentItr, &v, sizeof(v));
965 componentItr += sizeof(v);
966 break;
967 }
968
969 case GL_BYTE:
970 {
971 GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
972 deMemcpy(componentItr, &v, sizeof(v));
973 componentItr += sizeof(v);
974 break;
975 }
976
977 case GL_UNSIGNED_BYTE:
978 {
979 GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
980 deMemcpy(componentItr, &v, sizeof(v));
981 componentItr += sizeof(v);
982 break;
983 }
984
985 default:
986 DE_ASSERT(false);
987 };
988 }
989
990 itr += stride;
991 }
992
993 return data;
994 }
995
createProgram(const VertexArrayState & state)996 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state)
997 {
998 std::stringstream vertexShaderStream;
999 std::stringstream value;
1000
1001 vertexShaderStream << "#version 300 es\n";
1002
1003 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1004 {
1005 if (state.attributes[attribNdx].integer)
1006 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
1007 else
1008 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
1009
1010 if (state.attributes[attribNdx].integer)
1011 {
1012 float scale = 0.0f;
1013
1014 switch (state.attributes[0].type)
1015 {
1016 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1017 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1018 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1019 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1020 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1021 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1022
1023 default:
1024 DE_ASSERT(DE_FALSE);
1025 }
1026 value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
1027 }
1028 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
1029 {
1030 float scale = 0.0f;
1031
1032 switch (state.attributes[0].type)
1033 {
1034 case GL_SHORT: scale = (0.5f/float((1u<<14)-1u)); break;
1035 case GL_UNSIGNED_SHORT: scale = (0.5f/float((1u<<15)-1u)); break;
1036 case GL_INT: scale = (0.5f/float((1u<<30)-1u)); break;
1037 case GL_UNSIGNED_INT: scale = (0.5f/float((1u<<31)-1u)); break;
1038 case GL_BYTE: scale = (0.5f/float((1u<<6)-1u)); break;
1039 case GL_UNSIGNED_BYTE: scale = (0.5f/float((1u<<7)-1u)); break;
1040
1041 default:
1042 DE_ASSERT(DE_FALSE);
1043 }
1044 value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
1045 }
1046 else
1047 value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
1048 }
1049
1050 vertexShaderStream
1051 << "out mediump vec4 v_value;\n"
1052 << "void main (void)\n"
1053 << "{\n"
1054 << "\tv_value = " << value.str() << ";\n";
1055
1056 if (state.attributes[0].integer)
1057 {
1058 float scale = 0.0f;
1059
1060 switch (state.attributes[0].type)
1061 {
1062 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1063 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1064 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1065 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1066 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1067 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1068
1069
1070 default:
1071 DE_ASSERT(DE_FALSE);
1072 }
1073
1074 vertexShaderStream
1075 << "\tgl_Position = vec4(" << scale << " * " << "a_attrib0.xyz, 1.0);\n"
1076 << "}";
1077 }
1078 else
1079 {
1080 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
1081 {
1082 vertexShaderStream
1083 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
1084 << "}";
1085 }
1086 else
1087 {
1088 float scale = 0.0f;
1089
1090 switch (state.attributes[0].type)
1091 {
1092 case GL_SHORT: scale = (1.0f/float((1u<<14)-1u)); break;
1093 case GL_UNSIGNED_SHORT: scale = (1.0f/float((1u<<15)-1u)); break;
1094 case GL_INT: scale = (1.0f/float((1u<<30)-1u)); break;
1095 case GL_UNSIGNED_INT: scale = (1.0f/float((1u<<31)-1u)); break;
1096 case GL_BYTE: scale = (1.0f/float((1u<<6)-1u)); break;
1097 case GL_UNSIGNED_BYTE: scale = (1.0f/float((1u<<7)-1u)); break;
1098
1099 default:
1100 DE_ASSERT(DE_FALSE);
1101 }
1102
1103 scale *= 0.5f;
1104
1105 vertexShaderStream
1106 << "\tgl_Position = vec4(" << scale << " * " << "vec3(a_attrib0.xyz), 1.0);\n"
1107 << "}";
1108 }
1109 }
1110
1111 const char* fragmentShader =
1112 "#version 300 es\n"
1113 "in mediump vec4 v_value;\n"
1114 "layout(location = 0) out mediump vec4 fragColor;\n"
1115 "void main (void)\n"
1116 "{\n"
1117 "\tfragColor = vec4(v_value.xyz, 1.0);\n"
1118 "}";
1119
1120 return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
1121 }
1122
setState(const VertexArrayState & state)1123 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state)
1124 {
1125 GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
1126
1127 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1128 {
1129 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
1130 if (state.attributes[attribNdx].enabled)
1131 GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
1132 else
1133 GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
1134
1135 if (state.attributes[attribNdx].integer)
1136 GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1137 else
1138 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)));
1139
1140 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
1141 }
1142 }
1143
makeDrawCall(const VertexArrayState & state)1144 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
1145 {
1146 GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
1147 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1148
1149 if (m_spec.useDrawElements)
1150 {
1151 if (state.elementArrayBuffer == 0)
1152 {
1153 if (m_spec.instances == 0)
1154 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
1155 else
1156 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
1157 }
1158 else
1159 {
1160 if (m_spec.instances == 0)
1161 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
1162 else
1163 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
1164 }
1165 }
1166 else
1167 {
1168 if (m_spec.instances == 0)
1169 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
1170 else
1171 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
1172 }
1173 }
1174
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)1175 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
1176 {
1177 GLuint vao = 0;
1178
1179 GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
1180 GLU_CHECK_CALL(glBindVertexArray(vao));
1181 setState(m_spec.vao);
1182 GLU_CHECK_CALL(glBindVertexArray(0));
1183
1184 setState(m_spec.state);
1185
1186 GLU_CHECK_CALL(glBindVertexArray(vao));
1187 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1188 makeDrawCall(m_spec.vao);
1189 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
1190 setState(m_spec.vao);
1191 GLU_CHECK_CALL(glBindVertexArray(0));
1192
1193 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1194 makeDrawCall(m_spec.state);
1195 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
1196 }
1197
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)1198 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
1199 {
1200 setState(m_spec.vao);
1201 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1202 makeDrawCall(m_spec.vao);
1203 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
1204
1205 setState(m_spec.state);
1206 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1207 makeDrawCall(m_spec.state);
1208 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
1209 }
1210
iterate(void)1211 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void)
1212 {
1213 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1214 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1215
1216 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1217 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1218
1219 bool isOk;
1220
1221 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
1222 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
1223 genReferences(stateReference, vaoReference);
1224 render(stateResult, vaoResult);
1225
1226 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);
1227 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);
1228
1229 if (isOk)
1230 {
1231 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1232 return STOP;
1233 }
1234 else
1235 {
1236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1237 return STOP;
1238 }
1239 }
1240
VertexArrayObjectTestGroup(Context & context)1241 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context)
1242 : TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases")
1243 {
1244 }
1245
~VertexArrayObjectTestGroup(void)1246 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void)
1247 {
1248 }
1249
init(void)1250 void VertexArrayObjectTestGroup::init (void)
1251 {
1252 BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1253 BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1254
1255 BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
1256
1257 // Different buffer
1258 {
1259 Spec spec;
1260
1261 VertexArrayState state;
1262
1263 state.attributes.push_back(Attribute());
1264
1265 state.attributes[0].enabled = true;
1266 state.attributes[0].size = 2;
1267 state.attributes[0].stride = 0;
1268 state.attributes[0].type = GL_FLOAT;
1269 state.attributes[0].integer = GL_FALSE;
1270 state.attributes[0].divisor = 0;
1271 state.attributes[0].offset = 0;
1272 state.attributes[0].normalized = GL_FALSE;
1273
1274 state.elementArrayBuffer = 0;
1275
1276 spec.buffers.push_back(floatCoordBuffer48_1);
1277 spec.buffers.push_back(floatCoordBuffer48_2);
1278
1279 spec.useDrawElements = false;
1280 spec.instances = 0;
1281 spec.count = 48;
1282 spec.vao = state;
1283 spec.state = state;
1284 spec.indexOffset = 0;
1285 spec.indexRangeMin = 0;
1286 spec.indexRangeMax = 0;
1287 spec.indexType = GL_NONE;
1288 spec.indexCount = 0;
1289
1290 spec.state.attributes[0].bufferNdx = 1;
1291 spec.vao.attributes[0].bufferNdx = 2;
1292 addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer"));
1293 }
1294 // Different size
1295 {
1296 Spec spec;
1297
1298 VertexArrayState state;
1299
1300 state.attributes.push_back(Attribute());
1301
1302 state.attributes[0].enabled = true;
1303 state.attributes[0].size = 2;
1304 state.attributes[0].stride = 0;
1305 state.attributes[0].type = GL_FLOAT;
1306 state.attributes[0].integer = GL_FALSE;
1307 state.attributes[0].divisor = 0;
1308 state.attributes[0].offset = 0;
1309 state.attributes[0].normalized = GL_FALSE;
1310 state.attributes[0].bufferNdx = 1;
1311
1312 state.elementArrayBuffer = 0;
1313
1314 spec.buffers.push_back(floatCoordBuffer48_1);
1315
1316 spec.useDrawElements = false;
1317 spec.instances = 0;
1318 spec.count = 24;
1319 spec.vao = state;
1320 spec.state = state;
1321 spec.indexOffset = 0;
1322 spec.indexRangeMin = 0;
1323 spec.indexRangeMax = 0;
1324 spec.indexType = GL_NONE;
1325 spec.indexCount = 0;
1326
1327 spec.state.attributes[0].size = 2;
1328 spec.vao.attributes[0].size = 3;
1329 addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size"));
1330 }
1331
1332 // Different stride
1333 {
1334 Spec spec;
1335
1336 VertexArrayState state;
1337
1338 state.attributes.push_back(Attribute());
1339
1340 state.attributes[0].enabled = true;
1341 state.attributes[0].size = 2;
1342 state.attributes[0].stride = 0;
1343 state.attributes[0].type = GL_SHORT;
1344 state.attributes[0].integer = GL_FALSE;
1345 state.attributes[0].divisor = 0;
1346 state.attributes[0].offset = 0;
1347 state.attributes[0].normalized = GL_TRUE;
1348 state.attributes[0].bufferNdx = 1;
1349
1350 state.elementArrayBuffer = 0;
1351
1352 spec.buffers.push_back(shortCoordBuffer48);
1353
1354 spec.useDrawElements = false;
1355 spec.instances = 0;
1356 spec.count = 24;
1357 spec.vao = state;
1358 spec.state = state;
1359 spec.indexOffset = 0;
1360 spec.indexRangeMin = 0;
1361 spec.indexRangeMax = 0;
1362 spec.indexType = GL_NONE;
1363 spec.indexCount = 0;
1364
1365 spec.vao.attributes[0].stride = 2;
1366 spec.state.attributes[0].stride = 4;
1367 addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride"));
1368 }
1369
1370 // Different types
1371 {
1372 Spec spec;
1373
1374 VertexArrayState state;
1375
1376 state.attributes.push_back(Attribute());
1377
1378 state.attributes[0].enabled = true;
1379 state.attributes[0].size = 2;
1380 state.attributes[0].stride = 0;
1381 state.attributes[0].type = GL_SHORT;
1382 state.attributes[0].integer = GL_FALSE;
1383 state.attributes[0].divisor = 0;
1384 state.attributes[0].offset = 0;
1385 state.attributes[0].normalized = GL_TRUE;
1386 state.attributes[0].bufferNdx = 1;
1387
1388 state.elementArrayBuffer = 0;
1389
1390 spec.buffers.push_back(shortCoordBuffer48);
1391
1392 spec.useDrawElements = false;
1393 spec.instances = 0;
1394 spec.count = 24;
1395 spec.vao = state;
1396 spec.state = state;
1397 spec.indexOffset = 0;
1398 spec.indexRangeMin = 0;
1399 spec.indexRangeMax = 0;
1400 spec.indexType = GL_NONE;
1401 spec.indexCount = 0;
1402
1403 spec.vao.attributes[0].type = GL_SHORT;
1404 spec.state.attributes[0].type = GL_BYTE;
1405 addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type"));
1406 }
1407 // Different "integer"
1408 {
1409 Spec spec;
1410
1411 VertexArrayState state;
1412
1413 state.attributes.push_back(Attribute());
1414
1415 state.attributes[0].enabled = true;
1416 state.attributes[0].size = 2;
1417 state.attributes[0].stride = 0;
1418 state.attributes[0].type = GL_BYTE;
1419 state.attributes[0].integer = GL_TRUE;
1420 state.attributes[0].divisor = 0;
1421 state.attributes[0].offset = 0;
1422 state.attributes[0].normalized = GL_FALSE;
1423 state.attributes[0].bufferNdx = 1;
1424
1425 state.elementArrayBuffer = 0;
1426
1427 spec.buffers.push_back(shortCoordBuffer48);
1428
1429 spec.useDrawElements = false;
1430 spec.count = 24;
1431 spec.vao = state;
1432 spec.state = state;
1433 spec.instances = 0;
1434 spec.indexOffset = 0;
1435 spec.indexRangeMin = 0;
1436 spec.indexRangeMax = 0;
1437 spec.indexType = GL_NONE;
1438 spec.indexCount = 0;
1439
1440 spec.state.attributes[0].integer = GL_FALSE;
1441 spec.vao.attributes[0].integer = GL_TRUE;
1442 addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer"));
1443 }
1444 // Different divisor
1445 {
1446 Spec spec;
1447
1448 VertexArrayState state;
1449
1450 state.attributes.push_back(Attribute());
1451 state.attributes.push_back(Attribute());
1452
1453 state.attributes[0].enabled = true;
1454 state.attributes[0].size = 2;
1455 state.attributes[0].stride = 0;
1456 state.attributes[0].type = GL_SHORT;
1457 state.attributes[0].integer = GL_FALSE;
1458 state.attributes[0].divisor = 0;
1459 state.attributes[0].offset = 0;
1460 state.attributes[0].normalized = GL_TRUE;
1461 state.attributes[0].bufferNdx = 1;
1462
1463 state.attributes[1].enabled = true;
1464 state.attributes[1].size = 4;
1465 state.attributes[1].stride = 0;
1466 state.attributes[1].type = GL_FLOAT;
1467 state.attributes[1].integer = GL_FALSE;
1468 state.attributes[1].divisor = 0;
1469 state.attributes[1].offset = 0;
1470 state.attributes[1].normalized = GL_FALSE;
1471 state.attributes[1].bufferNdx = 2;
1472
1473 state.elementArrayBuffer = 0;
1474
1475 spec.buffers.push_back(shortCoordBuffer48);
1476 spec.buffers.push_back(floatCoordBuffer48_1);
1477
1478 spec.useDrawElements = false;
1479 spec.instances = 10;
1480 spec.count = 12;
1481 spec.vao = state;
1482 spec.state = state;
1483 spec.indexOffset = 0;
1484 spec.indexRangeMin = 0;
1485 spec.indexRangeMax = 0;
1486 spec.indexType = GL_NONE;
1487 spec.indexCount = 0;
1488
1489 spec.vao.attributes[1].divisor = 3;
1490 spec.state.attributes[1].divisor = 2;
1491
1492 addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor"));
1493 }
1494 // Different offset
1495 {
1496 Spec spec;
1497
1498 VertexArrayState state;
1499
1500 state.attributes.push_back(Attribute());
1501
1502 state.attributes[0].enabled = true;
1503 state.attributes[0].size = 2;
1504 state.attributes[0].stride = 0;
1505 state.attributes[0].type = GL_SHORT;
1506 state.attributes[0].integer = GL_FALSE;
1507 state.attributes[0].divisor = 0;
1508 state.attributes[0].offset = 0;
1509 state.attributes[0].normalized = GL_TRUE;
1510 state.attributes[0].bufferNdx = 1;
1511
1512 state.elementArrayBuffer = 0;
1513
1514 spec.buffers.push_back(shortCoordBuffer48);
1515
1516 spec.useDrawElements = false;
1517 spec.instances = 0;
1518 spec.count = 24;
1519 spec.vao = state;
1520 spec.state = state;
1521 spec.indexOffset = 0;
1522 spec.indexRangeMin = 0;
1523 spec.indexRangeMax = 0;
1524 spec.indexType = GL_NONE;
1525 spec.indexCount = 0;
1526
1527 spec.vao.attributes[0].offset = 2;
1528 spec.state.attributes[0].offset = 4;
1529 addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset"));
1530 }
1531 // Different normalize
1532 {
1533 Spec spec;
1534
1535 VertexArrayState state;
1536
1537 state.attributes.push_back(Attribute());
1538
1539 state.attributes[0].enabled = true;
1540 state.attributes[0].size = 2;
1541 state.attributes[0].stride = 0;
1542 state.attributes[0].type = GL_SHORT;
1543 state.attributes[0].integer = GL_FALSE;
1544 state.attributes[0].divisor = 0;
1545 state.attributes[0].offset = 0;
1546 state.attributes[0].normalized = GL_TRUE;
1547 state.attributes[0].bufferNdx = 1;
1548
1549 state.elementArrayBuffer = 0;
1550
1551 spec.buffers.push_back(shortCoordBuffer48);
1552
1553 spec.useDrawElements = false;
1554 spec.instances = 0;
1555 spec.count = 48;
1556 spec.vao = state;
1557 spec.state = state;
1558 spec.indexOffset = 0;
1559 spec.indexRangeMin = 0;
1560 spec.indexRangeMax = 0;
1561 spec.indexType = GL_NONE;
1562 spec.indexCount = 0;
1563
1564 spec.vao.attributes[0].normalized = GL_TRUE;
1565 spec.state.attributes[0].normalized = GL_FALSE;;
1566 addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize"));
1567 }
1568 // DrawElements with buffer / Pointer
1569 {
1570 Spec spec;
1571
1572 VertexArrayState state;
1573
1574 state.attributes.push_back(Attribute());
1575
1576 state.attributes[0].enabled = true;
1577 state.attributes[0].size = 2;
1578 state.attributes[0].stride = 0;
1579 state.attributes[0].type = GL_FLOAT;
1580 state.attributes[0].integer = GL_FALSE;
1581 state.attributes[0].divisor = 0;
1582 state.attributes[0].offset = 0;
1583 state.attributes[0].normalized = GL_TRUE;
1584 state.attributes[0].bufferNdx = 1;
1585
1586 state.elementArrayBuffer = 0;
1587
1588 spec.buffers.push_back(floatCoordBuffer48_1);
1589
1590 BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f };
1591 spec.buffers.push_back(indexBuffer);
1592
1593 spec.useDrawElements = true;
1594 spec.count = 24;
1595 spec.vao = state;
1596 spec.state = state;
1597 spec.instances = 0;
1598 spec.indexOffset = 0;
1599 spec.indexRangeMin = 0;
1600 spec.indexRangeMax = 48;
1601 spec.indexType = GL_UNSIGNED_SHORT;
1602 spec.indexCount = 24;
1603
1604 spec.state.elementArrayBuffer = 0;
1605 spec.vao.elementArrayBuffer = 2;
1606 addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices"));
1607 }
1608 // Use all attributes
1609
1610 addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes"));
1611 }
1612
1613 } // Functional
1614 } // gles3
1615 } // deqp
1616