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