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 29using namespace deqp::gls; 30 31namespace deqp 32{ 33namespace gles3 34{ 35namespace Stress 36{ 37namespace 38{ 39 40 41class SingleVertexArrayUsageGroup : public TestCaseGroup 42{ 43public: 44 SingleVertexArrayUsageGroup (Context& context, Array::Usage usage); 45 virtual ~SingleVertexArrayUsageGroup (void); 46 47 virtual void init (void); 48 49private: 50 SingleVertexArrayUsageGroup (const SingleVertexArrayUsageGroup& other); 51 SingleVertexArrayUsageGroup& operator= (const SingleVertexArrayUsageGroup& other); 52 53 Array::Usage m_usage; 54}; 55 56SingleVertexArrayUsageGroup::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 62SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void) 63{ 64} 65 66template<class T> 67static std::string typeToString (T t) 68{ 69 std::stringstream strm; 70 strm << t; 71 return strm.str(); 72} 73 74void 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 114class SingleVertexArrayUsageTests : public TestCaseGroup 115{ 116public: 117 SingleVertexArrayUsageTests (Context& context); 118 virtual ~SingleVertexArrayUsageTests (void); 119 120 virtual void init (void); 121 122private: 123 SingleVertexArrayUsageTests (const SingleVertexArrayUsageTests& other); 124 SingleVertexArrayUsageTests& operator= (const SingleVertexArrayUsageTests& other); 125}; 126 127SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context) 128 : TestCaseGroup(context, "usages", "Single vertex atribute, usage") 129{ 130} 131 132SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void) 133{ 134} 135 136void 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 146class SingleVertexArrayStrideGroup : public TestCaseGroup 147{ 148public: 149 SingleVertexArrayStrideGroup (Context& context, Array::InputType type); 150 virtual ~SingleVertexArrayStrideGroup (void); 151 152 virtual void init (void); 153 154private: 155 SingleVertexArrayStrideGroup (const SingleVertexArrayStrideGroup& other); 156 SingleVertexArrayStrideGroup& operator= (const SingleVertexArrayStrideGroup& other); 157 158 Array::InputType m_type; 159}; 160 161SingleVertexArrayStrideGroup::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 167SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void) 168{ 169} 170 171void 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 220class SingleVertexArrayStrideTests : public TestCaseGroup 221{ 222public: 223 SingleVertexArrayStrideTests (Context& context); 224 virtual ~SingleVertexArrayStrideTests (void); 225 226 virtual void init (void); 227 228private: 229 SingleVertexArrayStrideTests (const SingleVertexArrayStrideTests& other); 230 SingleVertexArrayStrideTests& operator= (const SingleVertexArrayStrideTests& other); 231}; 232 233SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context) 234 : TestCaseGroup(context, "strides", "Single stride vertex atribute") 235{ 236} 237 238SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void) 239{ 240} 241 242void 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 252class SingleVertexArrayFirstGroup : public TestCaseGroup 253{ 254public: 255 SingleVertexArrayFirstGroup (Context& context, Array::InputType type); 256 virtual ~SingleVertexArrayFirstGroup (void); 257 258 virtual void init (void); 259 260private: 261 SingleVertexArrayFirstGroup (const SingleVertexArrayFirstGroup& other); 262 SingleVertexArrayFirstGroup& operator= (const SingleVertexArrayFirstGroup& other); 263 Array::InputType m_type; 264}; 265 266SingleVertexArrayFirstGroup::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 272SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void) 273{ 274} 275 276void 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 323class SingleVertexArrayFirstTests : public TestCaseGroup 324{ 325public: 326 SingleVertexArrayFirstTests (Context& context); 327 virtual ~SingleVertexArrayFirstTests (void); 328 329 virtual void init (void); 330 331private: 332 SingleVertexArrayFirstTests (const SingleVertexArrayFirstTests& other); 333 SingleVertexArrayFirstTests& operator= (const SingleVertexArrayFirstTests& other); 334}; 335 336SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context) 337 : TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays") 338{ 339} 340 341SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void) 342{ 343} 344 345void 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 356class SingleVertexArrayOffsetGroup : public TestCaseGroup 357{ 358public: 359 SingleVertexArrayOffsetGroup (Context& context, Array::InputType type); 360 virtual ~SingleVertexArrayOffsetGroup (void); 361 362 virtual void init (void); 363 364private: 365 SingleVertexArrayOffsetGroup (const SingleVertexArrayOffsetGroup& other); 366 SingleVertexArrayOffsetGroup& operator= (const SingleVertexArrayOffsetGroup& other); 367 Array::InputType m_type; 368}; 369 370SingleVertexArrayOffsetGroup::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 376SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void) 377{ 378} 379 380void 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 423class SingleVertexArrayOffsetTests : public TestCaseGroup 424{ 425public: 426 SingleVertexArrayOffsetTests (Context& context); 427 virtual ~SingleVertexArrayOffsetTests (void); 428 429 virtual void init (void); 430 431private: 432 SingleVertexArrayOffsetTests (const SingleVertexArrayOffsetTests& other); 433 SingleVertexArrayOffsetTests& operator= (const SingleVertexArrayOffsetTests& other); 434}; 435 436SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context) 437 : TestCaseGroup(context, "offset", "Single vertex atribute offset element") 438{ 439} 440 441SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void) 442{ 443} 444 445void 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 458VertexArrayTests::VertexArrayTests (Context& context) 459 : TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests") 460{ 461} 462 463VertexArrayTests::~VertexArrayTests (void) 464{ 465} 466 467void 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