1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Draw stress tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3sDrawTests.hpp"
25 #include "tcuVector.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuSurface.hpp"
29 #include "gluCallLogWrapper.hpp"
30 #include "gluObjectWrapper.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluRenderContext.hpp"
33 #include "gluShaderProgram.hpp"
34 #include "gluStrUtil.hpp"
35 #include "glsDrawTest.hpp"
36 #include "glwFunctions.hpp"
37 #include "glwEnums.hpp"
38 #include "deRandom.hpp"
39 #include "deStringUtil.hpp"
40 #include "deUniquePtr.hpp"
41
42 #include <set>
43
44 namespace deqp
45 {
46 namespace gles3
47 {
48 namespace Stress
49 {
50 namespace
51 {
52
53 static const char* const s_vertexSource = "#version 300 es\n"
54 "in highp vec4 a_position;\n"
55 "void main (void)\n"
56 "{\n"
57 " gl_Position = a_position;\n"
58 "}\n";
59 static const char* const s_fragmentSource = "#version 300 es\n"
60 "layout(location = 0) out mediump vec4 fragColor;\n"
61 "void main (void)\n"
62 "{\n"
63 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
64 "}\n";
65
66 class DrawInvalidRangeCase : public TestCase
67 {
68 public:
69 DrawInvalidRangeCase (Context& ctx, const char* name, const char* desc, deUint32 min, deUint32 max, bool useLimitMin = false, bool useLimitMax = false);
70 ~DrawInvalidRangeCase (void);
71
72 void init (void);
73 void deinit (void);
74 IterateResult iterate (void);
75
76 private:
77 const int m_min;
78 const int m_max;
79 const int m_bufferedElements;
80 const int m_numIndices;
81 const bool m_useLimitMin;
82 const bool m_useLimitMax;
83
84 deUint32 m_buffer;
85 deUint32 m_indexBuffer;
86 glu::ShaderProgram* m_program;
87 };
88
DrawInvalidRangeCase(Context & ctx,const char * name,const char * desc,deUint32 min,deUint32 max,bool useLimitMin,bool useLimitMax)89 DrawInvalidRangeCase::DrawInvalidRangeCase (Context& ctx, const char* name, const char* desc, deUint32 min, deUint32 max, bool useLimitMin, bool useLimitMax)
90 : TestCase (ctx, name, desc)
91 , m_min (min)
92 , m_max (max)
93 , m_bufferedElements (128)
94 , m_numIndices (64)
95 , m_useLimitMin (useLimitMin)
96 , m_useLimitMax (useLimitMax)
97 , m_buffer (0)
98 , m_indexBuffer (0)
99 , m_program (DE_NULL)
100 {
101 }
102
~DrawInvalidRangeCase(void)103 DrawInvalidRangeCase::~DrawInvalidRangeCase (void)
104 {
105 deinit();
106 }
107
init(void)108 void DrawInvalidRangeCase::init (void)
109 {
110 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
111 std::vector<tcu::Vec4> data (m_bufferedElements); // !< some junk data to make sure buffer is really allocated
112 std::vector<deUint32> indices (m_numIndices);
113
114 for (int ndx = 0; ndx < m_numIndices; ++ndx)
115 indices[ndx] = ndx;
116
117 gl.genBuffers(1, &m_buffer);
118 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
119 gl.bufferData(GL_ARRAY_BUFFER, int(m_bufferedElements * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
120 GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
121
122 gl.genBuffers(1, &m_indexBuffer);
123 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
124 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, int(m_numIndices * sizeof(deUint32)), &indices[0], GL_STATIC_DRAW);
125 GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
126
127 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_vertexSource) << glu::FragmentSource(s_fragmentSource));
128 if (!m_program->isOk())
129 {
130 m_testCtx.getLog() << *m_program;
131 throw tcu::TestError("could not build program");
132 }
133 }
134
deinit(void)135 void DrawInvalidRangeCase::deinit (void)
136 {
137 if (m_buffer)
138 {
139 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffer);
140 m_buffer = 0;
141 }
142
143 if (m_indexBuffer)
144 {
145 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBuffer);
146 m_indexBuffer = 0;
147 }
148
149 delete m_program;
150 m_program = DE_NULL;
151 }
152
iterate(void)153 DrawInvalidRangeCase::IterateResult DrawInvalidRangeCase::iterate (void)
154 {
155 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
156 const deInt32 positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
157 tcu::Surface dst (m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
158 glu::VertexArray vao (m_context.getRenderContext());
159
160 deInt64 indexLimit = 0;
161 deUint32 min = m_min;
162 deUint32 max = m_max;
163
164 gl.enableLogging(true);
165
166 if (m_useLimitMin || m_useLimitMax)
167 {
168 gl.glGetInteger64v(GL_MAX_ELEMENT_INDEX, &indexLimit);
169 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query limit");
170 }
171
172 if (m_useLimitMin)
173 {
174 if ((deUint64)indexLimit > 0xFFFFFFFFULL)
175 min = 0xFFFFFFF0;
176 else
177 min = (deUint32)(indexLimit - 16);
178 }
179
180 if (m_useLimitMax)
181 {
182 if ((deUint64)indexLimit > 0xFFFFFFFFULL)
183 max = 0xFFFFFFFF;
184 else
185 max = (deUint32)indexLimit;
186 }
187
188 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
189 gl.glClear(GL_COLOR_BUFFER_BIT);
190 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
191
192 gl.glUseProgram(m_program->getProgram());
193 GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
194
195 gl.glBindVertexArray(*vao);
196 gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
197
198 gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
199 gl.glEnableVertexAttribArray(positionLoc);
200 gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
201 GLU_EXPECT_NO_ERROR(gl.glGetError(), "set buffer");
202
203 gl.glDrawRangeElements(GL_POINTS, min, max, m_numIndices, GL_UNSIGNED_INT, DE_NULL);
204
205 // Indexing outside range is an error, but it doesnt need to be checked. Causes implementation-dependent behavior.
206 // Even if the indices are in range (m_min = 0), the specification allows partial processing of vertices in the range,
207 // which might cause access over buffer bounds. Causes implementation-dependent behavior.
208
209 // allow errors
210 {
211 const deUint32 error = gl.glGetError();
212
213 if (error != GL_NO_ERROR)
214 m_testCtx.getLog() << tcu::TestLog::Message << "Got error: " << glu::getErrorStr(error) << ", ignoring..." << tcu::TestLog::EndMessage;
215 }
216
217 // read pixels to wait for rendering
218 gl.glFinish();
219 glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
220
221 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
222 return STOP;
223 }
224
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)225 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
226 {
227 spec.apiType = glu::ApiType::es(3,0);
228 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
229 spec.primitiveCount = 5;
230 spec.drawMethod = method;
231 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST;
232 spec.indexPointerOffset = 0;
233 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST;
234 spec.first = 0;
235 spec.indexMin = 0;
236 spec.indexMax = 0;
237 spec.instanceCount = 1;
238
239 spec.attribs.resize(2);
240
241 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
242 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
243 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER;
244 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
245 spec.attribs[0].componentCount = 4;
246 spec.attribs[0].offset = 0;
247 spec.attribs[0].stride = 0;
248 spec.attribs[0].normalize = false;
249 spec.attribs[0].instanceDivisor = 0;
250 spec.attribs[0].useDefaultAttribute = false;
251
252 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT;
253 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
254 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER;
255 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW;
256 spec.attribs[1].componentCount = 2;
257 spec.attribs[1].offset = 0;
258 spec.attribs[1].stride = 0;
259 spec.attribs[1].normalize = false;
260 spec.attribs[1].instanceDivisor = 0;
261 spec.attribs[1].useDefaultAttribute = false;
262 }
263
264 class IndexGroup : public TestCaseGroup
265 {
266 public:
267 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
268 ~IndexGroup (void);
269
270 void init (void);
271
272 private:
273 gls::DrawTestSpec::DrawMethod m_method;
274 };
275
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)276 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
277 : TestCaseGroup (context, name, descr)
278 , m_method (drawMethod)
279 {
280 }
281
~IndexGroup(void)282 IndexGroup::~IndexGroup (void)
283 {
284 }
285
init(void)286 void IndexGroup::init (void)
287 {
288 struct IndexTest
289 {
290 gls::DrawTestSpec::Storage storage;
291 gls::DrawTestSpec::IndexType type;
292 bool aligned;
293 int offsets[3];
294 };
295
296 const IndexTest tests[] =
297 {
298 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } },
299 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_INT, false, { 2, 3, -1 } },
300 };
301
302 gls::DrawTestSpec spec;
303
304 tcu::TestCaseGroup* const unalignedBufferGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer");
305 const bool isRangedMethod = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED || m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX);
306
307 genBasicSpec(spec, m_method);
308
309 this->addChild(unalignedBufferGroup);
310
311 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
312 {
313 const IndexTest& indexTest = tests[testNdx];
314
315 DE_ASSERT(indexTest.storage != gls::DrawTestSpec::STORAGE_USER);
316 DE_ASSERT(!indexTest.aligned);
317 tcu::TestCaseGroup* group = unalignedBufferGroup;
318
319 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
320 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
321 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
322
323 spec.indexType = indexTest.type;
324 spec.indexStorage = indexTest.storage;
325
326 if (isRangedMethod)
327 {
328 spec.indexMin = 0;
329 spec.indexMax = 55;
330 }
331
332 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
333 {
334 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
335 spec.indexPointerOffset = indexTest.offsets[iterationNdx];
336 test->addIteration(spec, iterationDesc.c_str());
337 }
338
339 DE_ASSERT(spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
340 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
341 group->addChild(test.release());
342 }
343 }
344
345 class MethodGroup : public TestCaseGroup
346 {
347 public:
348 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
349 ~MethodGroup (void);
350
351 void init (void);
352
353 private:
354 gls::DrawTestSpec::DrawMethod m_method;
355 };
356
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)357 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
358 : TestCaseGroup (context, name, descr)
359 , m_method (drawMethod)
360 {
361 }
362
~MethodGroup(void)363 MethodGroup::~MethodGroup (void)
364 {
365 }
366
init(void)367 void MethodGroup::init (void)
368 {
369 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
370
371 DE_ASSERT(indexed);
372 DE_UNREF(indexed);
373
374 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
375 }
376
377 class RandomGroup : public TestCaseGroup
378 {
379 public:
380 RandomGroup (Context& context, const char* name, const char* descr);
381 ~RandomGroup (void);
382
383 void init (void);
384 };
385
386 template <int SIZE>
387 struct UniformWeightArray
388 {
389 float weights[SIZE];
390
UniformWeightArraydeqp::gles3::Stress::__anon0c4fdb020111::UniformWeightArray391 UniformWeightArray (void)
392 {
393 for (int i=0; i<SIZE; ++i)
394 weights[i] = 1.0f;
395 }
396 };
397
RandomGroup(Context & context,const char * name,const char * descr)398 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
399 : TestCaseGroup (context, name, descr)
400 {
401 }
402
~RandomGroup(void)403 RandomGroup::~RandomGroup (void)
404 {
405 }
406
init(void)407 void RandomGroup::init (void)
408 {
409 const int numAttempts = 300;
410
411 const int attribCounts[] = { 1, 2, 5 };
412 const float attribWeights[] = { 30, 10, 1 };
413 const int primitiveCounts[] = { 1, 5, 64 };
414 const float primitiveCountWeights[] = { 20, 10, 1 };
415 const int indexOffsets[] = { 0, 7, 13 };
416 const float indexOffsetWeights[] = { 20, 20, 1 };
417 const int firsts[] = { 0, 7, 13 };
418 const float firstWeights[] = { 20, 20, 1 };
419 const int instanceCounts[] = { 1, 2, 16, 17 };
420 const float instanceWeights[] = { 20, 10, 5, 1 };
421 const int indexMins[] = { 0, 1, 3, 8 };
422 const int indexMaxs[] = { 4, 8, 128, 257 };
423 const float indexWeights[] = { 50, 50, 50, 50 };
424 const int offsets[] = { 0, 1, 5, 12 };
425 const float offsetWeights[] = { 50, 10, 10, 10 };
426 const int strides[] = { 0, 7, 16, 17 };
427 const float strideWeights[] = { 50, 10, 10, 10 };
428 const int instanceDivisors[] = { 0, 1, 3, 129 };
429 const float instanceDivisorWeights[]= { 70, 30, 10, 10 };
430
431 gls::DrawTestSpec::Primitive primitives[] =
432 {
433 gls::DrawTestSpec::PRIMITIVE_POINTS,
434 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
435 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
436 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
437 gls::DrawTestSpec::PRIMITIVE_LINES,
438 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
439 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
440 };
441 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
442
443 gls::DrawTestSpec::DrawMethod drawMethods[] =
444 {
445 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
446 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
447 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
448 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
449 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED
450 };
451 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
452
453 gls::DrawTestSpec::IndexType indexTypes[] =
454 {
455 gls::DrawTestSpec::INDEXTYPE_BYTE,
456 gls::DrawTestSpec::INDEXTYPE_SHORT,
457 gls::DrawTestSpec::INDEXTYPE_INT,
458 };
459 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
460
461 gls::DrawTestSpec::Storage storages[] =
462 {
463 gls::DrawTestSpec::STORAGE_USER,
464 gls::DrawTestSpec::STORAGE_BUFFER,
465 };
466 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
467
468 gls::DrawTestSpec::InputType inputTypes[] =
469 {
470 gls::DrawTestSpec::INPUTTYPE_FLOAT,
471 gls::DrawTestSpec::INPUTTYPE_FIXED,
472 gls::DrawTestSpec::INPUTTYPE_BYTE,
473 gls::DrawTestSpec::INPUTTYPE_SHORT,
474 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
475 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
476 gls::DrawTestSpec::INPUTTYPE_INT,
477 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
478 gls::DrawTestSpec::INPUTTYPE_HALF,
479 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
480 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
481 };
482 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
483
484 gls::DrawTestSpec::OutputType outputTypes[] =
485 {
486 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
487 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
488 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
489 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
490 gls::DrawTestSpec::OUTPUTTYPE_INT,
491 gls::DrawTestSpec::OUTPUTTYPE_UINT,
492 gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
493 gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
494 gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
495 gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
496 gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
497 gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
498 };
499 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
500
501 gls::DrawTestSpec::Usage usages[] =
502 {
503 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
504 gls::DrawTestSpec::USAGE_STATIC_DRAW,
505 gls::DrawTestSpec::USAGE_STREAM_DRAW,
506 gls::DrawTestSpec::USAGE_STREAM_READ,
507 gls::DrawTestSpec::USAGE_STREAM_COPY,
508 gls::DrawTestSpec::USAGE_STATIC_READ,
509 gls::DrawTestSpec::USAGE_STATIC_COPY,
510 gls::DrawTestSpec::USAGE_DYNAMIC_READ,
511 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
512 };
513 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
514
515 std::set<deUint32> insertedHashes;
516 size_t insertedCount = 0;
517
518 for (int ndx = 0; ndx < numAttempts; ++ndx)
519 {
520 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
521
522 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
523 gls::DrawTestSpec spec;
524
525 spec.apiType = glu::ApiType::es(3,0);
526 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights);
527 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights);
528 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights);
529 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights);
530 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights);
531 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
532 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights);
533 spec.indexMin = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMins), DE_ARRAY_END(indexMins), indexWeights);
534 spec.indexMax = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMaxs), DE_ARRAY_END(indexMaxs), indexWeights);
535 spec.instanceCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(instanceCounts), DE_ARRAY_END(instanceCounts), instanceWeights);
536
537 // check spec is legal
538 if (!spec.valid())
539 continue;
540
541 for (int attrNdx = 0; attrNdx < attributeCount;)
542 {
543 bool valid;
544 gls::DrawTestSpec::AttributeSpec attribSpec;
545
546 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights);
547 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights);
548 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
549 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights);
550 attribSpec.componentCount = random.getInt(1, 4);
551 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
552 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
553 attribSpec.normalize = random.getBool();
554 attribSpec.instanceDivisor = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
555 attribSpec.useDefaultAttribute = random.getBool();
556
557 // check spec is legal
558 valid = attribSpec.valid(spec.apiType);
559
560 // we do not want interleaved elements. (Might result in some weird floating point values)
561 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
562 valid = false;
563
564 // try again if not valid
565 if (valid)
566 {
567 spec.attribs.push_back(attribSpec);
568 ++attrNdx;
569 }
570 }
571
572 // Do not collapse all vertex positions to a single positions
573 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
574 spec.attribs[0].instanceDivisor = 0;
575
576 // Is render result meaningful?
577 {
578 // Only one vertex
579 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
580 continue;
581 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
582 continue;
583
584 // Triangle only on one axis
585 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
586 {
587 if (spec.attribs[0].componentCount == 1)
588 continue;
589 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)
590 continue;
591 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
592 continue;
593 }
594 }
595
596 // Add case
597 {
598 deUint32 hash = spec.hash();
599 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
600 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
601
602 if (insertedHashes.find(hash) == insertedHashes.end())
603 {
604 // Only unaligned cases
605 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
606 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
607 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
608 insertedHashes.insert(hash);
609
610 ++insertedCount;
611 }
612 }
613 }
614 }
615
616 } // anonymous
617
DrawTests(Context & context)618 DrawTests::DrawTests (Context& context)
619 : TestCaseGroup(context, "draw", "Draw stress tests")
620 {
621 }
622
~DrawTests(void)623 DrawTests::~DrawTests (void)
624 {
625 }
626
init(void)627 void DrawTests::init (void)
628 {
629 tcu::TestCaseGroup* const unalignedGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
630 tcu::TestCaseGroup* const drawRangeGroup = new tcu::TestCaseGroup(m_testCtx, "draw_range_elements", "Test drawRangeElements");
631
632 addChild(unalignedGroup);
633 addChild(drawRangeGroup);
634
635 // .unaligned_data
636 {
637 const gls::DrawTestSpec::DrawMethod basicMethods[] =
638 {
639 // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
640 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
641 // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
642 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED,
643 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
644 };
645
646 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
647 {
648 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
649 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
650
651 unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
652 }
653
654 // Random
655
656 unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
657 }
658
659 // .draw_range_elements
660 {
661 // use a larger range than the buffer size is
662 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds", "Range over buffer bounds", 0x00000000, 0x00210000));
663 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_signed_wrap", "Range over buffer bounds", 0x00000000, 0x7FFFFFFF));
664 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_unsigned_wrap", "Range over buffer bounds", 0x00000000, 0xFFFFFFFF));
665 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_max", "Range over buffer bounds", 0x00000000, 0x00000000, false, true));
666
667 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds", "Range over buffer bounds", 0x00200000, 0x00210000));
668 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_signed_wrap", "Range over buffer bounds", 0x7FFFFFF0, 0x7FFFFFFF));
669 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_unsigned_wrap", "Range over buffer bounds", 0xFFFFFFF0, 0xFFFFFFFF));
670 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_max", "Range over buffer bounds", 0x00000000, 0x00000000, true, true));
671 }
672 }
673
674 } // Stress
675 } // gles3
676 } // deqp
677