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
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, 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
~InvalidDrawCase(void)136 InvalidDrawCase::~InvalidDrawCase (void)
137 {
138 deinit();
139 }
140
init(void)141 void InvalidDrawCase::init (void)
142 {
143 }
144
deinit(void)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
iterate(void)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
UniformWeightArraydeqp::gles31::Stress::__anonb348c3430111::UniformWeightArray315 UniformWeightArray (void)
316 {
317 for (int i=0; i<SIZE; ++i)
318 weights[i] = 1.0f;
319 }
320 };
321
RandomGroup(Context & context,const char * name,const char * descr)322 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
323 : TestCaseGroup (context, name, descr)
324 {
325 }
326
~RandomGroup(void)327 RandomGroup::~RandomGroup (void)
328 {
329 }
330
init(void)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
DrawTests(Context & context)552 DrawTests::DrawTests (Context& context)
553 : TestCaseGroup(context, "draw_indirect", "Indirect drawing tests")
554 {
555 }
556
~DrawTests(void)557 DrawTests::~DrawTests (void)
558 {
559 }
560
init(void)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
599