1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 "es3fDrawTests.hpp"
25 #include "glsDrawTest.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "sglrGLContext.hpp"
28 #include "glwEnums.hpp"
29 #include "deRandom.hpp"
30 #include "deStringUtil.hpp"
31 #include "deUniquePtr.hpp"
32 #include "deSTLUtil.hpp"
33
34 #include <set>
35
36 namespace deqp
37 {
38 namespace gles3
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 TYPE_INSTANCE_COUNT, // !< test with 1, 4, and 11 instances
49 TYPE_INDEX_RANGE, // !< test with index range of [0, 23], [23, 40], and [5, 5]
50
51 TYPE_LAST
52 };
53
addTestIterations(gls::DrawTest * test,const gls::DrawTestSpec & baseSpec,TestIterationType type)54 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type)
55 {
56 gls::DrawTestSpec spec(baseSpec);
57
58 if (type == TYPE_DRAW_COUNT)
59 {
60 spec.primitiveCount = 1;
61 test->addIteration(spec, "draw count = 1");
62
63 spec.primitiveCount = 5;
64 test->addIteration(spec, "draw count = 5");
65
66 spec.primitiveCount = 25;
67 test->addIteration(spec, "draw count = 25");
68 }
69 else if (type == TYPE_INSTANCE_COUNT)
70 {
71 spec.instanceCount = 1;
72 test->addIteration(spec, "instance count = 1");
73
74 spec.instanceCount = 4;
75 test->addIteration(spec, "instance count = 4");
76
77 spec.instanceCount = 11;
78 test->addIteration(spec, "instance count = 11");
79 }
80 else if (type == TYPE_INDEX_RANGE)
81 {
82 spec.indexMin = 0;
83 spec.indexMax = 23;
84 test->addIteration(spec, "index range = [0, 23]");
85
86 spec.indexMin = 23;
87 spec.indexMax = 40;
88 test->addIteration(spec, "index range = [23, 40]");
89
90 // Only makes sense with points
91 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_POINTS)
92 {
93 spec.indexMin = 5;
94 spec.indexMax = 5;
95 test->addIteration(spec, "index range = [5, 5]");
96 }
97 }
98 else
99 DE_ASSERT(false);
100 }
101
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)102 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
103 {
104 spec.apiType = glu::ApiType::es(3,0);
105 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
106 spec.primitiveCount = 5;
107 spec.drawMethod = method;
108 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST;
109 spec.indexPointerOffset = 0;
110 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST;
111 spec.first = 0;
112 spec.indexMin = 0;
113 spec.indexMax = 0;
114 spec.instanceCount = 1;
115
116 spec.attribs.resize(2);
117
118 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
119 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
120 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
121 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
122 spec.attribs[0].componentCount = 4;
123 spec.attribs[0].offset = 0;
124 spec.attribs[0].stride = 0;
125 spec.attribs[0].normalize = false;
126 spec.attribs[0].instanceDivisor = 0;
127 spec.attribs[0].useDefaultAttribute = false;
128
129 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
130 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
131 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
132 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
133 spec.attribs[1].componentCount = 2;
134 spec.attribs[1].offset = 0;
135 spec.attribs[1].stride = 0;
136 spec.attribs[1].normalize = false;
137 spec.attribs[1].instanceDivisor = 0;
138 spec.attribs[1].useDefaultAttribute = false;
139 }
140
141 class AttributeGroup : public TestCaseGroup
142 {
143 public:
144 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);
145 ~AttributeGroup (void);
146
147 void init (void);
148
149 private:
150 gls::DrawTestSpec::DrawMethod m_method;
151 gls::DrawTestSpec::Primitive m_primitive;
152 gls::DrawTestSpec::IndexType m_indexType;
153 gls::DrawTestSpec::Storage m_indexStorage;
154 };
155
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)156 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)
157 : TestCaseGroup (context, name, descr)
158 , m_method (drawMethod)
159 , m_primitive (primitive)
160 , m_indexType (indexType)
161 , m_indexStorage (indexStorage)
162 {
163 }
164
~AttributeGroup(void)165 AttributeGroup::~AttributeGroup (void)
166 {
167 }
168
init(void)169 void AttributeGroup::init (void)
170 {
171 // select test type
172 const bool instanced = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED) ||
173 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED);
174 const bool ranged = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
175 const TestIterationType testType = (instanced) ? (TYPE_INSTANCE_COUNT) : ((ranged) ? (TYPE_INDEX_RANGE) : (TYPE_DRAW_COUNT));
176
177 // Single attribute
178 {
179 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
180 gls::DrawTestSpec spec;
181
182 spec.apiType = glu::ApiType::es(3,0);
183 spec.primitive = m_primitive;
184 spec.primitiveCount = 5;
185 spec.drawMethod = m_method;
186 spec.indexType = m_indexType;
187 spec.indexPointerOffset = 0;
188 spec.indexStorage = m_indexStorage;
189 spec.first = 0;
190 spec.indexMin = 0;
191 spec.indexMax = 0;
192 spec.instanceCount = 1;
193
194 spec.attribs.resize(1);
195
196 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
197 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
198 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
199 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
200 spec.attribs[0].componentCount = 2;
201 spec.attribs[0].offset = 0;
202 spec.attribs[0].stride = 0;
203 spec.attribs[0].normalize = false;
204 spec.attribs[0].instanceDivisor = 0;
205 spec.attribs[0].useDefaultAttribute = false;
206
207 addTestIterations(test, spec, testType);
208
209 this->addChild(test);
210 }
211
212 // Multiple attribute
213 {
214 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
215 gls::DrawTestSpec spec;
216
217 spec.apiType = glu::ApiType::es(3,0);
218 spec.primitive = m_primitive;
219 spec.primitiveCount = 5;
220 spec.drawMethod = m_method;
221 spec.indexType = m_indexType;
222 spec.indexPointerOffset = 0;
223 spec.indexStorage = m_indexStorage;
224 spec.first = 0;
225 spec.indexMin = 0;
226 spec.indexMax = 0;
227 spec.instanceCount = 1;
228
229 spec.attribs.resize(2);
230
231 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
232 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
233 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
234 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
235 spec.attribs[0].componentCount = 4;
236 spec.attribs[0].offset = 0;
237 spec.attribs[0].stride = 0;
238 spec.attribs[0].normalize = false;
239 spec.attribs[0].instanceDivisor = 0;
240 spec.attribs[0].useDefaultAttribute = false;
241
242 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
243 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
244 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
245 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
246 spec.attribs[1].componentCount = 2;
247 spec.attribs[1].offset = 0;
248 spec.attribs[1].stride = 0;
249 spec.attribs[1].normalize = false;
250 spec.attribs[1].instanceDivisor = 0;
251 spec.attribs[1].useDefaultAttribute = false;
252
253 addTestIterations(test, spec, testType);
254
255 this->addChild(test);
256 }
257
258 // Multiple attribute, second one divided
259 {
260 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
261 gls::DrawTestSpec spec;
262
263 spec.apiType = glu::ApiType::es(3,0);
264 spec.primitive = m_primitive;
265 spec.primitiveCount = 5;
266 spec.drawMethod = m_method;
267 spec.indexType = m_indexType;
268 spec.indexPointerOffset = 0;
269 spec.indexStorage = m_indexStorage;
270 spec.first = 0;
271 spec.indexMin = 0;
272 spec.indexMax = 0;
273 spec.instanceCount = 1;
274
275 spec.attribs.resize(3);
276
277 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
278 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
279 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
280 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
281 spec.attribs[0].componentCount = 4;
282 spec.attribs[0].offset = 0;
283 spec.attribs[0].stride = 0;
284 spec.attribs[0].normalize = false;
285 spec.attribs[0].instanceDivisor = 0;
286 spec.attribs[0].useDefaultAttribute = false;
287
288 // Add another position component so the instances wont be drawn on each other
289 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
290 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
291 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
292 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
293 spec.attribs[1].componentCount = 2;
294 spec.attribs[1].offset = 0;
295 spec.attribs[1].stride = 0;
296 spec.attribs[1].normalize = false;
297 spec.attribs[1].instanceDivisor = 1;
298 spec.attribs[1].useDefaultAttribute = false;
299 spec.attribs[1].additionalPositionAttribute = true;
300
301 // Instanced color
302 spec.attribs[2].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
303 spec.attribs[2].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
304 spec.attribs[2].storage = gls::DrawTestSpec::STORAGE_BUFFER;
305 spec.attribs[2].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
306 spec.attribs[2].componentCount = 3;
307 spec.attribs[2].offset = 0;
308 spec.attribs[2].stride = 0;
309 spec.attribs[2].normalize = false;
310 spec.attribs[2].instanceDivisor = 1;
311 spec.attribs[2].useDefaultAttribute = false;
312
313 addTestIterations(test, spec, testType);
314
315 this->addChild(test);
316 }
317
318 // Multiple attribute, second one default
319 {
320 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
321 gls::DrawTestSpec spec;
322
323 spec.apiType = glu::ApiType::es(3,0);
324 spec.primitive = m_primitive;
325 spec.primitiveCount = 5;
326 spec.drawMethod = m_method;
327 spec.indexType = m_indexType;
328 spec.indexPointerOffset = 0;
329 spec.indexStorage = m_indexStorage;
330 spec.first = 0;
331 spec.indexMin = 0;
332 spec.indexMax = 20; // \note addTestIterations is not called for the spec, so we must ensure [indexMin, indexMax] is a good range
333 spec.instanceCount = 1;
334
335 spec.attribs.resize(2);
336
337 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
338 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
339 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
340 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
341 spec.attribs[0].componentCount = 2;
342 spec.attribs[0].offset = 0;
343 spec.attribs[0].stride = 0;
344 spec.attribs[0].normalize = false;
345 spec.attribs[0].instanceDivisor = 0;
346 spec.attribs[0].useDefaultAttribute = false;
347
348 struct IOPair
349 {
350 gls::DrawTestSpec::InputType input;
351 gls::DrawTestSpec::OutputType output;
352 int componentCount;
353 } iopairs[] =
354 {
355 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4 },
356 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2 },
357 { gls::DrawTestSpec::INPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
358 { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
359 };
360
361 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
362 {
363 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
364
365 spec.attribs[1].inputType = iopairs[ioNdx].input;
366 spec.attribs[1].outputType = iopairs[ioNdx].output;
367 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
368 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
369 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount;
370 spec.attribs[1].offset = 0;
371 spec.attribs[1].stride = 0;
372 spec.attribs[1].normalize = false;
373 spec.attribs[1].instanceDivisor = 0;
374 spec.attribs[1].useDefaultAttribute = true;
375
376 test->addIteration(spec, desc.c_str());
377 }
378
379 this->addChild(test);
380 }
381 }
382
383 class IndexGroup : public TestCaseGroup
384 {
385 public:
386 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
387 ~IndexGroup (void);
388
389 void init (void);
390
391 private:
392 gls::DrawTestSpec::DrawMethod m_method;
393 };
394
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)395 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
396 : TestCaseGroup (context, name, descr)
397 , m_method (drawMethod)
398 {
399 }
400
~IndexGroup(void)401 IndexGroup::~IndexGroup (void)
402 {
403 }
404
init(void)405 void IndexGroup::init (void)
406 {
407 struct IndexTest
408 {
409 gls::DrawTestSpec::Storage storage;
410 gls::DrawTestSpec::IndexType type;
411 bool aligned;
412 int offsets[3];
413 };
414
415 const IndexTest tests[] =
416 {
417 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } },
418 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } },
419 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } },
420
421 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } },
422 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, false, { 2, 3, -1 } },
423
424 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } },
425 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } },
426 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } },
427 };
428
429 gls::DrawTestSpec spec;
430
431 tcu::TestCaseGroup* userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
432 tcu::TestCaseGroup* unalignedUserPtrGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
433 tcu::TestCaseGroup* bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
434
435 genBasicSpec(spec, m_method);
436
437 this->addChild(userPtrGroup);
438 this->addChild(unalignedUserPtrGroup);
439 this->addChild(bufferGroup);
440
441 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
442 {
443 const IndexTest& indexTest = tests[testNdx];
444 tcu::TestCaseGroup* group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER)
445 ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup))
446 : ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
447
448 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
449 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
450 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
451
452 spec.indexType = indexTest.type;
453 spec.indexStorage = indexTest.storage;
454
455 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
456 {
457 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
458 spec.indexPointerOffset = indexTest.offsets[iterationNdx];
459 test->addIteration(spec, iterationDesc.c_str());
460 }
461
462 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
463 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
464 group->addChild(test.release());
465 }
466 }
467
468
469 class FirstGroup : public TestCaseGroup
470 {
471 public:
472 FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
473 ~FirstGroup (void);
474
475 void init (void);
476
477 private:
478 gls::DrawTestSpec::DrawMethod m_method;
479 };
480
FirstGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)481 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
482 : TestCaseGroup (context, name, descr)
483 , m_method (drawMethod)
484 {
485 }
486
~FirstGroup(void)487 FirstGroup::~FirstGroup (void)
488 {
489 }
490
init(void)491 void FirstGroup::init (void)
492 {
493 const int firsts[] =
494 {
495 1, 3, 17
496 };
497
498 gls::DrawTestSpec spec;
499 genBasicSpec(spec, m_method);
500
501 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
502 {
503 const std::string name = std::string("first_") + de::toString(firsts[firstNdx]);
504 const std::string desc = std::string("first ") + de::toString(firsts[firstNdx]);
505 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
506
507 spec.first = firsts[firstNdx];
508
509 addTestIterations(test, spec, TYPE_DRAW_COUNT);
510
511 this->addChild(test);
512 }
513 }
514
515 class MethodGroup : public TestCaseGroup
516 {
517 public:
518 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
519 ~MethodGroup (void);
520
521 void init (void);
522
523 private:
524 gls::DrawTestSpec::DrawMethod m_method;
525 };
526
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)527 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
528 : TestCaseGroup (context, name, descr)
529 , m_method (drawMethod)
530 {
531 }
532
~MethodGroup(void)533 MethodGroup::~MethodGroup (void)
534 {
535 }
536
init(void)537 void MethodGroup::init (void)
538 {
539 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
540 const bool hasFirst = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
541
542 const gls::DrawTestSpec::Primitive primitive[] =
543 {
544 gls::DrawTestSpec::PRIMITIVE_POINTS,
545 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
546 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
547 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
548 gls::DrawTestSpec::PRIMITIVE_LINES,
549 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
550 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
551 };
552
553 if (hasFirst)
554 {
555 // First-tests
556 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
557 }
558
559 if (indexed)
560 {
561 // Index-tests
562 if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
563 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
564 }
565
566 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
567 {
568 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
569 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
570
571 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
572 }
573 }
574
575 class GridProgram : public sglr::ShaderProgram
576 {
577 public:
578 GridProgram (void);
579
580 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
581 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
582 };
583
GridProgram(void)584 GridProgram::GridProgram (void)
585 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
586 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
587 << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT)
588 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
589 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
590 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
591 << sglr::pdec::VertexSource("#version 300 es\n"
592 "in highp vec4 a_position;\n"
593 "in highp vec4 a_offset;\n"
594 "in highp vec4 a_color;\n"
595 "out mediump vec4 v_color;\n"
596 "void main(void)\n"
597 "{\n"
598 " gl_Position = a_position + a_offset;\n"
599 " v_color = a_color;\n"
600 "}\n")
601 << sglr::pdec::FragmentSource(
602 "#version 300 es\n"
603 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
604 "in mediump vec4 v_color;\n"
605 "void main(void)\n"
606 "{\n"
607 " dEQP_FragColor = v_color;\n"
608 "}\n"))
609 {
610 }
611
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const612 void GridProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
613 {
614 for (int ndx = 0; ndx < numPackets; ++ndx)
615 {
616 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
617 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[2], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
618 }
619 }
620
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const621 void GridProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
622 {
623 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
624 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
625 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx));
626 }
627
628 class InstancedGridRenderTest : public TestCase
629 {
630 public:
631 InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices);
632 ~InstancedGridRenderTest (void);
633
634 IterateResult iterate (void);
635
636 private:
637 void renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst);
638 bool verifyImage (const tcu::Surface& image);
639
640 const int m_gridSide;
641 const bool m_useIndices;
642 };
643
InstancedGridRenderTest(Context & context,const char * name,const char * desc,int gridSide,bool useIndices)644 InstancedGridRenderTest::InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices)
645 : TestCase (context, name, desc)
646 , m_gridSide (gridSide)
647 , m_useIndices (useIndices)
648 {
649 }
650
~InstancedGridRenderTest(void)651 InstancedGridRenderTest::~InstancedGridRenderTest (void)
652 {
653 }
654
iterate(void)655 InstancedGridRenderTest::IterateResult InstancedGridRenderTest::iterate (void)
656 {
657 const int renderTargetWidth = de::min(1024, m_context.getRenderTarget().getWidth());
658 const int renderTargetHeight = de::min(1024, m_context.getRenderTarget().getHeight());
659
660 sglr::GLContext ctx (m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
661 tcu::Surface surface (renderTargetWidth, renderTargetHeight);
662 GridProgram program;
663
664 // render
665
666 renderTo(ctx, program, surface);
667
668 // verify image
669
670 if (verifyImage(surface))
671 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
672 else
673 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering result");
674 return STOP;
675 }
676
renderTo(sglr::Context & ctx,sglr::ShaderProgram & program,tcu::Surface & dst)677 void InstancedGridRenderTest::renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst)
678 {
679 const tcu::Vec4 green (0, 1, 0, 1);
680 const tcu::Vec4 yellow (1, 1, 0, 1);
681
682 deUint32 positionBuf = 0;
683 deUint32 offsetBuf = 0;
684 deUint32 colorBuf = 0;
685 deUint32 indexBuf = 0;
686 deUint32 programID = ctx.createProgram(&program);
687 deInt32 posLocation = ctx.getAttribLocation(programID, "a_position");
688 deInt32 offsetLocation = ctx.getAttribLocation(programID, "a_offset");
689 deInt32 colorLocation = ctx.getAttribLocation(programID, "a_color");
690
691 float cellW = 2.0f / (float)m_gridSide;
692 float cellH = 2.0f / (float)m_gridSide;
693 const tcu::Vec4 vertexPositions[] =
694 {
695 tcu::Vec4(0, 0, 0, 1),
696 tcu::Vec4(cellW, 0, 0, 1),
697 tcu::Vec4(0, cellH, 0, 1),
698
699 tcu::Vec4(0, cellH, 0, 1),
700 tcu::Vec4(cellW, 0, 0, 1),
701 tcu::Vec4(cellW, cellH, 0, 1),
702 };
703
704 const deUint16 indices[] =
705 {
706 0, 4, 3,
707 2, 1, 5
708 };
709
710 std::vector<tcu::Vec4> offsets;
711 for (int x = 0; x < m_gridSide; ++x)
712 for (int y = 0; y < m_gridSide; ++y)
713 offsets.push_back(tcu::Vec4((float)x * cellW - 1.0f, (float)y * cellW - 1.0f, 0, 0));
714
715 std::vector<tcu::Vec4> colors;
716 for (int x = 0; x < m_gridSide; ++x)
717 for (int y = 0; y < m_gridSide; ++y)
718 colors.push_back(((x + y) % 2 == 0) ? (green) : (yellow));
719
720 ctx.genBuffers(1, &positionBuf);
721 ctx.bindBuffer(GL_ARRAY_BUFFER, positionBuf);
722 ctx.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
723 ctx.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
724 ctx.vertexAttribDivisor(posLocation, 0);
725 ctx.enableVertexAttribArray(posLocation);
726
727 ctx.genBuffers(1, &offsetBuf);
728 ctx.bindBuffer(GL_ARRAY_BUFFER, offsetBuf);
729 ctx.bufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(tcu::Vec4), &offsets[0], GL_STATIC_DRAW);
730 ctx.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
731 ctx.vertexAttribDivisor(offsetLocation, 1);
732 ctx.enableVertexAttribArray(offsetLocation);
733
734 ctx.genBuffers(1, &colorBuf);
735 ctx.bindBuffer(GL_ARRAY_BUFFER, colorBuf);
736 ctx.bufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(tcu::Vec4), &colors[0], GL_STATIC_DRAW);
737 ctx.vertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
738 ctx.vertexAttribDivisor(colorLocation, 1);
739 ctx.enableVertexAttribArray(colorLocation);
740
741 if (m_useIndices)
742 {
743 ctx.genBuffers(1, &indexBuf);
744 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
745 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
746 }
747
748 ctx.clearColor(0, 0, 0, 1);
749 ctx.clear(GL_COLOR_BUFFER_BIT);
750
751 ctx.viewport(0, 0, dst.getWidth(), dst.getHeight());
752
753 ctx.useProgram(programID);
754 if (m_useIndices)
755 ctx.drawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL, m_gridSide * m_gridSide);
756 else
757 ctx.drawArraysInstanced(GL_TRIANGLES, 0, 6, m_gridSide * m_gridSide);
758 ctx.useProgram(0);
759
760 if (m_useIndices)
761 ctx.deleteBuffers(1, &indexBuf);
762 ctx.deleteBuffers(1, &colorBuf);
763 ctx.deleteBuffers(1, &offsetBuf);
764 ctx.deleteBuffers(1, &positionBuf);
765 ctx.deleteProgram(programID);
766
767 ctx.finish();
768 ctx.readPixels(dst, 0, 0, dst.getWidth(), dst.getHeight());
769
770 glu::checkError(ctx.getError(), "", __FILE__, __LINE__);
771 }
772
verifyImage(const tcu::Surface & image)773 bool InstancedGridRenderTest::verifyImage (const tcu::Surface& image)
774 {
775 // \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow.
776 using tcu::TestLog;
777
778 const int colorThreshold = 20;
779
780 tcu::Surface error (image.getWidth(), image.getHeight());
781 bool isOk = true;
782
783 for (int y = 0; y < image.getHeight(); y++)
784 for (int x = 0; x < image.getWidth(); x++)
785 {
786 if (x == 0 || y == 0 || y + 1 == image.getHeight() || x + 1 == image.getWidth())
787 {
788 // Background color might bleed in at the borders with msaa
789 error.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
790 }
791 else
792 {
793 const tcu::RGBA pixel = image.getPixel(x, y);
794 bool pixelOk = true;
795
796 // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
797 if (de::abs(pixel.getGreen() - 255) > colorThreshold)
798 pixelOk = false;
799
800 // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
801 if (de::abs(pixel.getBlue() - 0) > colorThreshold)
802 pixelOk = false;
803
804 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
805 isOk = isOk && pixelOk;
806 }
807 }
808
809 if (!isOk)
810 {
811 tcu::TestLog& log = m_testCtx.getLog();
812
813 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
814 log << TestLog::ImageSet("Verfication result", "Result of rendering")
815 << TestLog::Image("Result", "Result", image)
816 << TestLog::Image("ErrorMask", "Error mask", error)
817 << TestLog::EndImageSet;
818 }
819 else
820 {
821 tcu::TestLog& log = m_testCtx.getLog();
822
823 log << TestLog::ImageSet("Verfication result", "Result of rendering")
824 << TestLog::Image("Result", "Result", image)
825 << TestLog::EndImageSet;
826 }
827
828 return isOk;
829 }
830
831 class InstancingGroup : public TestCaseGroup
832 {
833 public:
834 InstancingGroup (Context& context, const char* name, const char* descr);
835 ~InstancingGroup (void);
836
837 void init (void);
838 };
839
InstancingGroup(Context & context,const char * name,const char * descr)840 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr)
841 : TestCaseGroup (context, name, descr)
842 {
843 }
844
~InstancingGroup(void)845 InstancingGroup::~InstancingGroup (void)
846 {
847 }
848
init(void)849 void InstancingGroup::init (void)
850 {
851 const int gridWidths[] =
852 {
853 2,
854 5,
855 10,
856 32,
857 100,
858 };
859
860 // drawArrays
861 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
862 {
863 const std::string name = std::string("draw_arrays_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
864 const std::string desc = std::string("DrawArraysInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
865
866 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], false));
867 }
868
869 // drawElements
870 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
871 {
872 const std::string name = std::string("draw_elements_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
873 const std::string desc = std::string("DrawElementsInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
874
875 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], true));
876 }
877 }
878
879 class RandomGroup : public TestCaseGroup
880 {
881 public:
882 RandomGroup (Context& context, const char* name, const char* descr);
883 ~RandomGroup (void);
884
885 void init (void);
886 };
887
888 template <int SIZE>
889 struct UniformWeightArray
890 {
891 float weights[SIZE];
892
UniformWeightArraydeqp::gles3::Functional::__anone39477c20111::UniformWeightArray893 UniformWeightArray (void)
894 {
895 for (int i=0; i<SIZE; ++i)
896 weights[i] = 1.0f;
897 }
898 };
899
RandomGroup(Context & context,const char * name,const char * descr)900 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
901 : TestCaseGroup (context, name, descr)
902 {
903 }
904
~RandomGroup(void)905 RandomGroup::~RandomGroup (void)
906 {
907 }
908
init(void)909 void RandomGroup::init (void)
910 {
911 const int numAttempts = 300;
912
913 static const int attribCounts[] = { 1, 2, 5 };
914 static const float attribWeights[] = { 30, 10, 1 };
915 static const int primitiveCounts[] = { 1, 5, 64 };
916 static const float primitiveCountWeights[] = { 20, 10, 1 };
917 static const int indexOffsets[] = { 0, 7, 13 };
918 static const float indexOffsetWeights[] = { 20, 20, 1 };
919 static const int firsts[] = { 0, 7, 13 };
920 static const float firstWeights[] = { 20, 20, 1 };
921 static const int instanceCounts[] = { 1, 2, 16, 17 };
922 static const float instanceWeights[] = { 20, 10, 5, 1 };
923 static const int indexMins[] = { 0, 1, 3, 8 };
924 static const int indexMaxs[] = { 4, 8, 128, 257 };
925 static const float indexWeights[] = { 50, 50, 50, 50 };
926 static const int offsets[] = { 0, 1, 5, 12 };
927 static const float offsetWeights[] = { 50, 10, 10, 10 };
928 static const int strides[] = { 0, 7, 16, 17 };
929 static const float strideWeights[] = { 50, 10, 10, 10 };
930 static const int instanceDivisors[] = { 0, 1, 3, 129 };
931 static const float instanceDivisorWeights[]= { 70, 30, 10, 10 };
932
933 static const gls::DrawTestSpec::Primitive primitives[] =
934 {
935 gls::DrawTestSpec::PRIMITIVE_POINTS,
936 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
937 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
938 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
939 gls::DrawTestSpec::PRIMITIVE_LINES,
940 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
941 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
942 };
943 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
944
945 static const gls::DrawTestSpec::DrawMethod drawMethods[] =
946 {
947 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
948 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
949 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
950 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
951 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED
952 };
953 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
954
955 static const gls::DrawTestSpec::IndexType indexTypes[] =
956 {
957 gls::DrawTestSpec::INDEXTYPE_BYTE,
958 gls::DrawTestSpec::INDEXTYPE_SHORT,
959 gls::DrawTestSpec::INDEXTYPE_INT,
960 };
961 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
962
963 static const gls::DrawTestSpec::Storage storages[] =
964 {
965 gls::DrawTestSpec::STORAGE_USER,
966 gls::DrawTestSpec::STORAGE_BUFFER,
967 };
968 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
969
970 static const gls::DrawTestSpec::InputType inputTypes[] =
971 {
972 gls::DrawTestSpec::INPUTTYPE_FLOAT,
973 gls::DrawTestSpec::INPUTTYPE_FIXED,
974 gls::DrawTestSpec::INPUTTYPE_BYTE,
975 gls::DrawTestSpec::INPUTTYPE_SHORT,
976 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
977 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
978 gls::DrawTestSpec::INPUTTYPE_INT,
979 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
980 gls::DrawTestSpec::INPUTTYPE_HALF,
981 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
982 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
983 };
984 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
985
986 static const gls::DrawTestSpec::OutputType outputTypes[] =
987 {
988 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
989 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
990 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
991 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
992 gls::DrawTestSpec::OUTPUTTYPE_INT,
993 gls::DrawTestSpec::OUTPUTTYPE_UINT,
994 gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
995 gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
996 gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
997 gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
998 gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
999 gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
1000 };
1001 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
1002
1003 static const gls::DrawTestSpec::Usage usages[] =
1004 {
1005 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
1006 gls::DrawTestSpec::USAGE_STATIC_DRAW,
1007 gls::DrawTestSpec::USAGE_STREAM_DRAW,
1008 gls::DrawTestSpec::USAGE_STREAM_READ,
1009 gls::DrawTestSpec::USAGE_STREAM_COPY,
1010 gls::DrawTestSpec::USAGE_STATIC_READ,
1011 gls::DrawTestSpec::USAGE_STATIC_COPY,
1012 gls::DrawTestSpec::USAGE_DYNAMIC_READ,
1013 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
1014 };
1015 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
1016
1017 static const deUint32 disallowedCases[]=
1018 {
1019 544, //!< extremely narrow triangle
1020 };
1021
1022 std::set<deUint32> insertedHashes;
1023 size_t insertedCount = 0;
1024
1025 for (int ndx = 0; ndx < numAttempts; ++ndx)
1026 {
1027 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
1028
1029 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
1030 gls::DrawTestSpec spec;
1031
1032 spec.apiType = glu::ApiType::es(3,0);
1033 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights);
1034 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights);
1035 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights);
1036 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights);
1037 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights);
1038 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
1039 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights);
1040 spec.indexMin = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMins), DE_ARRAY_END(indexMins), indexWeights);
1041 spec.indexMax = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMaxs), DE_ARRAY_END(indexMaxs), indexWeights);
1042 spec.instanceCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(instanceCounts), DE_ARRAY_END(instanceCounts), instanceWeights);
1043
1044 // check spec is legal
1045 if (!spec.valid())
1046 continue;
1047
1048 for (int attrNdx = 0; attrNdx < attributeCount;)
1049 {
1050 bool valid;
1051 gls::DrawTestSpec::AttributeSpec attribSpec;
1052
1053 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights);
1054 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights);
1055 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
1056 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights);
1057 attribSpec.componentCount = random.getInt(1, 4);
1058 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
1059 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
1060 attribSpec.normalize = random.getBool();
1061 attribSpec.instanceDivisor = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
1062 attribSpec.useDefaultAttribute = random.getBool();
1063
1064 // check spec is legal
1065 valid = attribSpec.valid(spec.apiType);
1066
1067 // we do not want interleaved elements. (Might result in some weird floating point values)
1068 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
1069 valid = false;
1070
1071 // try again if not valid
1072 if (valid)
1073 {
1074 spec.attribs.push_back(attribSpec);
1075 ++attrNdx;
1076 }
1077 }
1078
1079 // Do not collapse all vertex positions to a single positions
1080 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1081 spec.attribs[0].instanceDivisor = 0;
1082
1083 // Is render result meaningful?
1084 {
1085 // Only one vertex
1086 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1087 continue;
1088 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1089 continue;
1090
1091 // Triangle only on one axis
1092 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
1093 {
1094 if (spec.attribs[0].componentCount == 1)
1095 continue;
1096 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
1097 continue;
1098 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
1099 continue;
1100 }
1101 }
1102
1103 // Add case
1104 {
1105 deUint32 hash = spec.hash();
1106 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
1107 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
1108
1109 if (insertedHashes.find(hash) == insertedHashes.end())
1110 {
1111 // Only properly aligned and not disallowed cases
1112 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
1113 spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE &&
1114 !de::contains(DE_ARRAY_BEGIN(disallowedCases), DE_ARRAY_END(disallowedCases), hash))
1115 {
1116 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
1117 }
1118 insertedHashes.insert(hash);
1119
1120 ++insertedCount;
1121 }
1122 }
1123 }
1124 }
1125
1126 } // anonymous
1127
DrawTests(Context & context)1128 DrawTests::DrawTests (Context& context)
1129 : TestCaseGroup(context, "draw", "Drawing tests")
1130 {
1131 }
1132
~DrawTests(void)1133 DrawTests::~DrawTests (void)
1134 {
1135 }
1136
init(void)1137 void DrawTests::init (void)
1138 {
1139 // Basic
1140 {
1141 const gls::DrawTestSpec::DrawMethod basicMethods[] =
1142 {
1143 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
1144 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
1145 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
1146 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED,
1147 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
1148 };
1149
1150 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
1151 {
1152 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
1153 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
1154
1155 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
1156 }
1157 }
1158
1159 // extreme instancing
1160
1161 this->addChild(new InstancingGroup(m_context, "instancing", "draw tests with a large instance count."));
1162
1163 // Random
1164
1165 this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
1166 }
1167
1168 } // Functional
1169 } // gles3
1170 } // deqp
1171