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