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 38namespace deqp 39{ 40namespace gles31 41{ 42namespace Stress 43{ 44namespace 45{ 46 47static 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"; 56static 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"; 63struct DrawElementsCommand 64{ 65 deUint32 count; 66 deUint32 primCount; 67 deUint32 firstIndex; 68 deInt32 baseVertex; 69 deUint32 reservedMustBeZero; 70}; 71DE_STATIC_ASSERT(5 * sizeof(deUint32) == sizeof(DrawElementsCommand)); // tight packing 72 73struct DrawArraysCommand 74{ 75 deUint32 count; 76 deUint32 primCount; 77 deUint32 first; 78 deUint32 reservedMustBeZero; 79}; 80DE_STATIC_ASSERT(4 * sizeof(deUint32) == sizeof(DrawArraysCommand)); // tight packing 81 82class InvalidDrawCase : public TestCase 83{ 84public: 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 112private: 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 122InvalidDrawCase::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 136InvalidDrawCase::~InvalidDrawCase (void) 137{ 138 deinit(); 139} 140 141void InvalidDrawCase::init (void) 142{ 143} 144 145void 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 174InvalidDrawCase::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 301class RandomGroup : public TestCaseGroup 302{ 303public: 304 RandomGroup (Context& context, const char* name, const char* descr); 305 ~RandomGroup (void); 306 307 void init (void); 308}; 309 310template <int SIZE> 311struct UniformWeightArray 312{ 313 float weights[SIZE]; 314 315 UniformWeightArray (void) 316 { 317 for (int i=0; i<SIZE; ++i) 318 weights[i] = 1.0f; 319 } 320}; 321 322RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 323 : TestCaseGroup (context, name, descr) 324{ 325} 326 327RandomGroup::~RandomGroup (void) 328{ 329} 330 331void 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 552DrawTests::DrawTests (Context& context) 553 : TestCaseGroup(context, "draw_indirect", "Indirect drawing tests") 554{ 555} 556 557DrawTests::~DrawTests (void) 558{ 559} 560 561void 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