Add new compute negative coverage tests am: db4a886f3f
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / stress / es2sDrawTests.cpp
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 "es2sDrawTests.hpp"
25 #include "glsDrawTest.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "deRandom.hpp"
28 #include "deStringUtil.hpp"
29 #include "deUniquePtr.hpp"
30
31 #include "glwEnums.hpp"
32
33 #include <set>
34
35 namespace deqp
36 {
37 namespace gles2
38 {
39 namespace Stress
40 {
41 namespace
42 {
43
44 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
45 {
46         spec.apiType                                                    = glu::ApiType::es(2,0);
47         spec.primitive                                                  = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
48         spec.primitiveCount                                             = 5;
49         spec.drawMethod                                                 = method;
50         spec.indexType                                                  = gls::DrawTestSpec::INDEXTYPE_LAST;
51         spec.indexPointerOffset                                 = 0;
52         spec.indexStorage                                               = gls::DrawTestSpec::STORAGE_LAST;
53         spec.first                                                              = 0;
54         spec.indexMin                                                   = 0;
55         spec.indexMax                                                   = 0;
56         spec.instanceCount                                              = 1;
57
58         spec.attribs.resize(2);
59
60         spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
61         spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
62         spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
63         spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
64         spec.attribs[0].componentCount                  = 4;
65         spec.attribs[0].offset                                  = 0;
66         spec.attribs[0].stride                                  = 0;
67         spec.attribs[0].normalize                               = false;
68         spec.attribs[0].instanceDivisor                 = 0;
69         spec.attribs[0].useDefaultAttribute             = false;
70
71         spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
72         spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
73         spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
74         spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
75         spec.attribs[1].componentCount                  = 2;
76         spec.attribs[1].offset                                  = 0;
77         spec.attribs[1].stride                                  = 0;
78         spec.attribs[1].normalize                               = false;
79         spec.attribs[1].instanceDivisor                 = 0;
80         spec.attribs[1].useDefaultAttribute             = false;
81 }
82
83 class IndexGroup : public TestCaseGroup
84 {
85 public:
86                                                                         IndexGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
87                                                                         ~IndexGroup             (void);
88
89         void                                                    init                    (void);
90
91 private:
92         gls::DrawTestSpec::DrawMethod   m_method;
93 };
94
95 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
96         : TestCaseGroup         (context, name, descr)
97         , m_method                      (drawMethod)
98 {
99 }
100
101 IndexGroup::~IndexGroup (void)
102 {
103 }
104
105 void IndexGroup::init (void)
106 {
107         struct IndexTest
108         {
109                 gls::DrawTestSpec::Storage              storage;
110                 gls::DrawTestSpec::IndexType    type;
111                 bool                                                    aligned;
112                 int                                                             offsets[3];
113         };
114
115         const IndexTest tests[] =
116         {
117                 { gls::DrawTestSpec::STORAGE_BUFFER,    gls::DrawTestSpec::INDEXTYPE_SHORT,     false,  { 1, 3, -1 } },
118         };
119
120         gls::DrawTestSpec spec;
121
122         tcu::TestCaseGroup* unalignedBufferGroup        = new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer");
123
124         genBasicSpec(spec, m_method);
125
126         this->addChild(unalignedBufferGroup);
127
128         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
129         {
130                 const IndexTest&                                indexTest       = tests[testNdx];
131
132                 DE_ASSERT(indexTest.storage != gls::DrawTestSpec::STORAGE_USER);
133                 DE_ASSERT(!indexTest.aligned);
134                 tcu::TestCaseGroup*                             group           = unalignedBufferGroup;
135
136                 const std::string                               name            = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
137                 const std::string                               desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
138                 de::MovePtr<gls::DrawTest>              test            (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
139
140                 spec.indexType                  = indexTest.type;
141                 spec.indexStorage               = indexTest.storage;
142
143                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
144                 {
145                         const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
146                         spec.indexPointerOffset = indexTest.offsets[iterationNdx];
147                         test->addIteration(spec, iterationDesc.c_str());
148                 }
149
150                 DE_ASSERT(spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
151                                   spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
152                 group->addChild(test.release());
153         }
154 }
155
156 class MethodGroup : public TestCaseGroup
157 {
158 public:
159                                                                         MethodGroup                     (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
160                                                                         ~MethodGroup            (void);
161
162         void                                                    init                            (void);
163
164 private:
165         gls::DrawTestSpec::DrawMethod   m_method;
166 };
167
168 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
169         : TestCaseGroup         (context, name, descr)
170         , m_method                      (drawMethod)
171 {
172 }
173
174 MethodGroup::~MethodGroup (void)
175 {
176 }
177
178 void MethodGroup::init (void)
179 {
180         const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
181
182         DE_ASSERT(indexed);
183         DE_UNREF(indexed);
184
185         this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
186 }
187
188 class RandomGroup : public TestCaseGroup
189 {
190 public:
191                                                                         RandomGroup             (Context& context, const char* name, const char* descr);
192                                                                         ~RandomGroup    (void);
193
194         void                                                    init                    (void);
195 };
196
197 template <int SIZE>
198 struct UniformWeightArray
199 {
200         float weights[SIZE];
201
202         UniformWeightArray (void)
203         {
204                 for (int i=0; i<SIZE; ++i)
205                         weights[i] = 1.0f;
206         }
207 };
208
209 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
210         : TestCaseGroup (context, name, descr)
211 {
212 }
213
214 RandomGroup::~RandomGroup (void)
215 {
216 }
217
218 void RandomGroup::init (void)
219 {
220         const int       numAttempts                             = 100;
221
222         const int       attribCounts[]                  = { 1, 2, 5 };
223         const float     attribWeights[]                 = { 30, 10, 1 };
224         const int       primitiveCounts[]               = { 1, 5, 64 };
225         const float     primitiveCountWeights[] = { 20, 10, 1 };
226         const int       indexOffsets[]                  = { 0, 7, 13 };
227         const float     indexOffsetWeights[]    = { 20, 20, 1 };
228         const int       firsts[]                                = { 0, 7, 13 };
229         const float     firstWeights[]                  = { 20, 20, 1 };
230         const int       offsets[]                               = { 0, 1, 5, 12 };
231         const float     offsetWeights[]                 = { 50, 10, 10, 10 };
232         const int       strides[]                               = { 0, 7, 16, 17 };
233         const float     strideWeights[]                 = { 50, 10, 10, 10 };
234
235         gls::DrawTestSpec::Primitive primitives[] =
236         {
237                 gls::DrawTestSpec::PRIMITIVE_POINTS,
238                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
239                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
240                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
241                 gls::DrawTestSpec::PRIMITIVE_LINES,
242                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
243                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
244         };
245         const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
246
247         gls::DrawTestSpec::DrawMethod drawMethods[] =
248         {
249                 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
250                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
251         };
252         const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
253
254         gls::DrawTestSpec::IndexType indexTypes[] =
255         {
256                 gls::DrawTestSpec::INDEXTYPE_BYTE,
257                 gls::DrawTestSpec::INDEXTYPE_SHORT,
258         };
259         const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
260
261         gls::DrawTestSpec::Storage storages[] =
262         {
263                 gls::DrawTestSpec::STORAGE_USER,
264                 gls::DrawTestSpec::STORAGE_BUFFER,
265         };
266         const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
267
268         gls::DrawTestSpec::InputType inputTypes[] =
269         {
270                 gls::DrawTestSpec::INPUTTYPE_FLOAT,
271                 gls::DrawTestSpec::INPUTTYPE_FIXED,
272                 gls::DrawTestSpec::INPUTTYPE_BYTE,
273                 gls::DrawTestSpec::INPUTTYPE_SHORT,
274                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
275                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT
276         };
277         const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
278
279         gls::DrawTestSpec::OutputType outputTypes[] =
280         {
281                 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
282                 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
283                 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
284                 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
285         };
286         const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
287
288         gls::DrawTestSpec::Usage usages[] =
289         {
290                 gls::DrawTestSpec::USAGE_STATIC_DRAW,
291                 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
292                 gls::DrawTestSpec::USAGE_STREAM_DRAW,
293         };
294         const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
295
296         const deUint32 blacklistedCases[]=
297         {
298                 3153,   //!< extremely narrow triangle, results depend on sample positions
299         };
300
301         std::set<deUint32>      insertedHashes;
302         size_t                          insertedCount = 0;
303
304         for (int ndx = 0; ndx < numAttempts; ++ndx)
305         {
306                 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
307
308                 int                                     attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
309                 gls::DrawTestSpec       spec;
310
311                 spec.apiType                            = glu::ApiType::es(2,0);
312                 spec.primitive                          = random.chooseWeighted<gls::DrawTestSpec::Primitive>   (DE_ARRAY_BEGIN(primitives),            DE_ARRAY_END(primitives),               primitiveWeights.weights);
313                 spec.primitiveCount                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(primitiveCounts),       DE_ARRAY_END(primitiveCounts),  primitiveCountWeights);
314                 spec.drawMethod                         = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>  (DE_ARRAY_BEGIN(drawMethods),           DE_ARRAY_END(drawMethods),              drawMethodWeights.weights);
315                 spec.indexType                          = random.chooseWeighted<gls::DrawTestSpec::IndexType>   (DE_ARRAY_BEGIN(indexTypes),            DE_ARRAY_END(indexTypes),               indexTypeWeights.weights);
316                 spec.indexPointerOffset         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexOffsets),          DE_ARRAY_END(indexOffsets),             indexOffsetWeights);
317                 spec.indexStorage                       = random.chooseWeighted<gls::DrawTestSpec::Storage>             (DE_ARRAY_BEGIN(storages),                      DE_ARRAY_END(storages),                 storageWeights.weights);
318                 spec.first                                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(firsts),                        DE_ARRAY_END(firsts),                   firstWeights);
319                 spec.indexMin                           = 0;
320                 spec.indexMax                           = 0;
321                 spec.instanceCount                      = 0;
322
323                 // check spec is legal
324                 if (!spec.valid())
325                         continue;
326
327                 for (int attrNdx = 0; attrNdx < attributeCount;)
328                 {
329                         bool valid;
330                         gls::DrawTestSpec::AttributeSpec attribSpec;
331
332                         attribSpec.inputType                    = random.chooseWeighted<gls::DrawTestSpec::InputType>   (DE_ARRAY_BEGIN(inputTypes),            DE_ARRAY_END(inputTypes),               inputTypeWeights.weights);
333                         attribSpec.outputType                   = random.chooseWeighted<gls::DrawTestSpec::OutputType>  (DE_ARRAY_BEGIN(outputTypes),           DE_ARRAY_END(outputTypes),              outputTypeWeights.weights);
334                         attribSpec.storage                              = random.chooseWeighted<gls::DrawTestSpec::Storage>             (DE_ARRAY_BEGIN(storages),                      DE_ARRAY_END(storages),                 storageWeights.weights);
335                         attribSpec.usage                                = random.chooseWeighted<gls::DrawTestSpec::Usage>               (DE_ARRAY_BEGIN(usages),                        DE_ARRAY_END(usages),                   usageWeights.weights);
336                         attribSpec.componentCount               = random.getInt(1, 4);
337                         attribSpec.offset                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
338                         attribSpec.stride                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
339                         attribSpec.normalize                    = random.getBool();
340                         attribSpec.instanceDivisor              = 0;
341                         attribSpec.useDefaultAttribute  = random.getBool();
342
343                         // check spec is legal
344                         valid = attribSpec.valid(spec.apiType);
345
346                         // we do not want interleaved elements. (Might result in some weird floating point values)
347                         if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
348                                 valid = false;
349
350                         // try again if not valid
351                         if (valid)
352                         {
353                                 spec.attribs.push_back(attribSpec);
354                                 ++attrNdx;
355                         }
356                 }
357
358                 // Do not collapse all vertex positions to a single positions
359                 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
360                         spec.attribs[0].instanceDivisor = 0;
361
362                 // Is render result meaningful?
363                 {
364                         // Only one vertex
365                         if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
366                                 continue;
367                         if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
368                                 continue;
369
370                         // Triangle only on one axis
371                         if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
372                         {
373                                 if (spec.attribs[0].componentCount == 1)
374                                         continue;
375                                 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)
376                                         continue;
377                                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
378                                         continue;
379                         }
380                 }
381
382                 // Add case
383                 {
384                         deUint32 hash = spec.hash();
385                         for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
386                                 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
387
388                         if (insertedHashes.find(hash) == insertedHashes.end() &&
389                                 std::find(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash) == DE_ARRAY_END(blacklistedCases))
390                         {
391                                 // Only unaligned cases
392                                 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
393                                         spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
394                                         this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
395                                 insertedHashes.insert(hash);
396
397                                 ++insertedCount;
398                         }
399                 }
400         }
401 }
402
403 } // anonymous
404
405 DrawTests::DrawTests (Context& context)
406         : TestCaseGroup(context, "draw", "Drawing tests")
407 {
408 }
409
410 DrawTests::~DrawTests (void)
411 {
412 }
413
414 void DrawTests::init (void)
415 {
416         tcu::TestCaseGroup* const unalignedGroup        = new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
417
418         addChild(unalignedGroup);
419
420         // .unaligned_data
421         {
422                 const gls::DrawTestSpec::DrawMethod basicMethods[] =
423                 {
424                         // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
425                         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
426                 };
427
428                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
429                 {
430                         std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
431                         std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
432
433                         unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
434                 }
435
436                 // Random
437
438                 unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
439         }
440
441 }
442
443 } // Stress
444 } // gles2
445 } // deqp