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