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 Vertex array and buffer unaligned access stress tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3sVertexArrayTests.hpp" 25 #include "glsVertexArrayTests.hpp" 26 27 #include <sstream> 28 29 using namespace deqp::gls; 30 31 namespace deqp 32 { 33 namespace gles3 34 { 35 namespace Stress 36 { 37 namespace 38 { 39 40 41 class SingleVertexArrayUsageGroup : public TestCaseGroup 42 { 43 public: 44 SingleVertexArrayUsageGroup (Context& context, Array::Usage usage); 45 virtual ~SingleVertexArrayUsageGroup (void); 46 47 virtual void init (void); 48 49 private: 50 SingleVertexArrayUsageGroup (const SingleVertexArrayUsageGroup& other); 51 SingleVertexArrayUsageGroup& operator= (const SingleVertexArrayUsageGroup& other); 52 53 Array::Usage m_usage; 54 }; 55 56 SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup (Context& context, Array::Usage usage) 57 : TestCaseGroup (context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str()) 58 , m_usage (usage) 59 { 60 } 61 62 SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void) 63 { 64 } 65 66 template<class T> 67 static std::string typeToString (T t) 68 { 69 std::stringstream strm; 70 strm << t; 71 return strm.str(); 72 } 73 74 void SingleVertexArrayUsageGroup::init (void) 75 { 76 int counts[] = {1, 256}; 77 int strides[] = {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL. 78 Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE}; 79 80 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++) 81 { 82 for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++) 83 { 84 for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++) 85 { 86 const int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]); 87 const bool aligned = (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0; 88 const std::string name = "stride" + typeToString(stride) + "_" + Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" + typeToString(counts[countNdx]); 89 90 MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx], 91 Array::OUTPUTTYPE_VEC2, 92 Array::STORAGE_BUFFER, 93 m_usage, 94 2, 95 0, 96 stride, 97 false, 98 GLValue::getMinValue(inputTypes[inputTypeNdx]), 99 GLValue::getMaxValue(inputTypes[inputTypeNdx])); 100 101 MultiVertexArrayTest::Spec spec; 102 spec.primitive = Array::PRIMITIVE_TRIANGLES; 103 spec.drawCount = counts[countNdx]; 104 spec.first = 0; 105 spec.arrays.push_back(arraySpec); 106 107 if (!aligned) 108 addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str())); 109 } 110 } 111 } 112 } 113 114 class SingleVertexArrayUsageTests : public TestCaseGroup 115 { 116 public: 117 SingleVertexArrayUsageTests (Context& context); 118 virtual ~SingleVertexArrayUsageTests (void); 119 120 virtual void init (void); 121 122 private: 123 SingleVertexArrayUsageTests (const SingleVertexArrayUsageTests& other); 124 SingleVertexArrayUsageTests& operator= (const SingleVertexArrayUsageTests& other); 125 }; 126 127 SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context) 128 : TestCaseGroup(context, "usages", "Single vertex atribute, usage") 129 { 130 } 131 132 SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void) 133 { 134 } 135 136 void SingleVertexArrayUsageTests::init (void) 137 { 138 // Test usage 139 Array::Usage usages[] = { Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW, Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY, Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ }; 140 for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++) 141 { 142 addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx])); 143 } 144 } 145 146 class SingleVertexArrayStrideGroup : public TestCaseGroup 147 { 148 public: 149 SingleVertexArrayStrideGroup (Context& context, Array::InputType type); 150 virtual ~SingleVertexArrayStrideGroup (void); 151 152 virtual void init (void); 153 154 private: 155 SingleVertexArrayStrideGroup (const SingleVertexArrayStrideGroup& other); 156 SingleVertexArrayStrideGroup& operator= (const SingleVertexArrayStrideGroup& other); 157 158 Array::InputType m_type; 159 }; 160 161 SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup (Context& context, Array::InputType type) 162 : TestCaseGroup (context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str()) 163 , m_type (type) 164 { 165 } 166 167 SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void) 168 { 169 } 170 171 void SingleVertexArrayStrideGroup::init (void) 172 { 173 Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER}; 174 int counts[] = {1, 256}; 175 int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL. 176 177 for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++) 178 { 179 for (int componentCount = 2; componentCount < 5; componentCount++) 180 { 181 for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++) 182 { 183 for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++) 184 { 185 const bool packed = m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10; 186 const int stride = (strides[strideNdx] < 0) ? ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]); 187 const int alignment = (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type)); 188 const bool bufferUnaligned = (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0; 189 190 std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) + "_components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]); 191 192 if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4) 193 continue; 194 195 MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type, 196 Array::OUTPUTTYPE_VEC4, 197 storages[storageNdx], 198 Array::USAGE_DYNAMIC_DRAW, 199 componentCount, 200 0, 201 stride, 202 false, 203 GLValue::getMinValue(m_type), 204 GLValue::getMaxValue(m_type)); 205 206 MultiVertexArrayTest::Spec spec; 207 spec.primitive = Array::PRIMITIVE_TRIANGLES; 208 spec.drawCount = counts[countNdx]; 209 spec.first = 0; 210 spec.arrays.push_back(arraySpec); 211 212 if (bufferUnaligned) 213 addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str())); 214 } 215 } 216 } 217 } 218 } 219 220 class SingleVertexArrayStrideTests : public TestCaseGroup 221 { 222 public: 223 SingleVertexArrayStrideTests (Context& context); 224 virtual ~SingleVertexArrayStrideTests (void); 225 226 virtual void init (void); 227 228 private: 229 SingleVertexArrayStrideTests (const SingleVertexArrayStrideTests& other); 230 SingleVertexArrayStrideTests& operator= (const SingleVertexArrayStrideTests& other); 231 }; 232 233 SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context) 234 : TestCaseGroup(context, "strides", "Single stride vertex atribute") 235 { 236 } 237 238 SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void) 239 { 240 } 241 242 void SingleVertexArrayStrideTests::init (void) 243 { 244 Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED, Array::INPUTTYPE_INT_2_10_10_10 }; 245 246 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++) 247 { 248 addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx])); 249 } 250 } 251 252 class SingleVertexArrayFirstGroup : public TestCaseGroup 253 { 254 public: 255 SingleVertexArrayFirstGroup (Context& context, Array::InputType type); 256 virtual ~SingleVertexArrayFirstGroup (void); 257 258 virtual void init (void); 259 260 private: 261 SingleVertexArrayFirstGroup (const SingleVertexArrayFirstGroup& other); 262 SingleVertexArrayFirstGroup& operator= (const SingleVertexArrayFirstGroup& other); 263 Array::InputType m_type; 264 }; 265 266 SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup (Context& context, Array::InputType type) 267 : TestCaseGroup (context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str()) 268 , m_type (type) 269 { 270 } 271 272 SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void) 273 { 274 } 275 276 void SingleVertexArrayFirstGroup::init (void) 277 { 278 int counts[] = {5, 256}; 279 int firsts[] = {6, 24}; 280 int offsets[] = {1, 17}; 281 int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL. 282 283 for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++) 284 { 285 for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++) 286 { 287 for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++) 288 { 289 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++) 290 { 291 const bool packed = m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10; 292 const int componentCount = (packed) ? (4) : (2); 293 const int stride = (strides[strideNdx] < 0) ? ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]); 294 const int alignment = (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type)); 295 const bool aligned = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0); 296 std::string name = "first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]); 297 298 MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type, 299 Array::OUTPUTTYPE_VEC2, 300 Array::STORAGE_BUFFER, 301 Array::USAGE_DYNAMIC_DRAW, 302 componentCount, 303 offsets[offsetNdx], 304 stride, 305 false, 306 GLValue::getMinValue(m_type), 307 GLValue::getMaxValue(m_type)); 308 309 MultiVertexArrayTest::Spec spec; 310 spec.primitive = Array::PRIMITIVE_TRIANGLES; 311 spec.drawCount = counts[countNdx]; 312 spec.first = firsts[firstNdx]; 313 spec.arrays.push_back(arraySpec); 314 315 if (!aligned) 316 addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str())); 317 } 318 } 319 } 320 } 321 } 322 323 class SingleVertexArrayFirstTests : public TestCaseGroup 324 { 325 public: 326 SingleVertexArrayFirstTests (Context& context); 327 virtual ~SingleVertexArrayFirstTests (void); 328 329 virtual void init (void); 330 331 private: 332 SingleVertexArrayFirstTests (const SingleVertexArrayFirstTests& other); 333 SingleVertexArrayFirstTests& operator= (const SingleVertexArrayFirstTests& other); 334 }; 335 336 SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context) 337 : TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays") 338 { 339 } 340 341 SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void) 342 { 343 } 344 345 void SingleVertexArrayFirstTests::init (void) 346 { 347 // Test offset with different input types, component counts and storage, Usage(?) 348 Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_INT_2_10_10_10 }; 349 350 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++) 351 { 352 addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx])); 353 } 354 } 355 356 class SingleVertexArrayOffsetGroup : public TestCaseGroup 357 { 358 public: 359 SingleVertexArrayOffsetGroup (Context& context, Array::InputType type); 360 virtual ~SingleVertexArrayOffsetGroup (void); 361 362 virtual void init (void); 363 364 private: 365 SingleVertexArrayOffsetGroup (const SingleVertexArrayOffsetGroup& other); 366 SingleVertexArrayOffsetGroup& operator= (const SingleVertexArrayOffsetGroup& other); 367 Array::InputType m_type; 368 }; 369 370 SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup (Context& context, Array::InputType type) 371 : TestCaseGroup (context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str()) 372 , m_type (type) 373 { 374 } 375 376 SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void) 377 { 378 } 379 380 void SingleVertexArrayOffsetGroup::init (void) 381 { 382 int counts[] = {1, 256}; 383 int offsets[] = {1, 4, 17, 32}; 384 int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL. 385 386 for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++) 387 { 388 for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++) 389 { 390 for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++) 391 { 392 const bool packed = m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10; 393 const int componentCount = (packed) ? (4) : (2); 394 const int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]); 395 const int alignment = (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type)); 396 const bool aligned = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0); 397 const std::string name = "offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(strides[strideNdx]) + "_quads" + typeToString(counts[countNdx]); 398 399 MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type, 400 Array::OUTPUTTYPE_VEC2, 401 Array::STORAGE_BUFFER, 402 Array::USAGE_DYNAMIC_DRAW, 403 componentCount, 404 offsets[offsetNdx], 405 stride, 406 false, 407 GLValue::getMinValue(m_type), 408 GLValue::getMaxValue(m_type)); 409 410 MultiVertexArrayTest::Spec spec; 411 spec.primitive = Array::PRIMITIVE_TRIANGLES; 412 spec.drawCount = counts[countNdx]; 413 spec.first = 0; 414 spec.arrays.push_back(arraySpec); 415 416 if (!aligned) 417 addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str())); 418 } 419 } 420 } 421 } 422 423 class SingleVertexArrayOffsetTests : public TestCaseGroup 424 { 425 public: 426 SingleVertexArrayOffsetTests (Context& context); 427 virtual ~SingleVertexArrayOffsetTests (void); 428 429 virtual void init (void); 430 431 private: 432 SingleVertexArrayOffsetTests (const SingleVertexArrayOffsetTests& other); 433 SingleVertexArrayOffsetTests& operator= (const SingleVertexArrayOffsetTests& other); 434 }; 435 436 SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context) 437 : TestCaseGroup(context, "offset", "Single vertex atribute offset element") 438 { 439 } 440 441 SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void) 442 { 443 } 444 445 void SingleVertexArrayOffsetTests::init (void) 446 { 447 // Test offset with different input types, component counts and storage, Usage(?) 448 Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_INT_2_10_10_10 }; 449 450 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++) 451 { 452 addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx])); 453 } 454 } 455 456 } // anonymous 457 458 VertexArrayTests::VertexArrayTests (Context& context) 459 : TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests") 460 { 461 } 462 463 VertexArrayTests::~VertexArrayTests (void) 464 { 465 } 466 467 void VertexArrayTests::init (void) 468 { 469 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "single_attribute", "Single attribute"); 470 addChild(group); 471 472 // .single_attribute 473 { 474 group->addChild(new SingleVertexArrayStrideTests(m_context)); 475 group->addChild(new SingleVertexArrayUsageTests(m_context)); 476 group->addChild(new SingleVertexArrayOffsetTests(m_context)); 477 group->addChild(new SingleVertexArrayFirstTests(m_context)); 478 } 479 } 480 481 } // Stress 482 } // gles3 483 } // deqp 484