1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 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 Drawing tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fDrawTests.hpp"
25 #include "glsDrawTest.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "deRandom.hpp"
28 #include "deStringUtil.hpp"
29 #include "deUniquePtr.hpp"
30 #include "deSTLUtil.hpp"
31
32 #include "glwEnums.hpp"
33
34 #include <set>
35
36 namespace deqp
37 {
38 namespace gles2
39 {
40 namespace Functional
41 {
42 namespace
43 {
44
45 enum TestIterationType
46 {
47 TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives
48
49 TYPE_LAST
50 };
51
addTestIterations(gls::DrawTest * test,const gls::DrawTestSpec & baseSpec,TestIterationType type)52 static void addTestIterations(gls::DrawTest *test, const gls::DrawTestSpec &baseSpec, TestIterationType type)
53 {
54 gls::DrawTestSpec spec(baseSpec);
55
56 if (type == TYPE_DRAW_COUNT)
57 {
58 spec.primitiveCount = 1;
59 test->addIteration(spec, "draw count = 1");
60
61 spec.primitiveCount = 5;
62 test->addIteration(spec, "draw count = 5");
63
64 spec.primitiveCount = 25;
65 test->addIteration(spec, "draw count = 25");
66 }
67 else
68 DE_ASSERT(false);
69 }
70
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)71 static void genBasicSpec(gls::DrawTestSpec &spec, gls::DrawTestSpec::DrawMethod method)
72 {
73 spec.apiType = glu::ApiType::es(2, 0);
74 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
75 spec.primitiveCount = 5;
76 spec.drawMethod = method;
77 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST;
78 spec.indexPointerOffset = 0;
79 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST;
80 spec.first = 0;
81 spec.indexMin = 0;
82 spec.indexMax = 0;
83 spec.instanceCount = 1;
84
85 spec.attribs.resize(2);
86
87 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
88 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
89 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
90 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
91 spec.attribs[0].componentCount = 4;
92 spec.attribs[0].offset = 0;
93 spec.attribs[0].stride = 0;
94 spec.attribs[0].normalize = false;
95 spec.attribs[0].instanceDivisor = 0;
96 spec.attribs[0].useDefaultAttribute = false;
97
98 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
99 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
100 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
101 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
102 spec.attribs[1].componentCount = 2;
103 spec.attribs[1].offset = 0;
104 spec.attribs[1].stride = 0;
105 spec.attribs[1].normalize = false;
106 spec.attribs[1].instanceDivisor = 0;
107 spec.attribs[1].useDefaultAttribute = false;
108 }
109
110 class AttributeGroup : public TestCaseGroup
111 {
112 public:
113 AttributeGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod,
114 gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType,
115 gls::DrawTestSpec::Storage indexStorage);
116 ~AttributeGroup(void);
117
118 void init(void);
119
120 private:
121 gls::DrawTestSpec::DrawMethod m_method;
122 gls::DrawTestSpec::Primitive m_primitive;
123 gls::DrawTestSpec::IndexType m_indexType;
124 gls::DrawTestSpec::Storage m_indexStorage;
125 };
126
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)127 AttributeGroup::AttributeGroup(Context &context, const char *name, const char *descr,
128 gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive,
129 gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
130 : TestCaseGroup(context, name, descr)
131 , m_method(drawMethod)
132 , m_primitive(primitive)
133 , m_indexType(indexType)
134 , m_indexStorage(indexStorage)
135 {
136 }
137
~AttributeGroup(void)138 AttributeGroup::~AttributeGroup(void)
139 {
140 }
141
init(void)142 void AttributeGroup::init(void)
143 {
144 // Single attribute
145 {
146 gls::DrawTest *test =
147 new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
148 gls::DrawTestSpec spec;
149
150 spec.apiType = glu::ApiType::es(2, 0);
151 spec.primitive = m_primitive;
152 spec.primitiveCount = 0;
153 spec.drawMethod = m_method;
154 spec.indexType = m_indexType;
155 spec.indexPointerOffset = 0;
156 spec.indexStorage = m_indexStorage;
157 spec.first = 0;
158 spec.indexMin = 0;
159 spec.indexMax = 0;
160 spec.instanceCount = 1;
161
162 spec.attribs.resize(1);
163
164 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
165 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
166 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
167 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
168 spec.attribs[0].componentCount = 2;
169 spec.attribs[0].offset = 0;
170 spec.attribs[0].stride = 0;
171 spec.attribs[0].normalize = false;
172 spec.attribs[0].instanceDivisor = 0;
173 spec.attribs[0].useDefaultAttribute = false;
174
175 addTestIterations(test, spec, TYPE_DRAW_COUNT);
176
177 this->addChild(test);
178 }
179
180 // Multiple attribute
181 {
182 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes",
183 "Multiple attribute arrays");
184 gls::DrawTestSpec spec;
185
186 spec.apiType = glu::ApiType::es(2, 0);
187 spec.primitive = m_primitive;
188 spec.primitiveCount = 0;
189 spec.drawMethod = m_method;
190 spec.indexType = m_indexType;
191 spec.indexPointerOffset = 0;
192 spec.indexStorage = m_indexStorage;
193 spec.first = 0;
194 spec.indexMin = 0;
195 spec.indexMax = 0;
196 spec.instanceCount = 1;
197
198 spec.attribs.resize(2);
199
200 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
201 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
202 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
203 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
204 spec.attribs[0].componentCount = 4;
205 spec.attribs[0].offset = 0;
206 spec.attribs[0].stride = 0;
207 spec.attribs[0].normalize = false;
208 spec.attribs[0].instanceDivisor = 0;
209 spec.attribs[0].useDefaultAttribute = false;
210
211 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
212 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
213 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
214 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
215 spec.attribs[1].componentCount = 2;
216 spec.attribs[1].offset = 0;
217 spec.attribs[1].stride = 0;
218 spec.attribs[1].normalize = false;
219 spec.attribs[1].instanceDivisor = 0;
220 spec.attribs[1].useDefaultAttribute = false;
221
222 addTestIterations(test, spec, TYPE_DRAW_COUNT);
223
224 this->addChild(test);
225 }
226
227 // Multiple attribute, second one default.
228 {
229 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute",
230 "Attribute specified with glVertexAttrib*.");
231 gls::DrawTestSpec spec;
232
233 spec.apiType = glu::ApiType::es(2, 0);
234 spec.primitive = m_primitive;
235 spec.primitiveCount = 5;
236 spec.drawMethod = m_method;
237 spec.indexType = m_indexType;
238 spec.indexPointerOffset = 0;
239 spec.indexStorage = m_indexStorage;
240 spec.first = 0;
241 spec.indexMin = 0;
242 spec.indexMax = 0;
243 spec.instanceCount = 1;
244
245 spec.attribs.resize(2);
246
247 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
248 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
249 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
250 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
251 spec.attribs[0].componentCount = 2;
252 spec.attribs[0].offset = 0;
253 spec.attribs[0].stride = 0;
254 spec.attribs[0].normalize = false;
255 spec.attribs[0].instanceDivisor = 0;
256 spec.attribs[0].useDefaultAttribute = false;
257
258 struct IOPair
259 {
260 gls::DrawTestSpec::InputType input;
261 gls::DrawTestSpec::OutputType output;
262 int componentCount;
263 } iopairs[] = {
264 {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4},
265 {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2},
266 };
267
268 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
269 {
270 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) +
271 de::toString(iopairs[ioNdx].componentCount) + " to " +
272 gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
273
274 spec.attribs[1].inputType = iopairs[ioNdx].input;
275 spec.attribs[1].outputType = iopairs[ioNdx].output;
276 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
277 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
278 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount;
279 spec.attribs[1].offset = 0;
280 spec.attribs[1].stride = 0;
281 spec.attribs[1].normalize = false;
282 spec.attribs[1].instanceDivisor = 0;
283 spec.attribs[1].useDefaultAttribute = true;
284
285 test->addIteration(spec, desc.c_str());
286 }
287
288 this->addChild(test);
289 }
290 }
291
292 class IndexGroup : public TestCaseGroup
293 {
294 public:
295 IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
296 ~IndexGroup(void);
297
298 void init(void);
299
300 private:
301 gls::DrawTestSpec::DrawMethod m_method;
302 };
303
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)304 IndexGroup::IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod)
305 : TestCaseGroup(context, name, descr)
306 , m_method(drawMethod)
307 {
308 }
309
~IndexGroup(void)310 IndexGroup::~IndexGroup(void)
311 {
312 }
313
init(void)314 void IndexGroup::init(void)
315 {
316 struct IndexTest
317 {
318 gls::DrawTestSpec::Storage storage;
319 gls::DrawTestSpec::IndexType type;
320 bool aligned;
321 int offsets[3];
322 };
323
324 const IndexTest tests[] = {
325 {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, {0, 1, -1}},
326 {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, {0, 2, -1}},
327
328 {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, {1, 3, -1}},
329
330 {gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, {0, 1, -1}},
331 {gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, {0, 2, -1}},
332 };
333
334 gls::DrawTestSpec spec;
335
336 tcu::TestCaseGroup *userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
337 tcu::TestCaseGroup *unalignedUserPtrGroup =
338 new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
339 tcu::TestCaseGroup *bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
340
341 genBasicSpec(spec, m_method);
342
343 this->addChild(userPtrGroup);
344 this->addChild(unalignedUserPtrGroup);
345 this->addChild(bufferGroup);
346
347 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
348 {
349 const IndexTest &indexTest = tests[testNdx];
350 tcu::TestCaseGroup *group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ?
351 ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) :
352 ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
353
354 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
355 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " +
356 gls::DrawTestSpec::storageToString(indexTest.storage);
357 de::MovePtr<gls::DrawTest> test(
358 new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
359
360 spec.indexType = indexTest.type;
361 spec.indexStorage = indexTest.storage;
362
363 for (int iterationNdx = 0;
364 iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1;
365 ++iterationNdx)
366 {
367 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
368 spec.indexPointerOffset = indexTest.offsets[iterationNdx];
369 test->addIteration(spec, iterationDesc.c_str());
370 }
371
372 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
373 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
374 group->addChild(test.release());
375 }
376 }
377
378 class FirstGroup : public TestCaseGroup
379 {
380 public:
381 FirstGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
382 ~FirstGroup(void);
383
384 void init(void);
385
386 private:
387 gls::DrawTestSpec::DrawMethod m_method;
388 };
389
FirstGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)390 FirstGroup::FirstGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod)
391 : TestCaseGroup(context, name, descr)
392 , m_method(drawMethod)
393 {
394 }
395
~FirstGroup(void)396 FirstGroup::~FirstGroup(void)
397 {
398 }
399
init(void)400 void FirstGroup::init(void)
401 {
402 const int firsts[] = {0, 1, 17};
403
404 gls::DrawTestSpec spec;
405 genBasicSpec(spec, m_method);
406
407 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
408 {
409 const std::string name = std::string("first_") + de::toString(firsts[firstNdx]);
410 const std::string desc = std::string("first ") + de::toString(firsts[firstNdx]);
411 gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
412
413 spec.first = firsts[firstNdx];
414
415 addTestIterations(test, spec, TYPE_DRAW_COUNT);
416
417 this->addChild(test);
418 }
419 }
420
421 class MethodGroup : public TestCaseGroup
422 {
423 public:
424 MethodGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
425 ~MethodGroup(void);
426
427 void init(void);
428
429 private:
430 gls::DrawTestSpec::DrawMethod m_method;
431 };
432
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)433 MethodGroup::MethodGroup(Context &context, const char *name, const char *descr,
434 gls::DrawTestSpec::DrawMethod drawMethod)
435 : TestCaseGroup(context, name, descr)
436 , m_method(drawMethod)
437 {
438 }
439
~MethodGroup(void)440 MethodGroup::~MethodGroup(void)
441 {
442 }
443
init(void)444 void MethodGroup::init(void)
445 {
446 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) ||
447 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) ||
448 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
449 const bool hasFirst = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) ||
450 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
451
452 const gls::DrawTestSpec::Primitive primitive[] = {
453 gls::DrawTestSpec::PRIMITIVE_POINTS, gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
454 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
455 gls::DrawTestSpec::PRIMITIVE_LINES, gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
456 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
457
458 if (hasFirst)
459 {
460 // First-tests
461 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
462 }
463
464 if (indexed)
465 {
466 // Index-tests
467 if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
468 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
469 }
470
471 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
472 {
473 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
474 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
475
476 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx],
477 gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
478 }
479 }
480
481 class RandomGroup : public TestCaseGroup
482 {
483 public:
484 RandomGroup(Context &context, const char *name, const char *descr);
485 ~RandomGroup(void);
486
487 void init(void);
488 };
489
490 template <int SIZE>
491 struct UniformWeightArray
492 {
493 float weights[SIZE];
494
UniformWeightArraydeqp::gles2::Functional::__anon5cf4d8b80111::UniformWeightArray495 UniformWeightArray(void)
496 {
497 for (int i = 0; i < SIZE; ++i)
498 weights[i] = 1.0f;
499 }
500 };
501
RandomGroup(Context & context,const char * name,const char * descr)502 RandomGroup::RandomGroup(Context &context, const char *name, const char *descr) : TestCaseGroup(context, name, descr)
503 {
504 }
505
~RandomGroup(void)506 RandomGroup::~RandomGroup(void)
507 {
508 }
509
init(void)510 void RandomGroup::init(void)
511 {
512 const int numAttempts = 100;
513
514 static const int attribCounts[] = {1, 2, 5};
515 static const float attribWeights[] = {30, 10, 1};
516 static const int primitiveCounts[] = {1, 5, 64};
517 static const float primitiveCountWeights[] = {20, 10, 1};
518 static const int indexOffsets[] = {0, 7, 13};
519 static const float indexOffsetWeights[] = {20, 20, 1};
520 static const int firsts[] = {0, 7, 13};
521 static const float firstWeights[] = {20, 20, 1};
522 static const int offsets[] = {0, 1, 5, 12};
523 static const float offsetWeights[] = {50, 10, 10, 10};
524 static const int strides[] = {0, 7, 16, 17};
525 static const float strideWeights[] = {50, 10, 10, 10};
526
527 static const gls::DrawTestSpec::Primitive primitives[] = {
528 gls::DrawTestSpec::PRIMITIVE_POINTS, gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
529 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
530 gls::DrawTestSpec::PRIMITIVE_LINES, gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
531 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
532 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
533
534 static const gls::DrawTestSpec::DrawMethod drawMethods[] = {
535 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
536 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
537 };
538 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
539
540 static const gls::DrawTestSpec::IndexType indexTypes[] = {
541 gls::DrawTestSpec::INDEXTYPE_BYTE,
542 gls::DrawTestSpec::INDEXTYPE_SHORT,
543 };
544 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
545
546 static const gls::DrawTestSpec::Storage storages[] = {
547 gls::DrawTestSpec::STORAGE_USER,
548 gls::DrawTestSpec::STORAGE_BUFFER,
549 };
550 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
551
552 static const gls::DrawTestSpec::InputType inputTypes[] = {
553 gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::INPUTTYPE_FIXED,
554 gls::DrawTestSpec::INPUTTYPE_BYTE, gls::DrawTestSpec::INPUTTYPE_SHORT,
555 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT};
556 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
557
558 static const gls::DrawTestSpec::OutputType outputTypes[] = {
559 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
560 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
561 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
562 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
563 };
564 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
565
566 static const gls::DrawTestSpec::Usage usages[] = {
567 gls::DrawTestSpec::USAGE_STATIC_DRAW,
568 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
569 gls::DrawTestSpec::USAGE_STREAM_DRAW,
570 };
571 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
572
573 static const uint32_t disallowedCases[] = {
574 3153, //!< extremely narrow triangle, results depend on sample positions
575 };
576
577 std::set<uint32_t> insertedHashes;
578 size_t insertedCount = 0;
579
580 for (int ndx = 0; ndx < numAttempts; ++ndx)
581 {
582 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
583
584 int attributeCount = random.chooseWeighted<int, const int *, const float *>(
585 DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
586 gls::DrawTestSpec spec;
587
588 spec.apiType = glu::ApiType::es(2, 0);
589 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive>(
590 DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights);
591 spec.primitiveCount = random.chooseWeighted<int, const int *, const float *>(
592 DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights);
593 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>(
594 DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights);
595 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType>(
596 DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights);
597 spec.indexPointerOffset = random.chooseWeighted<int, const int *, const float *>(
598 DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights);
599 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage>(
600 DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
601 spec.first = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(firsts),
602 DE_ARRAY_END(firsts), firstWeights);
603 spec.indexMin = 0;
604 spec.indexMax = 0;
605 spec.instanceCount = 0;
606
607 // check spec is legal
608 if (!spec.valid())
609 continue;
610
611 for (int attrNdx = 0; attrNdx < attributeCount;)
612 {
613 bool valid;
614 gls::DrawTestSpec::AttributeSpec attribSpec;
615
616 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType>(
617 DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights);
618 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType>(
619 DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights);
620 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage>(
621 DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
622 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage>(
623 DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights);
624 attribSpec.componentCount = random.getInt(1, 4);
625 attribSpec.offset = random.chooseWeighted<int, const int *, const float *>(
626 DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
627 attribSpec.stride = random.chooseWeighted<int, const int *, const float *>(
628 DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
629 attribSpec.normalize = random.getBool();
630 attribSpec.instanceDivisor = 0;
631 attribSpec.useDefaultAttribute = random.getBool();
632
633 // check spec is legal
634 valid = attribSpec.valid(spec.apiType);
635
636 // we do not want interleaved elements. (Might result in some weird floating point values)
637 if (attribSpec.stride &&
638 attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
639 valid = false;
640
641 // try again if not valid
642 if (valid)
643 {
644 spec.attribs.push_back(attribSpec);
645 ++attrNdx;
646 }
647 }
648
649 // Do not collapse all vertex positions to a single positions
650 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
651 spec.attribs[0].instanceDivisor = 0;
652
653 // Is render result meaningful?
654 {
655 // Only one vertex
656 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
657 spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
658 continue;
659 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
660 continue;
661
662 // Triangle only on one axis
663 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES ||
664 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN ||
665 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
666 {
667 if (spec.attribs[0].componentCount == 1)
668 continue;
669 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT ||
670 spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT ||
671 spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
672 continue;
673 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
674 (spec.indexMax - spec.indexMin) < 2)
675 continue;
676 }
677 }
678
679 // Add case
680 {
681 uint32_t hash = spec.hash();
682 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
683 hash = (hash << 2) ^ (uint32_t)spec.attribs[attrNdx].hash();
684
685 if (insertedHashes.find(hash) == insertedHashes.end() &&
686 !de::contains(DE_ARRAY_BEGIN(disallowedCases), DE_ARRAY_END(disallowedCases), hash))
687 {
688 // Only aligned cases
689 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
690 spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
691 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec,
692 de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
693 insertedHashes.insert(hash);
694
695 ++insertedCount;
696 }
697 }
698 }
699 }
700
701 } // namespace
702
DrawTests(Context & context)703 DrawTests::DrawTests(Context &context) : TestCaseGroup(context, "draw", "Drawing tests")
704 {
705 }
706
~DrawTests(void)707 DrawTests::~DrawTests(void)
708 {
709 }
710
init(void)711 void DrawTests::init(void)
712 {
713 // Basic
714 {
715 const gls::DrawTestSpec::DrawMethod basicMethods[] = {
716 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
717 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
718 };
719
720 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
721 {
722 std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
723 std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
724
725 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
726 }
727 }
728
729 // Random
730
731 this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
732 }
733
734 } // namespace Functional
735 } // namespace gles2
736 } // namespace deqp
737