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 uint32_t count;
66 uint32_t primCount;
67 uint32_t firstIndex;
68 int32_t baseVertex;
69 uint32_t reservedMustBeZero;
70 };
71 DE_STATIC_ASSERT(5 * sizeof(uint32_t) == sizeof(DrawElementsCommand)); // tight packing
72
73 struct DrawArraysCommand
74 {
75 uint32_t count;
76 uint32_t primCount;
77 uint32_t first;
78 uint32_t reservedMustBeZero;
79 };
80 DE_STATIC_ASSERT(4 * sizeof(uint32_t) == 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
InvalidDrawCase(Context & context,const char * name,const char * desc,DrawType type,InvalidOperation op)122 InvalidDrawCase::InvalidDrawCase(Context &context, const char *name, const char *desc, DrawType type,
123 InvalidOperation op)
124 : TestCase(context, name, desc)
125 , m_drawType(type)
126 , m_op(op)
127 , m_dataBufferID(0)
128 , m_indexBufferID(0)
129 , m_cmdBufferID(0)
130 , m_colorBufferID(0)
131 , m_vao(0)
132 {
133 DE_ASSERT(type < DRAW_LAST);
134 DE_ASSERT(op < INVALID_LAST);
135 }
136
~InvalidDrawCase(void)137 InvalidDrawCase::~InvalidDrawCase(void)
138 {
139 deinit();
140 }
141
init(void)142 void InvalidDrawCase::init(void)
143 {
144 }
145
deinit(void)146 void InvalidDrawCase::deinit(void)
147 {
148 if (m_dataBufferID)
149 {
150 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_dataBufferID);
151 m_dataBufferID = 0;
152 }
153 if (m_indexBufferID)
154 {
155 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBufferID);
156 m_indexBufferID = 0;
157 }
158 if (m_cmdBufferID)
159 {
160 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_cmdBufferID);
161 m_cmdBufferID = 0;
162 }
163 if (m_colorBufferID)
164 {
165 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_colorBufferID);
166 m_colorBufferID = 0;
167 }
168 if (m_vao)
169 {
170 m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
171 m_vao = 0;
172 }
173 }
174
iterate(void)175 InvalidDrawCase::IterateResult InvalidDrawCase::iterate(void)
176 {
177 const int drawCount = 10; //!< number of elements safe to draw (all buffers have this)
178 const int overBoundDrawCount = 10000; //!< number of elements in all other buffers than our target buffer
179 const int drawInstances = 1;
180 const int overBoundInstances = 1000;
181
182 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
183 glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources()
184 << glu::VertexSource(s_colorVertexShaderSource)
185 << glu::FragmentSource(s_colorFragmentShaderSource));
186 const uint32_t programID = program.getProgram();
187 const int32_t posLocation = gl.glGetAttribLocation(programID, "a_position");
188 const int32_t colorLocation = gl.glGetAttribLocation(programID, "a_color");
189
190 gl.enableLogging(true);
191
192 gl.glGenVertexArrays(1, &m_vao);
193 gl.glBindVertexArray(m_vao);
194 glu::checkError(gl.glGetError(), "gen vao", __FILE__, __LINE__);
195
196 // indices
197 if (m_drawType == DRAW_ELEMENTS)
198 {
199 const int indexBufferSize = (m_op == INVALID_INDEX_COUNT) ? (drawCount) : (overBoundDrawCount);
200 std::vector<uint16_t> indices(indexBufferSize);
201
202 for (int ndx = 0; ndx < (int)indices.size(); ++ndx)
203 indices[ndx] = (uint16_t)((m_op == INVALID_INDEX) ? (overBoundDrawCount + ndx) : (ndx));
204
205 gl.glGenBuffers(1, &m_indexBufferID);
206 gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferID);
207 gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size() * sizeof(uint16_t)), &indices[0], GL_STATIC_DRAW);
208 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
209 }
210
211 // data
212 {
213 const int dataSize = (m_op == INVALID_DATA_COUNT) ? (drawCount) : (overBoundDrawCount);
214
215 // any data is ok
216 gl.glGenBuffers(1, &m_dataBufferID);
217 gl.glBindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
218 gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
219 gl.glVertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
220 gl.glEnableVertexAttribArray(posLocation);
221 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
222 }
223
224 // potentially instanced data
225 {
226 const int dataSize = drawInstances;
227
228 gl.glGenBuffers(1, &m_colorBufferID);
229 gl.glBindBuffer(GL_ARRAY_BUFFER, m_colorBufferID);
230 gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
231 gl.glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
232 gl.glEnableVertexAttribArray(colorLocation);
233 gl.glVertexAttribDivisor(colorLocation, 1);
234 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
235 }
236
237 // command
238 if (m_drawType == DRAW_ARRAYS)
239 {
240 DrawArraysCommand drawCommand;
241 drawCommand.count = overBoundDrawCount;
242 drawCommand.primCount = (m_op == INVALID_DATA_INSTANCED) ? (overBoundInstances) : (drawInstances);
243 drawCommand.first = (m_op == INVALID_DATA_FIRST) ? (overBoundDrawCount) : (0);
244 drawCommand.reservedMustBeZero = (m_op == INVALID_RESERVED) ? (5) : (0);
245
246 m_testCtx.getLog() << tcu::TestLog::Message << "drawCommand:"
247 << "\n\tcount:\t" << drawCommand.count << "\n\tprimCount\t" << drawCommand.primCount
248 << "\n\tfirst\t" << drawCommand.first << "\n\treservedMustBeZero\t"
249 << drawCommand.reservedMustBeZero << tcu::TestLog::EndMessage;
250
251 gl.glGenBuffers(1, &m_cmdBufferID);
252 gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
253 gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
254 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
255 }
256 else if (m_drawType == DRAW_ELEMENTS)
257 {
258 DrawElementsCommand drawCommand;
259 drawCommand.count = overBoundDrawCount;
260 drawCommand.primCount = (m_op == INVALID_DATA_INSTANCED) ? (overBoundInstances) : (drawInstances);
261 drawCommand.firstIndex = (m_op == INVALID_INDEX_FIRST) ? (overBoundDrawCount) : (0);
262 drawCommand.baseVertex = (m_op == INVALID_DATA_FIRST) ? (overBoundDrawCount) : (0);
263 drawCommand.reservedMustBeZero = (m_op == INVALID_RESERVED) ? (5) : (0);
264
265 m_testCtx.getLog() << tcu::TestLog::Message << "drawCommand:"
266 << "\n\tcount:\t" << drawCommand.count << "\n\tprimCount\t" << drawCommand.primCount
267 << "\n\tfirstIndex\t" << drawCommand.firstIndex << "\n\tbaseVertex\t"
268 << drawCommand.baseVertex << "\n\treservedMustBeZero\t" << drawCommand.reservedMustBeZero
269 << tcu::TestLog::EndMessage;
270
271 gl.glGenBuffers(1, &m_cmdBufferID);
272 gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
273 gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
274 glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
275 }
276 else
277 DE_ASSERT(false);
278
279 gl.glViewport(0, 0, 1, 1);
280 gl.glUseProgram(programID);
281
282 if (m_drawType == DRAW_ELEMENTS)
283 gl.glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, DE_NULL);
284 else if (m_drawType == DRAW_ARRAYS)
285 gl.glDrawArraysIndirect(GL_TRIANGLES, DE_NULL);
286 else
287 DE_ASSERT(false);
288
289 gl.glUseProgram(0);
290 gl.glFinish();
291
292 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
293 return STOP;
294 }
295
296 class RandomGroup : public TestCaseGroup
297 {
298 public:
299 RandomGroup(Context &context, const char *name, const char *descr);
300 ~RandomGroup(void);
301
302 void init(void);
303 };
304
305 template <int SIZE>
306 struct UniformWeightArray
307 {
308 float weights[SIZE];
309
UniformWeightArraydeqp::gles31::Stress::__anon9c7365ba0111::UniformWeightArray310 UniformWeightArray(void)
311 {
312 for (int i = 0; i < SIZE; ++i)
313 weights[i] = 1.0f;
314 }
315 };
316
RandomGroup(Context & context,const char * name,const char * descr)317 RandomGroup::RandomGroup(Context &context, const char *name, const char *descr) : TestCaseGroup(context, name, descr)
318 {
319 }
320
~RandomGroup(void)321 RandomGroup::~RandomGroup(void)
322 {
323 }
324
init(void)325 void RandomGroup::init(void)
326 {
327 const int numAttempts = 100;
328
329 const int attribCounts[] = {1, 2, 5};
330 const float attribWeights[] = {30, 10, 1};
331 const int primitiveCounts[] = {1, 5, 64};
332 const float primitiveCountWeights[] = {20, 10, 1};
333 const int indexOffsets[] = {0, 7, 13};
334 const float indexOffsetWeights[] = {20, 20, 1};
335 const int firsts[] = {0, 7, 13};
336 const float firstWeights[] = {20, 20, 1};
337
338 const int instanceCounts[] = {1, 2, 16, 17};
339 const float instanceWeights[] = {20, 10, 5, 1};
340 const int indexMins[] = {0, 1, 3, 8};
341 const int indexMaxs[] = {4, 8, 128, 257};
342 const float indexWeights[] = {50, 50, 50, 50};
343 const int offsets[] = {0, 1, 5, 12};
344 const float offsetWeights[] = {50, 10, 10, 10};
345 const int strides[] = {0, 7, 16, 17};
346 const float strideWeights[] = {50, 10, 10, 10};
347 const int instanceDivisors[] = {0, 1, 3, 129};
348 const float instanceDivisorWeights[] = {70, 30, 10, 10};
349
350 const int indirectOffsets[] = {0, 1, 2};
351 const float indirectOffsetWeigths[] = {2, 1, 1};
352 const int baseVertices[] = {0, 1, -2, 4, 3};
353 const float baseVertexWeigths[] = {4, 1, 1, 1, 1};
354
355 gls::DrawTestSpec::Primitive primitives[] = {
356 gls::DrawTestSpec::PRIMITIVE_POINTS, gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
357 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
358 gls::DrawTestSpec::PRIMITIVE_LINES, gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
359 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
360 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
361
362 gls::DrawTestSpec::DrawMethod drawMethods[] = {
363 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT,
364 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT,
365 };
366 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
367
368 gls::DrawTestSpec::IndexType indexTypes[] = {
369 gls::DrawTestSpec::INDEXTYPE_BYTE,
370 gls::DrawTestSpec::INDEXTYPE_SHORT,
371 gls::DrawTestSpec::INDEXTYPE_INT,
372 };
373 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
374
375 gls::DrawTestSpec::InputType inputTypes[] = {
376 gls::DrawTestSpec::INPUTTYPE_FLOAT,
377 gls::DrawTestSpec::INPUTTYPE_FIXED,
378 gls::DrawTestSpec::INPUTTYPE_BYTE,
379 gls::DrawTestSpec::INPUTTYPE_SHORT,
380 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
381 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
382 gls::DrawTestSpec::INPUTTYPE_INT,
383 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
384 gls::DrawTestSpec::INPUTTYPE_HALF,
385 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
386 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
387 };
388 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
389
390 gls::DrawTestSpec::OutputType outputTypes[] = {
391 gls::DrawTestSpec::OUTPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, gls::DrawTestSpec::OUTPUTTYPE_VEC3,
392 gls::DrawTestSpec::OUTPUTTYPE_VEC4, gls::DrawTestSpec::OUTPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_UINT,
393 gls::DrawTestSpec::OUTPUTTYPE_IVEC2, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
394 gls::DrawTestSpec::OUTPUTTYPE_UVEC2, gls::DrawTestSpec::OUTPUTTYPE_UVEC3, gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
395 };
396 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
397
398 gls::DrawTestSpec::Usage usages[] = {
399 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW, gls::DrawTestSpec::USAGE_STATIC_DRAW,
400 gls::DrawTestSpec::USAGE_STREAM_DRAW, gls::DrawTestSpec::USAGE_STREAM_READ,
401 gls::DrawTestSpec::USAGE_STREAM_COPY, gls::DrawTestSpec::USAGE_STATIC_READ,
402 gls::DrawTestSpec::USAGE_STATIC_COPY, gls::DrawTestSpec::USAGE_DYNAMIC_READ,
403 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
404 };
405 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
406
407 std::set<uint32_t> insertedHashes;
408 size_t insertedCount = 0;
409
410 for (int ndx = 0; ndx < numAttempts; ++ndx)
411 {
412 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
413
414 int attributeCount = random.chooseWeighted<int, const int *, const float *>(
415 DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
416 int drawCommandSize;
417 gls::DrawTestSpec spec;
418
419 spec.apiType = glu::ApiType::es(3, 1);
420 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive>(
421 DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights);
422 spec.primitiveCount = random.chooseWeighted<int, const int *, const float *>(
423 DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights);
424 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>(
425 DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights);
426
427 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
428 drawCommandSize = sizeof(uint32_t[4]);
429 else if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
430 drawCommandSize = sizeof(uint32_t[5]);
431 else
432 {
433 DE_ASSERT(false);
434 return;
435 }
436
437 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType>(
438 DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights);
439 spec.indexPointerOffset = random.chooseWeighted<int, const int *, const float *>(
440 DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights);
441 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
442 spec.first = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(firsts),
443 DE_ARRAY_END(firsts), firstWeights);
444 spec.indexMin = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(indexMins),
445 DE_ARRAY_END(indexMins), indexWeights);
446 spec.indexMax = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(indexMaxs),
447 DE_ARRAY_END(indexMaxs), indexWeights);
448 spec.instanceCount = random.chooseWeighted<int, const int *, const float *>(
449 DE_ARRAY_BEGIN(instanceCounts), DE_ARRAY_END(instanceCounts), instanceWeights);
450 spec.indirectOffset = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(indirectOffsets),
451 DE_ARRAY_END(indirectOffsets),
452 indirectOffsetWeigths) *
453 drawCommandSize;
454 spec.baseVertex = random.chooseWeighted<int, const int *, const float *>(
455 DE_ARRAY_BEGIN(baseVertices), DE_ARRAY_END(baseVertices), baseVertexWeigths);
456
457 // check spec is legal
458 if (!spec.valid())
459 continue;
460
461 for (int attrNdx = 0; attrNdx < attributeCount;)
462 {
463 bool valid;
464 gls::DrawTestSpec::AttributeSpec attribSpec;
465
466 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType>(
467 DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights);
468 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType>(
469 DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights);
470 attribSpec.storage = gls::DrawTestSpec::STORAGE_BUFFER;
471 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage>(
472 DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights);
473 attribSpec.componentCount = random.getInt(1, 4);
474 attribSpec.offset = random.chooseWeighted<int, const int *, const float *>(
475 DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
476 attribSpec.stride = random.chooseWeighted<int, const int *, const float *>(
477 DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
478 attribSpec.normalize = random.getBool();
479 attribSpec.instanceDivisor = random.chooseWeighted<int, const int *, const float *>(
480 DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
481 attribSpec.useDefaultAttribute = random.getBool();
482
483 // check spec is legal
484 valid = attribSpec.valid(spec.apiType);
485
486 // we do not want interleaved elements. (Might result in some weird floating point values)
487 if (attribSpec.stride &&
488 attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
489 valid = false;
490
491 // try again if not valid
492 if (valid)
493 {
494 spec.attribs.push_back(attribSpec);
495 ++attrNdx;
496 }
497 }
498
499 // Do not collapse all vertex positions to a single positions
500 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
501 spec.attribs[0].instanceDivisor = 0;
502
503 // Is render result meaningful?
504 {
505 // Only one vertex
506 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
507 spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
508 continue;
509 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
510 continue;
511
512 // Triangle only on one axis
513 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES ||
514 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN ||
515 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
516 {
517 if (spec.attribs[0].componentCount == 1)
518 continue;
519 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT ||
520 spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT ||
521 spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
522 continue;
523 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
524 (spec.indexMax - spec.indexMin) < 2)
525 continue;
526 }
527 }
528
529 // Add case
530 {
531 uint32_t hash = spec.hash();
532 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
533 hash = (hash << 2) ^ (uint32_t)spec.attribs[attrNdx].hash();
534
535 if (insertedHashes.find(hash) == insertedHashes.end())
536 {
537 // Only unaligned cases
538 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
539 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
540 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec,
541 de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
542 insertedHashes.insert(hash);
543
544 ++insertedCount;
545 }
546 }
547 }
548 }
549
550 } // namespace
551
DrawTests(Context & context)552 DrawTests::DrawTests(Context &context) : TestCaseGroup(context, "draw_indirect", "Indirect drawing tests")
553 {
554 }
555
~DrawTests(void)556 DrawTests::~DrawTests(void)
557 {
558 }
559
init(void)560 void DrawTests::init(void)
561 {
562 tcu::TestCaseGroup *const unalignedGroup =
563 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(
579 m_context, "data_over_bounds_with_count", "Draw arrays vertex elements beyond the array end are accessed",
580 InvalidDrawCase::DRAW_ARRAYS, InvalidDrawCase::INVALID_DATA_COUNT));
581 drawArraysGroup->addChild(new InvalidDrawCase(
582 m_context, "data_over_bounds_with_first", "Draw arrays vertex elements beyond the array end are accessed",
583 InvalidDrawCase::DRAW_ARRAYS, InvalidDrawCase::INVALID_DATA_FIRST));
584 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",
585 "Draw arrays vertex elements beyond the array end are accessed",
586 InvalidDrawCase::DRAW_ARRAYS,
587 InvalidDrawCase::INVALID_DATA_INSTANCED));
588 drawArraysGroup->addChild(new InvalidDrawCase(m_context, "reserved_non_zero",
589 "reservedMustBeZero is set to non-zero value",
590 InvalidDrawCase::DRAW_ARRAYS, InvalidDrawCase::INVALID_RESERVED));
591 }
592
593 // .drawelements
594 {
595 drawElementsGroup->addChild(new InvalidDrawCase(
596 m_context, "data_over_bounds_with_count", "Draw elements vertex elements beyond the array end are accessed",
597 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_COUNT));
598 drawElementsGroup->addChild(
599 new InvalidDrawCase(m_context, "data_over_bounds_with_basevertex",
600 "Draw elements vertex elements beyond the array end are accessed",
601 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_FIRST));
602 drawElementsGroup->addChild(
603 new InvalidDrawCase(m_context, "data_over_bounds_with_indices",
604 "Draw elements vertex elements beyond the array end are accessed",
605 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX));
606 drawElementsGroup->addChild(
607 new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",
608 "Draw elements vertex elements beyond the array end are accessed",
609 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_INSTANCED));
610 drawElementsGroup->addChild(new InvalidDrawCase(
611 m_context, "index_over_bounds_with_count", "Draw elements index elements beyond the array end are accessed",
612 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX_COUNT));
613 drawElementsGroup->addChild(
614 new InvalidDrawCase(m_context, "index_over_bounds_with_firstindex",
615 "Draw elements index elements beyond the array end are accessed",
616 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_INDEX_FIRST));
617 drawElementsGroup->addChild(
618 new InvalidDrawCase(m_context, "reserved_non_zero", "reservedMustBeZero is set to non-zero value",
619 InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_RESERVED));
620 }
621 }
622
623 } // namespace Stress
624 } // namespace gles31
625 } // namespace deqp
626