1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.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 Drawing tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2sDrawTests.hpp" 25#include "glsDrawTest.hpp" 26#include "tcuRenderTarget.hpp" 27#include "deRandom.hpp" 28#include "deStringUtil.hpp" 29#include "deUniquePtr.hpp" 30 31#include "glwEnums.hpp" 32 33#include <set> 34 35namespace deqp 36{ 37namespace gles2 38{ 39namespace Stress 40{ 41namespace 42{ 43 44static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method) 45{ 46 spec.apiType = glu::ApiType::es(2,0); 47 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES; 48 spec.primitiveCount = 5; 49 spec.drawMethod = method; 50 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST; 51 spec.indexPointerOffset = 0; 52 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST; 53 spec.first = 0; 54 spec.indexMin = 0; 55 spec.indexMax = 0; 56 spec.instanceCount = 1; 57 58 spec.attribs.resize(2); 59 60 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 61 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 62 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 63 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 64 spec.attribs[0].componentCount = 4; 65 spec.attribs[0].offset = 0; 66 spec.attribs[0].stride = 0; 67 spec.attribs[0].normalize = false; 68 spec.attribs[0].instanceDivisor = 0; 69 spec.attribs[0].useDefaultAttribute = false; 70 71 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 72 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 73 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 74 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 75 spec.attribs[1].componentCount = 2; 76 spec.attribs[1].offset = 0; 77 spec.attribs[1].stride = 0; 78 spec.attribs[1].normalize = false; 79 spec.attribs[1].instanceDivisor = 0; 80 spec.attribs[1].useDefaultAttribute = false; 81} 82 83class IndexGroup : public TestCaseGroup 84{ 85public: 86 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 87 ~IndexGroup (void); 88 89 void init (void); 90 91private: 92 gls::DrawTestSpec::DrawMethod m_method; 93}; 94 95IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 96 : TestCaseGroup (context, name, descr) 97 , m_method (drawMethod) 98{ 99} 100 101IndexGroup::~IndexGroup (void) 102{ 103} 104 105void IndexGroup::init (void) 106{ 107 struct IndexTest 108 { 109 gls::DrawTestSpec::Storage storage; 110 gls::DrawTestSpec::IndexType type; 111 bool aligned; 112 int offsets[3]; 113 }; 114 115 const IndexTest tests[] = 116 { 117 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 118 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 119 120 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 121 122 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 123 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 124 125 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 126 }; 127 128 gls::DrawTestSpec spec; 129 130 tcu::TestCaseGroup* userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer"); 131 tcu::TestCaseGroup* unalignedUserPtrGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer"); 132 tcu::TestCaseGroup* bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer"); 133 tcu::TestCaseGroup* unalignedBufferGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer"); 134 135 genBasicSpec(spec, m_method); 136 137 this->addChild(userPtrGroup); 138 this->addChild(unalignedUserPtrGroup); 139 this->addChild(bufferGroup); 140 this->addChild(unalignedBufferGroup); 141 142 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 143 { 144 const IndexTest& indexTest = tests[testNdx]; 145 tcu::TestCaseGroup* group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) : ((indexTest.aligned) ? (bufferGroup) : (unalignedBufferGroup)); 146 147 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 148 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage); 149 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str())); 150 151 spec.indexType = indexTest.type; 152 spec.indexStorage = indexTest.storage; 153 154 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) 155 { 156 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]); 157 spec.indexPointerOffset = indexTest.offsets[iterationNdx]; 158 test->addIteration(spec, iterationDesc.c_str()); 159 } 160 161 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET || 162 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 163 group->addChild(test.release()); 164 } 165} 166 167class MethodGroup : public TestCaseGroup 168{ 169public: 170 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 171 ~MethodGroup (void); 172 173 void init (void); 174 175private: 176 gls::DrawTestSpec::DrawMethod m_method; 177}; 178 179MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 180 : TestCaseGroup (context, name, descr) 181 , m_method (drawMethod) 182{ 183} 184 185MethodGroup::~MethodGroup (void) 186{ 187} 188 189void MethodGroup::init (void) 190{ 191 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED); 192 193 DE_ASSERT(indexed); 194 DE_UNREF(indexed); 195 196 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method)); 197} 198 199class RandomGroup : public TestCaseGroup 200{ 201public: 202 RandomGroup (Context& context, const char* name, const char* descr); 203 ~RandomGroup (void); 204 205 void init (void); 206}; 207 208template <int SIZE> 209struct UniformWeightArray 210{ 211 float weights[SIZE]; 212 213 UniformWeightArray (void) 214 { 215 for (int i=0; i<SIZE; ++i) 216 weights[i] = 1.0f; 217 } 218}; 219 220RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 221 : TestCaseGroup (context, name, descr) 222{ 223} 224 225RandomGroup::~RandomGroup (void) 226{ 227} 228 229void RandomGroup::init (void) 230{ 231 const int numAttempts = 100; 232 233 const int attribCounts[] = { 1, 2, 5 }; 234 const float attribWeights[] = { 30, 10, 1 }; 235 const int primitiveCounts[] = { 1, 5, 64 }; 236 const float primitiveCountWeights[] = { 20, 10, 1 }; 237 const int indexOffsets[] = { 0, 7, 13 }; 238 const float indexOffsetWeights[] = { 20, 20, 1 }; 239 const int firsts[] = { 0, 7, 13 }; 240 const float firstWeights[] = { 20, 20, 1 }; 241 const int offsets[] = { 0, 1, 5, 12 }; 242 const float offsetWeights[] = { 50, 10, 10, 10 }; 243 const int strides[] = { 0, 7, 16, 17 }; 244 const float strideWeights[] = { 50, 10, 10, 10 }; 245 246 gls::DrawTestSpec::Primitive primitives[] = 247 { 248 gls::DrawTestSpec::PRIMITIVE_POINTS, 249 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 250 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 251 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 252 gls::DrawTestSpec::PRIMITIVE_LINES, 253 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 254 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 255 }; 256 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights; 257 258 gls::DrawTestSpec::DrawMethod drawMethods[] = 259 { 260 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 261 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 262 }; 263 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights; 264 265 gls::DrawTestSpec::IndexType indexTypes[] = 266 { 267 gls::DrawTestSpec::INDEXTYPE_BYTE, 268 gls::DrawTestSpec::INDEXTYPE_SHORT, 269 }; 270 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights; 271 272 gls::DrawTestSpec::Storage storages[] = 273 { 274 gls::DrawTestSpec::STORAGE_USER, 275 gls::DrawTestSpec::STORAGE_BUFFER, 276 }; 277 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights; 278 279 gls::DrawTestSpec::InputType inputTypes[] = 280 { 281 gls::DrawTestSpec::INPUTTYPE_FLOAT, 282 gls::DrawTestSpec::INPUTTYPE_FIXED, 283 gls::DrawTestSpec::INPUTTYPE_BYTE, 284 gls::DrawTestSpec::INPUTTYPE_SHORT, 285 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, 286 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT 287 }; 288 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights; 289 290 gls::DrawTestSpec::OutputType outputTypes[] = 291 { 292 gls::DrawTestSpec::OUTPUTTYPE_FLOAT, 293 gls::DrawTestSpec::OUTPUTTYPE_VEC2, 294 gls::DrawTestSpec::OUTPUTTYPE_VEC3, 295 gls::DrawTestSpec::OUTPUTTYPE_VEC4, 296 }; 297 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights; 298 299 gls::DrawTestSpec::Usage usages[] = 300 { 301 gls::DrawTestSpec::USAGE_STATIC_DRAW, 302 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW, 303 gls::DrawTestSpec::USAGE_STREAM_DRAW, 304 }; 305 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights; 306 307 const deUint32 blacklistedCases[]= 308 { 309 3153, //!< extremely narrow triangle, results depend on sample positions 310 }; 311 312 std::set<deUint32> insertedHashes; 313 size_t insertedCount = 0; 314 315 for (int ndx = 0; ndx < numAttempts; ++ndx) 316 { 317 de::Random random(0xc551393 + ndx); // random does not depend on previous cases 318 319 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights); 320 gls::DrawTestSpec spec; 321 322 spec.apiType = glu::ApiType::es(2,0); 323 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights); 324 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights); 325 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights); 326 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights); 327 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights); 328 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 329 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights); 330 spec.indexMin = 0; 331 spec.indexMax = 0; 332 spec.instanceCount = 0; 333 334 // check spec is legal 335 if (!spec.valid()) 336 continue; 337 338 for (int attrNdx = 0; attrNdx < attributeCount;) 339 { 340 bool valid; 341 gls::DrawTestSpec::AttributeSpec attribSpec; 342 343 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights); 344 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights); 345 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 346 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights); 347 attribSpec.componentCount = random.getInt(1, 4); 348 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights); 349 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights); 350 attribSpec.normalize = random.getBool(); 351 attribSpec.instanceDivisor = 0; 352 attribSpec.useDefaultAttribute = random.getBool(); 353 354 // check spec is legal 355 valid = attribSpec.valid(spec.apiType); 356 357 // we do not want interleaved elements. (Might result in some weird floating point values) 358 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride) 359 valid = false; 360 361 // try again if not valid 362 if (valid) 363 { 364 spec.attribs.push_back(attribSpec); 365 ++attrNdx; 366 } 367 } 368 369 // Do not collapse all vertex positions to a single positions 370 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 371 spec.attribs[0].instanceDivisor = 0; 372 373 // Is render result meaningful? 374 { 375 // Only one vertex 376 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 377 continue; 378 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 379 continue; 380 381 // Triangle only on one axis 382 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP) 383 { 384 if (spec.attribs[0].componentCount == 1) 385 continue; 386 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) 387 continue; 388 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2) 389 continue; 390 } 391 } 392 393 // Add case 394 { 395 deUint32 hash = spec.hash(); 396 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx) 397 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash(); 398 399 if (insertedHashes.find(hash) == insertedHashes.end() && 400 std::find(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash) == DE_ARRAY_END(blacklistedCases)) 401 { 402 // Only unaligned cases 403 if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET || 404 spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 405 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str())); 406 insertedHashes.insert(hash); 407 408 ++insertedCount; 409 } 410 } 411 } 412} 413 414} // anonymous 415 416DrawTests::DrawTests (Context& context) 417 : TestCaseGroup(context, "draw", "Drawing tests") 418{ 419} 420 421DrawTests::~DrawTests (void) 422{ 423} 424 425void DrawTests::init (void) 426{ 427 tcu::TestCaseGroup* const unalignedGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data"); 428 429 addChild(unalignedGroup); 430 431 // .unaligned_data 432 { 433 const gls::DrawTestSpec::DrawMethod basicMethods[] = 434 { 435 // gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 436 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 437 }; 438 439 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx) 440 { 441 std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 442 std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 443 444 unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx])); 445 } 446 447 // Random 448 449 unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands.")); 450 } 451 452} 453 454} // Stress 455} // gles2 456} // deqp 457