glsVertexArrayTests.cpp revision 3c827367444ee418f129b2c238299f49d3264554
1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL (ES) 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 tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "glsVertexArrayTests.hpp" 25 26#include "deRandom.h" 27 28#include "tcuTestLog.hpp" 29#include "tcuPixelFormat.hpp" 30#include "tcuRGBA.hpp" 31#include "tcuSurface.hpp" 32#include "tcuVector.hpp" 33#include "tcuTestLog.hpp" 34#include "tcuRenderTarget.hpp" 35#include "tcuStringTemplate.hpp" 36#include "tcuImageCompare.hpp" 37 38#include "gluPixelTransfer.hpp" 39#include "gluCallLogWrapper.hpp" 40 41#include "sglrContext.hpp" 42#include "sglrReferenceContext.hpp" 43#include "sglrGLContext.hpp" 44 45#include "deMath.h" 46#include "deStringUtil.hpp" 47 48#include <cstring> 49#include <cmath> 50#include <vector> 51#include <sstream> 52#include <limits> 53#include <algorithm> 54 55#include "glwDefs.hpp" 56#include "glwEnums.hpp" 57 58namespace deqp 59{ 60namespace gls 61{ 62 63using tcu::TestLog; 64using namespace glw; // GL types 65 66std::string Array::targetToString(Target target) 67{ 68 DE_ASSERT(target < TARGET_LAST); 69 70 static const char* targets[] = 71 { 72 "element_array", // TARGET_ELEMENT_ARRAY = 0, 73 "array" // TARGET_ARRAY, 74 }; 75 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(targets) == Array::TARGET_LAST); 76 77 return targets[(int)target]; 78} 79 80std::string Array::inputTypeToString(InputType type) 81{ 82 DE_ASSERT(type < INPUTTYPE_LAST); 83 84 static const char* types[] = 85 { 86 "float", // INPUTTYPE_FLOAT = 0, 87 "fixed", // INPUTTYPE_FIXED, 88 "double", // INPUTTYPE_DOUBLE 89 90 "byte", // INPUTTYPE_BYTE, 91 "short", // INPUTTYPE_SHORT, 92 93 "unsigned_byte", // INPUTTYPE_UNSIGNED_BYTE, 94 "unsigned_short", // INPUTTYPE_UNSIGNED_SHORT, 95 96 "int", // INPUTTYPE_INT, 97 "unsigned_int", // INPUTTYPE_UNSIGNED_INT, 98 "half", // INPUTTYPE_HALF, 99 "usigned_int2_10_10_10", // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 100 "int2_10_10_10" // INPUTTYPE_INT_2_10_10_10, 101 }; 102 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::INPUTTYPE_LAST); 103 104 return types[(int)type]; 105} 106 107std::string Array::outputTypeToString(OutputType type) 108{ 109 DE_ASSERT(type < OUTPUTTYPE_LAST); 110 111 static const char* types[] = 112 { 113 "float", // OUTPUTTYPE_FLOAT = 0, 114 "vec2", // OUTPUTTYPE_VEC2, 115 "vec3", // OUTPUTTYPE_VEC3, 116 "vec4", // OUTPUTTYPE_VEC4, 117 118 "int", // OUTPUTTYPE_INT, 119 "uint", // OUTPUTTYPE_UINT, 120 121 "ivec2", // OUTPUTTYPE_IVEC2, 122 "ivec3", // OUTPUTTYPE_IVEC3, 123 "ivec4", // OUTPUTTYPE_IVEC4, 124 125 "uvec2", // OUTPUTTYPE_UVEC2, 126 "uvec3", // OUTPUTTYPE_UVEC3, 127 "uvec4", // OUTPUTTYPE_UVEC4, 128 }; 129 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::OUTPUTTYPE_LAST); 130 131 return types[(int)type]; 132} 133 134std::string Array::usageTypeToString(Usage usage) 135{ 136 DE_ASSERT(usage < USAGE_LAST); 137 138 static const char* usages[] = 139 { 140 "dynamic_draw", // USAGE_DYNAMIC_DRAW = 0, 141 "static_draw", // USAGE_STATIC_DRAW, 142 "stream_draw", // USAGE_STREAM_DRAW, 143 144 "stream_read", // USAGE_STREAM_READ, 145 "stream_copy", // USAGE_STREAM_COPY, 146 147 "static_read", // USAGE_STATIC_READ, 148 "static_copy", // USAGE_STATIC_COPY, 149 150 "dynamic_read", // USAGE_DYNAMIC_READ, 151 "dynamic_copy", // USAGE_DYNAMIC_COPY, 152 }; 153 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(usages) == Array::USAGE_LAST); 154 155 return usages[(int)usage]; 156} 157 158std::string Array::storageToString (Storage storage) 159{ 160 DE_ASSERT(storage < STORAGE_LAST); 161 162 static const char* storages[] = 163 { 164 "user_ptr", // STORAGE_USER = 0, 165 "buffer" // STORAGE_BUFFER, 166 }; 167 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(storages) == Array::STORAGE_LAST); 168 169 return storages[(int)storage]; 170} 171 172std::string Array::primitiveToString (Primitive primitive) 173{ 174 DE_ASSERT(primitive < PRIMITIVE_LAST); 175 176 static const char* primitives[] = 177 { 178 "points", // PRIMITIVE_POINTS , 179 "triangles", // PRIMITIVE_TRIANGLES, 180 "triangle_fan", // PRIMITIVE_TRIANGLE_FAN, 181 "triangle_strip" // PRIMITIVE_TRIANGLE_STRIP, 182 }; 183 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitives) == Array::PRIMITIVE_LAST); 184 185 return primitives[(int)primitive]; 186} 187 188int Array::inputTypeSize (InputType type) 189{ 190 DE_ASSERT(type < INPUTTYPE_LAST); 191 192 static const int size[] = 193 { 194 sizeof(float), // INPUTTYPE_FLOAT = 0, 195 sizeof(deInt32), // INPUTTYPE_FIXED, 196 sizeof(double), // INPUTTYPE_DOUBLE 197 198 sizeof(deInt8), // INPUTTYPE_BYTE, 199 sizeof(deInt16), // INPUTTYPE_SHORT, 200 201 sizeof(deUint8), // INPUTTYPE_UNSIGNED_BYTE, 202 sizeof(deUint16), // INPUTTYPE_UNSIGNED_SHORT, 203 204 sizeof(deInt32), // INPUTTYPE_INT, 205 sizeof(deUint32), // INPUTTYPE_UNSIGNED_INT, 206 sizeof(deFloat16), // INPUTTYPE_HALF, 207 sizeof(deUint32) / 4, // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 208 sizeof(deUint32) / 4 // INPUTTYPE_INT_2_10_10_10, 209 }; 210 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(size) == Array::INPUTTYPE_LAST); 211 212 return size[(int)type]; 213} 214 215static bool inputTypeIsFloatType (Array::InputType type) 216{ 217 if (type == Array::INPUTTYPE_FLOAT) 218 return true; 219 if (type == Array::INPUTTYPE_FIXED) 220 return true; 221 if (type == Array::INPUTTYPE_DOUBLE) 222 return true; 223 if (type == Array::INPUTTYPE_HALF) 224 return true; 225 return false; 226} 227 228static bool outputTypeIsFloatType (Array::OutputType type) 229{ 230 if (type == Array::OUTPUTTYPE_FLOAT 231 || type == Array::OUTPUTTYPE_VEC2 232 || type == Array::OUTPUTTYPE_VEC3 233 || type == Array::OUTPUTTYPE_VEC4) 234 return true; 235 236 return false; 237} 238 239template<class T> 240inline T getRandom (deRandom& rnd, T min, T max); 241 242template<> 243inline GLValue::Float getRandom (deRandom& rnd, GLValue::Float min, GLValue::Float max) 244{ 245 if (max < min) 246 return min; 247 248 return GLValue::Float::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>())); 249} 250 251template<> 252inline GLValue::Short getRandom (deRandom& rnd, GLValue::Short min, GLValue::Short max) 253{ 254 if (max < min) 255 return min; 256 257 return GLValue::Short::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))); 258} 259 260template<> 261inline GLValue::Ushort getRandom (deRandom& rnd, GLValue::Ushort min, GLValue::Ushort max) 262{ 263 if (max < min) 264 return min; 265 266 return GLValue::Ushort::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))); 267} 268 269template<> 270inline GLValue::Byte getRandom (deRandom& rnd, GLValue::Byte min, GLValue::Byte max) 271{ 272 if (max < min) 273 return min; 274 275 return GLValue::Byte::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))); 276} 277 278template<> 279inline GLValue::Ubyte getRandom (deRandom& rnd, GLValue::Ubyte min, GLValue::Ubyte max) 280{ 281 if (max < min) 282 return min; 283 284 return GLValue::Ubyte::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))); 285} 286 287template<> 288inline GLValue::Fixed getRandom (deRandom& rnd, GLValue::Fixed min, GLValue::Fixed max) 289{ 290 if (max < min) 291 return min; 292 293 return GLValue::Fixed::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>())))); 294} 295 296template<> 297inline GLValue::Half getRandom (deRandom& rnd, GLValue::Half min, GLValue::Half max) 298{ 299 if (max < min) 300 return min; 301 302 float fMax = max.to<float>(); 303 float fMin = min.to<float>(); 304 GLValue::Half h = GLValue::Half::create(fMin + deRandom_getFloat(&rnd) * (fMax - fMin)); 305 return h; 306} 307 308template<> 309inline GLValue::Int getRandom (deRandom& rnd, GLValue::Int min, GLValue::Int max) 310{ 311 if (max < min) 312 return min; 313 314 return GLValue::Int::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>())))); 315} 316 317template<> 318inline GLValue::Uint getRandom (deRandom& rnd, GLValue::Uint min, GLValue::Uint max) 319{ 320 if (max < min) 321 return min; 322 323 return GLValue::Uint::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>())))); 324} 325 326template<> 327inline GLValue::Double getRandom (deRandom& rnd, GLValue::Double min, GLValue::Double max) 328{ 329 if (max < min) 330 return min; 331 332 return GLValue::Double::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>())); 333} 334 335// Minimum difference required between coordinates 336template<class T> 337inline T minValue (void); 338 339template<> 340inline GLValue::Float minValue (void) 341{ 342 return GLValue::Float::create(4 * 1.0f); 343} 344 345template<> 346inline GLValue::Short minValue (void) 347{ 348 return GLValue::Short::create(4 * 256); 349} 350 351template<> 352inline GLValue::Ushort minValue (void) 353{ 354 return GLValue::Ushort::create(4 * 256); 355} 356 357template<> 358inline GLValue::Byte minValue (void) 359{ 360 return GLValue::Byte::create(4 * 1); 361} 362 363template<> 364inline GLValue::Ubyte minValue (void) 365{ 366 return GLValue::Ubyte::create(4 * 2); 367} 368 369template<> 370inline GLValue::Fixed minValue (void) 371{ 372 return GLValue::Fixed::create(4 * 512); 373} 374 375template<> 376inline GLValue::Int minValue (void) 377{ 378 return GLValue::Int::create(4 * 16777216); 379} 380 381template<> 382inline GLValue::Uint minValue (void) 383{ 384 return GLValue::Uint::create(4 * 16777216); 385} 386 387template<> 388inline GLValue::Half minValue (void) 389{ 390 return GLValue::Half::create(4 * 1.0f); 391} 392 393template<> 394inline GLValue::Double minValue (void) 395{ 396 return GLValue::Double::create(4 * 1.0f); 397} 398 399template<class T> 400inline T abs (T val); 401 402template<> 403inline GLValue::Fixed abs (GLValue::Fixed val) 404{ 405 return GLValue::Fixed::create(0x7FFFu & val.getValue()); 406} 407 408template<> 409inline GLValue::Ubyte abs (GLValue::Ubyte val) 410{ 411 return val; 412} 413 414template<> 415inline GLValue::Byte abs (GLValue::Byte val) 416{ 417 return GLValue::Byte::create(0x7Fu & val.getValue()); 418} 419 420template<> 421inline GLValue::Ushort abs (GLValue::Ushort val) 422{ 423 return val; 424} 425 426template<> 427inline GLValue::Short abs (GLValue::Short val) 428{ 429 return GLValue::Short::create(0x7FFFu & val.getValue()); 430} 431 432template<> 433inline GLValue::Float abs (GLValue::Float val) 434{ 435 return GLValue::Float::create(std::fabs(val.to<float>())); 436} 437 438template<> 439inline GLValue::Uint abs (GLValue::Uint val) 440{ 441 return val; 442} 443 444template<> 445inline GLValue::Int abs (GLValue::Int val) 446{ 447 return GLValue::Int::create(0x7FFFFFFFu & val.getValue()); 448} 449 450template<> 451inline GLValue::Half abs (GLValue::Half val) 452{ 453 return GLValue::Half::create(std::fabs(val.to<float>())); 454} 455 456template<> 457inline GLValue::Double abs (GLValue::Double val) 458{ 459 return GLValue::Double::create(std::fabs(val.to<float>())); 460} 461 462template<class T> 463inline static void alignmentSafeAssignment (char* dst, T val) 464{ 465 std::memcpy(dst, &val, sizeof(T)); 466} 467 468ContextArray::ContextArray (Storage storage, sglr::Context& context) 469 : m_storage (storage) 470 , m_ctx (context) 471 , m_glBuffer (0) 472 , m_bound (false) 473 , m_attribNdx (0) 474 , m_size (0) 475 , m_data (DE_NULL) 476 , m_componentCount (1) 477 , m_target (Array::TARGET_ARRAY) 478 , m_inputType (Array::INPUTTYPE_FLOAT) 479 , m_outputType (Array::OUTPUTTYPE_VEC4) 480 , m_normalize (false) 481 , m_stride (0) 482 , m_offset (0) 483{ 484 if (m_storage == STORAGE_BUFFER) 485 { 486 m_ctx.genBuffers(1, &m_glBuffer); 487 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glGenBuffers()"); 488 } 489} 490 491ContextArray::~ContextArray (void) 492{ 493 if (m_storage == STORAGE_BUFFER) 494 { 495 m_ctx.deleteBuffers(1, &m_glBuffer); 496 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDeleteBuffers()"); 497 } 498 else if (m_storage == STORAGE_USER) 499 delete[] m_data; 500 else 501 DE_ASSERT(false); 502} 503 504Array* ContextArrayPack::getArray (int i) 505{ 506 return m_arrays.at(i); 507} 508 509void ContextArray::data (Target target, int size, const char* ptr, Usage usage) 510{ 511 m_size = size; 512 m_target = target; 513 514 if (m_storage == STORAGE_BUFFER) 515 { 516 m_ctx.bindBuffer(targetToGL(target), m_glBuffer); 517 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()"); 518 519 m_ctx.bufferData(targetToGL(target), size, ptr, usageToGL(usage)); 520 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferData()"); 521 } 522 else if (m_storage == STORAGE_USER) 523 { 524 if (m_data) 525 delete[] m_data; 526 527 m_data = new char[size]; 528 std::memcpy(m_data, ptr, size); 529 } 530 else 531 DE_ASSERT(false); 532} 533 534void ContextArray::subdata (Target target, int offset, int size, const char* ptr) 535{ 536 m_target = target; 537 538 if (m_storage == STORAGE_BUFFER) 539 { 540 m_ctx.bindBuffer(targetToGL(target), m_glBuffer); 541 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()"); 542 543 m_ctx.bufferSubData(targetToGL(target), offset, size, ptr); 544 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferSubData()"); 545 } 546 else if (m_storage == STORAGE_USER) 547 std::memcpy(m_data + offset, ptr, size); 548 else 549 DE_ASSERT(false); 550} 551 552void ContextArray::bind (int attribNdx, int offset, int size, InputType inputType, OutputType outType, bool normalized, int stride) 553{ 554 m_attribNdx = attribNdx; 555 m_bound = true; 556 m_componentCount = size; 557 m_inputType = inputType; 558 m_outputType = outType; 559 m_normalize = normalized; 560 m_stride = stride; 561 m_offset = offset; 562} 563 564void ContextArray::bindIndexArray (Array::Target target) 565{ 566 if (m_storage == STORAGE_USER) 567 { 568 } 569 else if (m_storage == STORAGE_BUFFER) 570 { 571 m_ctx.bindBuffer(targetToGL(target), m_glBuffer); 572 } 573} 574 575void ContextArray::glBind (deUint32 loc) 576{ 577 if (m_storage == STORAGE_BUFFER) 578 { 579 m_ctx.bindBuffer(targetToGL(m_target), m_glBuffer); 580 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()"); 581 582 if (!inputTypeIsFloatType(m_inputType)) 583 { 584 // Input is not float type 585 586 if (outputTypeIsFloatType(m_outputType)) 587 { 588 // Output type is float type 589 m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset)); 590 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()"); 591 } 592 else 593 { 594 // Output type is int type 595 m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, (GLvoid*)((GLintptr)m_offset)); 596 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()"); 597 } 598 } 599 else 600 { 601 // Input type is float type 602 603 // Output type must be float type 604 DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4); 605 606 m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset)); 607 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()"); 608 } 609 610 m_ctx.bindBuffer(targetToGL(m_target), 0); 611 } 612 else if (m_storage == STORAGE_USER) 613 { 614 m_ctx.bindBuffer(targetToGL(m_target), 0); 615 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()"); 616 617 if (!inputTypeIsFloatType(m_inputType)) 618 { 619 // Input is not float type 620 621 if (outputTypeIsFloatType(m_outputType)) 622 { 623 // Output type is float type 624 m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset); 625 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()"); 626 } 627 else 628 { 629 // Output type is int type 630 m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, m_data + m_offset); 631 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()"); 632 } 633 } 634 else 635 { 636 // Input type is float type 637 638 // Output type must be float type 639 DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4); 640 641 m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset); 642 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()"); 643 } 644 } 645 else 646 DE_ASSERT(false); 647} 648 649GLenum ContextArray::targetToGL (Array::Target target) 650{ 651 DE_ASSERT(target < TARGET_LAST); 652 653 static const GLenum targets[] = 654 { 655 GL_ELEMENT_ARRAY_BUFFER, // TARGET_ELEMENT_ARRAY = 0, 656 GL_ARRAY_BUFFER // TARGET_ARRAY, 657 }; 658 659 return targets[(int)target]; 660} 661 662GLenum ContextArray::usageToGL (Array::Usage usage) 663{ 664 DE_ASSERT(usage < USAGE_LAST); 665 666 static const GLenum usages[] = 667 { 668 GL_DYNAMIC_DRAW, // USAGE_DYNAMIC_DRAW = 0, 669 GL_STATIC_DRAW, // USAGE_STATIC_DRAW, 670 GL_STREAM_DRAW, // USAGE_STREAM_DRAW, 671 672 GL_STREAM_READ, // USAGE_STREAM_READ, 673 GL_STREAM_COPY, // USAGE_STREAM_COPY, 674 675 GL_STATIC_READ, // USAGE_STATIC_READ, 676 GL_STATIC_COPY, // USAGE_STATIC_COPY, 677 678 GL_DYNAMIC_READ, // USAGE_DYNAMIC_READ, 679 GL_DYNAMIC_COPY // USAGE_DYNAMIC_COPY, 680 }; 681 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(usages) == Array::USAGE_LAST); 682 683 return usages[(int)usage]; 684} 685 686GLenum ContextArray::inputTypeToGL (Array::InputType type) 687{ 688 DE_ASSERT(type < INPUTTYPE_LAST); 689 690 static const GLenum types[] = 691 { 692 GL_FLOAT, // INPUTTYPE_FLOAT = 0, 693 GL_FIXED, // INPUTTYPE_FIXED, 694 GL_DOUBLE, // INPUTTYPE_DOUBLE 695 GL_BYTE, // INPUTTYPE_BYTE, 696 GL_SHORT, // INPUTTYPE_SHORT, 697 GL_UNSIGNED_BYTE, // INPUTTYPE_UNSIGNED_BYTE, 698 GL_UNSIGNED_SHORT, // INPUTTYPE_UNSIGNED_SHORT, 699 700 GL_INT, // INPUTTYPE_INT, 701 GL_UNSIGNED_INT, // INPUTTYPE_UNSIGNED_INT, 702 GL_HALF_FLOAT, // INPUTTYPE_HALF, 703 GL_UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 704 GL_INT_2_10_10_10_REV // INPUTTYPE_INT_2_10_10_10, 705 }; 706 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::INPUTTYPE_LAST); 707 708 return types[(int)type]; 709} 710 711std::string ContextArray::outputTypeToGLType (Array::OutputType type) 712{ 713 DE_ASSERT(type < OUTPUTTYPE_LAST); 714 715 static const char* types[] = 716 { 717 "float", // OUTPUTTYPE_FLOAT = 0, 718 "vec2", // OUTPUTTYPE_VEC2, 719 "vec3", // OUTPUTTYPE_VEC3, 720 "vec4", // OUTPUTTYPE_VEC4, 721 722 "int", // OUTPUTTYPE_INT, 723 "uint", // OUTPUTTYPE_UINT, 724 725 "ivec2", // OUTPUTTYPE_IVEC2, 726 "ivec3", // OUTPUTTYPE_IVEC3, 727 "ivec4", // OUTPUTTYPE_IVEC4, 728 729 "uvec2", // OUTPUTTYPE_UVEC2, 730 "uvec3", // OUTPUTTYPE_UVEC3, 731 "uvec4", // OUTPUTTYPE_UVEC4, 732 }; 733 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::OUTPUTTYPE_LAST); 734 735 return types[type]; 736} 737 738GLenum ContextArray::primitiveToGL (Array::Primitive primitive) 739{ 740 GLenum primitives[] = 741 { 742 GL_POINTS, // PRIMITIVE_POINTS = 0, 743 GL_TRIANGLES, // PRIMITIVE_TRIANGLES, 744 GL_TRIANGLE_FAN, // PRIMITIVE_TRIANGLE_FAN, 745 GL_TRIANGLE_STRIP // PRIMITIVE_TRIANGLE_STRIP, 746 }; 747 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitives) == Array::PRIMITIVE_LAST); 748 749 return primitives[(int)primitive]; 750} 751 752ContextArrayPack::ContextArrayPack (glu::RenderContext& renderCtx, sglr::Context& drawContext) 753 : m_renderCtx (renderCtx) 754 , m_ctx (drawContext) 755 , m_program (DE_NULL) 756 , m_screen (std::min(512, renderCtx.getRenderTarget().getWidth()), std::min(512, renderCtx.getRenderTarget().getHeight())) 757{ 758} 759 760ContextArrayPack::~ContextArrayPack (void) 761{ 762 for (std::vector<ContextArray*>::iterator itr = m_arrays.begin(); itr != m_arrays.end(); itr++) 763 delete *itr; 764 765 delete m_program; 766} 767 768int ContextArrayPack::getArrayCount (void) 769{ 770 return (int)m_arrays.size(); 771} 772 773void ContextArrayPack::newArray (Array::Storage storage) 774{ 775 m_arrays.push_back(new ContextArray(storage, m_ctx)); 776} 777 778class ContextShaderProgram : public sglr::ShaderProgram 779{ 780public: 781 ContextShaderProgram (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays); 782 783 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 784 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 785 786private: 787 static std::string genVertexSource (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays); 788 static std::string genFragmentSource (const glu::RenderContext& ctx); 789 static rr::GenericVecType mapOutputType (const Array::OutputType& type); 790 static int getComponentCount (const Array::OutputType& type); 791 792 static sglr::pdec::ShaderProgramDeclaration createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays); 793 794 std::vector<int> m_componentCount; 795 std::vector<rr::GenericVecType> m_attrType; 796}; 797 798ContextShaderProgram::ContextShaderProgram (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays) 799 : sglr::ShaderProgram (createProgramDeclaration(ctx, arrays)) 800 , m_componentCount (arrays.size()) 801 , m_attrType (arrays.size()) 802{ 803 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++) 804 { 805 m_componentCount[arrayNdx] = getComponentCount(arrays[arrayNdx]->getOutputType()); 806 m_attrType[arrayNdx] = mapOutputType(arrays[arrayNdx]->getOutputType()); 807 } 808} 809 810template <typename T> 811void calcShaderColorCoord (tcu::Vec2& coord, tcu::Vec3& color, const tcu::Vector<T, 4>& attribValue, bool isCoordinate, int numComponents) 812{ 813 if (isCoordinate) 814 switch (numComponents) 815 { 816 case 1: coord = tcu::Vec2((float)attribValue.x(), (float)attribValue.x()); break; 817 case 2: coord = tcu::Vec2((float)attribValue.x(), (float)attribValue.y()); break; 818 case 3: coord = tcu::Vec2((float)attribValue.x() + attribValue.z(), (float)attribValue.y()); break; 819 case 4: coord = tcu::Vec2((float)attribValue.x() + attribValue.z(), (float)attribValue.y() + attribValue.w()); break; 820 821 default: 822 DE_ASSERT(false); 823 } 824 else 825 { 826 switch (numComponents) 827 { 828 case 1: 829 color = color * (float)attribValue.x(); 830 break; 831 832 case 2: 833 color.x() = color.x() * attribValue.x(); 834 color.y() = color.y() * attribValue.y(); 835 break; 836 837 case 3: 838 color.x() = color.x() * attribValue.x(); 839 color.y() = color.y() * attribValue.y(); 840 color.z() = color.z() * attribValue.z(); 841 break; 842 843 case 4: 844 color.x() = color.x() * attribValue.x() * attribValue.w(); 845 color.y() = color.y() * attribValue.y() * attribValue.w(); 846 color.z() = color.z() * attribValue.z() * attribValue.w(); 847 break; 848 849 default: 850 DE_ASSERT(false); 851 } 852 } 853} 854 855void ContextShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 856{ 857 const float u_coordScale = getUniformByName("u_coordScale").value.f; 858 const float u_colorScale = getUniformByName("u_colorScale").value.f; 859 860 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 861 { 862 const size_t varyingLocColor = 0; 863 864 rr::VertexPacket& packet = *packets[packetNdx]; 865 866 // Calc output color 867 tcu::Vec2 coord = tcu::Vec2(1.0, 1.0); 868 tcu::Vec3 color = tcu::Vec3(1.0, 1.0, 1.0); 869 870 for (int attribNdx = 0; attribNdx < (int)m_attrType.size(); attribNdx++) 871 { 872 const int numComponents = m_componentCount[attribNdx]; 873 874 switch (m_attrType[attribNdx]) 875 { 876 case rr::GENERICVECTYPE_FLOAT: calcShaderColorCoord(coord, color, rr::readVertexAttribFloat(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents); break; 877 case rr::GENERICVECTYPE_INT32: calcShaderColorCoord(coord, color, rr::readVertexAttribInt (inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents); break; 878 case rr::GENERICVECTYPE_UINT32: calcShaderColorCoord(coord, color, rr::readVertexAttribUint (inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents); break; 879 default: 880 DE_ASSERT(false); 881 } 882 } 883 884 // Transform position 885 { 886 packet.position = tcu::Vec4(u_coordScale * coord.x(), u_coordScale * coord.y(), 1.0f, 1.0f); 887 } 888 889 // Pass color to FS 890 { 891 packet.outputs[varyingLocColor] = tcu::Vec4(u_colorScale * color.x(), u_colorScale * color.y(), u_colorScale * color.z(), 1.0f); 892 } 893 } 894} 895 896void ContextShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 897{ 898 const size_t varyingLocColor = 0; 899 900 // Triangles are flashaded 901 tcu::Vec4 color = rr::readTriangleVarying<float>(packets[0], context, varyingLocColor, 0); 902 903 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 904 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 905 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 906} 907 908std::string ContextShaderProgram::genVertexSource (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays) 909{ 910 std::stringstream vertexShaderTmpl; 911 std::map<std::string, std::string> params; 912 913 if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES)) 914 { 915 params["VTX_IN"] = "in"; 916 params["VTX_OUT"] = "out"; 917 params["FRAG_IN"] = "in"; 918 params["FRAG_COLOR"] = "dEQP_FragColor"; 919 params["VTX_HDR"] = "#version 300 es\n"; 920 params["FRAG_HDR"] = "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 921 } 922 else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES)) 923 { 924 params["VTX_IN"] = "attribute"; 925 params["VTX_OUT"] = "varying"; 926 params["FRAG_IN"] = "varying"; 927 params["FRAG_COLOR"] = "gl_FragColor"; 928 params["VTX_HDR"] = ""; 929 params["FRAG_HDR"] = ""; 930 } 931 else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330)) 932 { 933 params["VTX_IN"] = "in"; 934 params["VTX_OUT"] = "out"; 935 params["FRAG_IN"] = "in"; 936 params["FRAG_COLOR"] = "dEQP_FragColor"; 937 params["VTX_HDR"] = "#version 330\n"; 938 params["FRAG_HDR"] = "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 939 } 940 else 941 DE_ASSERT(DE_FALSE); 942 943 vertexShaderTmpl << "${VTX_HDR}"; 944 945 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++) 946 { 947 vertexShaderTmpl 948 << "${VTX_IN} highp " << ContextArray::outputTypeToGLType(arrays[arrayNdx]->getOutputType()) << " a_" << arrays[arrayNdx]->getAttribNdx() << ";\n"; 949 } 950 951 vertexShaderTmpl << 952 "uniform highp float u_coordScale;\n" 953 "uniform highp float u_colorScale;\n" 954 "${VTX_OUT} mediump vec4 v_color;\n" 955 "void main(void)\n" 956 "{\n" 957 "\tgl_PointSize = 1.0;\n" 958 "\thighp vec2 coord = vec2(1.0, 1.0);\n" 959 "\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n"; 960 961 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++) 962 { 963 if (arrays[arrayNdx]->getAttribNdx() == 0) 964 { 965 switch (arrays[arrayNdx]->getOutputType()) 966 { 967 case (Array::OUTPUTTYPE_FLOAT): 968 vertexShaderTmpl << 969 "\tcoord = vec2(a_0);\n"; 970 break; 971 972 case (Array::OUTPUTTYPE_VEC2): 973 vertexShaderTmpl << 974 "\tcoord = a_0.xy;\n"; 975 break; 976 977 case (Array::OUTPUTTYPE_VEC3): 978 vertexShaderTmpl << 979 "\tcoord = a_0.xy;\n" 980 "\tcoord.x = coord.x + a_0.z;\n"; 981 break; 982 983 case (Array::OUTPUTTYPE_VEC4): 984 vertexShaderTmpl << 985 "\tcoord = a_0.xy;\n" 986 "\tcoord += a_0.zw;\n"; 987 break; 988 989 case (Array::OUTPUTTYPE_IVEC2): 990 case (Array::OUTPUTTYPE_UVEC2): 991 vertexShaderTmpl << 992 "\tcoord = vec2(a_0.xy);\n"; 993 break; 994 995 case (Array::OUTPUTTYPE_IVEC3): 996 case (Array::OUTPUTTYPE_UVEC3): 997 vertexShaderTmpl << 998 "\tcoord = vec2(a_0.xy);\n" 999 "\tcoord.x = coord.x + float(a_0.z);\n"; 1000 break; 1001 1002 case (Array::OUTPUTTYPE_IVEC4): 1003 case (Array::OUTPUTTYPE_UVEC4): 1004 vertexShaderTmpl << 1005 "\tcoord = vec2(a_0.xy);\n" 1006 "\tcoord += vec2(a_0.zw);\n"; 1007 break; 1008 1009 default: 1010 DE_ASSERT(false); 1011 break; 1012 } 1013 continue; 1014 } 1015 1016 switch (arrays[arrayNdx]->getOutputType()) 1017 { 1018 case (Array::OUTPUTTYPE_FLOAT): 1019 vertexShaderTmpl << 1020 "\tcolor = color * a_" << arrays[arrayNdx]->getAttribNdx() << ";\n"; 1021 break; 1022 1023 case (Array::OUTPUTTYPE_VEC2): 1024 vertexShaderTmpl << 1025 "\tcolor.rg = color.rg * a_" << arrays[arrayNdx]->getAttribNdx() << ".xy;\n"; 1026 break; 1027 1028 case (Array::OUTPUTTYPE_VEC3): 1029 vertexShaderTmpl << 1030 "\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz;\n"; 1031 break; 1032 1033 case (Array::OUTPUTTYPE_VEC4): 1034 vertexShaderTmpl << 1035 "\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz * a_" << arrays[arrayNdx]->getAttribNdx() << ".w;\n"; 1036 break; 1037 1038 default: 1039 DE_ASSERT(false); 1040 break; 1041 } 1042 } 1043 1044 vertexShaderTmpl << 1045 "\tv_color = vec4(u_colorScale * color, 1.0);\n" 1046 "\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n" 1047 "}\n"; 1048 1049 return tcu::StringTemplate(vertexShaderTmpl.str().c_str()).specialize(params); 1050} 1051 1052std::string ContextShaderProgram::genFragmentSource (const glu::RenderContext& ctx) 1053{ 1054 std::map<std::string, std::string> params; 1055 1056 if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES)) 1057 { 1058 params["VTX_IN"] = "in"; 1059 params["VTX_OUT"] = "out"; 1060 params["FRAG_IN"] = "in"; 1061 params["FRAG_COLOR"] = "dEQP_FragColor"; 1062 params["VTX_HDR"] = "#version 300 es\n"; 1063 params["FRAG_HDR"] = "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 1064 } 1065 else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES)) 1066 { 1067 params["VTX_IN"] = "attribute"; 1068 params["VTX_OUT"] = "varying"; 1069 params["FRAG_IN"] = "varying"; 1070 params["FRAG_COLOR"] = "gl_FragColor"; 1071 params["VTX_HDR"] = ""; 1072 params["FRAG_HDR"] = ""; 1073 } 1074 else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330)) 1075 { 1076 params["VTX_IN"] = "in"; 1077 params["VTX_OUT"] = "out"; 1078 params["FRAG_IN"] = "in"; 1079 params["FRAG_COLOR"] = "dEQP_FragColor"; 1080 params["VTX_HDR"] = "#version 330\n"; 1081 params["FRAG_HDR"] = "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 1082 } 1083 else 1084 DE_ASSERT(DE_FALSE); 1085 1086 static const char* fragmentShaderTmpl = 1087 "${FRAG_HDR}" 1088 "${FRAG_IN} mediump vec4 v_color;\n" 1089 "void main(void)\n" 1090 "{\n" 1091 "\t${FRAG_COLOR} = v_color;\n" 1092 "}\n"; 1093 1094 return tcu::StringTemplate(fragmentShaderTmpl).specialize(params); 1095} 1096 1097rr::GenericVecType ContextShaderProgram::mapOutputType (const Array::OutputType& type) 1098{ 1099 switch (type) 1100 { 1101 case (Array::OUTPUTTYPE_FLOAT): 1102 case (Array::OUTPUTTYPE_VEC2): 1103 case (Array::OUTPUTTYPE_VEC3): 1104 case (Array::OUTPUTTYPE_VEC4): 1105 return rr::GENERICVECTYPE_FLOAT; 1106 1107 case (Array::OUTPUTTYPE_INT): 1108 case (Array::OUTPUTTYPE_IVEC2): 1109 case (Array::OUTPUTTYPE_IVEC3): 1110 case (Array::OUTPUTTYPE_IVEC4): 1111 return rr::GENERICVECTYPE_INT32; 1112 1113 case (Array::OUTPUTTYPE_UINT): 1114 case (Array::OUTPUTTYPE_UVEC2): 1115 case (Array::OUTPUTTYPE_UVEC3): 1116 case (Array::OUTPUTTYPE_UVEC4): 1117 return rr::GENERICVECTYPE_UINT32; 1118 1119 default: 1120 DE_ASSERT(false); 1121 return rr::GENERICVECTYPE_LAST; 1122 } 1123} 1124 1125int ContextShaderProgram::getComponentCount (const Array::OutputType& type) 1126{ 1127 switch (type) 1128 { 1129 case (Array::OUTPUTTYPE_FLOAT): 1130 case (Array::OUTPUTTYPE_INT): 1131 case (Array::OUTPUTTYPE_UINT): 1132 return 1; 1133 1134 case (Array::OUTPUTTYPE_VEC2): 1135 case (Array::OUTPUTTYPE_IVEC2): 1136 case (Array::OUTPUTTYPE_UVEC2): 1137 return 2; 1138 1139 case (Array::OUTPUTTYPE_VEC3): 1140 case (Array::OUTPUTTYPE_IVEC3): 1141 case (Array::OUTPUTTYPE_UVEC3): 1142 return 3; 1143 1144 case (Array::OUTPUTTYPE_VEC4): 1145 case (Array::OUTPUTTYPE_IVEC4): 1146 case (Array::OUTPUTTYPE_UVEC4): 1147 return 4; 1148 1149 default: 1150 DE_ASSERT(false); 1151 return 0; 1152 } 1153} 1154 1155sglr::pdec::ShaderProgramDeclaration ContextShaderProgram::createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays) 1156{ 1157 sglr::pdec::ShaderProgramDeclaration decl; 1158 1159 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++) 1160 decl << sglr::pdec::VertexAttribute(std::string("a_") + de::toString(arrayNdx), mapOutputType(arrays[arrayNdx]->getOutputType())); 1161 1162 decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT); 1163 decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT); 1164 1165 decl << sglr::pdec::VertexSource(genVertexSource(ctx, arrays)); 1166 decl << sglr::pdec::FragmentSource(genFragmentSource(ctx)); 1167 1168 decl << sglr::pdec::Uniform("u_coordScale", glu::TYPE_FLOAT); 1169 decl << sglr::pdec::Uniform("u_colorScale", glu::TYPE_FLOAT); 1170 1171 return decl; 1172} 1173 1174void ContextArrayPack::updateProgram (void) 1175{ 1176 delete m_program; 1177 m_program = new ContextShaderProgram(m_renderCtx, m_arrays); 1178} 1179 1180void ContextArrayPack::render (Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale) 1181{ 1182 deUint32 program = 0; 1183 deUint32 vaoId = 0; 1184 1185 updateProgram(); 1186 1187 m_ctx.viewport(0, 0, m_screen.getWidth(), m_screen.getHeight()); 1188 m_ctx.clearColor(0.0, 0.0, 0.0, 1.0); 1189 m_ctx.clear(GL_COLOR_BUFFER_BIT); 1190 1191 program = m_ctx.createProgram(m_program); 1192 1193 m_ctx.useProgram(program); 1194 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glUseProgram()"); 1195 1196 m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_coordScale"), coordScale); 1197 m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_colorScale"), colorScale); 1198 1199 if (useVao) 1200 { 1201 m_ctx.genVertexArrays(1, &vaoId); 1202 m_ctx.bindVertexArray(vaoId); 1203 } 1204 1205 for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++) 1206 { 1207 if (m_arrays[arrayNdx]->isBound()) 1208 { 1209 std::stringstream attribName; 1210 attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx(); 1211 1212 deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str()); 1213 m_ctx.enableVertexAttribArray(loc); 1214 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glEnableVertexAttribArray()"); 1215 1216 m_arrays[arrayNdx]->glBind(loc); 1217 } 1218 } 1219 1220 DE_ASSERT((firstVertex % 6) == 0); 1221 m_ctx.drawArrays(ContextArray::primitiveToGL(primitive), firstVertex, vertexCount - firstVertex); 1222 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArrays()"); 1223 1224 for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++) 1225 { 1226 if (m_arrays[arrayNdx]->isBound()) 1227 { 1228 std::stringstream attribName; 1229 attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx(); 1230 1231 deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str()); 1232 1233 m_ctx.disableVertexAttribArray(loc); 1234 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDisableVertexAttribArray()"); 1235 } 1236 } 1237 1238 if (useVao) 1239 m_ctx.deleteVertexArrays(1, &vaoId); 1240 1241 m_ctx.deleteProgram(program); 1242 m_ctx.useProgram(0); 1243 m_ctx.readPixels(m_screen, 0, 0, m_screen.getWidth(), m_screen.getHeight()); 1244} 1245 1246// GLValue 1247 1248GLValue GLValue::getMaxValue (Array::InputType type) 1249{ 1250 GLValue rangesHi[(int)Array::INPUTTYPE_LAST]; 1251 1252 rangesHi[(int)Array::INPUTTYPE_FLOAT] = GLValue(Float::create(127.0f)); 1253 rangesHi[(int)Array::INPUTTYPE_DOUBLE] = GLValue(Double::create(127.0f)); 1254 rangesHi[(int)Array::INPUTTYPE_BYTE] = GLValue(Byte::create(127)); 1255 rangesHi[(int)Array::INPUTTYPE_UNSIGNED_BYTE] = GLValue(Ubyte::create(255)); 1256 rangesHi[(int)Array::INPUTTYPE_UNSIGNED_SHORT] = GLValue(Ushort::create(65530)); 1257 rangesHi[(int)Array::INPUTTYPE_SHORT] = GLValue(Short::create(32760)); 1258 rangesHi[(int)Array::INPUTTYPE_FIXED] = GLValue(Fixed::create(32760)); 1259 rangesHi[(int)Array::INPUTTYPE_INT] = GLValue(Int::create(2147483647)); 1260 rangesHi[(int)Array::INPUTTYPE_UNSIGNED_INT] = GLValue(Uint::create(4294967295u)); 1261 rangesHi[(int)Array::INPUTTYPE_HALF] = GLValue(Half::create(256.0f)); 1262 1263 return rangesHi[(int)type]; 1264} 1265 1266GLValue GLValue::getMinValue (Array::InputType type) 1267{ 1268 GLValue rangesLo[(int)Array::INPUTTYPE_LAST]; 1269 1270 rangesLo[(int)Array::INPUTTYPE_FLOAT] = GLValue(Float::create(-127.0f)); 1271 rangesLo[(int)Array::INPUTTYPE_DOUBLE] = GLValue(Double::create(-127.0f)); 1272 rangesLo[(int)Array::INPUTTYPE_BYTE] = GLValue(Byte::create(-127)); 1273 rangesLo[(int)Array::INPUTTYPE_UNSIGNED_BYTE] = GLValue(Ubyte::create(0)); 1274 rangesLo[(int)Array::INPUTTYPE_UNSIGNED_SHORT] = GLValue(Ushort::create(0)); 1275 rangesLo[(int)Array::INPUTTYPE_SHORT] = GLValue(Short::create(-32760)); 1276 rangesLo[(int)Array::INPUTTYPE_FIXED] = GLValue(Fixed::create(-32760)); 1277 rangesLo[(int)Array::INPUTTYPE_INT] = GLValue(Int::create(-2147483647)); 1278 rangesLo[(int)Array::INPUTTYPE_UNSIGNED_INT] = GLValue(Uint::create(0)); 1279 rangesLo[(int)Array::INPUTTYPE_HALF] = GLValue(Half::create(-256.0f)); 1280 1281 return rangesLo[(int)type]; 1282} 1283 1284float GLValue::toFloat (void) const 1285{ 1286 switch (type) 1287 { 1288 case Array::INPUTTYPE_FLOAT: 1289 return fl.getValue(); 1290 break; 1291 1292 case Array::INPUTTYPE_BYTE: 1293 return b.getValue(); 1294 break; 1295 1296 case Array::INPUTTYPE_UNSIGNED_BYTE: 1297 return ub.getValue(); 1298 break; 1299 1300 case Array::INPUTTYPE_SHORT: 1301 return s.getValue(); 1302 break; 1303 1304 case Array::INPUTTYPE_UNSIGNED_SHORT: 1305 return us.getValue(); 1306 break; 1307 1308 case Array::INPUTTYPE_FIXED: 1309 { 1310 int maxValue = 65536; 1311 return (float)(double(2 * fi.getValue() + 1) / (maxValue - 1)); 1312 1313 break; 1314 } 1315 1316 case Array::INPUTTYPE_UNSIGNED_INT: 1317 return (float)ui.getValue(); 1318 break; 1319 1320 case Array::INPUTTYPE_INT: 1321 return (float)i.getValue(); 1322 break; 1323 1324 case Array::INPUTTYPE_HALF: 1325 return h.to<float>(); 1326 break; 1327 1328 case Array::INPUTTYPE_DOUBLE: 1329 return (float)d.getValue(); 1330 break; 1331 1332 default: 1333 DE_ASSERT(false); 1334 return 0.0f; 1335 break; 1336 }; 1337} 1338 1339class RandomArrayGenerator 1340{ 1341public: 1342 static char* generateArray (int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type); 1343 static char* generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max); 1344 static char* generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max); 1345 1346private: 1347 template<typename T> 1348 static char* createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max); 1349 template<typename T> 1350 static char* createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max); 1351 static char* createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive); 1352 static void setData (char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max); 1353}; 1354 1355void RandomArrayGenerator::setData (char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max) 1356{ 1357 switch (type) 1358 { 1359 case Array::INPUTTYPE_FLOAT: 1360 { 1361 alignmentSafeAssignment<float>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl)); 1362 break; 1363 } 1364 1365 case Array::INPUTTYPE_DOUBLE: 1366 { 1367 alignmentSafeAssignment<double>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl)); 1368 break; 1369 } 1370 1371 case Array::INPUTTYPE_SHORT: 1372 { 1373 alignmentSafeAssignment<deInt16>(data, getRandom<GLValue::Short>(rnd, min.s, max.s)); 1374 break; 1375 } 1376 1377 case Array::INPUTTYPE_UNSIGNED_SHORT: 1378 { 1379 alignmentSafeAssignment<deUint16>(data, getRandom<GLValue::Ushort>(rnd, min.us, max.us)); 1380 break; 1381 } 1382 1383 case Array::INPUTTYPE_BYTE: 1384 { 1385 alignmentSafeAssignment<deInt8>(data, getRandom<GLValue::Byte>(rnd, min.b, max.b)); 1386 break; 1387 } 1388 1389 case Array::INPUTTYPE_UNSIGNED_BYTE: 1390 { 1391 alignmentSafeAssignment<deUint8>(data, getRandom<GLValue::Ubyte>(rnd, min.ub, max.ub)); 1392 break; 1393 } 1394 1395 case Array::INPUTTYPE_FIXED: 1396 { 1397 alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Fixed>(rnd, min.fi, max.fi)); 1398 break; 1399 } 1400 1401 case Array::INPUTTYPE_INT: 1402 { 1403 alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Int>(rnd, min.i, max.i)); 1404 break; 1405 } 1406 1407 case Array::INPUTTYPE_UNSIGNED_INT: 1408 { 1409 alignmentSafeAssignment<deUint32>(data, getRandom<GLValue::Uint>(rnd, min.ui, max.ui)); 1410 break; 1411 } 1412 1413 case Array::INPUTTYPE_HALF: 1414 { 1415 alignmentSafeAssignment<deFloat16>(data, getRandom<GLValue::Half>(rnd, min.h, max.h).getValue()); 1416 break; 1417 } 1418 1419 default: 1420 DE_ASSERT(false); 1421 break; 1422 } 1423} 1424 1425char* RandomArrayGenerator::generateArray (int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type) 1426{ 1427 char* data = NULL; 1428 1429 deRandom rnd; 1430 deRandom_init(&rnd, seed); 1431 1432 if (stride == 0) 1433 stride = componentCount * Array::inputTypeSize(type); 1434 1435 data = new char[stride * count]; 1436 1437 for (int vertexNdx = 0; vertexNdx < count; vertexNdx++) 1438 { 1439 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++) 1440 { 1441 setData(&(data[vertexNdx * stride + Array::inputTypeSize(type) * componentNdx]), type, rnd, min, max); 1442 } 1443 } 1444 1445 return data; 1446} 1447 1448char* RandomArrayGenerator::generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max) 1449{ 1450 char* data = DE_NULL; 1451 1452 switch (type) 1453 { 1454 case Array::INPUTTYPE_FLOAT: 1455 data = createQuads<GLValue::Float>(seed, count, componentCount, offset, stride, primitive, min.fl, max.fl); 1456 break; 1457 1458 case Array::INPUTTYPE_FIXED: 1459 data = createQuads<GLValue::Fixed>(seed, count, componentCount, offset, stride, primitive, min.fi, max.fi); 1460 break; 1461 1462 case Array::INPUTTYPE_DOUBLE: 1463 data = createQuads<GLValue::Double>(seed, count, componentCount, offset, stride, primitive, min.d, max.d); 1464 break; 1465 1466 case Array::INPUTTYPE_BYTE: 1467 data = createQuads<GLValue::Byte>(seed, count, componentCount, offset, stride, primitive, min.b, max.b); 1468 break; 1469 1470 case Array::INPUTTYPE_SHORT: 1471 data = createQuads<GLValue::Short>(seed, count, componentCount, offset, stride, primitive, min.s, max.s); 1472 break; 1473 1474 case Array::INPUTTYPE_UNSIGNED_BYTE: 1475 data = createQuads<GLValue::Ubyte>(seed, count, componentCount, offset, stride, primitive, min.ub, max.ub); 1476 break; 1477 1478 case Array::INPUTTYPE_UNSIGNED_SHORT: 1479 data = createQuads<GLValue::Ushort>(seed, count, componentCount, offset, stride, primitive, min.us, max.us); 1480 break; 1481 1482 case Array::INPUTTYPE_UNSIGNED_INT: 1483 data = createQuads<GLValue::Uint>(seed, count, componentCount, offset, stride, primitive, min.ui, max.ui); 1484 break; 1485 1486 case Array::INPUTTYPE_INT: 1487 data = createQuads<GLValue::Int>(seed, count, componentCount, offset, stride, primitive, min.i, max.i); 1488 break; 1489 1490 case Array::INPUTTYPE_HALF: 1491 data = createQuads<GLValue::Half>(seed, count, componentCount, offset, stride, primitive, min.h, max.h); 1492 break; 1493 1494 case Array::INPUTTYPE_INT_2_10_10_10: 1495 case Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10: 1496 data = createQuadsPacked(seed, count, componentCount, offset, stride, primitive); 1497 break; 1498 1499 default: 1500 DE_ASSERT(false); 1501 break; 1502 } 1503 1504 return data; 1505} 1506 1507char* RandomArrayGenerator::createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive) 1508{ 1509 DE_ASSERT(componentCount == 4); 1510 DE_UNREF(componentCount); 1511 int quadStride = 0; 1512 1513 if (stride == 0) 1514 stride = sizeof(deUint32); 1515 1516 switch (primitive) 1517 { 1518 case Array::PRIMITIVE_TRIANGLES: 1519 quadStride = stride * 6; 1520 break; 1521 1522 default: 1523 DE_ASSERT(false); 1524 break; 1525 } 1526 1527 char* const _data = new char[offset + quadStride * (count - 1) + stride * 5 + componentCount * Array::inputTypeSize(Array::INPUTTYPE_INT_2_10_10_10)]; // last element must be fully in the array 1528 char* const resultData = _data + offset; 1529 1530 const deUint32 max = 1024; 1531 const deUint32 min = 10; 1532 const deUint32 max2 = 4; 1533 1534 deRandom rnd; 1535 deRandom_init(&rnd, seed); 1536 1537 switch (primitive) 1538 { 1539 case Array::PRIMITIVE_TRIANGLES: 1540 { 1541 for (int quadNdx = 0; quadNdx < count; quadNdx++) 1542 { 1543 deUint32 x1 = min + deRandom_getUint32(&rnd) % (max - min); 1544 deUint32 x2 = min + deRandom_getUint32(&rnd) % (max - x1); 1545 1546 deUint32 y1 = min + deRandom_getUint32(&rnd) % (max - min); 1547 deUint32 y2 = min + deRandom_getUint32(&rnd) % (max - y1); 1548 1549 deUint32 z = min + deRandom_getUint32(&rnd) % (max - min); 1550 deUint32 w = deRandom_getUint32(&rnd) % max2; 1551 1552 deUint32 val1 = (w << 30) | (z << 20) | (y1 << 10) | x1; 1553 deUint32 val2 = (w << 30) | (z << 20) | (y1 << 10) | x2; 1554 deUint32 val3 = (w << 30) | (z << 20) | (y2 << 10) | x1; 1555 1556 deUint32 val4 = (w << 30) | (z << 20) | (y2 << 10) | x1; 1557 deUint32 val5 = (w << 30) | (z << 20) | (y1 << 10) | x2; 1558 deUint32 val6 = (w << 30) | (z << 20) | (y2 << 10) | x2; 1559 1560 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 0]), val1); 1561 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 1]), val2); 1562 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 2]), val3); 1563 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 3]), val4); 1564 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 4]), val5); 1565 alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 5]), val6); 1566 } 1567 1568 break; 1569 } 1570 1571 default: 1572 DE_ASSERT(false); 1573 break; 1574 } 1575 1576 return _data; 1577} 1578 1579template<typename T> 1580char* RandomArrayGenerator::createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max) 1581{ 1582 int componentStride = sizeof(T); 1583 int quadStride = 0; 1584 1585 if (stride == 0) 1586 stride = componentCount * componentStride; 1587 DE_ASSERT(stride >= componentCount * componentStride); 1588 1589 switch (primitive) 1590 { 1591 case Array::PRIMITIVE_TRIANGLES: 1592 quadStride = stride * 6; 1593 break; 1594 1595 default: 1596 DE_ASSERT(false); 1597 break; 1598 } 1599 1600 char* resultData = new char[offset + quadStride * count]; 1601 char* _data = resultData; 1602 resultData = resultData + offset; 1603 1604 deRandom rnd; 1605 deRandom_init(&rnd, seed); 1606 1607 switch (primitive) 1608 { 1609 case Array::PRIMITIVE_TRIANGLES: 1610 { 1611 for (int quadNdx = 0; quadNdx < count; ++quadNdx) 1612 { 1613 T x1, x2; 1614 T y1, y2; 1615 T z, w; 1616 1617 // attempt to find a good (i.e not extremely small) quad 1618 for (int attemptNdx = 0; attemptNdx < 4; ++attemptNdx) 1619 { 1620 x1 = getRandom<T>(rnd, min, max); 1621 x2 = getRandom<T>(rnd, minValue<T>(), abs<T>(max - x1)); 1622 1623 y1 = getRandom<T>(rnd, min, max); 1624 y2 = getRandom<T>(rnd, minValue<T>(), abs<T>(max - y1)); 1625 1626 z = (componentCount > 2) ? (getRandom<T>(rnd, min, max)) : (T::create(0)); 1627 w = (componentCount > 3) ? (getRandom<T>(rnd, min, max)) : (T::create(1)); 1628 1629 // no additional components, all is good 1630 if (componentCount <= 2) 1631 break; 1632 1633 // The result quad is too thin? 1634 if ((deFloatAbs(x2.template to<float>() + z.template to<float>()) < minValue<T>().template to<float>()) || 1635 (deFloatAbs(y2.template to<float>() + w.template to<float>()) < minValue<T>().template to<float>())) 1636 continue; 1637 1638 // all ok 1639 break; 1640 } 1641 1642 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride]), x1); 1643 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + componentStride]), y1); 1644 1645 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride]), x1 + x2); 1646 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride + componentStride]), y1); 1647 1648 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2]), x1); 1649 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2 + componentStride]), y1 + y2); 1650 1651 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3]), x1); 1652 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3 + componentStride]), y1 + y2); 1653 1654 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4]), x1 + x2); 1655 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4 + componentStride]), y1); 1656 1657 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5]), x1 + x2); 1658 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5 + componentStride]), y1 + y2); 1659 1660 if (componentCount > 2) 1661 { 1662 for (int i = 0; i < 6; i++) 1663 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 2]), z); 1664 } 1665 1666 if (componentCount > 3) 1667 { 1668 for (int i = 0; i < 6; i++) 1669 alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 3]), w); 1670 } 1671 } 1672 1673 break; 1674 } 1675 1676 default: 1677 DE_ASSERT(false); 1678 break; 1679 } 1680 1681 return _data; 1682} 1683 1684char* RandomArrayGenerator::generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max) 1685{ 1686 char* data = DE_NULL; 1687 1688 switch (type) 1689 { 1690 case Array::INPUTTYPE_FLOAT: 1691 data = createPerQuads<GLValue::Float>(seed, count, componentCount, stride, primitive, min.fl, max.fl); 1692 break; 1693 1694 case Array::INPUTTYPE_FIXED: 1695 data = createPerQuads<GLValue::Fixed>(seed, count, componentCount, stride, primitive, min.fi, max.fi); 1696 break; 1697 1698 case Array::INPUTTYPE_DOUBLE: 1699 data = createPerQuads<GLValue::Double>(seed, count, componentCount, stride, primitive, min.d, max.d); 1700 break; 1701 1702 case Array::INPUTTYPE_BYTE: 1703 data = createPerQuads<GLValue::Byte>(seed, count, componentCount, stride, primitive, min.b, max.b); 1704 break; 1705 1706 case Array::INPUTTYPE_SHORT: 1707 data = createPerQuads<GLValue::Short>(seed, count, componentCount, stride, primitive, min.s, max.s); 1708 break; 1709 1710 case Array::INPUTTYPE_UNSIGNED_BYTE: 1711 data = createPerQuads<GLValue::Ubyte>(seed, count, componentCount, stride, primitive, min.ub, max.ub); 1712 break; 1713 1714 case Array::INPUTTYPE_UNSIGNED_SHORT: 1715 data = createPerQuads<GLValue::Ushort>(seed, count, componentCount, stride, primitive, min.us, max.us); 1716 break; 1717 1718 case Array::INPUTTYPE_UNSIGNED_INT: 1719 data = createPerQuads<GLValue::Uint>(seed, count, componentCount, stride, primitive, min.ui, max.ui); 1720 break; 1721 1722 case Array::INPUTTYPE_INT: 1723 data = createPerQuads<GLValue::Int>(seed, count, componentCount, stride, primitive, min.i, max.i); 1724 break; 1725 1726 case Array::INPUTTYPE_HALF: 1727 data = createPerQuads<GLValue::Half>(seed, count, componentCount, stride, primitive, min.h, max.h); 1728 break; 1729 1730 default: 1731 DE_ASSERT(false); 1732 break; 1733 } 1734 1735 return data; 1736} 1737 1738template<typename T> 1739char* RandomArrayGenerator::createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max) 1740{ 1741 deRandom rnd; 1742 deRandom_init(&rnd, seed); 1743 1744 int componentStride = sizeof(T); 1745 1746 if (stride == 0) 1747 stride = componentStride * componentCount; 1748 1749 int quadStride = 0; 1750 1751 switch (primitive) 1752 { 1753 case Array::PRIMITIVE_TRIANGLES: 1754 quadStride = stride * 6; 1755 break; 1756 1757 default: 1758 DE_ASSERT(false); 1759 break; 1760 } 1761 1762 char* data = new char[count * quadStride]; 1763 1764 for (int quadNdx = 0; quadNdx < count; quadNdx++) 1765 { 1766 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++) 1767 { 1768 T val = getRandom<T>(rnd, min, max); 1769 1770 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 0 + componentStride * componentNdx, val); 1771 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 1 + componentStride * componentNdx, val); 1772 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 2 + componentStride * componentNdx, val); 1773 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 3 + componentStride * componentNdx, val); 1774 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 4 + componentStride * componentNdx, val); 1775 alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 5 + componentStride * componentNdx, val); 1776 } 1777 } 1778 1779 return data; 1780} 1781 1782// VertexArrayTest 1783 1784VertexArrayTest::VertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc) 1785 : TestCase (testCtx, name, desc) 1786 , m_renderCtx (renderCtx) 1787 , m_refBuffers (DE_NULL) 1788 , m_refContext (DE_NULL) 1789 , m_glesContext (DE_NULL) 1790 , m_glArrayPack (DE_NULL) 1791 , m_rrArrayPack (DE_NULL) 1792 , m_isOk (false) 1793 , m_maxDiffRed (deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().redBits)))) 1794 , m_maxDiffGreen (deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().greenBits)))) 1795 , m_maxDiffBlue (deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().blueBits)))) 1796{ 1797} 1798 1799VertexArrayTest::~VertexArrayTest (void) 1800{ 1801 deinit(); 1802} 1803 1804void VertexArrayTest::init (void) 1805{ 1806 const int renderTargetWidth = de::min(512, m_renderCtx.getRenderTarget().getWidth()); 1807 const int renderTargetHeight = de::min(512, m_renderCtx.getRenderTarget().getHeight()); 1808 sglr::ReferenceContextLimits limits (m_renderCtx); 1809 1810 m_glesContext = new sglr::GLContext(m_renderCtx, m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight)); 1811 1812 m_refBuffers = new sglr::ReferenceContextBuffers(m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, renderTargetWidth, renderTargetHeight); 1813 m_refContext = new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer()); 1814 1815 m_glArrayPack = new ContextArrayPack(m_renderCtx, *m_glesContext); 1816 m_rrArrayPack = new ContextArrayPack(m_renderCtx, *m_refContext); 1817} 1818 1819void VertexArrayTest::deinit (void) 1820{ 1821 delete m_glArrayPack; 1822 delete m_rrArrayPack; 1823 delete m_refBuffers; 1824 delete m_refContext; 1825 delete m_glesContext; 1826 1827 m_glArrayPack = DE_NULL; 1828 m_rrArrayPack = DE_NULL; 1829 m_refBuffers = DE_NULL; 1830 m_refContext = DE_NULL; 1831 m_glesContext = DE_NULL; 1832} 1833 1834void VertexArrayTest::compare (void) 1835{ 1836 const tcu::Surface& ref = m_rrArrayPack->getSurface(); 1837 const tcu::Surface& screen = m_glArrayPack->getSurface(); 1838 1839 if (m_renderCtx.getRenderTarget().getNumSamples() > 1) 1840 { 1841 // \todo [mika] Improve compare when using multisampling 1842 m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Comparision of result from multisample render targets are not as stricts as without multisampling. Might produce false positives!" << tcu::TestLog::EndMessage; 1843 m_isOk = tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", ref.getAccess(), screen.getAccess(), 1.5f, tcu::COMPARE_LOG_RESULT); 1844 } 1845 else 1846 { 1847 tcu::RGBA threshold (m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue, 255); 1848 tcu::Surface error (ref.getWidth(), ref.getHeight()); 1849 1850 m_isOk = true; 1851 1852 for (int y = 1; y < ref.getHeight()-1; y++) 1853 { 1854 for (int x = 1; x < ref.getWidth()-1; x++) 1855 { 1856 tcu::RGBA refPixel = ref.getPixel(x, y); 1857 tcu::RGBA screenPixel = screen.getPixel(x, y); 1858 bool isOkPixel = false; 1859 1860 // Don't do comparisons for this pixel if it belongs to a one-pixel-thin part (i.e. it doesn't have similar-color neighbors in both x and y directions) in both result and reference. 1861 // This fixes some false negatives. 1862 bool refThin = (!tcu::compareThreshold(refPixel, ref.getPixel(x-1, y ), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x+1, y ), threshold)) || 1863 (!tcu::compareThreshold(refPixel, ref.getPixel(x , y-1), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x , y+1), threshold)); 1864 bool screenThin = (!tcu::compareThreshold(screenPixel, screen.getPixel(x-1, y ), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x+1, y ), threshold)) || 1865 (!tcu::compareThreshold(screenPixel, screen.getPixel(x , y-1), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x , y+1), threshold)); 1866 1867 if (refThin && screenThin) 1868 isOkPixel = true; 1869 else 1870 { 1871 for (int dy = -1; dy < 2 && !isOkPixel; dy++) 1872 { 1873 for (int dx = -1; dx < 2 && !isOkPixel; dx++) 1874 { 1875 // Check reference pixel against screen pixel 1876 { 1877 tcu::RGBA screenCmpPixel = screen.getPixel(x+dx, y+dy); 1878 deUint8 r = deAbs32(refPixel.getRed() - screenCmpPixel.getRed()); 1879 deUint8 g = deAbs32(refPixel.getGreen() - screenCmpPixel.getGreen()); 1880 deUint8 b = deAbs32(refPixel.getBlue() - screenCmpPixel.getBlue()); 1881 1882 if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue) 1883 isOkPixel = true; 1884 } 1885 1886 // Check screen pixels against reference pixel 1887 { 1888 tcu::RGBA refCmpPixel = ref.getPixel(x+dx, y+dy); 1889 deUint8 r = deAbs32(refCmpPixel.getRed() - screenPixel.getRed()); 1890 deUint8 g = deAbs32(refCmpPixel.getGreen() - screenPixel.getGreen()); 1891 deUint8 b = deAbs32(refCmpPixel.getBlue() - screenPixel.getBlue()); 1892 1893 if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue) 1894 isOkPixel = true; 1895 } 1896 } 1897 } 1898 } 1899 1900 if (isOkPixel) 1901 error.setPixel(x, y, tcu::RGBA(screen.getPixel(x, y).getRed(), (screen.getPixel(x, y).getGreen() + 255) / 2, screen.getPixel(x, y).getBlue(), 255)); 1902 else 1903 { 1904 error.setPixel(x, y, tcu::RGBA(255, 0, 0, 255)); 1905 m_isOk = false; 1906 } 1907 } 1908 } 1909 1910 tcu::TestLog& log = m_testCtx.getLog(); 1911 if (!m_isOk) 1912 { 1913 log << TestLog::Message << "Image comparison failed, threshold = (" << m_maxDiffRed << ", " << m_maxDiffGreen << ", " << m_maxDiffBlue << ")" << TestLog::EndMessage; 1914 log << TestLog::ImageSet("Compare result", "Result of rendering") 1915 << TestLog::Image("Result", "Result", screen) 1916 << TestLog::Image("Reference", "Reference", ref) 1917 << TestLog::Image("ErrorMask", "Error mask", error) 1918 << TestLog::EndImageSet; 1919 } 1920 else 1921 { 1922 log << TestLog::ImageSet("Compare result", "Result of rendering") 1923 << TestLog::Image("Result", "Result", screen) 1924 << TestLog::EndImageSet; 1925 } 1926 } 1927} 1928 1929// MultiVertexArrayTest 1930 1931MultiVertexArrayTest::Spec::ArraySpec::ArraySpec(Array::InputType inputType_, Array::OutputType outputType_, Array::Storage storage_, Array::Usage usage_, int componentCount_, int offset_, int stride_, bool normalize_, GLValue min_, GLValue max_) 1932 : inputType (inputType_) 1933 , outputType (outputType_) 1934 , storage (storage_) 1935 , usage (usage_) 1936 , componentCount(componentCount_) 1937 , offset (offset_) 1938 , stride (stride_) 1939 , normalize (normalize_) 1940 , min (min_) 1941 , max (max_) 1942{ 1943} 1944 1945std::string MultiVertexArrayTest::Spec::getName (void) const 1946{ 1947 std::stringstream name; 1948 1949 for (size_t ndx = 0; ndx < arrays.size(); ++ndx) 1950 { 1951 const ArraySpec& array = arrays[ndx]; 1952 1953 if (arrays.size() > 1) 1954 name << "array" << ndx << "_"; 1955 1956 name 1957 << Array::storageToString(array.storage) << "_" 1958 << array.offset << "_" 1959 << array.stride << "_" 1960 << Array::inputTypeToString((Array::InputType)array.inputType); 1961 if (array.inputType != Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && array.inputType != Array::INPUTTYPE_INT_2_10_10_10) 1962 name << array.componentCount; 1963 name 1964 << "_" 1965 << (array.normalize ? "normalized_" : "") 1966 << Array::outputTypeToString(array.outputType) << "_" 1967 << Array::usageTypeToString(array.usage) << "_"; 1968 } 1969 1970 if (first) 1971 name << "first" << first << "_"; 1972 1973 switch (primitive) 1974 { 1975 case Array::PRIMITIVE_TRIANGLES: 1976 name << "quads_"; 1977 break; 1978 case Array::PRIMITIVE_POINTS: 1979 name << "points_"; 1980 break; 1981 1982 default: 1983 DE_ASSERT(false); 1984 break; 1985 } 1986 1987 name << drawCount; 1988 1989 return name.str(); 1990} 1991 1992std::string MultiVertexArrayTest::Spec::getDesc (void) const 1993{ 1994 std::stringstream desc; 1995 1996 for (size_t ndx = 0; ndx < arrays.size(); ++ndx) 1997 { 1998 const ArraySpec& array = arrays[ndx]; 1999 2000 desc 2001 << "Array " << ndx << ": " 2002 << "Storage in " << Array::storageToString(array.storage) << ", " 2003 << "stride " << array.stride << ", " 2004 << "input datatype " << Array::inputTypeToString((Array::InputType)array.inputType) << ", " 2005 << "input component count " << array.componentCount << ", " 2006 << (array.normalize ? "normalized, " : "") 2007 << "used as " << Array::outputTypeToString(array.outputType) << ", "; 2008 } 2009 2010 desc 2011 << "drawArrays(), " 2012 << "first " << first << ", " 2013 << drawCount; 2014 2015 switch (primitive) 2016 { 2017 case Array::PRIMITIVE_TRIANGLES: 2018 desc << "quads "; 2019 break; 2020 case Array::PRIMITIVE_POINTS: 2021 desc << "points"; 2022 break; 2023 2024 default: 2025 DE_ASSERT(false); 2026 break; 2027 } 2028 2029 2030 return desc.str(); 2031} 2032 2033MultiVertexArrayTest::MultiVertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc) 2034 : VertexArrayTest (testCtx, renderCtx, name, desc) 2035 , m_spec (spec) 2036 , m_iteration (0) 2037{ 2038} 2039 2040MultiVertexArrayTest::~MultiVertexArrayTest (void) 2041{ 2042} 2043 2044MultiVertexArrayTest::IterateResult MultiVertexArrayTest::iterate (void) 2045{ 2046 if (m_iteration == 0) 2047 { 2048 const size_t primitiveSize = (m_spec.primitive == Array::PRIMITIVE_TRIANGLES) ? (6) : (1); // in non-indexed draw Triangles means rectangles 2049 float coordScale = 1.0f; 2050 float colorScale = 1.0f; 2051 const bool useVao = m_renderCtx.getType().getProfile() == glu::PROFILE_CORE; 2052 2053 // Log info 2054 m_testCtx.getLog() << TestLog::Message << m_spec.getDesc() << TestLog::EndMessage; 2055 2056 // Color and Coord scale 2057 { 2058 // First array is always position 2059 { 2060 Spec::ArraySpec arraySpec = m_spec.arrays[0]; 2061 if (arraySpec.inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10) 2062 { 2063 if (arraySpec.normalize) 2064 coordScale = 1.0f; 2065 else 2066 coordScale = 1.0 / 1024.0; 2067 } 2068 else if (arraySpec.inputType == Array::INPUTTYPE_INT_2_10_10_10) 2069 { 2070 if (arraySpec.normalize) 2071 coordScale = 1.0f; 2072 else 2073 coordScale = 1.0 / 512.0; 2074 } 2075 else 2076 coordScale = (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(0.9 / double(arraySpec.max.toFloat()))); 2077 2078 if (arraySpec.outputType == Array::OUTPUTTYPE_VEC3 || arraySpec.outputType == Array::OUTPUTTYPE_VEC4 2079 || arraySpec.outputType == Array::OUTPUTTYPE_IVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_IVEC4 2080 || arraySpec.outputType == Array::OUTPUTTYPE_UVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_UVEC4) 2081 coordScale = coordScale * 0.5f; 2082 } 2083 2084 // And other arrays are color-like 2085 for (int arrayNdx = 1; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++) 2086 { 2087 Spec::ArraySpec arraySpec = m_spec.arrays[arrayNdx]; 2088 2089 colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat()))); 2090 if (arraySpec.outputType == Array::OUTPUTTYPE_VEC4) 2091 colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat()))); 2092 } 2093 } 2094 2095 // Data 2096 for (int arrayNdx = 0; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++) 2097 { 2098 Spec::ArraySpec arraySpec = m_spec.arrays[arrayNdx]; 2099 const int seed = int(arraySpec.inputType) + 10 * int(arraySpec.outputType) + 100 * int(arraySpec.storage) + 1000 * int(m_spec.primitive) + 10000 * int(arraySpec.usage) + int(m_spec.drawCount) + 12 * int(arraySpec.componentCount) + int(arraySpec.stride) + int(arraySpec.normalize); 2100 const char* data = DE_NULL; 2101 const size_t stride = (arraySpec.stride == 0) ? (arraySpec.componentCount * Array::inputTypeSize(arraySpec.inputType)) : (arraySpec.stride); 2102 const size_t bufferSize = arraySpec.offset + stride * (m_spec.drawCount * primitiveSize - 1) + arraySpec.componentCount * Array::inputTypeSize(arraySpec.inputType); 2103 2104 switch (m_spec.primitive) 2105 { 2106 // case Array::PRIMITIVE_POINTS: 2107 // data = RandomArrayGenerator::generateArray(seed, arraySpec.min, arraySpec.max, arraySpec.count, arraySpec.componentCount, arraySpec.stride, arraySpec.inputType); 2108 // break; 2109 case Array::PRIMITIVE_TRIANGLES: 2110 if (arrayNdx == 0) 2111 { 2112 data = RandomArrayGenerator::generateQuads(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.offset, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max); 2113 } 2114 else 2115 { 2116 DE_ASSERT(arraySpec.offset == 0); // \note [jarkko] it just hasn't been implemented 2117 data = RandomArrayGenerator::generatePerQuad(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max); 2118 } 2119 break; 2120 2121 default: 2122 DE_ASSERT(false); 2123 break; 2124 } 2125 2126 m_glArrayPack->newArray(arraySpec.storage); 2127 m_rrArrayPack->newArray(arraySpec.storage); 2128 2129 m_glArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage); 2130 m_rrArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage); 2131 2132 m_glArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride); 2133 m_rrArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride); 2134 2135 delete [] data; 2136 } 2137 2138 try 2139 { 2140 m_glArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale); 2141 m_rrArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale); 2142 } 2143 catch (glu::Error& err) 2144 { 2145 // GL Errors are ok if the mode is not properly aligned 2146 2147 m_testCtx.getLog() << TestLog::Message << "Got error: " << err.what() << TestLog::EndMessage; 2148 2149 if (isUnalignedBufferOffsetTest()) 2150 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers."); 2151 else if (isUnalignedBufferStrideTest()) 2152 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride."); 2153 else 2154 throw; 2155 2156 return STOP; 2157 } 2158 2159 m_iteration++; 2160 return CONTINUE; 2161 } 2162 else if (m_iteration == 1) 2163 { 2164 compare(); 2165 2166 if (m_isOk) 2167 { 2168 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2169 } 2170 else 2171 { 2172 if (isUnalignedBufferOffsetTest()) 2173 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers."); 2174 else if (isUnalignedBufferStrideTest()) 2175 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride."); 2176 else 2177 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed."); 2178 } 2179 2180 m_iteration++; 2181 return STOP; 2182 } 2183 else 2184 { 2185 DE_ASSERT(false); 2186 return STOP; 2187 } 2188} 2189 2190bool MultiVertexArrayTest::isUnalignedBufferOffsetTest (void) const 2191{ 2192 // Buffer offsets should be data type size aligned 2193 for (size_t i = 0; i < m_spec.arrays.size(); ++i) 2194 { 2195 if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER) 2196 { 2197 const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10; 2198 2199 int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType); 2200 if (inputTypePacked) 2201 dataTypeSize = 4; 2202 2203 if (m_spec.arrays[i].offset % dataTypeSize != 0) 2204 return true; 2205 } 2206 } 2207 2208 return false; 2209} 2210 2211bool MultiVertexArrayTest::isUnalignedBufferStrideTest (void) const 2212{ 2213 // Buffer strides should be data type size aligned 2214 for (size_t i = 0; i < m_spec.arrays.size(); ++i) 2215 { 2216 if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER) 2217 { 2218 const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10; 2219 2220 int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType); 2221 if (inputTypePacked) 2222 dataTypeSize = 4; 2223 2224 if (m_spec.arrays[i].stride % dataTypeSize != 0) 2225 return true; 2226 } 2227 } 2228 2229 return false; 2230} 2231 2232} // gls 2233} // deqp 2234