1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2017 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 GL_EXT_draw_elements_base_vertex tests.
22 *//*--------------------------------------------------------------------*/
23
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"
34
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37
38 #include <string>
39 #include <set>
40
41 using std::string;
42 using std::vector;
43 using tcu::TestLog;
44
45 using namespace glw;
46
47 namespace deqp
48 {
49 namespace gles31
50 {
51 namespace Functional
52 {
53 namespace
54 {
55
56 enum TestIterationType
57 {
58 TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives
59 TYPE_INSTANCE_COUNT, // !< test with 1, 4, and 11 instances
60
61 TYPE_LAST
62 };
63
getElementCount(gls::DrawTestSpec::Primitive primitive,size_t primitiveCount)64 static size_t getElementCount(gls::DrawTestSpec::Primitive primitive, size_t primitiveCount)
65 {
66 switch (primitive)
67 {
68 case gls::DrawTestSpec::PRIMITIVE_POINTS:
69 return primitiveCount;
70 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES:
71 return primitiveCount * 3;
72 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
73 return primitiveCount + 2;
74 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
75 return primitiveCount + 2;
76 case gls::DrawTestSpec::PRIMITIVE_LINES:
77 return primitiveCount * 2;
78 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP:
79 return primitiveCount + 1;
80 case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP:
81 return (primitiveCount == 1) ? (2) : (primitiveCount);
82 case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
83 return primitiveCount * 4;
84 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
85 return primitiveCount + 3;
86 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
87 return primitiveCount * 6;
88 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
89 return primitiveCount * 2 + 4;
90 default:
91 DE_ASSERT(false);
92 return 0;
93 }
94 }
95
addRangeElementsToSpec(gls::DrawTestSpec & spec)96 static void addRangeElementsToSpec(gls::DrawTestSpec &spec)
97 {
98 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
99 {
100 spec.indexMin = 0;
101 spec.indexMax = (int)getElementCount(spec.primitive, spec.primitiveCount);
102 }
103 }
104
addTestIterations(gls::DrawTest * test,gls::DrawTestSpec & spec,TestIterationType type)105 static void addTestIterations(gls::DrawTest *test, gls::DrawTestSpec &spec, TestIterationType type)
106 {
107 if (type == TYPE_DRAW_COUNT)
108 {
109 spec.primitiveCount = 1;
110 addRangeElementsToSpec(spec);
111 test->addIteration(spec, "draw count = 1");
112
113 spec.primitiveCount = 5;
114 addRangeElementsToSpec(spec);
115 test->addIteration(spec, "draw count = 5");
116
117 spec.primitiveCount = 25;
118 addRangeElementsToSpec(spec);
119 test->addIteration(spec, "draw count = 25");
120 }
121 else if (type == TYPE_INSTANCE_COUNT)
122 {
123 spec.instanceCount = 1;
124 addRangeElementsToSpec(spec);
125 test->addIteration(spec, "instance count = 1");
126
127 spec.instanceCount = 4;
128 addRangeElementsToSpec(spec);
129 test->addIteration(spec, "instance count = 4");
130
131 spec.instanceCount = 11;
132 addRangeElementsToSpec(spec);
133 test->addIteration(spec, "instance count = 11");
134 }
135 else
136 DE_ASSERT(false);
137 }
138
genBasicSpec(gls::DrawTestSpec & spec,glu::ContextType & contextType,gls::DrawTestSpec::DrawMethod method)139 static void genBasicSpec(gls::DrawTestSpec &spec, glu::ContextType &contextType, gls::DrawTestSpec::DrawMethod method)
140 {
141 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3, 1) : contextType.getAPI();
142 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
143 spec.primitiveCount = 5;
144 spec.drawMethod = method;
145 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST;
146 spec.indexPointerOffset = 0;
147 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST;
148 spec.first = 0;
149 spec.indexMin = 0;
150 spec.indexMax = 0;
151 spec.instanceCount = 1;
152 spec.indirectOffset = 0;
153
154 spec.attribs.resize(2);
155
156 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
157 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
158 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
159 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
160 spec.attribs[0].componentCount = 4;
161 spec.attribs[0].offset = 0;
162 spec.attribs[0].stride = 0;
163 spec.attribs[0].normalize = false;
164 spec.attribs[0].instanceDivisor = 0;
165 spec.attribs[0].useDefaultAttribute = false;
166
167 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
168 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
169 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
170 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
171 spec.attribs[1].componentCount = 2;
172 spec.attribs[1].offset = 0;
173 spec.attribs[1].stride = 0;
174 spec.attribs[1].normalize = false;
175 spec.attribs[1].instanceDivisor = 0;
176 spec.attribs[1].useDefaultAttribute = false;
177
178 addRangeElementsToSpec(spec);
179 }
180
181 class VertexIDCase : public TestCase
182 {
183 public:
184 VertexIDCase(Context &context, gls::DrawTestSpec::DrawMethod drawMethod);
185 ~VertexIDCase(void);
186
187 void init(void);
188 void deinit(void);
189 IterateResult iterate(void);
190
191 void draw(GLenum mode, GLsizei count, GLenum type, GLvoid *indices, GLint baseVertex);
192 void verifyImage(const tcu::Surface &image);
193
194 private:
195 const glw::Functions &m_gl;
196 glu::ShaderProgram *m_program;
197 GLuint m_vao;
198 GLuint m_coordinatesBuffer;
199 GLuint m_elementsBuffer;
200 int m_iterNdx;
201 gls::DrawTestSpec::DrawMethod m_method;
202
203 enum
204 {
205 VIEWPORT_WIDTH = 64,
206 VIEWPORT_HEIGHT = 64
207 };
208
209 enum
210 {
211 MAX_VERTICES = 2 * 3 //!< 2 triangles, totals 6 vertices
212 };
213 };
214
VertexIDCase(Context & context,gls::DrawTestSpec::DrawMethod drawMethod)215 VertexIDCase::VertexIDCase(Context &context, gls::DrawTestSpec::DrawMethod drawMethod)
216 : TestCase(context, "vertex_id", "gl_VertexID Test")
217 , m_gl(m_context.getRenderContext().getFunctions())
218 , m_program(DE_NULL)
219 , m_vao(0)
220 , m_coordinatesBuffer(0)
221 , m_elementsBuffer(0)
222 , m_iterNdx(0)
223 , m_method(drawMethod)
224 {
225 }
226
~VertexIDCase(void)227 VertexIDCase::~VertexIDCase(void)
228 {
229 VertexIDCase::deinit();
230 }
231
init(void)232 void VertexIDCase::init(void)
233 {
234 auto ctxType = m_context.getRenderContext().getType();
235 if (m_method == deqp::gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX ||
236 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX ||
237 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
238 {
239 const bool supportsES32orGL45 =
240 contextSupports(ctxType, glu::ApiType::es(3, 2)) || contextSupports(ctxType, glu::ApiType::core(4, 5));
241 TCU_CHECK_AND_THROW(NotSupportedError,
242 supportsES32orGL45 ||
243 m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_elements_base_vertex"),
244 "GL_EXT_draw_elements_base_vertex is not supported.");
245 }
246
247 m_testCtx.getLog() << TestLog::Message
248 << "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. "
249 "indices[i] + basevertex"
250 << TestLog::EndMessage;
251
252 DE_ASSERT(!m_program);
253 m_program = new glu::ShaderProgram(m_context.getRenderContext(),
254 glu::makeVtxFragSources("#version 310 es\n"
255 "in highp vec4 a_position;\n"
256 "out mediump vec4 v_color;\n"
257 "uniform highp vec4 u_colors[8];\n"
258 "void main (void)\n"
259 "{\n"
260 " gl_Position = a_position;\n"
261 " v_color = u_colors[gl_VertexID];\n"
262 "}\n",
263
264 "#version 310 es\n"
265 "in mediump vec4 v_color;\n"
266 "layout(location = 0) out mediump vec4 o_color;\n"
267 "void main (void)\n"
268 "{\n"
269 " o_color = v_color;\n"
270 "}\n"));
271
272 m_testCtx.getLog() << *m_program;
273
274 if (!m_program->isOk())
275 {
276 delete m_program;
277 m_program = DE_NULL;
278 TCU_FAIL("Failed to compile shader program");
279 }
280
281 GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram()));
282
283 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
284 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer));
285
286 if (!glu::isContextTypeES(ctxType))
287 GLU_CHECK_GLW_CALL(m_gl, genVertexArrays(1, &m_vao));
288 }
289
deinit(void)290 void VertexIDCase::deinit(void)
291 {
292 delete m_program;
293 m_program = DE_NULL;
294
295 if (m_elementsBuffer)
296 {
297 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer));
298 m_elementsBuffer = 0;
299 }
300
301 if (m_coordinatesBuffer)
302 {
303 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
304 m_coordinatesBuffer = 0;
305 }
306
307 if (m_vao)
308 {
309 GLU_CHECK_GLW_CALL(m_gl, deleteVertexArrays(1, &m_vao));
310 m_vao = 0;
311 }
312 }
313
draw(GLenum mode,GLsizei count,GLenum type,GLvoid * indices,GLint baseVertex)314 void VertexIDCase::draw(GLenum mode, GLsizei count, GLenum type, GLvoid *indices, GLint baseVertex)
315 {
316 switch (m_method)
317 {
318 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX:
319 GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex));
320 break;
321
322 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX:
323 {
324 GLint maxElementsVertices = 0;
325 GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices));
326 GLU_CHECK_GLW_CALL(m_gl,
327 drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex));
328 break;
329 }
330
331 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX:
332 GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex));
333 break;
334
335 default:
336 DE_FATAL("Draw method not supported");
337 }
338 }
339
verifyImage(const tcu::Surface & image)340 void VertexIDCase::verifyImage(const tcu::Surface &image)
341 {
342 tcu::TestLog &log = m_testCtx.getLog();
343 bool isOk = true;
344
345 const int colorThreshold = 0; // expect perfect match
346 tcu::Surface error(image.getWidth(), image.getHeight());
347
348 for (int y = 0; y < image.getHeight(); y++)
349 for (int x = 0; x < image.getWidth(); x++)
350 {
351 const tcu::RGBA pixel = image.getPixel(x, y);
352 bool pixelOk = true;
353
354 // Ignore pixels not drawn with basevertex
355 if ((x < image.getWidth() * 1 / 4) || (x > image.getWidth() * 3 / 4) || (y < image.getHeight() * 1 / 4) ||
356 (y > image.getHeight() * 3 / 4))
357 continue;
358
359 // Any pixel with !(B ~= 255) is faulty
360 if (de::abs(pixel.getBlue() - 255) > colorThreshold)
361 pixelOk = false;
362
363 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
364 isOk = isOk && pixelOk;
365 }
366
367 if (!isOk)
368 {
369 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
370 log << TestLog::ImageSet("Verification result", "Result of rendering")
371 << TestLog::Image("Result", "Result", image) << TestLog::Image("Error Mask", "Error mask", error)
372 << TestLog::EndImageSet;
373 }
374 else
375 {
376 log << TestLog::ImageSet("Verification result", "Result of rendering")
377 << TestLog::Image("Result", "Result", image) << TestLog::EndImageSet;
378 }
379
380 if (isOk)
381 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
382 else
383 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
384 }
385
iterate(void)386 VertexIDCase::IterateResult VertexIDCase::iterate(void)
387 {
388 const GLuint drawCount = 6;
389 const GLuint baseVertex = 4;
390 const GLuint coordLocation = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
391 const GLuint colorLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
392
393 tcu::Surface surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
394
395 const GLfloat coords[] = {
396 // full viewport quad
397 -1.0f,
398 -1.0f,
399 +1.0f,
400 -1.0f,
401 +1.0f,
402 +1.0f,
403 -1.0f,
404 +1.0f,
405
406 // half viewport quad centred
407 -0.5f,
408 -0.5f,
409 +0.5f,
410 -0.5f,
411 +0.5f,
412 +0.5f,
413 -0.5f,
414 +0.5f,
415 };
416
417 const GLushort indices[] = {
418 0, 1, 2, 2, 3, 0,
419 };
420
421 const GLfloat colors[] = {
422 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
423
424 0.0f, 0.0f, 1.0f, 1.0f, // blue
425 0.0f, 0.0f, 1.0f, 1.0f, // blue
426 0.0f, 0.0f, 1.0f, 1.0f, // blue
427 0.0f, 0.0f, 1.0f, 1.0f, // blue
428 };
429
430 GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT));
431 GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white
432 GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT));
433
434 GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0]));
435
436 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
437 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
438
439 if (m_vao)
440 GLU_CHECK_GLW_CALL(m_gl, bindVertexArray(m_vao));
441 GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation));
442 GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
443
444 if (m_iterNdx == 0)
445 {
446 tcu::ScopedLogSection logSection(m_testCtx.getLog(), "Iter0", "Indices in client-side array");
447 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid *)indices, baseVertex);
448 }
449
450 if (m_iterNdx == 1)
451 {
452 tcu::ScopedLogSection logSection(m_testCtx.getLog(), "Iter1", "Indices in element array buffer");
453 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer));
454 GLU_CHECK_GLW_CALL(
455 m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW));
456 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex);
457 }
458
459 glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess());
460 verifyImage(surface);
461
462 m_iterNdx += 1;
463
464 return (m_iterNdx < 2) ? CONTINUE : STOP;
465 }
466
467 class BuiltInVariableGroup : public TestCaseGroup
468 {
469 public:
470 BuiltInVariableGroup(Context &context, const char *name, const char *descr,
471 gls::DrawTestSpec::DrawMethod drawMethod);
472 ~BuiltInVariableGroup(void);
473
474 void init(void);
475
476 private:
477 gls::DrawTestSpec::DrawMethod m_method;
478 };
479
BuiltInVariableGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)480 BuiltInVariableGroup::BuiltInVariableGroup(Context &context, const char *name, const char *descr,
481 gls::DrawTestSpec::DrawMethod drawMethod)
482 : TestCaseGroup(context, name, descr)
483 , m_method(drawMethod)
484 {
485 }
486
~BuiltInVariableGroup(void)487 BuiltInVariableGroup::~BuiltInVariableGroup(void)
488 {
489 }
490
init(void)491 void BuiltInVariableGroup::init(void)
492 {
493 addChild(new VertexIDCase(m_context, m_method));
494 }
495
496 class IndexGroup : public TestCaseGroup
497 {
498 public:
499 IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
500 ~IndexGroup(void);
501
502 void init(void);
503
504 private:
505 gls::DrawTestSpec::DrawMethod m_method;
506 };
507
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)508 IndexGroup::IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod)
509 : TestCaseGroup(context, name, descr)
510 , m_method(drawMethod)
511 {
512 }
513
~IndexGroup(void)514 IndexGroup::~IndexGroup(void)
515 {
516 }
517
init(void)518 void IndexGroup::init(void)
519 {
520 struct IndexTest
521 {
522 gls::DrawTestSpec::IndexType type;
523 int offsets[3];
524 };
525
526 const IndexTest tests[] = {
527 {gls::DrawTestSpec::INDEXTYPE_BYTE, {0, 1, -1}},
528 {gls::DrawTestSpec::INDEXTYPE_SHORT, {0, 2, -1}},
529 {gls::DrawTestSpec::INDEXTYPE_INT, {0, 4, -1}},
530 };
531
532 gls::DrawTestSpec spec;
533 glu::ContextType contextType = m_context.getRenderContext().getType();
534 genBasicSpec(spec, contextType, m_method);
535
536 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
537
538 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
539 {
540 const IndexTest &indexTest = tests[testNdx];
541
542 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
543 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
544 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
545
546 spec.indexType = indexTest.type;
547
548 for (int iterationNdx = 0;
549 iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1;
550 ++iterationNdx)
551 {
552 const std::string iterationDesc =
553 std::string("first vertex ") +
554 de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
555 spec.indexPointerOffset = indexTest.offsets[iterationNdx];
556 test->addIteration(spec, iterationDesc.c_str());
557 }
558
559 addChild(test);
560 }
561 }
562
563 class BaseVertexGroup : public TestCaseGroup
564 {
565 public:
566 BaseVertexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
567 ~BaseVertexGroup(void);
568
569 void init(void);
570
571 private:
572 gls::DrawTestSpec::DrawMethod m_method;
573 };
574
BaseVertexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)575 BaseVertexGroup::BaseVertexGroup(Context &context, const char *name, const char *descr,
576 gls::DrawTestSpec::DrawMethod drawMethod)
577 : TestCaseGroup(context, name, descr)
578 , m_method(drawMethod)
579 {
580 }
581
~BaseVertexGroup(void)582 BaseVertexGroup::~BaseVertexGroup(void)
583 {
584 }
585
init(void)586 void BaseVertexGroup::init(void)
587 {
588 struct IndexTest
589 {
590 bool positiveBase;
591 gls::DrawTestSpec::IndexType type;
592 int baseVertex[2];
593 };
594
595 const IndexTest tests[] = {
596 {true, gls::DrawTestSpec::INDEXTYPE_BYTE, {1, 2}}, {true, gls::DrawTestSpec::INDEXTYPE_SHORT, {1, 2}},
597 {true, gls::DrawTestSpec::INDEXTYPE_INT, {1, 2}}, {false, gls::DrawTestSpec::INDEXTYPE_BYTE, {-1, -2}},
598 {false, gls::DrawTestSpec::INDEXTYPE_SHORT, {-1, -2}}, {false, gls::DrawTestSpec::INDEXTYPE_INT, {-1, -2}},
599 };
600
601 gls::DrawTestSpec spec;
602 glu::ContextType contextType = m_context.getRenderContext().getType();
603 genBasicSpec(spec, contextType, m_method);
604
605 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
606
607 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
608 {
609 const IndexTest &indexTest = tests[testNdx];
610
611 const std::string name = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") +
612 gls::DrawTestSpec::indexTypeToString(indexTest.type);
613 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
614 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
615
616 spec.indexType = indexTest.type;
617
618 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
619 {
620 const std::string iterationDesc =
621 std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
622 spec.baseVertex = indexTest.baseVertex[iterationNdx];
623 // spec.indexMin + spec.baseVertex can not be a negative value
624 if (spec.indexMin + spec.baseVertex < 0)
625 {
626 spec.indexMax -= (spec.indexMin + spec.baseVertex);
627 spec.indexMin -= (spec.indexMin + spec.baseVertex);
628 }
629 test->addIteration(spec, iterationDesc.c_str());
630 }
631
632 addChild(test);
633 }
634 }
635
636 class AttributeGroup : public TestCaseGroup
637 {
638 public:
639 AttributeGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod,
640 gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType,
641 gls::DrawTestSpec::Storage indexStorage);
642 ~AttributeGroup(void);
643
644 void init(void);
645
646 private:
647 gls::DrawTestSpec::DrawMethod m_method;
648 gls::DrawTestSpec::Primitive m_primitive;
649 gls::DrawTestSpec::IndexType m_indexType;
650 gls::DrawTestSpec::Storage m_indexStorage;
651 };
652
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)653 AttributeGroup::AttributeGroup(Context &context, const char *name, const char *descr,
654 gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive,
655 gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
656 : TestCaseGroup(context, name, descr)
657 , m_method(drawMethod)
658 , m_primitive(primitive)
659 , m_indexType(indexType)
660 , m_indexStorage(indexStorage)
661 {
662 }
663
~AttributeGroup(void)664 AttributeGroup::~AttributeGroup(void)
665 {
666 }
667
init(void)668 void AttributeGroup::init(void)
669 {
670 // Single attribute
671 {
672 gls::DrawTest *test =
673 new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
674 gls::DrawTestSpec spec;
675 glu::ContextType contextType = m_context.getRenderContext().getType();
676
677 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3, 1) : contextType.getAPI();
678 spec.primitive = m_primitive;
679 spec.primitiveCount = 5;
680 spec.drawMethod = m_method;
681 spec.indexType = m_indexType;
682 spec.indexPointerOffset = 0;
683 spec.indexStorage = m_indexStorage;
684 spec.first = 0;
685 spec.indexMin = 0;
686 spec.indexMax = 0;
687 spec.instanceCount = 1;
688 spec.indirectOffset = 0;
689
690 spec.attribs.resize(1);
691
692 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
693 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
694 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
695 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
696 spec.attribs[0].componentCount = 2;
697 spec.attribs[0].offset = 0;
698 spec.attribs[0].stride = 0;
699 spec.attribs[0].normalize = false;
700 spec.attribs[0].instanceDivisor = 0;
701 spec.attribs[0].useDefaultAttribute = false;
702
703 addTestIterations(test, spec, TYPE_DRAW_COUNT);
704
705 this->addChild(test);
706 }
707
708 // Multiple attribute
709 {
710 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes",
711 "Multiple attribute arrays.");
712 gls::DrawTestSpec spec;
713 glu::ContextType contextType = m_context.getRenderContext().getType();
714
715 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3, 1) : contextType.getAPI();
716 spec.primitive = m_primitive;
717 spec.primitiveCount = 5;
718 spec.drawMethod = m_method;
719 spec.indexType = m_indexType;
720 spec.indexPointerOffset = 0;
721 spec.indexStorage = m_indexStorage;
722 spec.first = 0;
723 spec.indexMin = 0;
724 spec.indexMax = 0;
725 spec.instanceCount = 1;
726 spec.indirectOffset = 0;
727
728 spec.attribs.resize(2);
729
730 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
731 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
732 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
733 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
734 spec.attribs[0].componentCount = 4;
735 spec.attribs[0].offset = 0;
736 spec.attribs[0].stride = 0;
737 spec.attribs[0].normalize = false;
738 spec.attribs[0].instanceDivisor = 0;
739 spec.attribs[0].useDefaultAttribute = false;
740
741 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
742 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
743 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
744 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
745 spec.attribs[1].componentCount = 2;
746 spec.attribs[1].offset = 0;
747 spec.attribs[1].stride = 0;
748 spec.attribs[1].normalize = false;
749 spec.attribs[1].instanceDivisor = 0;
750 spec.attribs[1].useDefaultAttribute = false;
751
752 addTestIterations(test, spec, TYPE_DRAW_COUNT);
753
754 this->addChild(test);
755 }
756
757 // Multiple attribute, second one divided
758 {
759 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes",
760 "Instanced attribute array.");
761 gls::DrawTestSpec spec;
762 glu::ContextType contextType = m_context.getRenderContext().getType();
763
764 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3, 1) : contextType.getAPI();
765 spec.primitive = m_primitive;
766 spec.primitiveCount = 5;
767 spec.drawMethod = m_method;
768 spec.indexType = m_indexType;
769 spec.indexPointerOffset = 0;
770 spec.indexStorage = m_indexStorage;
771 spec.first = 0;
772 spec.indexMin = 0;
773 spec.indexMax = 0;
774 spec.instanceCount = 1;
775 spec.indirectOffset = 0;
776
777 spec.attribs.resize(3);
778
779 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
780 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
781 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
782 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
783 spec.attribs[0].componentCount = 4;
784 spec.attribs[0].offset = 0;
785 spec.attribs[0].stride = 0;
786 spec.attribs[0].normalize = false;
787 spec.attribs[0].instanceDivisor = 0;
788 spec.attribs[0].useDefaultAttribute = false;
789
790 // Add another position component so the instances wont be drawn on each other
791 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
792 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
793 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
794 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
795 spec.attribs[1].componentCount = 2;
796 spec.attribs[1].offset = 0;
797 spec.attribs[1].stride = 0;
798 spec.attribs[1].normalize = false;
799 spec.attribs[1].instanceDivisor = 1;
800 spec.attribs[1].useDefaultAttribute = false;
801 spec.attribs[1].additionalPositionAttribute = true;
802
803 // Instanced color
804 spec.attribs[2].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
805 spec.attribs[2].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
806 spec.attribs[2].storage = gls::DrawTestSpec::STORAGE_BUFFER;
807 spec.attribs[2].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
808 spec.attribs[2].componentCount = 3;
809 spec.attribs[2].offset = 0;
810 spec.attribs[2].stride = 0;
811 spec.attribs[2].normalize = false;
812 spec.attribs[2].instanceDivisor = 1;
813 spec.attribs[2].useDefaultAttribute = false;
814
815 addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
816
817 this->addChild(test);
818 }
819
820 // Multiple attribute, second one default
821 {
822 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute",
823 "Attribute specified with glVertexAttrib*.");
824 gls::DrawTestSpec spec;
825 glu::ContextType contextType = m_context.getRenderContext().getType();
826
827 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3, 1) : contextType.getAPI();
828 spec.primitive = m_primitive;
829 spec.primitiveCount = 5;
830 spec.drawMethod = m_method;
831 spec.indexType = m_indexType;
832 spec.indexPointerOffset = 0;
833 spec.indexStorage = m_indexStorage;
834 spec.first = 0;
835 spec.indexMin = 0;
836 spec.indexMax = 0;
837 spec.instanceCount = 1;
838 spec.indirectOffset = 0;
839
840 spec.attribs.resize(2);
841
842 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
843 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
844 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
845 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
846 spec.attribs[0].componentCount = 2;
847 spec.attribs[0].offset = 0;
848 spec.attribs[0].stride = 0;
849 spec.attribs[0].normalize = false;
850 spec.attribs[0].instanceDivisor = 0;
851 spec.attribs[0].useDefaultAttribute = false;
852
853 struct IOPair
854 {
855 gls::DrawTestSpec::InputType input;
856 gls::DrawTestSpec::OutputType output;
857 int componentCount;
858 } iopairs[] = {
859 {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4},
860 {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2},
861 {gls::DrawTestSpec::INPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4},
862 {gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4},
863 };
864
865 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
866 {
867 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) +
868 de::toString(iopairs[ioNdx].componentCount) + " to " +
869 gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
870
871 spec.attribs[1].inputType = iopairs[ioNdx].input;
872 spec.attribs[1].outputType = iopairs[ioNdx].output;
873 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
874 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
875 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount;
876 spec.attribs[1].offset = 0;
877 spec.attribs[1].stride = 0;
878 spec.attribs[1].normalize = false;
879 spec.attribs[1].instanceDivisor = 0;
880 spec.attribs[1].useDefaultAttribute = true;
881
882 test->addIteration(spec, desc.c_str());
883 }
884
885 this->addChild(test);
886 }
887 }
888
889 class MethodGroup : public TestCaseGroup
890 {
891 public:
892 MethodGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
893 ~MethodGroup(void);
894
895 void init(void);
896
897 private:
898 gls::DrawTestSpec::DrawMethod m_method;
899 };
900
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)901 MethodGroup::MethodGroup(Context &context, const char *name, const char *descr,
902 gls::DrawTestSpec::DrawMethod drawMethod)
903 : TestCaseGroup(context, name, descr)
904 , m_method(drawMethod)
905 {
906 }
907
~MethodGroup(void)908 MethodGroup::~MethodGroup(void)
909 {
910 }
911
init(void)912 void MethodGroup::init(void)
913 {
914 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX) ||
915 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX) ||
916 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
917
918 const gls::DrawTestSpec::Primitive primitive[] = {
919 gls::DrawTestSpec::PRIMITIVE_POINTS, gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
920 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
921 gls::DrawTestSpec::PRIMITIVE_LINES, gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
922 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
923
924 if (indexed)
925 {
926 // Index-tests
927 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
928 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
929 this->addChild(
930 new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
931 }
932
933 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
934 {
935 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
936 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
937
938 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx],
939 gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
940 }
941 }
942
943 } // namespace
944
DrawElementsBaseVertexTests(Context & context)945 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(Context &context)
946 : TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
947 {
948 }
949
~DrawElementsBaseVertexTests(void)950 DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests(void)
951 {
952 }
953
init(void)954 void DrawElementsBaseVertexTests::init(void)
955 {
956 const gls::DrawTestSpec::DrawMethod basicMethods[] = {
957 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
958 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
959 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
960 };
961
962 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
963 {
964 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
965 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
966
967 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
968 }
969 }
970
971 } // namespace Functional
972 } // namespace gles31
973 } // namespace deqp
974