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 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 103 DrawInvalidRangeCase::~DrawInvalidRangeCase (void) 104 { 105 deinit(); 106 } 107 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 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 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 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 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 282 IndexGroup::~IndexGroup (void) 283 { 284 } 285 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 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 363 MethodGroup::~MethodGroup (void) 364 { 365 } 366 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 391 UniformWeightArray (void) 392 { 393 for (int i=0; i<SIZE; ++i) 394 weights[i] = 1.0f; 395 } 396 }; 397 398 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 399 : TestCaseGroup (context, name, descr) 400 { 401 } 402 403 RandomGroup::~RandomGroup (void) 404 { 405 } 406 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 618 DrawTests::DrawTests (Context& context) 619 : TestCaseGroup(context, "draw", "Draw stress tests") 620 { 621 } 622 623 DrawTests::~DrawTests (void) 624 { 625 } 626 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