Lower correlation threshold in flush-finish tests again am: 6455e6f987 am: 2e18b48b04
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / stress / es31sDrawTests.cpp
1
2 /*-------------------------------------------------------------------------
3  * drawElements Quality Program OpenGL ES 3.1 Module
4  * -------------------------------------------------
5  *
6  * Copyright 2014 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Drawing stress tests.
23  *//*--------------------------------------------------------------------*/
24
25 #include "es31sDrawTests.hpp"
26 #include "glsDrawTest.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluCallLogWrapper.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 #include "deRandom.hpp"
33 #include "deStringUtil.hpp"
34 #include "deUniquePtr.hpp"
35
36 #include <set>
37
38 namespace deqp
39 {
40 namespace gles31
41 {
42 namespace Stress
43 {
44 namespace
45 {
46
47 static const char* s_colorVertexShaderSource =          "#version 310 es\n"
48                                                                                                         "in highp vec4 a_position;\n"
49                                                                                                         "in highp vec4 a_color;\n"
50                                                                                                         "out highp vec4 v_color;\n"
51                                                                                                         "void main (void)\n"
52                                                                                                         "{\n"
53                                                                                                         "       gl_Position = a_position;\n"
54                                                                                                         "       v_color = a_color;\n"
55                                                                                                         "}\n";
56 static const char* s_colorFragmentShaderSource  =       "#version 310 es\n"
57                                                                                                         "layout(location = 0) out highp vec4 fragColor;\n"
58                                                                                                         "in highp vec4 v_color;\n"
59                                                                                                         "void main (void)\n"
60                                                                                                         "{\n"
61                                                                                                         "       fragColor = v_color;\n"
62                                                                                                         "}\n";
63 struct DrawElementsCommand
64 {
65         deUint32 count;
66         deUint32 primCount;
67         deUint32 firstIndex;
68         deInt32  baseVertex;
69         deUint32 reservedMustBeZero;
70 };
71 DE_STATIC_ASSERT(5 * sizeof(deUint32) == sizeof(DrawElementsCommand)); // tight packing
72
73 struct DrawArraysCommand
74 {
75         deUint32 count;
76         deUint32 primCount;
77         deUint32 first;
78         deUint32 reservedMustBeZero;
79 };
80 DE_STATIC_ASSERT(4 * sizeof(deUint32) == sizeof(DrawArraysCommand)); // tight packing
81
82 class InvalidDrawCase : public TestCase
83 {
84 public:
85         enum DrawType
86         {
87                 DRAW_ARRAYS,
88                 DRAW_ELEMENTS,
89
90                 DRAW_LAST
91         };
92         enum InvalidOperation
93         {
94                 INVALID_DATA_COUNT = 0,
95                 INVALID_DATA_FIRST,
96                 INVALID_DATA_INSTANCED,
97                 INVALID_INDEX_COUNT,
98                 INVALID_INDEX_FIRST,
99                 INVALID_RESERVED,
100                 INVALID_INDEX,
101
102                 INVALID_LAST
103         };
104
105                                                         InvalidDrawCase         (Context& context, const char* name, const char* desc, DrawType type, InvalidOperation op);
106                                                         ~InvalidDrawCase        (void);
107
108         void                                    init                            (void);
109         void                                    deinit                          (void);
110         IterateResult                   iterate                         (void);
111
112 private:
113         const DrawType                  m_drawType;
114         const InvalidOperation  m_op;
115         glw::GLuint                             m_dataBufferID;
116         glw::GLuint                             m_indexBufferID;
117         glw::GLuint                             m_cmdBufferID;
118         glw::GLuint                             m_colorBufferID;
119         glw::GLuint                             m_vao;
120 };
121
122 InvalidDrawCase::InvalidDrawCase (Context& context, const char* name, const char* desc, DrawType type, InvalidOperation op)
123         : TestCase                      (context, name, desc)
124         , m_drawType            (type)
125         , m_op                          (op)
126         , m_dataBufferID        (0)
127         , m_indexBufferID       (0)
128         , m_cmdBufferID         (0)
129         , m_colorBufferID       (0)
130         , m_vao                         (0)
131 {
132         DE_ASSERT(type < DRAW_LAST);
133         DE_ASSERT(op < INVALID_LAST);
134 }
135
136 InvalidDrawCase::~InvalidDrawCase (void)
137 {
138         deinit();
139 }
140
141 void InvalidDrawCase::init (void)
142 {
143 }
144
145 void InvalidDrawCase::deinit (void)
146 {
147         if (m_dataBufferID)
148         {
149                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_dataBufferID);
150                 m_dataBufferID = 0;
151         }
152         if (m_indexBufferID)
153         {
154                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBufferID);
155                 m_indexBufferID = 0;
156         }
157         if (m_cmdBufferID)
158         {
159                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_cmdBufferID);
160                 m_cmdBufferID = 0;
161         }
162         if (m_colorBufferID)
163         {
164                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_colorBufferID);
165                 m_colorBufferID = 0;
166         }
167         if (m_vao)
168         {
169                 m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
170                 m_vao = 0;
171         }
172 }
173
174 InvalidDrawCase::IterateResult InvalidDrawCase::iterate (void)
175 {
176         const int drawCount                             = 10;           //!< number of elements safe to draw (all buffers have this)
177         const int overBoundDrawCount    = 10000;        //!< number of elements in all other buffers than our target buffer
178         const int drawInstances                 = 1;
179         const int overBoundInstances    = 1000;
180
181         glu::CallLogWrapper gl                          (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
182         glu::ShaderProgram      program                 (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_colorVertexShaderSource) << glu::FragmentSource(s_colorFragmentShaderSource));
183         const deUint32          programID               = program.getProgram();
184         const deInt32           posLocation             = gl.glGetAttribLocation(programID, "a_position");
185         const deInt32           colorLocation   = gl.glGetAttribLocation(programID, "a_color");
186
187         gl.enableLogging(true);
188
189         gl.glGenVertexArrays(1, &m_vao);
190         gl.glBindVertexArray(m_vao);
191         glu::checkError(gl.glGetError(), "gen vao", __FILE__, __LINE__);
192
193         // indices
194         if (m_drawType == DRAW_ELEMENTS)
195         {
196                 const int                               indexBufferSize = (m_op == INVALID_INDEX_COUNT) ? (drawCount) : (overBoundDrawCount);
197                 std::vector<deUint16>   indices                 (indexBufferSize);
198
199                 for (int ndx = 0; ndx < (int)indices.size(); ++ndx)
200                         indices[ndx] = (deUint16)((m_op == INVALID_INDEX) ? (overBoundDrawCount + ndx) : (ndx));
201
202                 gl.glGenBuffers(1, &m_indexBufferID);
203                 gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferID);
204                 gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size() * sizeof(deUint16)), &indices[0], GL_STATIC_DRAW);
205                 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
206         }
207
208         // data
209         {
210                 const int dataSize = (m_op == INVALID_DATA_COUNT) ? (drawCount) : (overBoundDrawCount);
211
212                 // any data is ok
213                 gl.glGenBuffers(1, &m_dataBufferID);
214                 gl.glBindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
215                 gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
216                 gl.glVertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
217                 gl.glEnableVertexAttribArray(posLocation);
218                 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
219         }
220
221         // potentially instanced data
222         {
223                 const int dataSize = drawInstances;
224
225                 gl.glGenBuffers(1, &m_colorBufferID);
226                 gl.glBindBuffer(GL_ARRAY_BUFFER, m_colorBufferID);
227                 gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
228                 gl.glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
229                 gl.glEnableVertexAttribArray(colorLocation);
230                 gl.glVertexAttribDivisor(colorLocation, 1);
231                 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
232         }
233
234         // command
235         if (m_drawType == DRAW_ARRAYS)
236         {
237                 DrawArraysCommand drawCommand;
238                 drawCommand.count                               = overBoundDrawCount;
239                 drawCommand.primCount                   = (m_op == INVALID_DATA_INSTANCED)      ? (overBoundInstances)  : (drawInstances);
240                 drawCommand.first                               = (m_op == INVALID_DATA_FIRST)          ? (overBoundDrawCount)  : (0);
241                 drawCommand.reservedMustBeZero  = (m_op == INVALID_RESERVED)            ? (5)                                   : (0);
242
243                 m_testCtx.getLog()
244                         << tcu::TestLog::Message
245                         << "drawCommand:"
246                         << "\n\tcount:\t" << drawCommand.count
247                         << "\n\tprimCount\t" << drawCommand.primCount
248                         << "\n\tfirst\t" << drawCommand.first
249                         << "\n\treservedMustBeZero\t" << drawCommand.reservedMustBeZero
250                         << tcu::TestLog::EndMessage;
251
252                 gl.glGenBuffers(1, &m_cmdBufferID);
253                 gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
254                 gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
255                 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
256         }
257         else if (m_drawType == DRAW_ELEMENTS)
258         {
259                 DrawElementsCommand drawCommand;
260                 drawCommand.count                               = overBoundDrawCount;
261                 drawCommand.primCount                   = (m_op == INVALID_DATA_INSTANCED)      ? (overBoundInstances)  : (drawInstances);
262                 drawCommand.firstIndex                  = (m_op == INVALID_INDEX_FIRST)         ? (overBoundDrawCount)  : (0);
263                 drawCommand.baseVertex                  = (m_op == INVALID_DATA_FIRST)          ? (overBoundDrawCount)  : (0);
264                 drawCommand.reservedMustBeZero  = (m_op == INVALID_RESERVED)            ? (5)                                   : (0);
265
266                 m_testCtx.getLog()
267                         << tcu::TestLog::Message
268                         << "drawCommand:"
269                         << "\n\tcount:\t" << drawCommand.count
270                         << "\n\tprimCount\t" << drawCommand.primCount
271                         << "\n\tfirstIndex\t" << drawCommand.firstIndex
272                         << "\n\tbaseVertex\t" << drawCommand.baseVertex
273                         << "\n\treservedMustBeZero\t" << drawCommand.reservedMustBeZero
274                         << tcu::TestLog::EndMessage;
275
276                 gl.glGenBuffers(1, &m_cmdBufferID);
277                 gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
278                 gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
279                 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
280         }
281         else
282                 DE_ASSERT(DE_FALSE);
283
284         gl.glViewport(0, 0, 1, 1);
285         gl.glUseProgram(programID);
286
287         if (m_drawType == DRAW_ELEMENTS)
288                 gl.glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, DE_NULL);
289         else if (m_drawType == DRAW_ARRAYS)
290                 gl.glDrawArraysIndirect(GL_TRIANGLES, DE_NULL);
291         else
292                 DE_ASSERT(DE_FALSE);
293
294         gl.glUseProgram(0);
295         gl.glFinish();
296
297         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
298         return STOP;
299 }
300
301 class RandomGroup : public TestCaseGroup
302 {
303 public:
304                         RandomGroup             (Context& context, const char* name, const char* descr);
305                         ~RandomGroup    (void);
306
307         void    init                    (void);
308 };
309
310 template <int SIZE>
311 struct UniformWeightArray
312 {
313         float weights[SIZE];
314
315         UniformWeightArray (void)
316         {
317                 for (int i=0; i<SIZE; ++i)
318                         weights[i] = 1.0f;
319         }
320 };
321
322 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
323         : TestCaseGroup (context, name, descr)
324 {
325 }
326
327 RandomGroup::~RandomGroup (void)
328 {
329 }
330
331 void RandomGroup::init (void)
332 {
333         const int       numAttempts                             = 100;
334
335         const int       attribCounts[]                  = { 1,   2,   5 };
336         const float     attribWeights[]                 = { 30, 10,   1 };
337         const int       primitiveCounts[]               = { 1,   5,  64 };
338         const float     primitiveCountWeights[] = { 20, 10,   1 };
339         const int       indexOffsets[]                  = { 0,   7,  13 };
340         const float     indexOffsetWeights[]    = { 20, 20,   1 };
341         const int       firsts[]                                = { 0,   7,  13 };
342         const float     firstWeights[]                  = { 20, 20,   1 };
343
344         const int       instanceCounts[]                = { 1,   2,  16,  17 };
345         const float     instanceWeights[]               = { 20, 10,   5,   1 };
346         const int       indexMins[]                             = { 0,   1,   3,   8 };
347         const int       indexMaxs[]                             = { 4,   8, 128, 257 };
348         const float     indexWeights[]                  = { 50, 50,  50,  50 };
349         const int       offsets[]                               = { 0,   1,   5,  12 };
350         const float     offsetWeights[]                 = { 50, 10,  10,  10 };
351         const int       strides[]                               = { 0,   7,  16,  17 };
352         const float     strideWeights[]                 = { 50, 10,  10,  10 };
353         const int       instanceDivisors[]              = { 0,   1,   3, 129 };
354         const float     instanceDivisorWeights[]= { 70, 30,  10,  10 };
355
356         const int       indirectOffsets[]               = { 0,   1,   2 };
357         const float indirectOffsetWeigths[]     = { 2,   1,   1 };
358         const int       baseVertices[]                  = { 0,   1,  -2,   4,  3 };
359         const float baseVertexWeigths[]         = { 4,   1,   1,   1,  1 };
360
361         gls::DrawTestSpec::Primitive primitives[] =
362         {
363                 gls::DrawTestSpec::PRIMITIVE_POINTS,
364                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
365                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
366                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
367                 gls::DrawTestSpec::PRIMITIVE_LINES,
368                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
369                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
370         };
371         const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
372
373         gls::DrawTestSpec::DrawMethod drawMethods[] =
374         {
375                 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT,
376                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT,
377         };
378         const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
379
380         gls::DrawTestSpec::IndexType indexTypes[] =
381         {
382                 gls::DrawTestSpec::INDEXTYPE_BYTE,
383                 gls::DrawTestSpec::INDEXTYPE_SHORT,
384                 gls::DrawTestSpec::INDEXTYPE_INT,
385         };
386         const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
387
388         gls::DrawTestSpec::InputType inputTypes[] =
389         {
390                 gls::DrawTestSpec::INPUTTYPE_FLOAT,
391                 gls::DrawTestSpec::INPUTTYPE_FIXED,
392                 gls::DrawTestSpec::INPUTTYPE_BYTE,
393                 gls::DrawTestSpec::INPUTTYPE_SHORT,
394                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
395                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
396                 gls::DrawTestSpec::INPUTTYPE_INT,
397                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
398                 gls::DrawTestSpec::INPUTTYPE_HALF,
399                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
400                 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
401         };
402         const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
403
404         gls::DrawTestSpec::OutputType outputTypes[] =
405         {
406                 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
407                 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
408                 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
409                 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
410                 gls::DrawTestSpec::OUTPUTTYPE_INT,
411                 gls::DrawTestSpec::OUTPUTTYPE_UINT,
412                 gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
413                 gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
414                 gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
415                 gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
416                 gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
417                 gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
418         };
419         const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
420
421         gls::DrawTestSpec::Usage usages[] =
422         {
423                 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
424                 gls::DrawTestSpec::USAGE_STATIC_DRAW,
425                 gls::DrawTestSpec::USAGE_STREAM_DRAW,
426                 gls::DrawTestSpec::USAGE_STREAM_READ,
427                 gls::DrawTestSpec::USAGE_STREAM_COPY,
428                 gls::DrawTestSpec::USAGE_STATIC_READ,
429                 gls::DrawTestSpec::USAGE_STATIC_COPY,
430                 gls::DrawTestSpec::USAGE_DYNAMIC_READ,
431                 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
432         };
433         const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
434
435         std::set<deUint32>      insertedHashes;
436         size_t                          insertedCount = 0;
437
438         for (int ndx = 0; ndx < numAttempts; ++ndx)
439         {
440                 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
441
442                 int                                     attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
443                 int                                     drawCommandSize;
444                 gls::DrawTestSpec       spec;
445
446                 spec.apiType                            = glu::ApiType::es(3,1);
447                 spec.primitive                          = random.chooseWeighted<gls::DrawTestSpec::Primitive>   (DE_ARRAY_BEGIN(primitives),            DE_ARRAY_END(primitives),               primitiveWeights.weights);
448                 spec.primitiveCount                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(primitiveCounts),       DE_ARRAY_END(primitiveCounts),  primitiveCountWeights);
449                 spec.drawMethod                         = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>  (DE_ARRAY_BEGIN(drawMethods),           DE_ARRAY_END(drawMethods),              drawMethodWeights.weights);
450
451                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
452                         drawCommandSize = sizeof(deUint32[4]);
453                 else if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
454                         drawCommandSize = sizeof(deUint32[5]);
455                 else
456                 {
457                         DE_ASSERT(DE_FALSE);
458                         return;
459                 }
460
461                 spec.indexType                          = random.chooseWeighted<gls::DrawTestSpec::IndexType>   (DE_ARRAY_BEGIN(indexTypes),            DE_ARRAY_END(indexTypes),               indexTypeWeights.weights);
462                 spec.indexPointerOffset         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexOffsets),          DE_ARRAY_END(indexOffsets),             indexOffsetWeights);
463                 spec.indexStorage                       = gls::DrawTestSpec::STORAGE_BUFFER;
464                 spec.first                                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(firsts),                        DE_ARRAY_END(firsts),                   firstWeights);
465                 spec.indexMin                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMins),                     DE_ARRAY_END(indexMins),                indexWeights);
466                 spec.indexMax                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMaxs),                     DE_ARRAY_END(indexMaxs),                indexWeights);
467                 spec.instanceCount                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(instanceCounts),        DE_ARRAY_END(instanceCounts),   instanceWeights);
468                 spec.indirectOffset                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indirectOffsets),       DE_ARRAY_END(indirectOffsets),  indirectOffsetWeigths) * drawCommandSize;
469                 spec.baseVertex                         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(baseVertices),          DE_ARRAY_END(baseVertices),             baseVertexWeigths);
470
471                 // check spec is legal
472                 if (!spec.valid())
473                         continue;
474
475                 for (int attrNdx = 0; attrNdx < attributeCount;)
476                 {
477                         bool valid;
478                         gls::DrawTestSpec::AttributeSpec attribSpec;
479
480                         attribSpec.inputType                    = random.chooseWeighted<gls::DrawTestSpec::InputType>   (DE_ARRAY_BEGIN(inputTypes),            DE_ARRAY_END(inputTypes),               inputTypeWeights.weights);
481                         attribSpec.outputType                   = random.chooseWeighted<gls::DrawTestSpec::OutputType>  (DE_ARRAY_BEGIN(outputTypes),           DE_ARRAY_END(outputTypes),              outputTypeWeights.weights);
482                         attribSpec.storage                              = gls::DrawTestSpec::STORAGE_BUFFER;
483                         attribSpec.usage                                = random.chooseWeighted<gls::DrawTestSpec::Usage>               (DE_ARRAY_BEGIN(usages),                        DE_ARRAY_END(usages),                   usageWeights.weights);
484                         attribSpec.componentCount               = random.getInt(1, 4);
485                         attribSpec.offset                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
486                         attribSpec.stride                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
487                         attribSpec.normalize                    = random.getBool();
488                         attribSpec.instanceDivisor              = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
489                         attribSpec.useDefaultAttribute  = random.getBool();
490
491                         // check spec is legal
492                         valid = attribSpec.valid(spec.apiType);
493
494                         // we do not want interleaved elements. (Might result in some weird floating point values)
495                         if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
496                                 valid = false;
497
498                         // try again if not valid
499                         if (valid)
500                         {
501                                 spec.attribs.push_back(attribSpec);
502                                 ++attrNdx;
503                         }
504                 }
505
506                 // Do not collapse all vertex positions to a single positions
507                 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
508                         spec.attribs[0].instanceDivisor = 0;
509
510                 // Is render result meaningful?
511                 {
512                         // Only one vertex
513                         if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
514                                 continue;
515                         if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
516                                 continue;
517
518                         // Triangle only on one axis
519                         if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
520                         {
521                                 if (spec.attribs[0].componentCount == 1)
522                                         continue;
523                                 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)
524                                         continue;
525                                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
526                                         continue;
527                         }
528                 }
529
530                 // Add case
531                 {
532                         deUint32 hash = spec.hash();
533                         for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
534                                 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
535
536                         if (insertedHashes.find(hash) == insertedHashes.end())
537                         {
538                                 // Only unaligned cases
539                                 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
540                                         spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
541                                         this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
542                                 insertedHashes.insert(hash);
543
544                                 ++insertedCount;
545                         }
546                 }
547         }
548 }
549
550 } // anonymous
551
552 DrawTests::DrawTests (Context& context)
553         : TestCaseGroup(context, "draw_indirect", "Indirect drawing tests")
554 {
555 }
556
557 DrawTests::~DrawTests (void)
558 {
559 }
560
561 void DrawTests::init (void)
562 {
563         tcu::TestCaseGroup* const unalignedGroup        = new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
564         tcu::TestCaseGroup* const drawArraysGroup       = new tcu::TestCaseGroup(m_testCtx, "drawarrays", "draw arrays");
565         tcu::TestCaseGroup* const drawElementsGroup     = new tcu::TestCaseGroup(m_testCtx, "drawelements", "draw elements");
566
567         addChild(unalignedGroup);
568         addChild(drawArraysGroup);
569         addChild(drawElementsGroup);
570
571         // .unaligned_data
572         {
573                 unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
574         }
575
576         // .drawarrays
577         {
578                 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_count",                 "Draw arrays vertex elements beyond the array end are accessed",        InvalidDrawCase::DRAW_ARRAYS,   InvalidDrawCase::INVALID_DATA_COUNT));
579                 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_first",                 "Draw arrays vertex elements beyond the array end are accessed",        InvalidDrawCase::DRAW_ARRAYS,   InvalidDrawCase::INVALID_DATA_FIRST));
580                 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",             "Draw arrays vertex elements beyond the array end are accessed",        InvalidDrawCase::DRAW_ARRAYS,   InvalidDrawCase::INVALID_DATA_INSTANCED));
581                 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "reserved_non_zero",                                   "reservedMustBeZero is set to non-zero value",                                          InvalidDrawCase::DRAW_ARRAYS,   InvalidDrawCase::INVALID_RESERVED));
582         }
583
584         // .drawelements
585         {
586                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_count",               "Draw elements vertex elements beyond the array end are accessed",      InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_COUNT));
587                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_basevertex",  "Draw elements vertex elements beyond the array end are accessed",      InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_FIRST));
588                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_indices",             "Draw elements vertex elements beyond the array end are accessed",      InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX));
589                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",   "Draw elements vertex elements beyond the array end are accessed",      InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_INSTANCED));
590                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "index_over_bounds_with_count",              "Draw elements index elements beyond the array end are accessed",       InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX_COUNT));
591                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "index_over_bounds_with_firstindex", "Draw elements index elements beyond the array end are accessed",       InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX_FIRST));
592                 drawElementsGroup->addChild(new InvalidDrawCase(m_context, "reserved_non_zero",                                 "reservedMustBeZero is set to non-zero value",                                          InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_RESERVED));
593         }
594 }
595
596 } // Stress
597 } // gles31
598 } // deqp