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_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 299 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 300 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } }, 301 302 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 303 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, false, { 2, 3, -1 } }, 304 305 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 306 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 307 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } }, 308 309 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 310 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_INT, false, { 2, 3, -1 } }, 311 }; 312 313 gls::DrawTestSpec spec; 314 315 tcu::TestCaseGroup* const userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer"); 316 tcu::TestCaseGroup* const unalignedUserPtrGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer"); 317 tcu::TestCaseGroup* const bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer"); 318 tcu::TestCaseGroup* const unalignedBufferGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer"); 319 const bool isRangedMethod = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED || m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX); 320 321 genBasicSpec(spec, m_method); 322 323 this->addChild(userPtrGroup); 324 this->addChild(unalignedUserPtrGroup); 325 this->addChild(bufferGroup); 326 this->addChild(unalignedBufferGroup); 327 328 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 329 { 330 const IndexTest& indexTest = tests[testNdx]; 331 tcu::TestCaseGroup* group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) : ((indexTest.aligned) ? (bufferGroup) : (unalignedBufferGroup)); 332 333 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 334 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage); 335 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str())); 336 337 spec.indexType = indexTest.type; 338 spec.indexStorage = indexTest.storage; 339 340 if (isRangedMethod) 341 { 342 spec.indexMin = 0; 343 spec.indexMax = 55; 344 } 345 346 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) 347 { 348 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]); 349 spec.indexPointerOffset = indexTest.offsets[iterationNdx]; 350 test->addIteration(spec, iterationDesc.c_str()); 351 } 352 353 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET || 354 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 355 group->addChild(test.release()); 356 } 357 } 358 359 class MethodGroup : public TestCaseGroup 360 { 361 public: 362 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 363 ~MethodGroup (void); 364 365 void init (void); 366 367 private: 368 gls::DrawTestSpec::DrawMethod m_method; 369 }; 370 371 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 372 : TestCaseGroup (context, name, descr) 373 , m_method (drawMethod) 374 { 375 } 376 377 MethodGroup::~MethodGroup (void) 378 { 379 } 380 381 void MethodGroup::init (void) 382 { 383 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED); 384 385 DE_ASSERT(indexed); 386 DE_UNREF(indexed); 387 388 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method)); 389 } 390 391 class RandomGroup : public TestCaseGroup 392 { 393 public: 394 RandomGroup (Context& context, const char* name, const char* descr); 395 ~RandomGroup (void); 396 397 void init (void); 398 }; 399 400 template <int SIZE> 401 struct UniformWeightArray 402 { 403 float weights[SIZE]; 404 405 UniformWeightArray (void) 406 { 407 for (int i=0; i<SIZE; ++i) 408 weights[i] = 1.0f; 409 } 410 }; 411 412 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 413 : TestCaseGroup (context, name, descr) 414 { 415 } 416 417 RandomGroup::~RandomGroup (void) 418 { 419 } 420 421 void RandomGroup::init (void) 422 { 423 const int numAttempts = 300; 424 425 const int attribCounts[] = { 1, 2, 5 }; 426 const float attribWeights[] = { 30, 10, 1 }; 427 const int primitiveCounts[] = { 1, 5, 64 }; 428 const float primitiveCountWeights[] = { 20, 10, 1 }; 429 const int indexOffsets[] = { 0, 7, 13 }; 430 const float indexOffsetWeights[] = { 20, 20, 1 }; 431 const int firsts[] = { 0, 7, 13 }; 432 const float firstWeights[] = { 20, 20, 1 }; 433 const int instanceCounts[] = { 1, 2, 16, 17 }; 434 const float instanceWeights[] = { 20, 10, 5, 1 }; 435 const int indexMins[] = { 0, 1, 3, 8 }; 436 const int indexMaxs[] = { 4, 8, 128, 257 }; 437 const float indexWeights[] = { 50, 50, 50, 50 }; 438 const int offsets[] = { 0, 1, 5, 12 }; 439 const float offsetWeights[] = { 50, 10, 10, 10 }; 440 const int strides[] = { 0, 7, 16, 17 }; 441 const float strideWeights[] = { 50, 10, 10, 10 }; 442 const int instanceDivisors[] = { 0, 1, 3, 129 }; 443 const float instanceDivisorWeights[]= { 70, 30, 10, 10 }; 444 445 gls::DrawTestSpec::Primitive primitives[] = 446 { 447 gls::DrawTestSpec::PRIMITIVE_POINTS, 448 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 449 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 450 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 451 gls::DrawTestSpec::PRIMITIVE_LINES, 452 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 453 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 454 }; 455 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights; 456 457 gls::DrawTestSpec::DrawMethod drawMethods[] = 458 { 459 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 460 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED, 461 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 462 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED, 463 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED 464 }; 465 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights; 466 467 gls::DrawTestSpec::IndexType indexTypes[] = 468 { 469 gls::DrawTestSpec::INDEXTYPE_BYTE, 470 gls::DrawTestSpec::INDEXTYPE_SHORT, 471 gls::DrawTestSpec::INDEXTYPE_INT, 472 }; 473 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights; 474 475 gls::DrawTestSpec::Storage storages[] = 476 { 477 gls::DrawTestSpec::STORAGE_USER, 478 gls::DrawTestSpec::STORAGE_BUFFER, 479 }; 480 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights; 481 482 gls::DrawTestSpec::InputType inputTypes[] = 483 { 484 gls::DrawTestSpec::INPUTTYPE_FLOAT, 485 gls::DrawTestSpec::INPUTTYPE_FIXED, 486 gls::DrawTestSpec::INPUTTYPE_BYTE, 487 gls::DrawTestSpec::INPUTTYPE_SHORT, 488 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, 489 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT, 490 gls::DrawTestSpec::INPUTTYPE_INT, 491 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, 492 gls::DrawTestSpec::INPUTTYPE_HALF, 493 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10, 494 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10, 495 }; 496 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights; 497 498 gls::DrawTestSpec::OutputType outputTypes[] = 499 { 500 gls::DrawTestSpec::OUTPUTTYPE_FLOAT, 501 gls::DrawTestSpec::OUTPUTTYPE_VEC2, 502 gls::DrawTestSpec::OUTPUTTYPE_VEC3, 503 gls::DrawTestSpec::OUTPUTTYPE_VEC4, 504 gls::DrawTestSpec::OUTPUTTYPE_INT, 505 gls::DrawTestSpec::OUTPUTTYPE_UINT, 506 gls::DrawTestSpec::OUTPUTTYPE_IVEC2, 507 gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 508 gls::DrawTestSpec::OUTPUTTYPE_IVEC4, 509 gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 510 gls::DrawTestSpec::OUTPUTTYPE_UVEC3, 511 gls::DrawTestSpec::OUTPUTTYPE_UVEC4, 512 }; 513 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights; 514 515 gls::DrawTestSpec::Usage usages[] = 516 { 517 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW, 518 gls::DrawTestSpec::USAGE_STATIC_DRAW, 519 gls::DrawTestSpec::USAGE_STREAM_DRAW, 520 gls::DrawTestSpec::USAGE_STREAM_READ, 521 gls::DrawTestSpec::USAGE_STREAM_COPY, 522 gls::DrawTestSpec::USAGE_STATIC_READ, 523 gls::DrawTestSpec::USAGE_STATIC_COPY, 524 gls::DrawTestSpec::USAGE_DYNAMIC_READ, 525 gls::DrawTestSpec::USAGE_DYNAMIC_COPY, 526 }; 527 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights; 528 529 std::set<deUint32> insertedHashes; 530 size_t insertedCount = 0; 531 532 for (int ndx = 0; ndx < numAttempts; ++ndx) 533 { 534 de::Random random(0xc551393 + ndx); // random does not depend on previous cases 535 536 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights); 537 gls::DrawTestSpec spec; 538 539 spec.apiType = glu::ApiType::es(3,0); 540 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights); 541 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights); 542 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights); 543 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights); 544 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights); 545 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 546 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights); 547 spec.indexMin = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMins), DE_ARRAY_END(indexMins), indexWeights); 548 spec.indexMax = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMaxs), DE_ARRAY_END(indexMaxs), indexWeights); 549 spec.instanceCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(instanceCounts), DE_ARRAY_END(instanceCounts), instanceWeights); 550 551 // check spec is legal 552 if (!spec.valid()) 553 continue; 554 555 for (int attrNdx = 0; attrNdx < attributeCount;) 556 { 557 bool valid; 558 gls::DrawTestSpec::AttributeSpec attribSpec; 559 560 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights); 561 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights); 562 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 563 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights); 564 attribSpec.componentCount = random.getInt(1, 4); 565 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights); 566 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights); 567 attribSpec.normalize = random.getBool(); 568 attribSpec.instanceDivisor = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights); 569 attribSpec.useDefaultAttribute = random.getBool(); 570 571 // check spec is legal 572 valid = attribSpec.valid(spec.apiType); 573 574 // we do not want interleaved elements. (Might result in some weird floating point values) 575 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride) 576 valid = false; 577 578 // try again if not valid 579 if (valid) 580 { 581 spec.attribs.push_back(attribSpec); 582 ++attrNdx; 583 } 584 } 585 586 // Do not collapse all vertex positions to a single positions 587 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 588 spec.attribs[0].instanceDivisor = 0; 589 590 // Is render result meaningful? 591 { 592 // Only one vertex 593 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 594 continue; 595 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 596 continue; 597 598 // Triangle only on one axis 599 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP) 600 { 601 if (spec.attribs[0].componentCount == 1) 602 continue; 603 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) 604 continue; 605 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2) 606 continue; 607 } 608 } 609 610 // Add case 611 { 612 deUint32 hash = spec.hash(); 613 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx) 614 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash(); 615 616 if (insertedHashes.find(hash) == insertedHashes.end()) 617 { 618 // Only unaligned cases 619 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET || 620 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 621 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str())); 622 insertedHashes.insert(hash); 623 624 ++insertedCount; 625 } 626 } 627 } 628 } 629 630 } // anonymous 631 632 DrawTests::DrawTests (Context& context) 633 : TestCaseGroup(context, "draw", "Draw stress tests") 634 { 635 } 636 637 DrawTests::~DrawTests (void) 638 { 639 } 640 641 void DrawTests::init (void) 642 { 643 tcu::TestCaseGroup* const unalignedGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data"); 644 tcu::TestCaseGroup* const drawRangeGroup = new tcu::TestCaseGroup(m_testCtx, "draw_range_elements", "Test drawRangeElements"); 645 646 addChild(unalignedGroup); 647 addChild(drawRangeGroup); 648 649 // .unaligned_data 650 { 651 const gls::DrawTestSpec::DrawMethod basicMethods[] = 652 { 653 // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 654 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 655 // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED, 656 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED, 657 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED, 658 }; 659 660 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx) 661 { 662 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 663 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 664 665 unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx])); 666 } 667 668 // Random 669 670 unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands.")); 671 } 672 673 // .draw_range_elements 674 { 675 // use a larger range than the buffer size is 676 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds", "Range over buffer bounds", 0x00000000, 0x00210000)); 677 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_signed_wrap", "Range over buffer bounds", 0x00000000, 0x7FFFFFFF)); 678 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_unsigned_wrap", "Range over buffer bounds", 0x00000000, 0xFFFFFFFF)); 679 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_max", "Range over buffer bounds", 0x00000000, 0x00000000, false, true)); 680 681 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds", "Range over buffer bounds", 0x00200000, 0x00210000)); 682 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_signed_wrap", "Range over buffer bounds", 0x7FFFFFF0, 0x7FFFFFFF)); 683 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_unsigned_wrap", "Range over buffer bounds", 0xFFFFFFF0, 0xFFFFFFFF)); 684 drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_max", "Range over buffer bounds", 0x00000000, 0x00000000, true, true)); 685 } 686 } 687 688 } // Stress 689 } // gles3 690 } // deqp 691