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