1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2017 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief GL_EXT_draw_elements_base_vertex tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es31fDrawElementsBaseVertexTests.hpp"
25 #include "deRandom.hpp"
26 #include "deStringUtil.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "sglrGLContext.hpp"
30 #include "glsDrawTest.hpp"
31 #include "gluStrUtil.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluContextInfo.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
56 enum TestIterationType
58 TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives
59 TYPE_INSTANCE_COUNT, // !< test with 1, 4, and 11 instances
64 static size_t getElementCount (gls::DrawTestSpec::Primitive primitive, size_t primitiveCount)
68 case gls::DrawTestSpec::PRIMITIVE_POINTS: return primitiveCount;
69 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES: return primitiveCount * 3;
70 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN: return primitiveCount + 2;
71 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP: return primitiveCount + 2;
72 case gls::DrawTestSpec::PRIMITIVE_LINES: return primitiveCount * 2;
73 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP: return primitiveCount + 1;
74 case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP: return (primitiveCount==1) ? (2) : (primitiveCount);
75 case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY: return primitiveCount * 4;
76 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY: return primitiveCount + 3;
77 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY: return primitiveCount * 6;
78 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY: return primitiveCount * 2 + 4;
85 static void addRangeElementsToSpec (gls::DrawTestSpec& spec)
87 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
90 spec.indexMax = (int)getElementCount(spec.primitive, spec.primitiveCount);
94 static void addTestIterations (gls::DrawTest* test, gls::DrawTestSpec& spec, TestIterationType type)
96 if (type == TYPE_DRAW_COUNT)
98 spec.primitiveCount = 1;
99 addRangeElementsToSpec(spec);
100 test->addIteration(spec, "draw count = 1");
102 spec.primitiveCount = 5;
103 addRangeElementsToSpec(spec);
104 test->addIteration(spec, "draw count = 5");
106 spec.primitiveCount = 25;
107 addRangeElementsToSpec(spec);
108 test->addIteration(spec, "draw count = 25");
110 else if (type == TYPE_INSTANCE_COUNT)
112 spec.instanceCount = 1;
113 addRangeElementsToSpec(spec);
114 test->addIteration(spec, "instance count = 1");
116 spec.instanceCount = 4;
117 addRangeElementsToSpec(spec);
118 test->addIteration(spec, "instance count = 4");
120 spec.instanceCount = 11;
121 addRangeElementsToSpec(spec);
122 test->addIteration(spec, "instance count = 11");
128 static void genBasicSpec (gls::DrawTestSpec& spec, glu::ContextType& contextType, gls::DrawTestSpec::DrawMethod method)
130 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI();
131 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
132 spec.primitiveCount = 5;
133 spec.drawMethod = method;
134 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST;
135 spec.indexPointerOffset = 0;
136 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST;
140 spec.instanceCount = 1;
141 spec.indirectOffset = 0;
143 spec.attribs.resize(2);
145 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
146 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
147 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
148 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
149 spec.attribs[0].componentCount = 4;
150 spec.attribs[0].offset = 0;
151 spec.attribs[0].stride = 0;
152 spec.attribs[0].normalize = false;
153 spec.attribs[0].instanceDivisor = 0;
154 spec.attribs[0].useDefaultAttribute = false;
156 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
157 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
158 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
159 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
160 spec.attribs[1].componentCount = 2;
161 spec.attribs[1].offset = 0;
162 spec.attribs[1].stride = 0;
163 spec.attribs[1].normalize = false;
164 spec.attribs[1].instanceDivisor = 0;
165 spec.attribs[1].useDefaultAttribute = false;
167 addRangeElementsToSpec(spec);
170 class VertexIDCase : public TestCase
173 VertexIDCase (Context& context, gls::DrawTestSpec::DrawMethod drawMethod);
174 ~VertexIDCase (void);
178 IterateResult iterate (void);
180 void draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex);
181 void verifyImage (const tcu::Surface& image);
184 const glw::Functions& m_gl;
185 glu::ShaderProgram* m_program;
187 GLuint m_coordinatesBuffer;
188 GLuint m_elementsBuffer;
190 gls::DrawTestSpec::DrawMethod m_method;
200 MAX_VERTICES = 2*3 //!< 2 triangles, totals 6 vertices
204 VertexIDCase::VertexIDCase (Context& context, gls::DrawTestSpec::DrawMethod drawMethod)
205 : TestCase (context, "vertex_id", "gl_VertexID Test")
206 , m_gl (m_context.getRenderContext().getFunctions())
207 , m_program (DE_NULL)
209 , m_coordinatesBuffer (0)
210 , m_elementsBuffer (0)
212 , m_method (drawMethod)
216 VertexIDCase::~VertexIDCase (void)
218 VertexIDCase::deinit();
221 void VertexIDCase::init (void)
223 auto ctxType = m_context.getRenderContext().getType();
224 if (m_method == deqp::gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX ||
225 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX ||
226 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
228 const bool supportsES32orGL45 = contextSupports(ctxType, glu::ApiType::es(3, 2)) || contextSupports(ctxType, glu::ApiType::core(4, 5));
229 TCU_CHECK_AND_THROW(NotSupportedError, supportsES32orGL45 || m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_elements_base_vertex"), "GL_EXT_draw_elements_base_vertex is not supported.");
232 m_testCtx.getLog() << TestLog::Message
233 << "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. indices[i] + basevertex"
234 << TestLog::EndMessage;
236 DE_ASSERT(!m_program);
237 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
239 "in highp vec4 a_position;\n"
240 "out mediump vec4 v_color;\n"
241 "uniform highp vec4 u_colors[8];\n"
244 " gl_Position = a_position;\n"
245 " v_color = u_colors[gl_VertexID];\n"
249 "in mediump vec4 v_color;\n"
250 "layout(location = 0) out mediump vec4 o_color;\n"
253 " o_color = v_color;\n"
256 m_testCtx.getLog() << *m_program;
258 if (!m_program->isOk())
262 TCU_FAIL("Failed to compile shader program");
265 GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram()));
267 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
268 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer));
270 if (!glu::isContextTypeES(ctxType))
271 GLU_CHECK_GLW_CALL(m_gl, genVertexArrays(1, &m_vao));
274 void VertexIDCase::deinit (void)
279 if (m_elementsBuffer)
281 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer));
282 m_elementsBuffer = 0;
285 if (m_coordinatesBuffer)
287 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
288 m_coordinatesBuffer = 0;
293 GLU_CHECK_GLW_CALL(m_gl, deleteVertexArrays(1, &m_vao));
298 void VertexIDCase::draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex)
302 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX:
303 GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex));
306 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX:
308 GLint maxElementsVertices = 0;
309 GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices));
310 GLU_CHECK_GLW_CALL(m_gl, drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex));
314 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX:
315 GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex));
319 DE_FATAL("Draw method not supported");
323 void VertexIDCase::verifyImage (const tcu::Surface& image)
325 tcu::TestLog& log = m_testCtx.getLog();
328 const int colorThreshold = 0; // expect perfect match
329 tcu::Surface error (image.getWidth(), image.getHeight());
331 for (int y = 0; y < image.getHeight(); y++)
332 for (int x = 0; x < image.getWidth(); x++)
334 const tcu::RGBA pixel = image.getPixel(x, y);
337 // Ignore pixels not drawn with basevertex
338 if ((x < image.getWidth()* 1/4) || (x > image.getWidth() * 3/4)
339 || (y < image.getHeight() * 1/4) || (y > image.getHeight() * 3/4))
342 // Any pixel with !(B ~= 255) is faulty
343 if (de::abs(pixel.getBlue() - 255) > colorThreshold)
346 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
347 isOk = isOk && pixelOk;
352 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
353 log << TestLog::ImageSet("Verification result", "Result of rendering")
354 << TestLog::Image("Result", "Result", image)
355 << TestLog::Image("Error Mask", "Error mask", error)
356 << TestLog::EndImageSet;
360 log << TestLog::ImageSet("Verification result", "Result of rendering")
361 << TestLog::Image("Result", "Result", image)
362 << TestLog::EndImageSet;
366 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
368 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
371 VertexIDCase::IterateResult VertexIDCase::iterate (void)
373 const GLuint drawCount = 6;
374 const GLuint baseVertex = 4;
375 const GLuint coordLocation = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
376 const GLuint colorLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
378 tcu::Surface surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
380 const GLfloat coords[] =
382 // full viewport quad
388 // half viewport quad centred
395 const GLushort indices[] =
400 const GLfloat colors[] =
402 0.0f, 0.0f, 0.0f, 1.0f,
403 0.5f, 1.0f, 0.5f, 1.0f,
404 0.0f, 0.5f, 1.0f, 1.0f,
405 0.0f, 1.0f, 0.0f, 1.0f,
407 0.0f, 0.0f, 1.0f, 1.0f, // blue
408 0.0f, 0.0f, 1.0f, 1.0f, // blue
409 0.0f, 0.0f, 1.0f, 1.0f, // blue
410 0.0f, 0.0f, 1.0f, 1.0f, // blue
413 GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT));
414 GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white
415 GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT));
417 GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0]));
419 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
420 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
423 GLU_CHECK_GLW_CALL(m_gl, bindVertexArray(m_vao));
424 GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation));
425 GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
429 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter0", "Indices in client-side array");
430 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid*)indices, baseVertex);
435 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter1", "Indices in element array buffer");
436 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer));
437 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW));
438 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex);
441 glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess());
442 verifyImage(surface);
446 return (m_iterNdx < 2) ? CONTINUE : STOP;
449 class BuiltInVariableGroup : public TestCaseGroup
452 BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
453 ~BuiltInVariableGroup (void);
458 gls::DrawTestSpec::DrawMethod m_method;
461 BuiltInVariableGroup::BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
462 : TestCaseGroup (context, name, descr)
463 , m_method (drawMethod)
467 BuiltInVariableGroup::~BuiltInVariableGroup (void)
471 void BuiltInVariableGroup::init (void)
473 addChild(new VertexIDCase(m_context, m_method));
476 class IndexGroup : public TestCaseGroup
479 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
485 gls::DrawTestSpec::DrawMethod m_method;
488 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
489 : TestCaseGroup (context, name, descr)
490 , m_method (drawMethod)
494 IndexGroup::~IndexGroup (void)
498 void IndexGroup::init (void)
502 gls::DrawTestSpec::IndexType type;
506 const IndexTest tests[] =
508 { gls::DrawTestSpec::INDEXTYPE_BYTE, { 0, 1, -1 } },
509 { gls::DrawTestSpec::INDEXTYPE_SHORT, { 0, 2, -1 } },
510 { gls::DrawTestSpec::INDEXTYPE_INT, { 0, 4, -1 } },
513 gls::DrawTestSpec spec;
514 glu::ContextType contextType = m_context.getRenderContext().getType();
515 genBasicSpec(spec, contextType, m_method);
517 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
519 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
521 const IndexTest& indexTest = tests[testNdx];
523 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
524 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
525 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
527 spec.indexType = indexTest.type;
529 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
531 const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
532 spec.indexPointerOffset = indexTest.offsets[iterationNdx];
533 test->addIteration(spec, iterationDesc.c_str());
540 class BaseVertexGroup : public TestCaseGroup
543 BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
544 ~BaseVertexGroup (void);
549 gls::DrawTestSpec::DrawMethod m_method;
552 BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
553 : TestCaseGroup (context, name, descr)
554 , m_method (drawMethod)
558 BaseVertexGroup::~BaseVertexGroup (void)
562 void BaseVertexGroup::init (void)
567 gls::DrawTestSpec::IndexType type;
571 const IndexTest tests[] =
573 { true, gls::DrawTestSpec::INDEXTYPE_BYTE, { 1, 2 } },
574 { true, gls::DrawTestSpec::INDEXTYPE_SHORT, { 1, 2 } },
575 { true, gls::DrawTestSpec::INDEXTYPE_INT, { 1, 2 } },
576 { false, gls::DrawTestSpec::INDEXTYPE_BYTE, { -1, -2 } },
577 { false, gls::DrawTestSpec::INDEXTYPE_SHORT, { -1, -2 } },
578 { false, gls::DrawTestSpec::INDEXTYPE_INT, { -1, -2 } },
581 gls::DrawTestSpec spec;
582 glu::ContextType contextType = m_context.getRenderContext().getType();
583 genBasicSpec(spec, contextType, m_method);
585 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
587 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
589 const IndexTest& indexTest = tests[testNdx];
591 const std::string name = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
592 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
593 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
595 spec.indexType = indexTest.type;
597 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
599 const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
600 spec.baseVertex = indexTest.baseVertex[iterationNdx];
601 // spec.indexMin + spec.baseVertex can not be a negative value
602 if (spec.indexMin + spec.baseVertex < 0)
604 spec.indexMax -= (spec.indexMin + spec.baseVertex);
605 spec.indexMin -= (spec.indexMin + spec.baseVertex);
607 test->addIteration(spec, iterationDesc.c_str());
614 class AttributeGroup : public TestCaseGroup
617 AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage);
618 ~AttributeGroup (void);
623 gls::DrawTestSpec::DrawMethod m_method;
624 gls::DrawTestSpec::Primitive m_primitive;
625 gls::DrawTestSpec::IndexType m_indexType;
626 gls::DrawTestSpec::Storage m_indexStorage;
629 AttributeGroup::AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
630 : TestCaseGroup (context, name, descr)
631 , m_method (drawMethod)
632 , m_primitive (primitive)
633 , m_indexType (indexType)
634 , m_indexStorage (indexStorage)
638 AttributeGroup::~AttributeGroup (void)
642 void AttributeGroup::init (void)
646 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
647 gls::DrawTestSpec spec;
648 glu::ContextType contextType = m_context.getRenderContext().getType();
650 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI();
651 spec.primitive = m_primitive;
652 spec.primitiveCount = 5;
653 spec.drawMethod = m_method;
654 spec.indexType = m_indexType;
655 spec.indexPointerOffset = 0;
656 spec.indexStorage = m_indexStorage;
660 spec.instanceCount = 1;
661 spec.indirectOffset = 0;
663 spec.attribs.resize(1);
665 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
666 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
667 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
668 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
669 spec.attribs[0].componentCount = 2;
670 spec.attribs[0].offset = 0;
671 spec.attribs[0].stride = 0;
672 spec.attribs[0].normalize = false;
673 spec.attribs[0].instanceDivisor = 0;
674 spec.attribs[0].useDefaultAttribute = false;
676 addTestIterations(test, spec, TYPE_DRAW_COUNT);
678 this->addChild(test);
681 // Multiple attribute
683 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
684 gls::DrawTestSpec spec;
685 glu::ContextType contextType = m_context.getRenderContext().getType();
687 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI();
688 spec.primitive = m_primitive;
689 spec.primitiveCount = 5;
690 spec.drawMethod = m_method;
691 spec.indexType = m_indexType;
692 spec.indexPointerOffset = 0;
693 spec.indexStorage = m_indexStorage;
697 spec.instanceCount = 1;
698 spec.indirectOffset = 0;
700 spec.attribs.resize(2);
702 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
703 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
704 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
705 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
706 spec.attribs[0].componentCount = 4;
707 spec.attribs[0].offset = 0;
708 spec.attribs[0].stride = 0;
709 spec.attribs[0].normalize = false;
710 spec.attribs[0].instanceDivisor = 0;
711 spec.attribs[0].useDefaultAttribute = false;
713 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
714 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
715 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
716 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
717 spec.attribs[1].componentCount = 2;
718 spec.attribs[1].offset = 0;
719 spec.attribs[1].stride = 0;
720 spec.attribs[1].normalize = false;
721 spec.attribs[1].instanceDivisor = 0;
722 spec.attribs[1].useDefaultAttribute = false;
724 addTestIterations(test, spec, TYPE_DRAW_COUNT);
726 this->addChild(test);
729 // Multiple attribute, second one divided
731 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
732 gls::DrawTestSpec spec;
733 glu::ContextType contextType = m_context.getRenderContext().getType();
735 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI();
736 spec.primitive = m_primitive;
737 spec.primitiveCount = 5;
738 spec.drawMethod = m_method;
739 spec.indexType = m_indexType;
740 spec.indexPointerOffset = 0;
741 spec.indexStorage = m_indexStorage;
745 spec.instanceCount = 1;
746 spec.indirectOffset = 0;
748 spec.attribs.resize(3);
750 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
751 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
752 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
753 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
754 spec.attribs[0].componentCount = 4;
755 spec.attribs[0].offset = 0;
756 spec.attribs[0].stride = 0;
757 spec.attribs[0].normalize = false;
758 spec.attribs[0].instanceDivisor = 0;
759 spec.attribs[0].useDefaultAttribute = false;
761 // Add another position component so the instances wont be drawn on each other
762 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
763 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
764 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
765 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
766 spec.attribs[1].componentCount = 2;
767 spec.attribs[1].offset = 0;
768 spec.attribs[1].stride = 0;
769 spec.attribs[1].normalize = false;
770 spec.attribs[1].instanceDivisor = 1;
771 spec.attribs[1].useDefaultAttribute = false;
772 spec.attribs[1].additionalPositionAttribute = true;
775 spec.attribs[2].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
776 spec.attribs[2].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
777 spec.attribs[2].storage = gls::DrawTestSpec::STORAGE_BUFFER;
778 spec.attribs[2].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
779 spec.attribs[2].componentCount = 3;
780 spec.attribs[2].offset = 0;
781 spec.attribs[2].stride = 0;
782 spec.attribs[2].normalize = false;
783 spec.attribs[2].instanceDivisor = 1;
784 spec.attribs[2].useDefaultAttribute = false;
786 addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
788 this->addChild(test);
791 // Multiple attribute, second one default
793 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
794 gls::DrawTestSpec spec;
795 glu::ContextType contextType = m_context.getRenderContext().getType();
797 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI();
798 spec.primitive = m_primitive;
799 spec.primitiveCount = 5;
800 spec.drawMethod = m_method;
801 spec.indexType = m_indexType;
802 spec.indexPointerOffset = 0;
803 spec.indexStorage = m_indexStorage;
807 spec.instanceCount = 1;
808 spec.indirectOffset = 0;
810 spec.attribs.resize(2);
812 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
813 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
814 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
815 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
816 spec.attribs[0].componentCount = 2;
817 spec.attribs[0].offset = 0;
818 spec.attribs[0].stride = 0;
819 spec.attribs[0].normalize = false;
820 spec.attribs[0].instanceDivisor = 0;
821 spec.attribs[0].useDefaultAttribute = false;
825 gls::DrawTestSpec::InputType input;
826 gls::DrawTestSpec::OutputType output;
830 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4 },
831 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2 },
832 { gls::DrawTestSpec::INPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
833 { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
836 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
838 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
840 spec.attribs[1].inputType = iopairs[ioNdx].input;
841 spec.attribs[1].outputType = iopairs[ioNdx].output;
842 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
843 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
844 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount;
845 spec.attribs[1].offset = 0;
846 spec.attribs[1].stride = 0;
847 spec.attribs[1].normalize = false;
848 spec.attribs[1].instanceDivisor = 0;
849 spec.attribs[1].useDefaultAttribute = true;
851 test->addIteration(spec, desc.c_str());
854 this->addChild(test);
858 class MethodGroup : public TestCaseGroup
861 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
867 gls::DrawTestSpec::DrawMethod m_method;
870 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
871 : TestCaseGroup (context, name, descr)
872 , m_method (drawMethod)
876 MethodGroup::~MethodGroup (void)
880 void MethodGroup::init (void)
882 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
883 || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
884 || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
886 const gls::DrawTestSpec::Primitive primitive[] =
888 gls::DrawTestSpec::PRIMITIVE_POINTS,
889 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
890 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
891 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
892 gls::DrawTestSpec::PRIMITIVE_LINES,
893 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
894 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
900 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
901 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
902 this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
905 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
907 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
908 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
910 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
916 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context)
917 : TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
921 DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void)
925 void DrawElementsBaseVertexTests::init (void)
927 const gls::DrawTestSpec::DrawMethod basicMethods[] =
929 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
930 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
931 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
934 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
936 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
937 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
939 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));