1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-2016 The Khronos Group Inc. 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 22 */ /*-------------------------------------------------------------------*/ 23 24 /** 25 * \file gl4cMultiBindTests.cpp 26 * \brief Implements conformance tests for "Multi Bind" functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "gl4cMultiBindTests.hpp" 30 31 #include "gluDefs.hpp" 32 #include "gluStrUtil.hpp" 33 #include "glwEnums.hpp" 34 #include "glwFunctions.hpp" 35 #include "tcuTestLog.hpp" 36 37 #include <string> 38 39 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0 40 41 #if DEBUG_ENBALE_MESSAGE_CALLBACK 42 #include <iomanip> 43 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 44 45 using namespace glw; 46 47 namespace gl4cts 48 { 49 namespace MultiBind 50 { 51 52 #if DEBUG_ENBALE_MESSAGE_CALLBACK 53 /** Debuging procedure. Logs parameters. 54 * 55 * @param source As specified in GL spec. 56 * @param type As specified in GL spec. 57 * @param id As specified in GL spec. 58 * @param severity As specified in GL spec. 59 * @param ignored 60 * @param message As specified in GL spec. 61 * @param info Pointer to instance of deqp::Context used by test. 62 */ 63 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */, 64 const GLchar* message, void* info) 65 { 66 deqp::Context* ctx = (deqp::Context*)info; 67 68 const GLchar* source_str = "Unknown"; 69 const GLchar* type_str = "Unknown"; 70 const GLchar* severity_str = "Unknown"; 71 72 switch (source) 73 { 74 case GL_DEBUG_SOURCE_API: 75 source_str = "API"; 76 break; 77 case GL_DEBUG_SOURCE_APPLICATION: 78 source_str = "APP"; 79 break; 80 case GL_DEBUG_SOURCE_OTHER: 81 source_str = "OTR"; 82 break; 83 case GL_DEBUG_SOURCE_SHADER_COMPILER: 84 source_str = "COM"; 85 break; 86 case GL_DEBUG_SOURCE_THIRD_PARTY: 87 source_str = "3RD"; 88 break; 89 case GL_DEBUG_SOURCE_WINDOW_SYSTEM: 90 source_str = "WS"; 91 break; 92 default: 93 break; 94 } 95 96 switch (type) 97 { 98 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: 99 type_str = "DEPRECATED_BEHAVIOR"; 100 break; 101 case GL_DEBUG_TYPE_ERROR: 102 type_str = "ERROR"; 103 break; 104 case GL_DEBUG_TYPE_MARKER: 105 type_str = "MARKER"; 106 break; 107 case GL_DEBUG_TYPE_OTHER: 108 type_str = "OTHER"; 109 break; 110 case GL_DEBUG_TYPE_PERFORMANCE: 111 type_str = "PERFORMANCE"; 112 break; 113 case GL_DEBUG_TYPE_POP_GROUP: 114 type_str = "POP_GROUP"; 115 break; 116 case GL_DEBUG_TYPE_PORTABILITY: 117 type_str = "PORTABILITY"; 118 break; 119 case GL_DEBUG_TYPE_PUSH_GROUP: 120 type_str = "PUSH_GROUP"; 121 break; 122 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: 123 type_str = "UNDEFINED_BEHAVIOR"; 124 break; 125 default: 126 break; 127 } 128 129 switch (severity) 130 { 131 case GL_DEBUG_SEVERITY_HIGH: 132 severity_str = "H"; 133 break; 134 case GL_DEBUG_SEVERITY_LOW: 135 severity_str = "L"; 136 break; 137 case GL_DEBUG_SEVERITY_MEDIUM: 138 severity_str = "M"; 139 break; 140 case GL_DEBUG_SEVERITY_NOTIFICATION: 141 severity_str = "N"; 142 break; 143 default: 144 break; 145 } 146 147 ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|" 148 << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id 149 << ": " << message << tcu::TestLog::EndMessage; 150 } 151 152 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 153 154 /** Represents buffer instance 155 * Provides basic buffer functionality 156 **/ 157 class Buffer 158 { 159 public: 160 /* Public methods */ 161 /* Ctr & Dtr */ 162 Buffer(); 163 ~Buffer(); 164 165 /* Init & Release */ 166 void Init(deqp::Context& context); 167 168 void InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 169 const glw::GLvoid* data); 170 171 void Release(); 172 173 /* Functionality */ 174 void Bind() const; 175 void BindBase(glw::GLuint index) const; 176 177 /* Public static routines */ 178 /* Functionality */ 179 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 180 181 static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index); 182 183 static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 184 const glw::GLvoid* data); 185 186 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 187 188 static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 189 glw::GLvoid* data); 190 191 /* Public fields */ 192 glw::GLuint m_id; 193 194 /* Public constants */ 195 static const glw::GLuint m_invalid_id; 196 197 private: 198 /* Private enums */ 199 200 /* Private fields */ 201 deqp::Context* m_context; 202 glw::GLenum m_target; 203 }; 204 205 /** Represents framebuffer 206 * Provides basic functionality 207 **/ 208 class Framebuffer 209 { 210 public: 211 /* Public methods */ 212 /* Ctr & Dtr */ 213 Framebuffer(deqp::Context& context); 214 ~Framebuffer(); 215 216 /* Init & Release */ 217 void Release(); 218 219 /* Public static routines */ 220 static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment, 221 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height); 222 223 static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id); 224 225 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 226 227 /* Public fields */ 228 glw::GLuint m_id; 229 230 /* Public constants */ 231 static const glw::GLuint m_invalid_id; 232 233 private: 234 /* Private fields */ 235 deqp::Context& m_context; 236 }; 237 238 /** Represents shader instance. 239 * Provides basic functionality for shaders. 240 **/ 241 class Shader 242 { 243 public: 244 /* Public methods */ 245 /* Ctr & Dtr */ 246 Shader(deqp::Context& context); 247 ~Shader(); 248 249 /* Init & Realese */ 250 void Init(glw::GLenum stage, const std::string& source); 251 void Release(); 252 253 /* Public static routines */ 254 /* Functionality */ 255 static void Compile(const glw::Functions& gl, glw::GLuint id); 256 257 static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id); 258 259 static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source); 260 261 /* Public fields */ 262 glw::GLuint m_id; 263 264 /* Public constants */ 265 static const glw::GLuint m_invalid_id; 266 267 private: 268 /* Private fields */ 269 deqp::Context& m_context; 270 }; 271 272 /** Represents program instance. 273 * Provides basic functionality 274 **/ 275 class Program 276 { 277 public: 278 /* Public methods */ 279 /* Ctr & Dtr */ 280 Program(deqp::Context& context); 281 ~Program(); 282 283 /* Init & Release */ 284 void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader, 285 const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader, 286 const std::string& vertex_shader); 287 void Release(); 288 289 /* Functionality */ 290 void Use() const; 291 292 /* Public static routines */ 293 /* Functionality */ 294 static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id); 295 296 static void Create(const glw::Functions& gl, glw::GLuint& out_id); 297 298 static void Link(const glw::Functions& gl, glw::GLuint id); 299 300 static void Use(const glw::Functions& gl, glw::GLuint id); 301 302 /* Public fields */ 303 glw::GLuint m_id; 304 305 Shader m_compute; 306 Shader m_fragment; 307 Shader m_geometry; 308 Shader m_tess_ctrl; 309 Shader m_tess_eval; 310 Shader m_vertex; 311 312 /* Public constants */ 313 static const glw::GLuint m_invalid_id; 314 315 private: 316 /* Private fields */ 317 deqp::Context& m_context; 318 }; 319 320 /** Represents texture instance 321 **/ 322 class Texture 323 { 324 public: 325 /* Public methods */ 326 /* Ctr & Dtr */ 327 Texture(); 328 ~Texture(); 329 330 /* Init & Release */ 331 void Init(deqp::Context& context); 332 333 void InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id); 334 335 void InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 336 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error = false); 337 338 void Release(); 339 340 /* Public static routines */ 341 /* Functionality */ 342 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 343 344 static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, 345 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth, 346 glw::GLsizei image_size, const glw::GLvoid* data); 347 348 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 349 350 static void GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format, 351 glw::GLenum type, glw::GLvoid* out_data); 352 353 static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname, 354 glw::GLint* param); 355 356 static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format, 357 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, 358 const glw::GLvoid* data); 359 360 static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 361 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error); 362 363 static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y, 364 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format, 365 glw::GLenum type, const glw::GLvoid* pixels); 366 367 /* Public fields */ 368 glw::GLuint m_id; 369 370 /* Public constants */ 371 static const glw::GLuint m_invalid_id; 372 373 private: 374 /* Private fields */ 375 deqp::Context* m_context; 376 }; 377 378 /* Buffer constants */ 379 const GLuint Buffer::m_invalid_id = -1; 380 381 /** Constructor. 382 * 383 **/ 384 Buffer::Buffer() : m_id(m_invalid_id), m_context(0), m_target(GL_ARRAY_BUFFER) 385 { 386 } 387 388 /** Destructor 389 * 390 **/ 391 Buffer::~Buffer() 392 { 393 Release(); 394 395 m_context = 0; 396 } 397 398 /** Initialize buffer instance 399 * 400 * @param context CTS context. 401 **/ 402 void Buffer::Init(deqp::Context& context) 403 { 404 Release(); 405 406 m_context = &context; 407 } 408 409 /** Initialize buffer instance with some data 410 * 411 * @param context CTS context. 412 * @param target Buffer target 413 * @param usage Buffer usage enum 414 * @param size <size> parameter 415 * @param data <data> parameter 416 **/ 417 void Buffer::InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 418 const glw::GLvoid* data) 419 { 420 Init(context); 421 422 m_target = target; 423 424 const Functions& gl = m_context->getRenderContext().getFunctions(); 425 426 Generate(gl, m_id); 427 Bind(gl, m_id, m_target); 428 Data(gl, m_target, usage, size, data); 429 } 430 431 /** Release buffer instance 432 * 433 **/ 434 void Buffer::Release() 435 { 436 if (m_invalid_id != m_id) 437 { 438 const Functions& gl = m_context->getRenderContext().getFunctions(); 439 440 gl.deleteBuffers(1, &m_id); 441 m_id = m_invalid_id; 442 } 443 } 444 445 /** Binds buffer to its target 446 * 447 **/ 448 void Buffer::Bind() const 449 { 450 if (m_invalid_id == m_id) 451 { 452 return; 453 } 454 455 const Functions& gl = m_context->getRenderContext().getFunctions(); 456 457 Bind(gl, m_id, m_target); 458 } 459 460 /** Binds indexed buffer 461 * 462 * @param index <index> parameter 463 **/ 464 void Buffer::BindBase(glw::GLuint index) const 465 { 466 if (m_invalid_id == m_id) 467 { 468 return; 469 } 470 471 const Functions& gl = m_context->getRenderContext().getFunctions(); 472 473 BindBase(gl, m_id, m_target, index); 474 } 475 476 /** Bind buffer to given target 477 * 478 * @param gl GL functions 479 * @param id Id of buffer 480 * @param target Buffer target 481 **/ 482 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target) 483 { 484 gl.bindBuffer(target, id); 485 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 486 } 487 488 /** Binds indexed buffer 489 * 490 * @param gl GL functions 491 * @param id Id of buffer 492 * @param target Buffer target 493 * @param index <index> parameter 494 **/ 495 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index) 496 { 497 gl.bindBufferBase(target, index, id); 498 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase"); 499 } 500 501 /** Allocate memory for buffer and sends initial content 502 * 503 * @param gl GL functions 504 * @param target Buffer target 505 * @param usage Buffer usage enum 506 * @param size <size> parameter 507 * @param data <data> parameter 508 **/ 509 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 510 const glw::GLvoid* data) 511 { 512 gl.bufferData(target, size, data, usage); 513 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 514 } 515 516 /** Generate buffer 517 * 518 * @param gl GL functions 519 * @param out_id Id of buffer 520 **/ 521 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id) 522 { 523 GLuint id = m_invalid_id; 524 525 gl.genBuffers(1, &id); 526 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 527 528 if (m_invalid_id == id) 529 { 530 TCU_FAIL("Got invalid id"); 531 } 532 533 out_id = id; 534 } 535 536 /** Update range of buffer 537 * 538 * @param gl GL functions 539 * @param target Buffer target 540 * @param offset Offset in buffer 541 * @param size <size> parameter 542 * @param data <data> parameter 543 **/ 544 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 545 glw::GLvoid* data) 546 { 547 gl.bufferSubData(target, offset, size, data); 548 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData"); 549 } 550 551 /* Framebuffer constants */ 552 const GLuint Framebuffer::m_invalid_id = -1; 553 554 /** Constructor. 555 * 556 * @param context CTS context. 557 **/ 558 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 559 { 560 /* Nothing to done here */ 561 } 562 563 /** Destructor 564 * 565 **/ 566 Framebuffer::~Framebuffer() 567 { 568 Release(); 569 } 570 571 /** Release texture instance 572 * 573 **/ 574 void Framebuffer::Release() 575 { 576 if (m_invalid_id != m_id) 577 { 578 const Functions& gl = m_context.getRenderContext().getFunctions(); 579 580 gl.deleteFramebuffers(1, &m_id); 581 m_id = m_invalid_id; 582 } 583 } 584 585 /** Attach texture to specified attachment 586 * 587 * @param gl GL functions 588 * @param target Framebuffer target 589 * @param attachment Attachment 590 * @param texture_id Texture id 591 * @param level Level of mipmap 592 * @param width Texture width 593 * @param height Texture height 594 **/ 595 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment, 596 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height) 597 { 598 gl.framebufferTexture(target, attachment, texture_id, level); 599 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture"); 600 601 gl.viewport(0 /* x */, 0 /* y */, width, height); 602 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 603 } 604 605 /** Binds framebuffer to DRAW_FRAMEBUFFER 606 * 607 * @param gl GL functions 608 * @param target Framebuffer target 609 * @param id ID of framebuffer 610 **/ 611 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id) 612 { 613 gl.bindFramebuffer(target, id); 614 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 615 } 616 617 /** Generate framebuffer 618 * 619 **/ 620 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id) 621 { 622 GLuint id = m_invalid_id; 623 624 gl.genFramebuffers(1, &id); 625 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 626 627 if (m_invalid_id == id) 628 { 629 TCU_FAIL("Invalid id"); 630 } 631 632 out_id = id; 633 } 634 635 /* Program constants */ 636 const GLuint Program::m_invalid_id = 0; 637 638 /** Constructor. 639 * 640 * @param context CTS context. 641 **/ 642 Program::Program(deqp::Context& context) 643 : m_id(m_invalid_id) 644 , m_compute(context) 645 , m_fragment(context) 646 , m_geometry(context) 647 , m_tess_ctrl(context) 648 , m_tess_eval(context) 649 , m_vertex(context) 650 , m_context(context) 651 { 652 /* Nothing to be done here */ 653 } 654 655 /** Destructor 656 * 657 **/ 658 Program::~Program() 659 { 660 Release(); 661 } 662 663 /** Initialize program instance 664 * 665 * @param compute_shader Compute shader source code 666 * @param fragment_shader Fragment shader source code 667 * @param geometry_shader Geometry shader source code 668 * @param tesselation_control_shader Tesselation control shader source code 669 * @param tesselation_evaluation_shader Tesselation evaluation shader source code 670 * @param vertex_shader Vertex shader source code 671 **/ 672 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader, 673 const std::string& geometry_shader, const std::string& tesselation_control_shader, 674 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader) 675 { 676 /* Delete previous program */ 677 Release(); 678 679 /* GL entry points */ 680 const Functions& gl = m_context.getRenderContext().getFunctions(); 681 682 /* Initialize shaders */ 683 m_compute.Init(GL_COMPUTE_SHADER, compute_shader); 684 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader); 685 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader); 686 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader); 687 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader); 688 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader); 689 690 /* Create program, set up transform feedback and attach shaders */ 691 Create(gl, m_id); 692 Attach(gl, m_id, m_compute.m_id); 693 Attach(gl, m_id, m_fragment.m_id); 694 Attach(gl, m_id, m_geometry.m_id); 695 Attach(gl, m_id, m_tess_ctrl.m_id); 696 Attach(gl, m_id, m_tess_eval.m_id); 697 Attach(gl, m_id, m_vertex.m_id); 698 699 /* Link program */ 700 Link(gl, m_id); 701 } 702 703 /** Release program instance 704 * 705 **/ 706 void Program::Release() 707 { 708 const Functions& gl = m_context.getRenderContext().getFunctions(); 709 710 if (m_invalid_id != m_id) 711 { 712 Use(gl, m_invalid_id); 713 714 gl.deleteProgram(m_id); 715 m_id = m_invalid_id; 716 } 717 718 m_compute.Release(); 719 m_fragment.Release(); 720 m_geometry.Release(); 721 m_tess_ctrl.Release(); 722 m_tess_eval.Release(); 723 m_vertex.Release(); 724 } 725 726 /** Set program as active 727 * 728 **/ 729 void Program::Use() const 730 { 731 const Functions& gl = m_context.getRenderContext().getFunctions(); 732 733 Use(gl, m_id); 734 } 735 736 /** Attach shader to program 737 * 738 * @param gl GL functions 739 * @param program_id Id of program 740 * @param shader_id Id of shader 741 **/ 742 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id) 743 { 744 /* Sanity checks */ 745 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id)) 746 { 747 return; 748 } 749 750 gl.attachShader(program_id, shader_id); 751 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 752 } 753 754 /** Create program instance 755 * 756 * @param gl GL functions 757 * @param out_id Id of program 758 **/ 759 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id) 760 { 761 const GLuint id = gl.createProgram(); 762 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 763 764 if (m_invalid_id == id) 765 { 766 TCU_FAIL("Failed to create program"); 767 } 768 769 out_id = id; 770 } 771 772 /** Link program 773 * 774 * @param gl GL functions 775 * @param id Id of program 776 **/ 777 void Program::Link(const glw::Functions& gl, glw::GLuint id) 778 { 779 GLint status = GL_FALSE; 780 781 gl.linkProgram(id); 782 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); 783 784 /* Get link status */ 785 gl.getProgramiv(id, GL_LINK_STATUS, &status); 786 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 787 788 /* Log link error */ 789 if (GL_TRUE != status) 790 { 791 glw::GLint length = 0; 792 std::string message; 793 794 /* Get error log length */ 795 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length); 796 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 797 798 message.resize(length, 0); 799 800 /* Get error log */ 801 gl.getProgramInfoLog(id, length, 0, &message[0]); 802 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); 803 804 TCU_FAIL(message.c_str()); 805 } 806 } 807 808 /** Use program 809 * 810 * @param gl GL functions 811 * @param id Id of program 812 **/ 813 void Program::Use(const glw::Functions& gl, glw::GLuint id) 814 { 815 gl.useProgram(id); 816 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 817 } 818 819 /* Shader's constants */ 820 const GLuint Shader::m_invalid_id = 0; 821 822 /** Constructor. 823 * 824 * @param context CTS context. 825 **/ 826 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 827 { 828 /* Nothing to be done here */ 829 } 830 831 /** Destructor 832 * 833 **/ 834 Shader::~Shader() 835 { 836 Release(); 837 } 838 839 /** Initialize shader instance 840 * 841 * @param stage Shader stage 842 * @param source Source code 843 **/ 844 void Shader::Init(glw::GLenum stage, const std::string& source) 845 { 846 if (true == source.empty()) 847 { 848 /* No source == no shader */ 849 return; 850 } 851 852 /* Delete any previous shader */ 853 Release(); 854 855 /* Create, set source and compile */ 856 const Functions& gl = m_context.getRenderContext().getFunctions(); 857 858 Create(gl, stage, m_id); 859 Source(gl, m_id, source); 860 861 Compile(gl, m_id); 862 } 863 864 /** Release shader instance 865 * 866 **/ 867 void Shader::Release() 868 { 869 if (m_invalid_id != m_id) 870 { 871 const Functions& gl = m_context.getRenderContext().getFunctions(); 872 873 gl.deleteShader(m_id); 874 m_id = m_invalid_id; 875 } 876 } 877 878 /** Compile shader 879 * 880 * @param gl GL functions 881 * @param id Shader id 882 **/ 883 void Shader::Compile(const glw::Functions& gl, glw::GLuint id) 884 { 885 GLint status = GL_FALSE; 886 887 /* Compile */ 888 gl.compileShader(id); 889 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); 890 891 /* Get compilation status */ 892 gl.getShaderiv(id, GL_COMPILE_STATUS, &status); 893 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 894 895 /* Log compilation error */ 896 if (GL_TRUE != status) 897 { 898 glw::GLint length = 0; 899 std::string message; 900 901 /* Error log length */ 902 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length); 903 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 904 905 /* Prepare storage */ 906 message.resize(length, 0); 907 908 /* Get error log */ 909 gl.getShaderInfoLog(id, length, 0, &message[0]); 910 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); 911 912 TCU_FAIL(message.c_str()); 913 } 914 } 915 916 /** Create shader 917 * 918 * @param gl GL functions 919 * @param stage Shader stage 920 * @param out_id Shader id 921 **/ 922 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id) 923 { 924 const GLuint id = gl.createShader(stage); 925 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 926 927 if (m_invalid_id == id) 928 { 929 TCU_FAIL("Failed to create shader"); 930 } 931 932 out_id = id; 933 } 934 935 /** Set shader's source code 936 * 937 * @param gl GL functions 938 * @param id Shader id 939 * @param source Shader source code 940 **/ 941 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source) 942 { 943 const GLchar* code = source.c_str(); 944 945 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */); 946 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); 947 } 948 949 /* Texture static fields */ 950 const GLuint Texture::m_invalid_id = -1; 951 952 /** Constructor. 953 * 954 **/ 955 Texture::Texture() : m_id(m_invalid_id), m_context(0) 956 { 957 /* Nothing to done here */ 958 } 959 960 /** Destructor 961 * 962 **/ 963 Texture::~Texture() 964 { 965 Release(); 966 } 967 968 /** Initialize texture instance 969 * 970 * @param context Test context 971 **/ 972 void Texture::Init(deqp::Context& context) 973 { 974 Release(); 975 976 m_context = &context; 977 } 978 979 /** Initialize texture instance as texture buffer 980 * 981 * @param context Test context 982 * @param internal_format Internal format of texture 983 * @param buufer_id ID of buffer that will be used as storage 984 **/ 985 void Texture::InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id) 986 { 987 Init(context); 988 989 const Functions& gl = m_context->getRenderContext().getFunctions(); 990 991 Generate(gl, m_id); 992 Bind(gl, m_id, GL_TEXTURE_BUFFER); 993 Buffer::Bind(gl, buffer_id, GL_TEXTURE_BUFFER); 994 995 gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id); 996 GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer"); 997 } 998 999 /** Initialize texture instance with storage 1000 * 1001 * @param context Test context 1002 * @param target Texture target 1003 * @param levels Number of levels 1004 * @param internal_format Internal format of texture 1005 * @param width Width of texture 1006 * @param height Height of texture 1007 * @param depth Depth of texture 1008 **/ 1009 void Texture::InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 1010 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error) 1011 { 1012 Init(context); 1013 1014 const Functions& gl = m_context->getRenderContext().getFunctions(); 1015 1016 Generate(gl, m_id); 1017 Bind(gl, m_id, target); 1018 Storage(gl, target, levels, internal_format, width, height, depth, allow_error); 1019 } 1020 1021 /** Release texture instance 1022 * 1023 * @param context CTS context. 1024 **/ 1025 void Texture::Release() 1026 { 1027 if (m_invalid_id != m_id) 1028 { 1029 const Functions& gl = m_context->getRenderContext().getFunctions(); 1030 1031 gl.deleteTextures(1, &m_id); 1032 m_id = m_invalid_id; 1033 } 1034 } 1035 1036 /** Bind texture to target 1037 * 1038 * @param gl GL functions 1039 * @param id Id of texture 1040 * @param tex_type Type of texture 1041 **/ 1042 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target) 1043 { 1044 gl.bindTexture(target, id); 1045 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 1046 } 1047 1048 /** Set contents of compressed texture 1049 * 1050 * @param gl GL functions 1051 * @param target Texture target 1052 * @param level Mipmap level 1053 * @param internal_format Format of data 1054 * @param width Width of texture 1055 * @param height Height of texture 1056 * @param depth Depth of texture 1057 * @param image_size Size of data 1058 * @param data Buffer with image data 1059 **/ 1060 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, 1061 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth, 1062 glw::GLsizei image_size, const glw::GLvoid* data) 1063 { 1064 switch (target) 1065 { 1066 case GL_TEXTURE_1D: 1067 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data); 1068 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D"); 1069 break; 1070 case GL_TEXTURE_1D_ARRAY: 1071 case GL_TEXTURE_2D: 1072 case GL_TEXTURE_RECTANGLE: 1073 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data); 1074 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D"); 1075 break; 1076 case GL_TEXTURE_CUBE_MAP: 1077 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, 1078 image_size, data); 1079 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, 1080 image_size, data); 1081 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, 1082 image_size, data); 1083 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, 1084 image_size, data); 1085 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, 1086 image_size, data); 1087 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, 1088 image_size, data); 1089 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D"); 1090 break; 1091 case GL_TEXTURE_3D: 1092 case GL_TEXTURE_2D_ARRAY: 1093 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data); 1094 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D"); 1095 break; 1096 default: 1097 TCU_FAIL("Invliad enum"); 1098 break; 1099 } 1100 } 1101 1102 /** Generate texture instance 1103 * 1104 * @param gl GL functions 1105 * @param out_id Id of texture 1106 **/ 1107 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id) 1108 { 1109 GLuint id = m_invalid_id; 1110 1111 gl.genTextures(1, &id); 1112 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 1113 1114 if (m_invalid_id == id) 1115 { 1116 TCU_FAIL("Invalid id"); 1117 } 1118 1119 out_id = id; 1120 } 1121 1122 /** Get texture data 1123 * 1124 * @param gl GL functions 1125 * @param target Texture target 1126 * @param format Format of data 1127 * @param type Type of data 1128 * @param out_data Buffer for data 1129 **/ 1130 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format, 1131 glw::GLenum type, glw::GLvoid* out_data) 1132 { 1133 gl.getTexImage(target, level, format, type, out_data); 1134 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); 1135 } 1136 1137 /** Generate texture instance 1138 * 1139 * @param gl GL functions 1140 * @param target Texture target 1141 * @param level Mipmap level 1142 * @param pname Parameter to query 1143 * @param param Result of query 1144 **/ 1145 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname, 1146 glw::GLint* param) 1147 { 1148 gl.getTexLevelParameteriv(target, level, pname, param); 1149 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv"); 1150 } 1151 1152 /** Set contents of texture 1153 * 1154 * @param gl GL functions 1155 * @param target Texture target 1156 * @param level Mipmap level 1157 * @param internal_format Format of data 1158 * @param width Width of texture 1159 * @param height Height of texture 1160 * @param depth Depth of texture 1161 * @param format Format of data 1162 * @param type Type of data 1163 * @param data Buffer with image data 1164 **/ 1165 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format, 1166 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, 1167 const glw::GLvoid* data) 1168 { 1169 switch (target) 1170 { 1171 case GL_TEXTURE_1D: 1172 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data); 1173 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D"); 1174 break; 1175 case GL_TEXTURE_1D_ARRAY: 1176 case GL_TEXTURE_2D: 1177 case GL_TEXTURE_RECTANGLE: 1178 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data); 1179 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D"); 1180 break; 1181 case GL_TEXTURE_CUBE_MAP: 1182 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format, 1183 type, data); 1184 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format, 1185 type, data); 1186 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format, 1187 type, data); 1188 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format, 1189 type, data); 1190 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format, 1191 type, data); 1192 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format, 1193 type, data); 1194 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D"); 1195 break; 1196 case GL_TEXTURE_3D: 1197 case GL_TEXTURE_2D_ARRAY: 1198 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data); 1199 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D"); 1200 break; 1201 default: 1202 TCU_FAIL("Invliad enum"); 1203 break; 1204 } 1205 } 1206 1207 /** Allocate storage for texture 1208 * 1209 * @param gl GL functions 1210 * @param target Texture target 1211 * @param levels Number of levels 1212 * @param internal_format Internal format of texture 1213 * @param width Width of texture 1214 * @param height Height of texture 1215 * @param depth Depth of texture 1216 **/ 1217 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 1218 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error) 1219 { 1220 switch (target) 1221 { 1222 case GL_TEXTURE_1D: 1223 gl.texStorage1D(target, levels, internal_format, width); 1224 if (!allow_error) 1225 { 1226 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D"); 1227 } 1228 break; 1229 case GL_TEXTURE_1D_ARRAY: 1230 case GL_TEXTURE_2D: 1231 case GL_TEXTURE_RECTANGLE: 1232 case GL_TEXTURE_CUBE_MAP: 1233 gl.texStorage2D(target, levels, internal_format, width, height); 1234 if (!allow_error) 1235 { 1236 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); 1237 } 1238 break; 1239 case GL_TEXTURE_2D_MULTISAMPLE: 1240 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE); 1241 if (!allow_error) 1242 { 1243 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample"); 1244 } 1245 break; 1246 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1247 gl.texStorage3DMultisample(target, levels, internal_format, width, height, depth, GL_FALSE); 1248 if (!allow_error) 1249 { 1250 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3DMultisample"); 1251 } 1252 break; 1253 case GL_TEXTURE_3D: 1254 case GL_TEXTURE_2D_ARRAY: 1255 case GL_TEXTURE_CUBE_MAP_ARRAY: 1256 gl.texStorage3D(target, levels, internal_format, width, height, depth); 1257 if (!allow_error) 1258 { 1259 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D"); 1260 } 1261 break; 1262 default: 1263 TCU_FAIL("Invliad enum"); 1264 break; 1265 } 1266 } 1267 1268 /** Set contents of texture 1269 * 1270 * @param gl GL functions 1271 * @param target Texture target 1272 * @param level Mipmap level 1273 * @param x X offset 1274 * @param y Y offset 1275 * @param z Z offset 1276 * @param width Width of texture 1277 * @param height Height of texture 1278 * @param depth Depth of texture 1279 * @param format Format of data 1280 * @param type Type of data 1281 * @param pixels Buffer with image data 1282 **/ 1283 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y, 1284 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format, 1285 glw::GLenum type, const glw::GLvoid* pixels) 1286 { 1287 switch (target) 1288 { 1289 case GL_TEXTURE_1D: 1290 gl.texSubImage1D(target, level, x, width, format, type, pixels); 1291 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D"); 1292 break; 1293 case GL_TEXTURE_1D_ARRAY: 1294 case GL_TEXTURE_2D: 1295 case GL_TEXTURE_RECTANGLE: 1296 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels); 1297 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 1298 break; 1299 case GL_TEXTURE_CUBE_MAP: 1300 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels); 1301 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels); 1302 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels); 1303 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels); 1304 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels); 1305 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels); 1306 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 1307 break; 1308 case GL_TEXTURE_3D: 1309 case GL_TEXTURE_2D_ARRAY: 1310 case GL_TEXTURE_CUBE_MAP_ARRAY: 1311 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels); 1312 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D"); 1313 break; 1314 default: 1315 TCU_FAIL("Invliad enum"); 1316 break; 1317 } 1318 } 1319 1320 /* Gather info about buffer target */ 1321 struct bufferTargetInfo 1322 { 1323 GLenum m_target; 1324 GLenum m_pname_alignment; 1325 GLenum m_pname_binding; 1326 GLenum m_pname_max; 1327 GLenum m_pname_max_size; 1328 }; 1329 1330 /* Gather info about texture target */ 1331 struct textureTargetInfo 1332 { 1333 GLenum m_target; 1334 GLenum m_pname_binding; 1335 const GLchar* m_name; 1336 }; 1337 1338 /* Collects information about buffers */ 1339 static const bufferTargetInfo s_buffer_infos[] = { 1340 { GL_ATOMIC_COUNTER_BUFFER, 0, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, 1341 GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE }, 1342 { 1343 GL_TRANSFORM_FEEDBACK_BUFFER, 0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, 1344 GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, 1345 }, 1346 { GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS, 1347 GL_MAX_UNIFORM_BLOCK_SIZE }, 1348 { GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, GL_SHADER_STORAGE_BUFFER_BINDING, 1349 GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE }, 1350 }; 1351 1352 static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]); 1353 1354 /* Collects information about textures */ 1355 static const textureTargetInfo s_texture_infos[] = { 1356 { GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1D" }, 1357 { GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1D_ARRAY" }, 1358 { GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2D" }, 1359 { GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2D_ARRAY" }, 1360 { GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, "3D" }, 1361 { GL_TEXTURE_BUFFER, GL_TEXTURE_BINDING_BUFFER, "BUFFER" }, 1362 { GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, "CUBE" }, 1363 { GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, "CUBE_ARRAY" }, 1364 { GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE, "RECTANGLE" }, 1365 { GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BINDING_2D_MULTISAMPLE, "2D_MS" }, 1366 { GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, "2D_MS_ARRAY" } 1367 }; 1368 1369 static const size_t s_n_texture_tragets = sizeof(s_texture_infos) / sizeof(s_texture_infos[0]); 1370 1371 /** Macro, verifies generated error, logs error message and throws failure 1372 * 1373 * @param expected_error Expected error value 1374 * @param error_message Message logged if generated error is not the expected one 1375 **/ 1376 #define CHECK_ERROR(expected_error, error_message) \ 1377 { \ 1378 GLenum generated_error = gl.getError(); \ 1379 \ 1380 if (expected_error != generated_error) \ 1381 { \ 1382 m_context.getTestContext().getLog() \ 1383 << tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__ \ 1384 << ". Got wrong error: " << glu::getErrorStr(generated_error) \ 1385 << ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \ 1386 << tcu::TestLog::EndMessage; \ 1387 TCU_FAIL("Invalid error generated"); \ 1388 } \ 1389 } 1390 1391 /* Prototypes */ 1392 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string); 1393 1394 /** Checks binding 1395 * 1396 * @param context Test contex 1397 * @param pname Pname of binding 1398 * @param index Index of binding 1399 * @param target_name Name of target 1400 * @param expected_value Expected value of binding 1401 **/ 1402 void checkBinding(deqp::Context& context, GLenum pname, GLuint index, const std::string& target_name, 1403 GLint expected_value) 1404 { 1405 const Functions& gl = context.getRenderContext().getFunctions(); 1406 1407 GLint binding = -1; 1408 1409 gl.getIntegeri_v(pname, index, &binding); 1410 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v"); 1411 1412 if (binding != expected_value) 1413 { 1414 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding 1415 << ", expected: " << expected_value << ". Target: " << target_name 1416 << " at index: " << index << tcu::TestLog::EndMessage; 1417 TCU_FAIL("Invalid binding"); 1418 } 1419 } 1420 1421 /** Checks bindings for given texture unit 1422 * 1423 * @param context Test contex 1424 * @param pname Binding pname of <expected_value> 1425 * @param index Index of texture unit 1426 * @param expected_value Expected value of binding at <pname> target 1427 **/ 1428 void checkTextureBinding(deqp::Context& context, GLenum pname, GLuint index, GLint expected_value) 1429 { 1430 const Functions& gl = context.getRenderContext().getFunctions(); 1431 1432 for (size_t i = 0; i < s_n_texture_tragets; ++i) 1433 { 1434 const GLenum pname_binding = s_texture_infos[i].m_pname_binding; 1435 const GLchar* target_name = s_texture_infos[i].m_name; 1436 1437 GLint binding = -1; 1438 GLint value = 0; 1439 1440 gl.getIntegeri_v(pname_binding, index, &binding); 1441 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v"); 1442 1443 if (pname_binding == pname) 1444 { 1445 value = (GLint)expected_value; 1446 } 1447 1448 if (binding != value) 1449 { 1450 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding 1451 << ", expected: " << expected_value << ". Target: " << target_name 1452 << " at index: " << index << tcu::TestLog::EndMessage; 1453 TCU_FAIL("Invalid binding"); 1454 } 1455 } 1456 } 1457 1458 /** Checks binding 1459 * 1460 * @param context Test context 1461 * @param index Index of binding 1462 * @param expected_value Expected value of binding 1463 **/ 1464 void checkVertexAttribBinding(deqp::Context& context, GLuint index, GLint expected_value) 1465 { 1466 const Functions& gl = context.getRenderContext().getFunctions(); 1467 1468 GLint binding = -1; 1469 1470 gl.getVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding); 1471 GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv"); 1472 1473 if (binding != expected_value) 1474 { 1475 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding 1476 << ", expected: " << expected_value << ". Target: Vertex attribute" 1477 << " at index: " << index << tcu::TestLog::EndMessage; 1478 TCU_FAIL("Invalid binding"); 1479 } 1480 } 1481 1482 /** Fills MS texture with specified value 1483 * 1484 * @param context Test context 1485 * @param texture_id Index of binding 1486 * @param value Value for texture 1487 * @param is_array Selects if array target should be used 1488 **/ 1489 void fillMSTexture(deqp::Context& context, GLuint texture_id, GLuint value, bool is_array) 1490 { 1491 /* */ 1492 static const GLchar* cs = "#version 430 core\n" 1493 "\n" 1494 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 1495 "\n" 1496 "layout (location = 0) writeonly uniform IMAGE uni_image;\n" 1497 "\n" 1498 "layout (location = 1) uniform uint uni_value;\n" 1499 "\n" 1500 "void main()\n" 1501 "{\n" 1502 " const POINT;\n" 1503 "\n" 1504 " imageStore(uni_image, point, 0, uvec4(uni_value, 0, 0, 0));\n" 1505 "}\n" 1506 "\n"; 1507 1508 static const GLchar* array_image = "uimage2DMSArray"; 1509 static const GLchar* array_point = "ivec3 point = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, 0)"; 1510 static const GLchar* regular_image = "uimage2DMS"; 1511 static const GLchar* regular_point = "ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)"; 1512 1513 /* */ 1514 const Functions& gl = context.getRenderContext().getFunctions(); 1515 const GLchar* image = (true == is_array) ? array_image : regular_image; 1516 const GLchar* point = (true == is_array) ? array_point : regular_point; 1517 size_t position = 0; 1518 std::string source = cs; 1519 1520 /* */ 1521 replaceToken("IMAGE", position, image, source); 1522 replaceToken("POINT", position, point, source); 1523 1524 /* */ 1525 Program program(context); 1526 program.Init(source.c_str(), "", "", "", "", ""); 1527 program.Use(); 1528 1529 /* */ 1530 if (true == is_array) 1531 { 1532 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_TRUE /* layered */, 0 /* layer */, 1533 GL_WRITE_ONLY, GL_R32UI); 1534 } 1535 else 1536 { 1537 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 1538 GL_WRITE_ONLY, GL_R32UI); 1539 } 1540 1541 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 1542 1543 gl.uniform1i(0 /* location */, 0 /* image unit*/); 1544 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 1545 1546 gl.uniform1ui(1 /* location */, value /* uni_value */); 1547 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1ui"); 1548 1549 /* */ 1550 gl.dispatchCompute(6, 6, 1); 1551 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 1552 } 1553 1554 /** Get texture binding pname for given index 1555 * 1556 * @param index Index of texture target 1557 * 1558 * @return Pname 1559 **/ 1560 GLenum getBinding(GLuint index) 1561 { 1562 if (index < s_n_texture_tragets) 1563 { 1564 return s_texture_infos[index].m_pname_binding; 1565 } 1566 else 1567 { 1568 return GL_TEXTURE_BINDING_2D; 1569 } 1570 } 1571 1572 /** Get texture target for given index 1573 * 1574 * @param index Index of texture target 1575 * 1576 * @return Target 1577 **/ 1578 GLenum getTarget(GLuint index) 1579 { 1580 if (index < s_n_texture_tragets) 1581 { 1582 return s_texture_infos[index].m_target; 1583 } 1584 else 1585 { 1586 return GL_TEXTURE_2D; 1587 } 1588 } 1589 1590 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion> 1591 * 1592 * @param token Token string 1593 * @param search_position Position at which find will start, it is updated to position at which replaced text ends 1594 * @param text String that will be used as replacement for <token> 1595 * @param string String to work on 1596 **/ 1597 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string) 1598 { 1599 const size_t text_length = strlen(text); 1600 const size_t token_length = strlen(token); 1601 const size_t token_position = string.find(token, search_position); 1602 1603 string.replace(token_position, token_length, text, text_length); 1604 1605 search_position = token_position + text_length; 1606 } 1607 1608 /** Constructor 1609 * 1610 * @param context Test context 1611 **/ 1612 ErrorsBindBuffersTest::ErrorsBindBuffersTest(deqp::Context& context) 1613 : TestCase(context, "errors_bind_buffers", "Verifies that proper errors are generated by buffer binding routines") 1614 { 1615 /* Nothing to be done */ 1616 } 1617 1618 /** Execute test 1619 * 1620 * @return tcu::TestNode::STOP 1621 **/ 1622 tcu::TestNode::IterateResult ErrorsBindBuffersTest::iterate() 1623 { 1624 const Functions& gl = m_context.getRenderContext().getFunctions(); 1625 1626 #if DEBUG_ENBALE_MESSAGE_CALLBACK 1627 gl.debugMessageCallback(debug_proc, &m_context); 1628 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 1629 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 1630 1631 /* - INVALID_ENUM when <target> is not valid; */ 1632 { 1633 static const GLintptr buffer_size = 16; 1634 static const GLsizei count = 1; 1635 static const GLuint first = 0; 1636 static const GLintptr offset = 4; 1637 static const GLintptr size = buffer_size - offset; 1638 1639 Buffer buffer; 1640 1641 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 1642 1643 gl.bindBuffersBase(GL_ARRAY_BUFFER, first, count, &buffer.m_id); 1644 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersBase with invalid <target>"); 1645 1646 gl.bindBuffersRange(GL_ARRAY_BUFFER, first, count, &buffer.m_id, &offset, &size); 1647 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersRange with invalid <target>"); 1648 } 1649 1650 for (size_t i = 0; i < s_n_buffer_tragets; ++i) 1651 { 1652 static const GLsizei n_buffers = 4; 1653 1654 const GLenum pname_alignment = s_buffer_infos[i].m_pname_alignment; 1655 const GLenum pname_max = s_buffer_infos[i].m_pname_max; 1656 const GLenum target = s_buffer_infos[i].m_target; 1657 const std::string& target_name = glu::getBufferTargetStr(target).toString(); 1658 1659 GLintptr buffer_size = 16; 1660 GLsizei count = n_buffers; 1661 GLuint first = 0; 1662 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 1663 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */ 1664 GLint offset_alignment = 1; 1665 GLint max_buffers = 0; 1666 GLintptr size = buffer_size - offset; 1667 size_t validated_index = n_buffers - 1; 1668 1669 /* Get alignment */ 1670 if (0 != pname_alignment) 1671 { 1672 gl.getIntegerv(pname_alignment, &offset_alignment); 1673 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 1674 1675 buffer_size += offset_alignment; 1676 offset = offset_alignment; 1677 size = buffer_size - offset; 1678 } 1679 1680 /* Get max */ 1681 gl.getIntegerv(pname_max, &max_buffers); 1682 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 1683 1684 /* Select count so <first + count> does not exceed max. 1685 * Validated index shall be in the specified range. 1686 */ 1687 if (n_buffers > max_buffers) 1688 { 1689 count = max_buffers; 1690 validated_index = max_buffers - 1; 1691 } 1692 1693 /* Storage */ 1694 Buffer buffer[n_buffers]; 1695 GLuint buffer_ids[n_buffers]; 1696 GLintptr offsets[n_buffers]; 1697 GLintptr sizes[n_buffers]; 1698 1699 /* Prepare buffers */ 1700 for (size_t j = 0; j < n_buffers; ++j) 1701 { 1702 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 1703 1704 buffer_ids[j] = buffer[j].m_id; 1705 offsets[j] = offset; 1706 sizes[j] = size; 1707 } 1708 1709 /* - INVALID_OPERATION when <first> + <count> is greater than allowed limit; */ 1710 { 1711 GLsizei t_count = n_buffers; 1712 GLuint t_first = 0; 1713 1714 /* Select first so <first + count> exceeds max, avoid negative first */ 1715 if (n_buffers <= max_buffers) 1716 { 1717 t_first = max_buffers - n_buffers + 1; 1718 } 1719 else 1720 { 1721 t_count = max_buffers + 1; 1722 /* first = 0; */ 1723 } 1724 1725 /* Test */ 1726 gl.bindBuffersBase(target, t_first, t_count, buffer_ids); 1727 CHECK_ERROR(GL_INVALID_OPERATION, 1728 "BindBuffersBase with invalid <first> + <count>, target: " << target_name); 1729 1730 gl.bindBuffersRange(target, t_first, t_count, buffer_ids, offsets, sizes); 1731 CHECK_ERROR(GL_INVALID_OPERATION, 1732 "BindBuffersRange with invalid <first> + <count>, target: " << target_name); 1733 } 1734 1735 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of 1736 * existing buffer; 1737 */ 1738 { 1739 GLuint t_buffer_ids[n_buffers]; 1740 1741 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids)); 1742 1743 /* Find invalid id */ 1744 while (1) 1745 { 1746 if (GL_TRUE != gl.isBuffer(invalid_id)) 1747 { 1748 break; 1749 } 1750 1751 invalid_id += 1; 1752 } 1753 1754 /* Invalidate the entry */ 1755 t_buffer_ids[validated_index] = invalid_id; 1756 1757 /* Test */ 1758 gl.bindBuffersBase(target, first, count, t_buffer_ids); 1759 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersBase with invalid buffer id, target: " << target_name); 1760 1761 gl.bindBuffersRange(target, first, count, t_buffer_ids, offsets, sizes); 1762 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id, target: " << target_name); 1763 } 1764 1765 /* - INVALID_VALUE if any value in <offsets> is less than zero; */ 1766 { 1767 GLintptr t_offsets[n_buffers]; 1768 GLintptr t_sizes[n_buffers]; 1769 1770 memcpy(t_offsets, offsets, sizeof(offsets)); 1771 memcpy(t_sizes, sizes, sizeof(sizes)); 1772 1773 /* Invalidate the entry */ 1774 t_offsets[validated_index] = -1; 1775 t_sizes[validated_index] = -1; 1776 1777 /* Test */ 1778 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes); 1779 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative offset, target: " << target_name); 1780 1781 /* Test */ 1782 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes); 1783 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative size, target: " << target_name); 1784 } 1785 1786 /* - INVALID_VALUE if any pair of <offsets> and <sizes> exceeds limits. */ 1787 { 1788 GLintptr t_offsets[n_buffers]; 1789 GLintptr t_sizes[n_buffers]; 1790 1791 memcpy(t_offsets, offsets, sizeof(offsets)); 1792 memcpy(t_sizes, sizes, sizeof(sizes)); 1793 1794 /* Invalidate the entry */ 1795 t_offsets[validated_index] -= 1; /* Not aligned by required value */ 1796 t_sizes[validated_index] = size - 1; /* Not aligned by required value */ 1797 1798 /* Test */ 1799 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes); 1800 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <offset>, target: " << target_name); 1801 1802 /* Test */ 1803 if (GL_TRANSFORM_FEEDBACK_BUFFER == target) 1804 { 1805 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes); 1806 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <size>, target: " << target_name); 1807 } 1808 } 1809 } 1810 1811 /* Set result */ 1812 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1813 1814 /* Done */ 1815 return tcu::TestNode::STOP; 1816 } 1817 1818 /** Constructor 1819 * 1820 * @param context Test context 1821 **/ 1822 ErrorsBindTexturesTest::ErrorsBindTexturesTest(deqp::Context& context) 1823 : TestCase(context, "errors_bind_textures", "Verifies that proper errors are generated by texture binding routines") 1824 { 1825 /* Nothing to be done */ 1826 } 1827 1828 /** Execute test 1829 * 1830 * @return tcu::TestNode::STOP 1831 **/ 1832 tcu::TestNode::IterateResult ErrorsBindTexturesTest::iterate() 1833 { 1834 static const GLuint depth = 8; 1835 static const GLuint height = 8; 1836 static const GLsizei n_textures = 4; 1837 static const GLuint width = 8; 1838 1839 const Functions& gl = m_context.getRenderContext().getFunctions(); 1840 1841 #if DEBUG_ENBALE_MESSAGE_CALLBACK 1842 gl.debugMessageCallback(debug_proc, &m_context); 1843 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 1844 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 1845 1846 GLsizei count = n_textures; 1847 GLuint first = 0; 1848 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 1849 GLint max_textures = 0; 1850 size_t validated_index = n_textures - 1; 1851 1852 /* Get max */ 1853 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures); 1854 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 1855 1856 /* Select count so <first + count> does not exceed max. 1857 * Validated index shall be in the specified range. 1858 */ 1859 if (n_textures > max_textures) 1860 { 1861 count = max_textures; 1862 validated_index = max_textures - 1; 1863 } 1864 1865 /* Storage */ 1866 Texture texture[n_textures]; 1867 GLuint texture_ids[n_textures]; 1868 1869 /* Prepare textures */ 1870 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, depth); 1871 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth); 1872 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth); 1873 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, width, height, depth); 1874 1875 for (size_t i = 0; i < n_textures; ++i) 1876 { 1877 texture_ids[i] = texture[i].m_id; 1878 } 1879 1880 /* - INVALID_OPERATION when <first> + <count> exceed limits; */ 1881 { 1882 GLsizei t_count = n_textures; 1883 GLuint t_first = 0; 1884 1885 /* Select first so <first + count> exceeds max, avoid negative first */ 1886 if (n_textures <= max_textures) 1887 { 1888 t_first = max_textures - n_textures + 1; 1889 } 1890 else 1891 { 1892 t_count = max_textures + 1; 1893 /* first = 0; */ 1894 } 1895 1896 /* Test */ 1897 gl.bindTextures(t_first, t_count, texture_ids); 1898 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid <first> + <count>"); 1899 } 1900 1901 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of 1902 * existing buffer; 1903 */ 1904 { 1905 GLuint t_texture_ids[n_textures]; 1906 1907 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids)); 1908 1909 /* Find invalid id */ 1910 while (1) 1911 { 1912 if (GL_TRUE != gl.isTexture(invalid_id)) 1913 { 1914 break; 1915 } 1916 1917 invalid_id += 1; 1918 } 1919 1920 /* Invalidate the entry */ 1921 t_texture_ids[validated_index] = invalid_id; 1922 1923 /* Test */ 1924 gl.bindTextures(first, count, t_texture_ids); 1925 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id"); 1926 } 1927 1928 /* Set result */ 1929 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1930 1931 /* Done */ 1932 return tcu::TestNode::STOP; 1933 } 1934 1935 /** Constructor 1936 * 1937 * @param context Test context 1938 **/ 1939 ErrorsBindSamplersTest::ErrorsBindSamplersTest(deqp::Context& context) 1940 : TestCase(context, "errors_bind_samplers", "Verifies that proper errors are generated by sampler binding routines") 1941 { 1942 /* Nothing to be done */ 1943 } 1944 1945 /** Execute test 1946 * 1947 * @return tcu::TestNode::STOP 1948 **/ 1949 tcu::TestNode::IterateResult ErrorsBindSamplersTest::iterate() 1950 { 1951 static const GLsizei n_samplers = 4; 1952 1953 const Functions& gl = m_context.getRenderContext().getFunctions(); 1954 1955 #if DEBUG_ENBALE_MESSAGE_CALLBACK 1956 gl.debugMessageCallback(debug_proc, &m_context); 1957 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 1958 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 1959 1960 GLsizei count = n_samplers; 1961 GLuint first = 0; 1962 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 1963 GLint max_samplers = 0; 1964 size_t validated_index = n_samplers - 1; 1965 1966 /* Get max */ 1967 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers); 1968 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 1969 1970 /* Select count so <first + count> does not exceed max. 1971 * Validated index shall be in the specified range. 1972 */ 1973 if (n_samplers > max_samplers) 1974 { 1975 count = max_samplers; 1976 validated_index = max_samplers - 1; 1977 } 1978 1979 /* Storage */ 1980 GLuint sampler_ids[n_samplers]; 1981 1982 /* Prepare samplers */ 1983 gl.genSamplers(n_samplers, sampler_ids); 1984 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers"); 1985 1986 try 1987 { 1988 /* - INVALID_OPERATION when <first> + <count> exceed limits; */ 1989 { 1990 GLsizei t_count = n_samplers; 1991 GLuint t_first = 0; 1992 1993 /* Select first so <first + count> exceeds max, avoid negative first */ 1994 if (n_samplers <= max_samplers) 1995 { 1996 t_first = max_samplers - n_samplers + 1; 1997 } 1998 else 1999 { 2000 t_count = max_samplers + 1; 2001 /* first = 0; */ 2002 } 2003 2004 /* Test */ 2005 gl.bindSamplers(t_first, t_count, sampler_ids); 2006 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid <first> + <count>"); 2007 } 2008 2009 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of 2010 * existing buffer; 2011 */ 2012 { 2013 GLuint t_sampler_ids[n_samplers]; 2014 2015 memcpy(t_sampler_ids, sampler_ids, sizeof(sampler_ids)); 2016 2017 /* Find invalid id */ 2018 while (1) 2019 { 2020 if (GL_TRUE != gl.isTexture(invalid_id)) 2021 { 2022 break; 2023 } 2024 2025 invalid_id += 1; 2026 } 2027 2028 /* Invalidate the entry */ 2029 t_sampler_ids[validated_index] = invalid_id; 2030 2031 /* Test */ 2032 gl.bindTextures(first, count, t_sampler_ids); 2033 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id"); 2034 } 2035 } 2036 catch (const std::exception&) 2037 { 2038 gl.deleteSamplers(n_samplers, sampler_ids); 2039 2040 TCU_FAIL("Invalid error generated"); 2041 } 2042 2043 /* Delete samplers */ 2044 gl.deleteSamplers(n_samplers, sampler_ids); 2045 2046 /* Set result */ 2047 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2048 2049 /* Done */ 2050 return tcu::TestNode::STOP; 2051 } 2052 2053 /** Constructor 2054 * 2055 * @param context Test context 2056 **/ 2057 ErrorsBindImageTexturesTest::ErrorsBindImageTexturesTest(deqp::Context& context) 2058 : TestCase(context, "errors_bind_image_textures", 2059 "Verifies that proper errors are generated by image binding routines") 2060 { 2061 /* Nothing to be done */ 2062 } 2063 2064 /** Execute test 2065 * 2066 * @return tcu::TestNode::STOP 2067 **/ 2068 tcu::TestNode::IterateResult ErrorsBindImageTexturesTest::iterate() 2069 { 2070 static const GLuint depth = 8; 2071 static const GLuint height = 8; 2072 static const GLsizei n_textures = 4; 2073 static const GLuint width = 8; 2074 2075 const Functions& gl = m_context.getRenderContext().getFunctions(); 2076 2077 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2078 gl.debugMessageCallback(debug_proc, &m_context); 2079 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2080 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2081 2082 GLsizei count = n_textures; 2083 GLuint first = 0; 2084 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 2085 GLint max_textures = 0; 2086 size_t validated_index = n_textures - 1; 2087 2088 /* Get max */ 2089 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures); 2090 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2091 2092 /* Select count so <first + count> does not exceed max. 2093 * Validated index shall be in the specified range. 2094 */ 2095 if (n_textures > max_textures) 2096 { 2097 count = max_textures; 2098 validated_index = max_textures - 1; 2099 } 2100 2101 /* Storage */ 2102 Texture texture[n_textures]; 2103 GLuint texture_ids[n_textures]; 2104 2105 /* Prepare textures */ 2106 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth); 2107 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, depth); 2108 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1, GL_RGBA8, width, height, depth); 2109 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1, GL_RGBA8, width, height, depth); 2110 2111 for (size_t i = 0; i < n_textures; ++i) 2112 { 2113 texture_ids[i] = texture[i].m_id; 2114 } 2115 2116 /* - INVALID_OPERATION when <first> + <count> exceed limits; */ 2117 { 2118 GLsizei t_count = n_textures; 2119 GLuint t_first = 0; 2120 2121 /* Select first so <first + count> exceeds max, avoid negative first */ 2122 if (n_textures <= max_textures) 2123 { 2124 t_first = max_textures - n_textures + 1; 2125 } 2126 else 2127 { 2128 t_count = max_textures + 1; 2129 /* first = 0; */ 2130 } 2131 2132 /* Test */ 2133 gl.bindImageTextures(t_first, t_count, texture_ids); 2134 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid <first> + <count>"); 2135 } 2136 2137 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of 2138 * existing buffer; 2139 */ 2140 { 2141 GLuint t_texture_ids[n_textures]; 2142 2143 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids)); 2144 2145 /* Find invalid id */ 2146 while (1) 2147 { 2148 if (GL_TRUE != gl.isTexture(invalid_id)) 2149 { 2150 break; 2151 } 2152 2153 invalid_id += 1; 2154 } 2155 2156 /* Invalidate the entry */ 2157 t_texture_ids[validated_index] = invalid_id; 2158 2159 /* Test */ 2160 gl.bindImageTextures(first, count, t_texture_ids); 2161 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id"); 2162 } 2163 2164 /* - INVALID_OPERATION if any entry found in <textures> has invalid internal 2165 * format at level 0; 2166 */ 2167 { 2168 GLuint t_texture_ids[n_textures]; 2169 2170 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids)); 2171 2172 /* Prepare texture with invalid format */ 2173 Texture t_texture; 2174 t_texture.Init(m_context); 2175 t_texture.Generate(gl, t_texture.m_id); 2176 t_texture.Bind(gl, t_texture.m_id, GL_TEXTURE_2D); 2177 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0); 2178 CHECK_ERROR(GL_INVALID_VALUE, "texStorage2D has height set to 0"); 2179 2180 /* Invalidate the entry */ 2181 t_texture_ids[validated_index] = t_texture.m_id; 2182 2183 /* Test */ 2184 gl.bindImageTextures(first, count, t_texture_ids); 2185 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid internal format"); 2186 } 2187 2188 /* - INVALID_VALUE when any entry in <textures> has any of dimensions equal 2189 * to 0 at level 0. 2190 */ 2191 { 2192 GLuint t_texture_ids[n_textures]; 2193 2194 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids)); 2195 2196 /* Prepare texture with invalid format */ 2197 Texture t_texture; 2198 t_texture.InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0, depth, true); 2199 2200 /* Invalidate the entry */ 2201 t_texture_ids[validated_index] = t_texture.m_id; 2202 2203 /* Test */ 2204 gl.bindImageTextures(first, count, t_texture_ids); 2205 CHECK_ERROR(GL_INVALID_VALUE, "BindImageTextures with 2D texture that has height set to 0"); 2206 } 2207 2208 /* Set result */ 2209 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2210 2211 /* Done */ 2212 return tcu::TestNode::STOP; 2213 } 2214 2215 /** Constructor 2216 * 2217 * @param context Test context 2218 **/ 2219 ErrorsBindVertexBuffersTest::ErrorsBindVertexBuffersTest(deqp::Context& context) 2220 : TestCase(context, "errors_bind_vertex_buffers", 2221 "Verifies that proper errors are generated by vertex buffer binding routines") 2222 { 2223 /* Nothing to be done */ 2224 } 2225 2226 /** Execute test 2227 * 2228 * @return tcu::TestNode::STOP 2229 **/ 2230 tcu::TestNode::IterateResult ErrorsBindVertexBuffersTest::iterate() 2231 { 2232 const Functions& gl = m_context.getRenderContext().getFunctions(); 2233 2234 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2235 gl.debugMessageCallback(debug_proc, &m_context); 2236 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2237 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2238 2239 static const GLsizei n_buffers = 4; 2240 static const GLsizei stride = 4; 2241 2242 GLintptr buffer_size = 16; 2243 GLsizei count = n_buffers; 2244 GLuint first = 0; 2245 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 2246 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */ 2247 GLint max_buffers = 0; 2248 size_t validated_index = n_buffers - 1; 2249 2250 /* Get max */ 2251 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers); 2252 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2253 2254 /* Select count so <first + count> does not exceed max. 2255 * Validated index shall be in the specified range. 2256 */ 2257 if (n_buffers > max_buffers) 2258 { 2259 count = max_buffers; 2260 validated_index = max_buffers - 1; 2261 } 2262 2263 /* Storage */ 2264 Buffer buffer[n_buffers]; 2265 GLuint buffer_ids[n_buffers]; 2266 GLintptr offsets[n_buffers]; 2267 GLsizei strides[n_buffers]; 2268 2269 /* Prepare buffers */ 2270 for (size_t j = 0; j < n_buffers; ++j) 2271 { 2272 buffer[j].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 2273 2274 buffer_ids[j] = buffer[j].m_id; 2275 offsets[j] = offset; 2276 strides[j] = stride; 2277 } 2278 2279 /* Prepare VAO */ 2280 GLuint vao = 0; 2281 gl.genVertexArrays(1, &vao); 2282 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 2283 try 2284 { 2285 gl.bindVertexArray(vao); 2286 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays"); 2287 2288 /* - INVALID_OPERATION when <first> + <count> exceeds limits; */ 2289 { 2290 GLsizei t_count = n_buffers; 2291 GLuint t_first = 0; 2292 2293 /* Select first so <first + count> exceeds max, avoid negative first */ 2294 if (n_buffers <= max_buffers) 2295 { 2296 t_first = max_buffers - n_buffers + 1; 2297 } 2298 else 2299 { 2300 t_count = max_buffers + 1; 2301 /* first = 0; */ 2302 } 2303 2304 /* Test */ 2305 gl.bindVertexBuffers(t_first, t_count, buffer_ids, offsets, strides); 2306 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid <first> + <count>"); 2307 } 2308 2309 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of 2310 * existing buffer; 2311 */ 2312 { 2313 GLuint t_buffer_ids[n_buffers]; 2314 2315 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids)); 2316 2317 /* Find invalid id */ 2318 while (1) 2319 { 2320 if (GL_TRUE != gl.isBuffer(invalid_id)) 2321 { 2322 break; 2323 } 2324 2325 invalid_id += 1; 2326 } 2327 2328 /* Invalidate the entry */ 2329 t_buffer_ids[validated_index] = invalid_id; 2330 2331 /* Test */ 2332 gl.bindVertexBuffers(first, count, t_buffer_ids, offsets, strides); 2333 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid buffer id"); 2334 } 2335 2336 /* - INVALID_VALUE if any value in <offsets> or <strides> is less than zero. */ 2337 { 2338 GLintptr t_offsets[n_buffers]; 2339 GLsizei t_strides[n_buffers]; 2340 2341 memcpy(t_offsets, offsets, sizeof(offsets)); 2342 memcpy(t_strides, strides, sizeof(strides)); 2343 2344 /* Invalidate the entry */ 2345 t_offsets[validated_index] = -1; 2346 t_strides[validated_index] = -1; 2347 2348 /* Test */ 2349 gl.bindVertexBuffers(first, count, buffer_ids, t_offsets, strides); 2350 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative offset"); 2351 2352 gl.bindVertexBuffers(first, count, buffer_ids, offsets, t_strides); 2353 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative stride"); 2354 } 2355 } 2356 catch (const std::exception&) 2357 { 2358 gl.deleteVertexArrays(1, &vao); 2359 TCU_FAIL("Unexpected error generated"); 2360 } 2361 2362 gl.deleteVertexArrays(1, &vao); 2363 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays"); 2364 2365 /* Set result */ 2366 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2367 2368 /* Done */ 2369 return tcu::TestNode::STOP; 2370 } 2371 2372 /** Constructor 2373 * 2374 * @param context Test context 2375 **/ 2376 FunctionalBindBuffersBaseTest::FunctionalBindBuffersBaseTest(deqp::Context& context) 2377 : TestCase(context, "functional_bind_buffers_base", "Verifies that BindBuffersBase works as expected") 2378 { 2379 /* Nothing to be done */ 2380 } 2381 2382 /** Execute test 2383 * 2384 * @return tcu::TestNode::STOP 2385 **/ 2386 tcu::TestNode::IterateResult FunctionalBindBuffersBaseTest::iterate() 2387 { 2388 const Functions& gl = m_context.getRenderContext().getFunctions(); 2389 2390 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2391 gl.debugMessageCallback(debug_proc, &m_context); 2392 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2393 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2394 2395 for (size_t i = 0; i < s_n_buffer_tragets; ++i) 2396 { 2397 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding; 2398 const GLenum pname_max = s_buffer_infos[i].m_pname_max; 2399 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size; 2400 const GLenum target = s_buffer_infos[i].m_target; 2401 const std::string& target_name = glu::getBufferTargetStr(target).toString(); 2402 2403 GLint max_buffers = 0; 2404 GLint max_size = 0; 2405 2406 /* Get max */ 2407 gl.getIntegerv(pname_max, &max_buffers); 2408 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2409 2410 /* Get max size */ 2411 gl.getIntegerv(pname_max_size, &max_size); 2412 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2413 2414 GLintptr buffer_size = max_size / max_buffers; 2415 2416 /* Storage */ 2417 std::vector<Buffer> buffer; 2418 std::vector<GLuint> buffer_ids; 2419 2420 buffer.resize(max_buffers); 2421 buffer_ids.resize(max_buffers); 2422 2423 /* Prepare buffers */ 2424 for (GLint j = 0; j < max_buffers; ++j) 2425 { 2426 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 2427 2428 buffer_ids[j] = buffer[j].m_id; 2429 } 2430 2431 /* 2432 * - execute BindBufferBase to bind all buffers to tested target; 2433 * - inspect if bindings were modified; 2434 */ 2435 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]); 2436 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase"); 2437 2438 for (GLint j = 0; j < max_buffers; ++j) 2439 { 2440 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2441 } 2442 2443 /* 2444 * 2445 * - execute BindBufferBase for first half of bindings with NULL as <buffers> 2446 * to unbind first half of bindings for tested target; 2447 * - inspect if bindings were modified; 2448 * - execute BindBufferBase for second half of bindings with NULL as <buffers> 2449 * to unbind rest of bindings; 2450 * - inspect if bindings were modified; 2451 */ 2452 GLint half_index = max_buffers / 2; 2453 gl.bindBuffersBase(target, 0 /* first */, half_index /* count */, 0); 2454 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase"); 2455 2456 for (GLint j = 0; j < half_index; ++j) 2457 { 2458 checkBinding(m_context, pname_binding, j, target_name, 0); 2459 } 2460 2461 for (GLint j = half_index; j < max_buffers; ++j) 2462 { 2463 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2464 } 2465 2466 gl.bindBuffersBase(target, half_index /* first */, max_buffers - half_index /* count */, 0); 2467 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase"); 2468 2469 for (GLint j = 0; j < max_buffers; ++j) 2470 { 2471 checkBinding(m_context, pname_binding, j, target_name, 0); 2472 } 2473 2474 /* 2475 * - change <buffers> so first entry is invalid; 2476 * - execute BindBufferBase to bind all buffers to tested target; It is 2477 * expected that INVALID_OPERATION will be generated; 2478 * - inspect if all bindings but first were modified; 2479 */ 2480 2481 /* Find invalid id */ 2482 GLuint invalid_id = 1; 2483 while (1) 2484 { 2485 if (GL_TRUE != gl.isBuffer(invalid_id)) 2486 { 2487 break; 2488 } 2489 2490 invalid_id += 1; 2491 } 2492 2493 buffer_ids[0] = invalid_id; 2494 2495 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]); 2496 CHECK_ERROR(GL_INVALID_OPERATION, "BindBufferBase with invalid buffer id"); 2497 2498 /* Update buffer_ids */ 2499 buffer_ids[0] = 0; /* 0 means unbound */ 2500 2501 for (GLint j = 0; j < max_buffers; ++j) 2502 { 2503 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2504 } 2505 2506 /* 2507 * - bind any buffer to first binding; 2508 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled 2509 * with zeros to unbind 1st binding for tested target; 2510 * - inspect if bindings were modified; 2511 */ 2512 gl.bindBufferBase(target, 0, buffer[0].m_id); 2513 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase"); 2514 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id); 2515 2516 std::vector<GLuint> t_buffer_ids; 2517 t_buffer_ids.resize(max_buffers); 2518 2519 gl.bindBuffersBase(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0]); 2520 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase"); 2521 2522 for (GLint j = 0; j < max_buffers; ++j) 2523 { 2524 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2525 } 2526 2527 /* - unbind all buffers. */ 2528 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0); 2529 } 2530 2531 /* Set result */ 2532 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2533 2534 /* Done */ 2535 return tcu::TestNode::STOP; 2536 } 2537 2538 /** Constructor 2539 * 2540 * @param context Test context 2541 **/ 2542 FunctionalBindBuffersRangeTest::FunctionalBindBuffersRangeTest(deqp::Context& context) 2543 : TestCase(context, "functional_bind_buffers_range", "Verifies that BindBuffersRange works as expected") 2544 { 2545 /* Nothing to be done */ 2546 } 2547 2548 /** Execute test 2549 * 2550 * @return tcu::TestNode::STOP 2551 **/ 2552 tcu::TestNode::IterateResult FunctionalBindBuffersRangeTest::iterate() 2553 { 2554 const Functions& gl = m_context.getRenderContext().getFunctions(); 2555 2556 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2557 gl.debugMessageCallback(debug_proc, &m_context); 2558 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2559 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2560 2561 for (size_t i = 0; i < s_n_buffer_tragets; ++i) 2562 { 2563 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding; 2564 const GLenum pname_max = s_buffer_infos[i].m_pname_max; 2565 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size; 2566 const GLenum target = s_buffer_infos[i].m_target; 2567 const std::string& target_name = glu::getBufferTargetStr(target).toString(); 2568 2569 GLint max_buffers = 0; 2570 GLint max_size = 0; 2571 2572 /* Get max */ 2573 gl.getIntegerv(pname_max, &max_buffers); 2574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2575 2576 /* Get max size */ 2577 gl.getIntegerv(pname_max_size, &max_size); 2578 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2579 2580 GLintptr buffer_size = max_size / max_buffers; 2581 2582 /* Storage */ 2583 std::vector<Buffer> buffer; 2584 std::vector<GLuint> buffer_ids; 2585 std::vector<GLintptr> offsets; 2586 std::vector<GLsizeiptr> sizes; 2587 2588 buffer.resize(max_buffers); 2589 buffer_ids.resize(max_buffers); 2590 offsets.resize(max_buffers); 2591 sizes.resize(max_buffers); 2592 2593 /* Prepare buffers */ 2594 for (GLint j = 0; j < max_buffers; ++j) 2595 { 2596 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 2597 2598 buffer_ids[j] = buffer[j].m_id; 2599 offsets[j] = 0; 2600 sizes[j] = buffer_size; 2601 } 2602 2603 /* 2604 * - execute BindBufferBase to bind all buffers to tested target; 2605 * - inspect if bindings were modified; 2606 */ 2607 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]); 2608 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange"); 2609 2610 for (GLint j = 0; j < max_buffers; ++j) 2611 { 2612 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2613 } 2614 2615 /* 2616 * 2617 * - execute BindBufferBase for first half of bindings with NULL as <buffers> 2618 * to unbind first half of bindings for tested target; 2619 * - inspect if bindings were modified; 2620 * - execute BindBufferBase for second half of bindings with NULL as <buffers> 2621 * to unbind rest of bindings; 2622 * - inspect if bindings were modified; 2623 */ 2624 GLint half_index = max_buffers / 2; 2625 gl.bindBuffersRange(target, 0 /* first */, half_index /* count */, 0, &offsets[0], &sizes[0]); 2626 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange"); 2627 2628 for (GLint j = 0; j < half_index; ++j) 2629 { 2630 checkBinding(m_context, pname_binding, j, target_name, 0); 2631 } 2632 2633 for (GLint j = half_index; j < max_buffers; ++j) 2634 { 2635 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2636 } 2637 2638 gl.bindBuffersRange(target, half_index /* first */, max_buffers - half_index /* count */, 0, &offsets[0], 2639 &sizes[0]); 2640 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange"); 2641 2642 for (GLint j = 0; j < max_buffers; ++j) 2643 { 2644 checkBinding(m_context, pname_binding, j, target_name, 0); 2645 } 2646 2647 /* 2648 * - change <buffers> so first entry is invalid; 2649 * - execute BindBufferBase to bind all buffers to tested target; It is 2650 * expected that INVALID_OPERATION will be generated; 2651 * - inspect if all bindings but first were modified; 2652 */ 2653 2654 /* Find invalid id */ 2655 GLuint invalid_id = 1; 2656 while (1) 2657 { 2658 if (GL_TRUE != gl.isBuffer(invalid_id)) 2659 { 2660 break; 2661 } 2662 2663 invalid_id += 1; 2664 } 2665 2666 buffer_ids[0] = invalid_id; 2667 2668 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]); 2669 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id"); 2670 2671 /* Update buffer_ids */ 2672 buffer_ids[0] = 0; /* 0 means unbound */ 2673 2674 for (GLint j = 0; j < max_buffers; ++j) 2675 { 2676 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2677 } 2678 2679 /* 2680 * - bind any buffer to first binding; 2681 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled 2682 * with zeros to unbind 1st binding for tested target; 2683 * - inspect if bindings were modified; 2684 */ 2685 gl.bindBufferBase(target, 0, buffer[0].m_id); 2686 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase"); 2687 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id); 2688 2689 std::vector<GLuint> t_buffer_ids; 2690 t_buffer_ids.resize(max_buffers); 2691 2692 gl.bindBuffersRange(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0], &offsets[0], &sizes[0]); 2693 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange"); 2694 2695 for (GLint j = 0; j < max_buffers; ++j) 2696 { 2697 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]); 2698 } 2699 2700 /* - unbind all buffers. */ 2701 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0); 2702 } 2703 2704 /* Set result */ 2705 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2706 2707 /* Done */ 2708 return tcu::TestNode::STOP; 2709 } 2710 2711 /** Constructor 2712 * 2713 * @param context Test context 2714 **/ 2715 FunctionalBindTexturesTest::FunctionalBindTexturesTest(deqp::Context& context) 2716 : TestCase(context, "functional_bind_textures", "Verifies that BindTextures works as expected") 2717 { 2718 /* Nothing to be done */ 2719 } 2720 2721 /** Execute test 2722 * 2723 * @return tcu::TestNode::STOP 2724 **/ 2725 tcu::TestNode::IterateResult FunctionalBindTexturesTest::iterate() 2726 { 2727 static const GLuint depth = 6; 2728 static const GLuint height = 6; 2729 static const GLuint width = 6; 2730 2731 const Functions& gl = m_context.getRenderContext().getFunctions(); 2732 2733 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2734 gl.debugMessageCallback(debug_proc, &m_context); 2735 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2736 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2737 2738 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 2739 GLint max_textures = 0; 2740 2741 /* Get max */ 2742 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures); 2743 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2744 2745 /* Storage */ 2746 Buffer buffer; 2747 std::vector<Texture> texture; 2748 std::vector<GLuint> texture_ids; 2749 std::vector<GLuint> t_texture_ids; 2750 2751 texture.resize(max_textures); 2752 texture_ids.resize(max_textures); 2753 t_texture_ids.resize(max_textures); 2754 2755 /* Prepare buffer */ 2756 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */); 2757 2758 /* Prepare textures */ 2759 for (size_t i = 0; i < s_n_texture_tragets; ++i) 2760 { 2761 const GLenum target = s_texture_infos[i].m_target; 2762 2763 if (GL_TEXTURE_BUFFER != target) 2764 { 2765 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth); 2766 } 2767 else 2768 { 2769 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id); 2770 } 2771 2772 /* Unbind */ 2773 Texture::Bind(gl, 0, target); 2774 } 2775 2776 for (GLint i = s_n_texture_tragets; i < max_textures; ++i) 2777 { 2778 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth); 2779 } 2780 2781 /* Unbind */ 2782 Texture::Bind(gl, 0, GL_TEXTURE_2D); 2783 2784 for (GLint i = 0; i < max_textures; ++i) 2785 { 2786 texture_ids[i] = texture[i].m_id; 2787 } 2788 2789 /* 2790 * - execute BindTextures to bind all textures; 2791 * - inspect bindings of all texture units to verify that proper bindings were 2792 * set; 2793 */ 2794 gl.bindTextures(0, max_textures, &texture_ids[0]); 2795 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 2796 2797 for (GLint i = 0; i < max_textures; ++i) 2798 { 2799 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]); 2800 } 2801 2802 /* 2803 * - execute BindTextures for the first half of units with <textures> filled 2804 * with zeros, to unbind those units; 2805 * - inspect bindings of all texture units to verify that proper bindings were 2806 * unbound; 2807 */ 2808 GLint half_index = max_textures / 2; 2809 2810 for (GLint i = 0; i < max_textures; ++i) 2811 { 2812 t_texture_ids[i] = 0; 2813 } 2814 2815 gl.bindTextures(0, half_index, &t_texture_ids[0]); 2816 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 2817 2818 for (GLint i = 0; i < half_index; ++i) 2819 { 2820 checkTextureBinding(m_context, getBinding(i), i, 0); 2821 } 2822 2823 for (GLint i = half_index; i < max_textures; ++i) 2824 { 2825 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]); 2826 } 2827 2828 /* 2829 * - execute BindTextures for the second half of units with NULL as<textures>, 2830 * to unbind those units; 2831 * - inspect bindings of all texture units to verify that proper bindings were 2832 * unbound; 2833 */ 2834 gl.bindTextures(half_index, max_textures - half_index, 0); 2835 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 2836 2837 for (GLint i = 0; i < max_textures; ++i) 2838 { 2839 checkTextureBinding(m_context, getBinding(i), i, 0); 2840 } 2841 2842 /* 2843 * - modify <textures> so first entry is invalid; 2844 * - execute BindTextures to bind all textures; It is expected that 2845 * INVALID_OPERATION will be generated; 2846 * - inspect bindings of all texture units to verify that proper bindings were 2847 * set; 2848 */ 2849 2850 /* Find invalid id */ 2851 while (1) 2852 { 2853 if (GL_TRUE != gl.isTexture(invalid_id)) 2854 { 2855 break; 2856 } 2857 2858 invalid_id += 1; 2859 } 2860 2861 /* Set invalid id */ 2862 texture_ids[0] = invalid_id; 2863 2864 gl.bindTextures(0, max_textures, &texture_ids[0]); 2865 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id"); 2866 2867 checkTextureBinding(m_context, getBinding(0), 0, 0); 2868 for (GLint i = 1; i < max_textures; ++i) 2869 { 2870 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]); 2871 } 2872 2873 /* - unbind all textures. */ 2874 gl.bindTextures(0, max_textures, 0); 2875 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 2876 2877 /* Set result */ 2878 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2879 2880 /* Done */ 2881 return tcu::TestNode::STOP; 2882 } 2883 2884 /** Constructor 2885 * 2886 * @param context Test context 2887 **/ 2888 FunctionalBindSamplersTest::FunctionalBindSamplersTest(deqp::Context& context) 2889 : TestCase(context, "functional_bind_samplers", "Verifies that BindSamplers works as expected") 2890 { 2891 /* Nothing to be done */ 2892 } 2893 2894 /** Execute test 2895 * 2896 * @return tcu::TestNode::STOP 2897 **/ 2898 tcu::TestNode::IterateResult FunctionalBindSamplersTest::iterate() 2899 { 2900 const Functions& gl = m_context.getRenderContext().getFunctions(); 2901 2902 #if DEBUG_ENBALE_MESSAGE_CALLBACK 2903 gl.debugMessageCallback(debug_proc, &m_context); 2904 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 2905 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 2906 2907 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 2908 GLint max_samplers = 0; 2909 2910 /* Get max */ 2911 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers); 2912 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 2913 2914 /* Storage */ 2915 std::vector<GLuint> sampler_ids; 2916 std::vector<GLuint> t_sampler_ids; 2917 2918 sampler_ids.resize(max_samplers); 2919 t_sampler_ids.resize(max_samplers); 2920 2921 for (GLint i = 0; i < max_samplers; ++i) 2922 { 2923 t_sampler_ids[i] = 0; 2924 } 2925 2926 /* Prepare samplers */ 2927 gl.genSamplers(max_samplers, &sampler_ids[0]); 2928 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers"); 2929 2930 try 2931 { 2932 /* - execute BindSamplers to bind all samplers; 2933 * - inspect bindings to verify that proper samplers were set; 2934 */ 2935 gl.bindSamplers(0 /* first */, max_samplers /* count */, &sampler_ids[0]); 2936 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers"); 2937 2938 for (GLint i = 0; i < max_samplers; ++i) 2939 { 2940 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]); 2941 } 2942 2943 /* - execute BindSamplers for first half of bindings with <samplers> filled 2944 * with zeros, to unbind those samplers; 2945 * - inspect bindings to verify that proper samplers were unbound; 2946 */ 2947 GLint half_index = max_samplers / 2; 2948 2949 gl.bindSamplers(0, half_index, &t_sampler_ids[0]); 2950 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers"); 2951 2952 for (GLint i = 0; i < half_index; ++i) 2953 { 2954 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0); 2955 } 2956 2957 for (GLint i = half_index; i < max_samplers; ++i) 2958 { 2959 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]); 2960 } 2961 2962 /* - execute BindSamplers for second half of bindings with NULL as <samplers>, 2963 * to unbind those samplers; 2964 * - inspect bindings to verify that proper samplers were unbound; 2965 */ 2966 gl.bindSamplers(half_index, max_samplers - half_index, 0); 2967 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers"); 2968 2969 for (GLint i = 0; i < max_samplers; ++i) 2970 { 2971 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0); 2972 } 2973 2974 /* - modify <samplers> so first entry is invalid; 2975 * - execute BindSamplers to bind all samplers; It is expected that 2976 * INVALID_OPERATION will be generated; 2977 * - inspect bindings to verify that proper samplers were set; 2978 */ 2979 2980 /* Find invalid id */ 2981 while (1) 2982 { 2983 if (GL_TRUE != gl.isSampler(invalid_id)) 2984 { 2985 break; 2986 } 2987 2988 invalid_id += 1; 2989 } 2990 2991 /* Prepare ids */ 2992 t_sampler_ids[0] = invalid_id; 2993 2994 for (GLint i = 1; i < max_samplers; ++i) 2995 { 2996 t_sampler_ids[i] = sampler_ids[i]; 2997 } 2998 2999 /* Bind */ 3000 gl.bindSamplers(0, max_samplers, &t_sampler_ids[0]); 3001 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id"); 3002 3003 /* Set 0 for invalid entry */ 3004 t_sampler_ids[0] = 0; 3005 3006 for (GLint i = 0; i < max_samplers; ++i) 3007 { 3008 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", t_sampler_ids[i]); 3009 } 3010 3011 /* - unbind all samplers. */ 3012 gl.bindSamplers(0, max_samplers, 0); 3013 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers"); 3014 } 3015 catch (const std::exception&) 3016 { 3017 gl.deleteSamplers(max_samplers, &sampler_ids[0]); 3018 3019 TCU_FAIL("Invalid error generated"); 3020 } 3021 3022 /* Delete samplers */ 3023 gl.deleteSamplers(max_samplers, &sampler_ids[0]); 3024 3025 /* Set result */ 3026 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3027 3028 /* Done */ 3029 return tcu::TestNode::STOP; 3030 } 3031 3032 /** Constructor 3033 * 3034 * @param context Test context 3035 **/ 3036 FunctionalBindImageTexturesTest::FunctionalBindImageTexturesTest(deqp::Context& context) 3037 : TestCase(context, "functional_bind_image_textures", "Verifies that BindImageTextures works as expected") 3038 { 3039 /* Nothing to be done */ 3040 } 3041 3042 /** Execute test 3043 * 3044 * @return tcu::TestNode::STOP 3045 **/ 3046 tcu::TestNode::IterateResult FunctionalBindImageTexturesTest::iterate() 3047 { 3048 static const GLuint depth = 6; 3049 static const GLuint height = 6; 3050 static const GLuint width = 6; 3051 3052 const Functions& gl = m_context.getRenderContext().getFunctions(); 3053 3054 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3055 gl.debugMessageCallback(debug_proc, &m_context); 3056 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3057 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3058 3059 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 3060 GLint max_textures = 0; 3061 3062 /* Get max */ 3063 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures); 3064 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3065 3066 /* Storage */ 3067 Buffer buffer; 3068 std::vector<Texture> texture; 3069 std::vector<GLuint> texture_ids; 3070 std::vector<GLuint> t_texture_ids; 3071 3072 texture.resize(max_textures); 3073 texture_ids.resize(max_textures); 3074 t_texture_ids.resize(max_textures); 3075 3076 /* Prepare buffer */ 3077 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */); 3078 3079 /* Prepare textures */ 3080 for (GLint i = 0; i < (GLint)s_n_texture_tragets; ++i) 3081 { 3082 const GLenum target = s_texture_infos[i].m_target; 3083 3084 if (i >= max_textures) 3085 { 3086 break; 3087 } 3088 3089 if (GL_TEXTURE_BUFFER != target) 3090 { 3091 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth); 3092 } 3093 else 3094 { 3095 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id); 3096 } 3097 3098 /* Unbind */ 3099 Texture::Bind(gl, 0, target); 3100 } 3101 3102 for (GLint i = (GLint)s_n_texture_tragets; i < max_textures; ++i) 3103 { 3104 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth); 3105 } 3106 3107 /* Unbind */ 3108 Texture::Bind(gl, 0, GL_TEXTURE_2D); 3109 3110 for (GLint i = 0; i < max_textures; ++i) 3111 { 3112 texture_ids[i] = texture[i].m_id; 3113 } 3114 3115 /* 3116 * - execute BindImageTextures to bind all images; 3117 * - inspect bindings to verify that proper images were set; 3118 */ 3119 gl.bindImageTextures(0, max_textures, &texture_ids[0]); 3120 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures"); 3121 3122 for (GLint i = 0; i < max_textures; ++i) 3123 { 3124 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]); 3125 } 3126 3127 /* 3128 * - execute BindTextures for the first half of units with <textures> filled 3129 * with zeros, to unbind those units; 3130 * - inspect bindings of all texture units to verify that proper bindings were 3131 * unbound; 3132 */ 3133 GLint half_index = max_textures / 2; 3134 3135 for (GLint i = 0; i < max_textures; ++i) 3136 { 3137 t_texture_ids[i] = 0; 3138 } 3139 3140 gl.bindImageTextures(0, half_index, &t_texture_ids[0]); 3141 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures"); 3142 3143 for (GLint i = 0; i < half_index; ++i) 3144 { 3145 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0); 3146 } 3147 3148 for (GLint i = half_index; i < max_textures; ++i) 3149 { 3150 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]); 3151 } 3152 3153 /* 3154 * - execute BindTextures for the second half of units with NULL as<textures>, 3155 * to unbind those units; 3156 * - inspect bindings of all texture units to verify that proper bindings were 3157 * unbound; 3158 */ 3159 gl.bindImageTextures(half_index, max_textures - half_index, 0); 3160 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures"); 3161 3162 for (GLint i = 0; i < max_textures; ++i) 3163 { 3164 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0); 3165 } 3166 3167 /* 3168 * - modify <textures> so first entry is invalid; 3169 * - execute BindTextures to bind all textures; It is expected that 3170 * INVALID_OPERATION will be generated; 3171 * - inspect bindings of all texture units to verify that proper bindings were 3172 * set; 3173 */ 3174 3175 /* Find invalid id */ 3176 while (1) 3177 { 3178 if (GL_TRUE != gl.isTexture(invalid_id)) 3179 { 3180 break; 3181 } 3182 3183 invalid_id += 1; 3184 } 3185 3186 /* Set invalid id */ 3187 texture_ids[0] = invalid_id; 3188 3189 gl.bindImageTextures(0, max_textures, &texture_ids[0]); 3190 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id"); 3191 3192 checkBinding(m_context, GL_IMAGE_BINDING_NAME, 0, "Image unit", 0); 3193 for (GLint i = 1; i < max_textures; ++i) 3194 { 3195 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]); 3196 } 3197 3198 /* - unbind all textures. */ 3199 gl.bindImageTextures(0, max_textures, 0); 3200 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures"); 3201 3202 /* Set result */ 3203 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3204 3205 /* Done */ 3206 return tcu::TestNode::STOP; 3207 } 3208 3209 /** Constructor 3210 * 3211 * @param context Test context 3212 **/ 3213 FunctionalBindVertexBuffersTest::FunctionalBindVertexBuffersTest(deqp::Context& context) 3214 : TestCase(context, "functional_bind_vertex_buffers", "Verifies that BindVertexBuffers works as expected") 3215 { 3216 /* Nothing to be done */ 3217 } 3218 3219 /** Execute test 3220 * 3221 * @return tcu::TestNode::STOP 3222 **/ 3223 tcu::TestNode::IterateResult FunctionalBindVertexBuffersTest::iterate() 3224 { 3225 const Functions& gl = m_context.getRenderContext().getFunctions(); 3226 3227 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3228 gl.debugMessageCallback(debug_proc, &m_context); 3229 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3230 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3231 3232 static const GLintptr buffer_size = 16; 3233 static const GLintptr offset = 4; 3234 static const GLsizei stride = 4; 3235 3236 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */ 3237 GLint max_buffers = 0; 3238 3239 /* Get max */ 3240 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers); 3241 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3242 3243 /* Storage */ 3244 std::vector<Buffer> buffer; 3245 std::vector<GLuint> buffer_ids; 3246 std::vector<GLintptr> offsets; 3247 std::vector<GLsizei> strides; 3248 std::vector<GLuint> t_buffer_ids; 3249 3250 buffer.resize(max_buffers); 3251 buffer_ids.resize(max_buffers); 3252 offsets.resize(max_buffers); 3253 strides.resize(max_buffers); 3254 t_buffer_ids.resize(max_buffers); 3255 3256 /* Prepare buffers */ 3257 for (GLint i = 0; i < max_buffers; ++i) 3258 { 3259 buffer[i].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 3260 3261 buffer_ids[i] = buffer[i].m_id; 3262 offsets[i] = offset; 3263 strides[i] = stride; 3264 t_buffer_ids[i] = 0; 3265 } 3266 3267 GLuint vao = 0; 3268 gl.genVertexArrays(1, &vao); 3269 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 3270 try 3271 { 3272 gl.bindVertexArray(vao); 3273 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays"); 3274 3275 /* - execute BindVertexBuffers to bind all buffer; 3276 * - inspect bindings to verify that proper buffers were set; 3277 */ 3278 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]); 3279 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers"); 3280 3281 for (GLint i = 0; i < max_buffers; ++i) 3282 { 3283 checkVertexAttribBinding(m_context, i, buffer_ids[i]); 3284 } 3285 3286 /* - execute BindVertexBuffers for first half of bindings with <buffers> filled 3287 * with zeros, to unbind those buffers; 3288 * - inspect bindings to verify that proper buffers were unbound; 3289 */ 3290 GLint half_index = max_buffers / 2; 3291 3292 gl.bindVertexBuffers(0, half_index, &t_buffer_ids[0], &offsets[0], &strides[0]); 3293 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers"); 3294 3295 for (GLint i = 0; i < half_index; ++i) 3296 { 3297 checkVertexAttribBinding(m_context, i, 0); 3298 } 3299 3300 for (GLint i = half_index; i < max_buffers; ++i) 3301 { 3302 checkVertexAttribBinding(m_context, i, buffer_ids[i]); 3303 } 3304 3305 /* - execute BindVertexBuffers for second half of bindings with NULL as 3306 * <buffers>, to unbind those buffers; 3307 * - inspect bindings to verify that proper buffers were unbound; 3308 */ 3309 gl.bindVertexBuffers(half_index, max_buffers - half_index, 0, &offsets[0], &strides[0]); 3310 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers"); 3311 3312 for (GLint i = 0; i < max_buffers; ++i) 3313 { 3314 checkVertexAttribBinding(m_context, i, 0); 3315 } 3316 3317 /* - modify <buffers> so first entry is invalid; 3318 * - execute BindVertexBuffers to bind all buffers; It is expected that 3319 * INVALID_OPERATION will be generated; 3320 * - inspect bindings to verify that proper buffers were set; 3321 */ 3322 3323 /* Find invalid id */ 3324 while (1) 3325 { 3326 if (GL_TRUE != gl.isBuffer(invalid_id)) 3327 { 3328 break; 3329 } 3330 3331 invalid_id += 1; 3332 } 3333 3334 buffer_ids[0] = invalid_id; 3335 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]); 3336 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid id"); 3337 3338 checkVertexAttribBinding(m_context, 0, 0); 3339 for (GLint i = 1; i < max_buffers; ++i) 3340 { 3341 checkVertexAttribBinding(m_context, i, buffer_ids[i]); 3342 } 3343 3344 /* - unbind all buffers. */ 3345 gl.bindVertexBuffers(0, max_buffers, 0, &offsets[0], &strides[0]); 3346 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers"); 3347 } 3348 catch (const std::exception&) 3349 { 3350 gl.deleteVertexArrays(1, &vao); 3351 3352 TCU_FAIL("Unexpected error generated"); 3353 } 3354 3355 gl.deleteVertexArrays(1, &vao); 3356 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays"); 3357 3358 /* Set result */ 3359 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3360 3361 /* Done */ 3362 return tcu::TestNode::STOP; 3363 } 3364 3365 /** Constructor 3366 * 3367 * @param context Test context 3368 **/ 3369 DispatchBindBuffersBaseTest::DispatchBindBuffersBaseTest(deqp::Context& context) 3370 : TestCase(context, "dispatch_bind_buffers_base", "Tests BindBuffersBase with dispatch command") 3371 { 3372 /* Nothing to be done */ 3373 } 3374 3375 /** Execute test 3376 * 3377 * @return tcu::TestNode::STOP 3378 **/ 3379 tcu::TestNode::IterateResult DispatchBindBuffersBaseTest::iterate() 3380 { 3381 static const GLchar* cs = "#version 440 core\n" 3382 "\n" 3383 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3384 "\n" 3385 "UBO_LIST\n" 3386 "layout (std140, binding = 0) buffer SSB {\n" 3387 " vec4 sum;\n" 3388 "} ssb;\n" 3389 "\n" 3390 "void main()\n" 3391 "{\n" 3392 " ssb.sum = SUM_LIST;\n" 3393 "}\n" 3394 "\n"; 3395 3396 static const GLchar* ubo = "layout (std140, binding = XXX) uniform BXXX { vec4 data; } bXXX;"; 3397 3398 static const GLintptr buffer_size = 4 * sizeof(GLfloat); 3399 3400 const Functions& gl = m_context.getRenderContext().getFunctions(); 3401 3402 bool test_result = true; 3403 3404 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3405 gl.debugMessageCallback(debug_proc, &m_context); 3406 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3407 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3408 3409 GLint max_buffers = 0; 3410 GLfloat sum[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 3411 3412 /* Get max */ 3413 gl.getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &max_buffers); 3414 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3415 3416 /* UBO */ 3417 /* Storage */ 3418 std::vector<Buffer> uni_buffer; 3419 std::vector<GLuint> uni_buffer_ids; 3420 3421 uni_buffer.resize(max_buffers); 3422 uni_buffer_ids.resize(max_buffers); 3423 3424 /* Prepare buffers */ 3425 for (GLint i = 0; i < max_buffers; ++i) 3426 { 3427 const GLfloat data[4] = { 3428 (GLfloat)(i * 4 + 0), (GLfloat)(i * 4 + 1), (GLfloat)(i * 4 + 2), (GLfloat)(i * 4 + 3), 3429 }; 3430 3431 sum[0] += data[0]; 3432 sum[1] += data[1]; 3433 sum[2] += data[2]; 3434 sum[3] += data[3]; 3435 3436 uni_buffer[i].InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, data); 3437 3438 uni_buffer_ids[i] = uni_buffer[i].m_id; 3439 } 3440 3441 gl.bindBuffersBase(GL_UNIFORM_BUFFER, 0 /* first */, max_buffers /* count */, &uni_buffer_ids[0]); 3442 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase"); 3443 3444 /* SSBO */ 3445 Buffer ssb_buffer; 3446 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */); 3447 3448 ssb_buffer.BindBase(0); 3449 3450 /* Prepare program */ 3451 size_t ubo_position = 0; 3452 size_t sum_position = 0; 3453 std::string cs_source = cs; 3454 for (GLint i = 0; i < max_buffers; ++i) 3455 { 3456 size_t ubo_start_position = ubo_position; 3457 size_t sum_start_position = sum_position; 3458 3459 GLchar index[16]; 3460 3461 sprintf(index, "%d", i); 3462 3463 /* Add entry to ubo list */ 3464 replaceToken("UBO_LIST", ubo_position, "UBO\nUBO_LIST", cs_source); 3465 ubo_position = ubo_start_position; 3466 3467 replaceToken("UBO", ubo_position, ubo, cs_source); 3468 ubo_position = ubo_start_position; 3469 3470 replaceToken("XXX", ubo_position, index, cs_source); 3471 replaceToken("XXX", ubo_position, index, cs_source); 3472 replaceToken("XXX", ubo_position, index, cs_source); 3473 3474 /* Add entry to sum list */ 3475 replaceToken("SUM_LIST", sum_position, "bXXX.data + SUM_LIST", cs_source); 3476 sum_position = sum_start_position; 3477 3478 replaceToken("XXX", sum_position, index, cs_source); 3479 } 3480 3481 /* Remove token for lists */ 3482 replaceToken(" + SUM_LIST", sum_position, "", cs_source); 3483 replaceToken("UBO_LIST", ubo_position, "", cs_source); 3484 3485 Program program(m_context); 3486 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 3487 3488 program.Use(); 3489 3490 gl.dispatchCompute(1, 1, 1); 3491 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 3492 3493 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 3494 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3495 3496 GLfloat* result = (GLfloat*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 3497 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 3498 3499 if (0 != memcmp(result, sum, 4 * sizeof(GLfloat))) 3500 { 3501 test_result = false; 3502 } 3503 3504 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 3505 gl.getError(); /* Ignore error */ 3506 3507 /* Set result */ 3508 if (true == test_result) 3509 { 3510 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3511 } 3512 else 3513 { 3514 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3515 } 3516 3517 /* Done */ 3518 return tcu::TestNode::STOP; 3519 } 3520 3521 /** Constructor 3522 * 3523 * @param context Test context 3524 **/ 3525 DispatchBindBuffersRangeTest::DispatchBindBuffersRangeTest(deqp::Context& context) 3526 : TestCase(context, "dispatch_bind_buffers_range", "Tests BindBuffersRange with dispatch command") 3527 { 3528 /* Nothing to be done */ 3529 } 3530 3531 /** Execute test 3532 * 3533 * @return tcu::TestNode::STOP 3534 **/ 3535 tcu::TestNode::IterateResult DispatchBindBuffersRangeTest::iterate() 3536 { 3537 static const GLchar* cs = "#version 440 core\n" 3538 "\n" 3539 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3540 "\n" 3541 "layout (std140, binding = 0) uniform B0 { int data; } b0;" 3542 "layout (std140, binding = 1) uniform B1 { int data; } b1;" 3543 "layout (std140, binding = 2) uniform B2 { int data; } b2;" 3544 "layout (std140, binding = 3) uniform B3 { int data; } b3;" 3545 "\n" 3546 "layout (std140, binding = 0) buffer SSB {\n" 3547 " int sum;\n" 3548 "} ssb;\n" 3549 "\n" 3550 "void main()\n" 3551 "{\n" 3552 " //ssb.sum = b1.data;// + b1.data + b2.data + b3.data;\n" 3553 " ssb.sum = b0.data + b1.data + b2.data + b3.data;\n" 3554 "}\n" 3555 "\n"; 3556 3557 static const GLint data[] = { 0x00010001, 0x01000100 }; 3558 static const size_t n_buffers = 4; 3559 static const GLint sum = 0x02020202; 3560 3561 const Functions& gl = m_context.getRenderContext().getFunctions(); 3562 3563 bool test_result = true; 3564 3565 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3566 gl.debugMessageCallback(debug_proc, &m_context); 3567 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3568 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3569 3570 /* UBO */ 3571 GLint offset_alignment = 0; 3572 3573 gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset_alignment); 3574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3575 3576 /* Storage */ 3577 Buffer uni_buffer; 3578 GLuint uni_buffer_ids[n_buffers]; 3579 std::vector<GLubyte> uni_data; 3580 GLintptr uni_offsets[n_buffers]; 3581 GLintptr uni_sizes[n_buffers]; 3582 3583 const size_t buffer_size = (n_buffers - 1) * offset_alignment + sizeof(GLint); 3584 uni_data.resize(buffer_size); 3585 3586 for (size_t i = 0; i < buffer_size; ++i) 3587 { 3588 uni_data[i] = 0xaa; 3589 } 3590 3591 for (size_t i = 0; i < n_buffers; ++i) 3592 { 3593 void* dst = &uni_data[i * offset_alignment]; 3594 const void* src = &data[(i % 2)]; 3595 3596 memcpy(dst, src, sizeof(GLint)); 3597 } 3598 3599 uni_buffer.InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, &uni_data[0]); 3600 3601 for (size_t i = 0; i < n_buffers; ++i) 3602 { 3603 uni_buffer_ids[i] = uni_buffer.m_id; 3604 uni_offsets[i] = i * offset_alignment; 3605 uni_sizes[i] = sizeof(GLint); 3606 } 3607 3608 gl.bindBuffersRange(GL_UNIFORM_BUFFER, 0 /* first */, n_buffers /* count */, &uni_buffer_ids[0], &uni_offsets[0], 3609 &uni_sizes[0]); 3610 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange"); 3611 3612 /* SSBO */ 3613 Buffer ssb_buffer; 3614 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLint), 0 /* data */); 3615 3616 ssb_buffer.BindBase(0); 3617 3618 /* Prepare program */ 3619 Program program(m_context); 3620 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 3621 3622 program.Use(); 3623 3624 gl.dispatchCompute(1, 1, 1); 3625 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 3626 3627 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 3628 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3629 3630 GLint* result = (GLint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 3631 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 3632 3633 if (0 != memcmp(result, &sum, sizeof(sum))) 3634 { 3635 test_result = false; 3636 } 3637 3638 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 3639 gl.getError(); /* Ignore error */ 3640 3641 /* Set result */ 3642 if (true == test_result) 3643 { 3644 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3645 } 3646 else 3647 { 3648 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3649 } 3650 3651 /* Done */ 3652 return tcu::TestNode::STOP; 3653 } 3654 3655 /** Constructor 3656 * 3657 * @param context Test context 3658 **/ 3659 DispatchBindTexturesTest::DispatchBindTexturesTest(deqp::Context& context) 3660 : TestCase(context, "dispatch_bind_textures", "Tests BindTextures with dispatch command") 3661 { 3662 /* Nothing to be done */ 3663 } 3664 3665 /** Execute test 3666 * 3667 * @return tcu::TestNode::STOP 3668 **/ 3669 tcu::TestNode::IterateResult DispatchBindTexturesTest::iterate() 3670 { 3671 static const GLchar* cs = "#version 440 core\n" 3672 "\n" 3673 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3674 "\n" 3675 "SAMPLER_LIST\n" 3676 "layout (std140, binding = 0) buffer SSB {\n" 3677 " uint sum;\n" 3678 "} ssb;\n" 3679 "\n" 3680 "void main()\n" 3681 "{\n" 3682 " uvec4 sum = SUM_LIST;\n" 3683 " ssb.sum = sum.r\n;" 3684 "}\n" 3685 "\n"; 3686 3687 static const GLchar* sampler = "layout (location = XXX) uniform SAMPLER sXXX;"; 3688 3689 static const GLchar* sampling[] = { 3690 "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", 3691 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", 3692 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS, 0)", "texelFetch(sXXX, COORDS, 0)" 3693 }; 3694 3695 static const GLchar* samplers[] = { "usampler1D", "usampler1DArray", "usampler2D", "usampler2DArray", 3696 "usampler3D", "usamplerBuffer", "usamplerCube", "usamplerCubeArray", 3697 "usampler2DRect", "usampler2DMS", "usampler2DMSArray" }; 3698 3699 static const GLchar* coordinates[] = { 3700 "0.5f", 3701 "vec2(0.5f, 0.0f)", 3702 "vec2(0.5f, 0.5f)", 3703 "vec3(0.5f, 0.5f, 0.0f)", 3704 "vec3(0.5f, 0.5f, 0.5f)", 3705 "0", 3706 "vec3(0.5f, 0.5f, 0.5f)", 3707 "vec4(0.5f, 0.5f, 0.5f, 0.0f)", 3708 "vec2(0.5f, 0.5f)", 3709 "ivec2(0, 0)", 3710 "ivec3(0, 0, 0)", 3711 }; 3712 3713 static const GLuint depth = 6; 3714 static const GLuint height = 6; 3715 static const GLuint width = 6; 3716 3717 const Functions& gl = m_context.getRenderContext().getFunctions(); 3718 3719 bool test_result = true; 3720 3721 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3722 gl.debugMessageCallback(debug_proc, &m_context); 3723 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3724 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3725 3726 GLint max_textures = 0; 3727 GLint max_image_samples = 0; 3728 GLuint sum = 0; 3729 3730 /* Get max */ 3731 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures); 3732 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3733 3734 /* Check if load/store from multisampled images is supported */ 3735 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples); 3736 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3737 3738 /* Textures */ 3739 /* Storage */ 3740 std::vector<Texture> texture; 3741 std::vector<GLuint> texture_ids; 3742 Buffer texture_buffer; 3743 3744 texture.resize(max_textures); 3745 texture_ids.resize(max_textures); 3746 3747 /* Prepare */ 3748 for (GLint i = 0; i < max_textures; ++i) 3749 { 3750 GLenum target = getTarget(i); 3751 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0) 3752 target = GL_TEXTURE_2D; 3753 3754 GLuint data[width * height * depth]; 3755 3756 for (GLuint j = 0; j < width * height * depth; ++j) 3757 { 3758 data[j] = i; 3759 } 3760 3761 sum += i; 3762 3763 bool is_array = false; 3764 3765 switch (target) 3766 { 3767 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 3768 is_array = true; 3769 /* Intended pass-through */ 3770 3771 case GL_TEXTURE_2D_MULTISAMPLE: 3772 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth); 3773 fillMSTexture(m_context, texture[i].m_id, i, is_array); 3774 break; 3775 3776 case GL_TEXTURE_BUFFER: 3777 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data); 3778 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id); 3779 break; 3780 3781 default: 3782 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth); 3783 Texture::Bind(gl, texture[i].m_id, target); 3784 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, 3785 GL_RED_INTEGER, GL_UNSIGNED_INT, &data); 3786 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3787 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3788 break; 3789 } 3790 3791 /* Clean */ 3792 Texture::Bind(gl, 0, target); 3793 3794 texture_ids[i] = texture[i].m_id; 3795 } 3796 3797 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]); 3798 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 3799 3800 /* SSBO */ 3801 Buffer ssb_buffer; 3802 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */); 3803 3804 ssb_buffer.BindBase(0); 3805 3806 /* Prepare program */ 3807 size_t sam_position = 0; 3808 size_t sum_position = 0; 3809 std::string cs_source = cs; 3810 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2); 3811 for (GLint i = 0; i < max_textures; ++i) 3812 { 3813 size_t sam_start_position = sam_position; 3814 size_t sum_start_position = sum_position; 3815 3816 GLchar index[16]; 3817 3818 sprintf(index, "%d", i); 3819 3820 const GLchar* coords = 0; 3821 const GLchar* sampler_type = 0; 3822 const GLchar* sampling_code = 0; 3823 3824 if (i < max_target_index) 3825 { 3826 coords = coordinates[i]; 3827 sampler_type = samplers[i]; 3828 sampling_code = sampling[i]; 3829 } 3830 else 3831 { 3832 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */ 3833 sampler_type = samplers[2]; /* usampler2D */ 3834 sampling_code = sampling[2]; /* texture(sXXX, COORDS) */ 3835 } 3836 3837 /* Add entry to ubo list */ 3838 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source); 3839 sam_position = sam_start_position; 3840 3841 replaceToken("SAMPLER", sam_position, sampler, cs_source); 3842 sam_position = sam_start_position; 3843 3844 replaceToken("XXX", sam_position, index, cs_source); 3845 replaceToken("SAMPLER", sam_position, sampler_type, cs_source); 3846 replaceToken("XXX", sam_position, index, cs_source); 3847 3848 /* Add entry to sum list */ 3849 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source); 3850 sum_position = sum_start_position; 3851 3852 replaceToken("SAMPLING", sum_position, sampling_code, cs_source); 3853 sum_position = sum_start_position; 3854 3855 replaceToken("XXX", sum_position, index, cs_source); 3856 replaceToken("COORDS", sum_position, coords, cs_source); 3857 } 3858 3859 /* Remove token for lists */ 3860 replaceToken(" + SUM_LIST", sum_position, "", cs_source); 3861 replaceToken("SAMPLER_LIST", sam_position, "", cs_source); 3862 3863 Program program(m_context); 3864 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 3865 3866 program.Use(); 3867 3868 /* Set samplers */ 3869 for (GLint i = 0; i < max_textures; ++i) 3870 { 3871 gl.uniform1i(i, i); 3872 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 3873 } 3874 3875 gl.dispatchCompute(1, 1, 1); 3876 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 3877 3878 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 3879 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3880 3881 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 3882 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 3883 3884 if (0 != memcmp(result, &sum, sizeof(sum))) 3885 { 3886 test_result = false; 3887 } 3888 3889 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 3890 gl.getError(); /* Ignore error */ 3891 3892 /* Set result */ 3893 if (true == test_result) 3894 { 3895 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3896 } 3897 else 3898 { 3899 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3900 } 3901 3902 /* Done */ 3903 return tcu::TestNode::STOP; 3904 } 3905 3906 /** Constructor 3907 * 3908 * @param context Test context 3909 **/ 3910 DispatchBindImageTexturesTest::DispatchBindImageTexturesTest(deqp::Context& context) 3911 : TestCase(context, "dispatch_bind_image_textures", "Tests BindImageTextures with dispatch command") 3912 { 3913 /* Nothing to be done */ 3914 } 3915 3916 /** Execute test 3917 * 3918 * @return tcu::TestNode::STOP 3919 **/ 3920 tcu::TestNode::IterateResult DispatchBindImageTexturesTest::iterate() 3921 { 3922 static const GLchar* cs = "#version 440 core\n" 3923 "\n" 3924 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3925 "\n" 3926 "IMAGE_LIST\n" 3927 "layout (std140, binding = 0) buffer SSB {\n" 3928 " uint sum;\n" 3929 "} ssb;\n" 3930 "\n" 3931 "void main()\n" 3932 "{\n" 3933 " uvec4 sum = SUM_LIST;\n" 3934 " ssb.sum = sum.r\n;" 3935 "}\n" 3936 "\n"; 3937 3938 static const GLchar* image = "layout (location = XXX, r32ui) readonly uniform IMAGE iXXX;"; 3939 3940 static const GLchar* loading[] = { 3941 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", 3942 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", 3943 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS, 0)", "imageLoad(iXXX, COORDS, 0)" 3944 }; 3945 3946 static const GLchar* images[] = { "uimage1D", "uimage1DArray", "uimage2D", "uimage2DArray", 3947 "uimage3D", "uimageBuffer", "uimageCube", "uimageCubeArray", 3948 "uimage2DRect", "uimage2DMS", "uimage2DMSArray" }; 3949 3950 static const GLchar* coordinates[] = { 3951 "0", 3952 "ivec2(0, 0)", 3953 "ivec2(0, 0)", 3954 "ivec3(0, 0, 0)", 3955 "ivec3(0, 0, 0)", 3956 "0", 3957 "ivec3(0, 0, 0)", 3958 "ivec3(0, 0, 0)", 3959 "ivec2(0, 0)", 3960 "ivec2(0, 0)", 3961 "ivec3(0, 0, 0)", 3962 }; 3963 3964 static const GLuint depth = 6; 3965 static const GLuint height = 6; 3966 static const GLuint width = 6; 3967 3968 const Functions& gl = m_context.getRenderContext().getFunctions(); 3969 3970 bool test_result = true; 3971 3972 #if DEBUG_ENBALE_MESSAGE_CALLBACK 3973 gl.debugMessageCallback(debug_proc, &m_context); 3974 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 3975 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 3976 3977 GLint max_textures = 0; 3978 GLint max_image_samples = 0; 3979 GLuint sum = 0; 3980 3981 /* Get max */ 3982 gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_textures); 3983 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3984 3985 /* Check if load/store from multisampled images is supported */ 3986 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples); 3987 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3988 3989 /* Textures */ 3990 /* Storage */ 3991 std::vector<Texture> texture; 3992 std::vector<GLuint> texture_ids; 3993 Buffer texture_buffer; 3994 3995 texture.resize(max_textures); 3996 texture_ids.resize(max_textures); 3997 3998 /* Prepare */ 3999 for (GLint i = 0; i < max_textures; ++i) 4000 { 4001 GLenum target = getTarget(i); 4002 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0) 4003 target = GL_TEXTURE_2D; 4004 4005 GLuint data[width * height * depth]; 4006 4007 for (GLuint j = 0; j < width * height * depth; ++j) 4008 { 4009 data[j] = i; 4010 } 4011 4012 sum += i; 4013 4014 bool is_array = false; 4015 4016 switch (target) 4017 { 4018 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 4019 is_array = true; 4020 /* Intended pass-through */ 4021 4022 case GL_TEXTURE_2D_MULTISAMPLE: 4023 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth); 4024 fillMSTexture(m_context, texture[i].m_id, i, is_array); 4025 break; 4026 4027 case GL_TEXTURE_BUFFER: 4028 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data); 4029 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id); 4030 break; 4031 4032 default: 4033 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth); 4034 Texture::Bind(gl, texture[i].m_id, target); 4035 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, 4036 GL_RED_INTEGER, GL_UNSIGNED_INT, &data); 4037 break; 4038 } 4039 4040 /* Clean */ 4041 Texture::Bind(gl, 0, target); 4042 4043 texture_ids[i] = texture[i].m_id; 4044 } 4045 4046 gl.bindImageTextures(0 /* first */, max_textures /* count */, &texture_ids[0]); 4047 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures"); 4048 4049 /* SSBO */ 4050 Buffer ssb_buffer; 4051 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */); 4052 4053 ssb_buffer.BindBase(0); 4054 4055 /* Prepare program */ 4056 size_t load_position = 0; 4057 size_t sum_position = 0; 4058 std::string cs_source = cs; 4059 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2); 4060 for (GLint i = 0; i < max_textures; ++i) 4061 { 4062 size_t load_start_position = load_position; 4063 size_t sum_start_position = sum_position; 4064 4065 GLchar index[16]; 4066 4067 sprintf(index, "%d", i); 4068 4069 const GLchar* coords = 0; 4070 const GLchar* image_type = 0; 4071 const GLchar* loading_code = 0; 4072 4073 if (i < max_target_index) 4074 { 4075 coords = coordinates[i]; 4076 image_type = images[i]; 4077 loading_code = loading[i]; 4078 } 4079 else 4080 { 4081 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */ 4082 image_type = images[2]; /* usampler2D */ 4083 loading_code = loading[2]; /* texture(sXXX, COORDS) */ 4084 } 4085 4086 /* Add entry to ubo list */ 4087 replaceToken("IMAGE_LIST", load_position, "IMAGE\nIMAGE_LIST", cs_source); 4088 load_position = load_start_position; 4089 4090 replaceToken("IMAGE", load_position, image, cs_source); 4091 load_position = load_start_position; 4092 4093 replaceToken("XXX", load_position, index, cs_source); 4094 replaceToken("IMAGE", load_position, image_type, cs_source); 4095 replaceToken("XXX", load_position, index, cs_source); 4096 4097 /* Add entry to sum list */ 4098 replaceToken("SUM_LIST", sum_position, "LOADING + SUM_LIST", cs_source); 4099 sum_position = sum_start_position; 4100 4101 replaceToken("LOADING", sum_position, loading_code, cs_source); 4102 sum_position = sum_start_position; 4103 4104 replaceToken("XXX", sum_position, index, cs_source); 4105 replaceToken("COORDS", sum_position, coords, cs_source); 4106 } 4107 4108 /* Remove token for lists */ 4109 replaceToken(" + SUM_LIST", sum_position, "", cs_source); 4110 replaceToken("IMAGE_LIST", load_position, "", cs_source); 4111 4112 Program program(m_context); 4113 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 4114 4115 program.Use(); 4116 4117 /* Set images */ 4118 for (GLint i = 0; i < max_textures; ++i) 4119 { 4120 gl.uniform1i(i, i); 4121 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 4122 } 4123 4124 gl.dispatchCompute(1, 1, 1); 4125 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 4126 4127 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 4128 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 4129 4130 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 4131 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4132 4133 if (0 != memcmp(result, &sum, sizeof(sum))) 4134 { 4135 test_result = false; 4136 } 4137 4138 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 4139 gl.getError(); /* Ignore error */ 4140 4141 /* Set result */ 4142 if (true == test_result) 4143 { 4144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4145 } 4146 else 4147 { 4148 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4149 } 4150 4151 /* Done */ 4152 return tcu::TestNode::STOP; 4153 } 4154 4155 /** Constructor 4156 * 4157 * @param context Test context 4158 **/ 4159 DispatchBindSamplersTest::DispatchBindSamplersTest(deqp::Context& context) 4160 : TestCase(context, "dispatch_bind_samplers", "Tests BindSamplers with dispatch command") 4161 { 4162 /* Nothing to be done */ 4163 } 4164 4165 /** Execute test 4166 * 4167 * @return tcu::TestNode::STOP 4168 **/ 4169 tcu::TestNode::IterateResult DispatchBindSamplersTest::iterate() 4170 { 4171 static const GLchar* cs = "#version 440 core\n" 4172 "\n" 4173 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 4174 "\n" 4175 "SAMPLER_LIST\n" 4176 "layout (std140, binding = 0) buffer SSB {\n" 4177 " uint sum;\n" 4178 "} ssb;\n" 4179 "\n" 4180 "void main()\n" 4181 "{\n" 4182 " uvec4 sum = SUM_LIST;\n" 4183 " ssb.sum = sum.r\n;" 4184 "}\n" 4185 "\n"; 4186 4187 static const GLchar* sampler = "layout (location = XXX) uniform usampler2D sXXX;"; 4188 4189 static const GLchar* sampling = "texture(sXXX, vec2(1.5f, 0.5f))"; 4190 4191 static const GLuint depth = 1; 4192 static const GLuint height = 8; 4193 static const GLuint width = 8; 4194 4195 const Functions& gl = m_context.getRenderContext().getFunctions(); 4196 4197 bool test_result = true; 4198 4199 #if DEBUG_ENBALE_MESSAGE_CALLBACK 4200 gl.debugMessageCallback(debug_proc, &m_context); 4201 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 4202 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 4203 4204 GLint max_textures = 0; 4205 4206 /* Get max */ 4207 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures); 4208 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 4209 4210 /* Textures */ 4211 /* Storage */ 4212 std::vector<GLuint> sampler_ids; 4213 std::vector<Texture> texture; 4214 std::vector<GLuint> texture_ids; 4215 4216 sampler_ids.resize(max_textures); 4217 texture.resize(max_textures); 4218 texture_ids.resize(max_textures); 4219 4220 GLuint data[width * height * depth]; 4221 4222 for (GLuint j = 0; j < width * height; ++j) 4223 { 4224 data[j] = 0; 4225 } 4226 4227 { 4228 const size_t last_line_offset = (height - 1) * width; 4229 const size_t last_pixel_in_line_offset = width - 1; 4230 4231 for (GLuint j = 0; j < width; ++j) 4232 { 4233 data[j] = 1; 4234 data[j + last_line_offset] = 1; 4235 } 4236 4237 for (GLuint j = 0; j < height; ++j) 4238 { 4239 const size_t line_offset = j * width; 4240 4241 data[line_offset] = 1; 4242 data[line_offset + last_pixel_in_line_offset] = 1; 4243 } 4244 } 4245 4246 /* Prepare */ 4247 for (GLint i = 0; i < max_textures; ++i) 4248 { 4249 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_R32UI, width, height, depth); 4250 Texture::Bind(gl, texture[i].m_id, GL_TEXTURE_2D); 4251 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, 4252 GL_RED_INTEGER, GL_UNSIGNED_INT, &data); 4253 4254 texture_ids[i] = texture[i].m_id; 4255 } 4256 4257 /* Clean */ 4258 Texture::Bind(gl, 0, GL_TEXTURE_2D); 4259 4260 /* Execute the test */ 4261 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]); 4262 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures"); 4263 4264 /* SSBO */ 4265 Buffer ssb_buffer; 4266 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */); 4267 4268 ssb_buffer.BindBase(0); 4269 4270 /* Prepare program */ 4271 size_t sam_position = 0; 4272 size_t sum_position = 0; 4273 std::string cs_source = cs; 4274 4275 for (GLint i = 0; i < max_textures; ++i) 4276 { 4277 size_t sam_start_position = sam_position; 4278 size_t sum_start_position = sum_position; 4279 4280 GLchar index[16]; 4281 4282 sprintf(index, "%d", i); 4283 4284 /* Add entry to ubo list */ 4285 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source); 4286 sam_position = sam_start_position; 4287 4288 replaceToken("SAMPLER", sam_position, sampler, cs_source); 4289 sam_position = sam_start_position; 4290 4291 replaceToken("XXX", sam_position, index, cs_source); 4292 replaceToken("XXX", sam_position, index, cs_source); 4293 4294 /* Add entry to sum list */ 4295 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source); 4296 sum_position = sum_start_position; 4297 4298 replaceToken("SAMPLING", sum_position, sampling, cs_source); 4299 sum_position = sum_start_position; 4300 4301 replaceToken("XXX", sum_position, index, cs_source); 4302 } 4303 4304 /* Remove token for lists */ 4305 replaceToken(" + SUM_LIST", sum_position, "", cs_source); 4306 replaceToken("SAMPLER_LIST", sam_position, "", cs_source); 4307 4308 Program program(m_context); 4309 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 4310 4311 program.Use(); 4312 4313 /* Set texture units */ 4314 for (GLint i = 0; i < max_textures; ++i) 4315 { 4316 gl.uniform1i(i, i); 4317 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 4318 } 4319 4320 /* Prepare samplers */ 4321 gl.genSamplers(max_textures, &sampler_ids[0]); 4322 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers"); 4323 4324 try 4325 { 4326 gl.bindSamplers(0 /* first */, max_textures /* count */, &sampler_ids[0]); 4327 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers"); 4328 4329 for (GLint i = 0; i < max_textures; ++i) 4330 { 4331 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 4332 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4333 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4334 GLU_EXPECT_NO_ERROR(gl.getError(), "SamplerParameteri"); 4335 } 4336 4337 gl.dispatchCompute(1, 1, 1); 4338 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 4339 4340 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 4341 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 4342 } 4343 catch (const std::exception&) 4344 { 4345 gl.deleteSamplers(max_textures, &sampler_ids[0]); 4346 4347 TCU_FAIL("Unexpected error generated"); 4348 } 4349 4350 /* Remove samplers */ 4351 gl.deleteSamplers(max_textures, &sampler_ids[0]); 4352 4353 /* Verify results */ 4354 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 4355 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4356 4357 if (0 != memcmp(result, &max_textures, sizeof(max_textures))) 4358 { 4359 test_result = false; 4360 } 4361 4362 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 4363 gl.getError(); /* Ignore error */ 4364 4365 /* Set result */ 4366 if (true == test_result) 4367 { 4368 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4369 } 4370 else 4371 { 4372 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4373 } 4374 4375 /* Done */ 4376 return tcu::TestNode::STOP; 4377 } 4378 4379 /** Constructor 4380 * 4381 * @param context Test context 4382 **/ 4383 DrawBindVertexBuffersTest::DrawBindVertexBuffersTest(deqp::Context& context) 4384 : TestCase(context, "draw_bind_vertex_buffers", "Tests BindVertexBuffers command with drawArrays") 4385 { 4386 /* Nothing to be done */ 4387 } 4388 4389 /** Execute test 4390 * 4391 * @return tcu::TestNode::STOP 4392 **/ 4393 tcu::TestNode::IterateResult DrawBindVertexBuffersTest::iterate() 4394 { 4395 static const GLchar* vs = "#version 440 core\n" 4396 "\n" 4397 "ATTRIBUTE_LIST\n" 4398 "\n" 4399 "out vec4 vs_gs_sum;\n" 4400 "\n" 4401 "void main()\n" 4402 "{\n" 4403 " vs_gs_sum = SUM_LIST;\n" 4404 "}\n" 4405 "\n"; 4406 4407 static const GLchar* gs = "#version 440 core\n" 4408 "\n" 4409 "layout(points) in;\n" 4410 "layout(triangle_strip, max_vertices = 4) out;\n" 4411 "\n" 4412 "in vec4 vs_gs_sum[];\n" 4413 "out vec4 gs_fs_sum;\n" 4414 "\n" 4415 "void main()\n" 4416 "{\n" 4417 " gs_fs_sum = vs_gs_sum[0];\n" 4418 " gl_Position = vec4(-1, -1, 0, 1);\n" 4419 " EmitVertex();\n" 4420 " gs_fs_sum = vs_gs_sum[0];\n" 4421 " gl_Position = vec4(-1, 1, 0, 1);\n" 4422 " EmitVertex();\n" 4423 " gs_fs_sum = vs_gs_sum[0];\n" 4424 " gl_Position = vec4(1, -1, 0, 1);\n" 4425 " EmitVertex();\n" 4426 " gs_fs_sum = vs_gs_sum[0];\n" 4427 " gl_Position = vec4(1, 1, 0, 1);\n" 4428 " EmitVertex();\n" 4429 "}\n" 4430 "\n"; 4431 4432 static const GLchar* fs = "#version 440 core\n" 4433 "\n" 4434 "in vec4 gs_fs_sum;\n" 4435 "out vec4 fs_out;\n" 4436 "\n" 4437 "void main()\n" 4438 "{\n" 4439 " fs_out = gs_fs_sum;\n" 4440 "}\n" 4441 "\n"; 4442 4443 static const GLchar* attribute = "layout (location = XXX) in vec4 aXXX;"; 4444 4445 static const GLuint height = 8; 4446 static const GLuint width = 8; 4447 4448 const Functions& gl = m_context.getRenderContext().getFunctions(); 4449 4450 bool test_result = true; 4451 4452 #if DEBUG_ENBALE_MESSAGE_CALLBACK 4453 gl.debugMessageCallback(debug_proc, &m_context); 4454 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback"); 4455 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ 4456 4457 static const GLintptr attribute_size = 4 * sizeof(GLfloat); 4458 4459 GLint max_buffers = 0; 4460 GLuint vao = 0; 4461 4462 /* Get max */ 4463 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers); 4464 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 4465 4466 /* Storage */ 4467 Buffer buffer; 4468 std::vector<GLuint> buffer_ids; 4469 std::vector<GLfloat> data; 4470 std::vector<GLintptr> offsets; 4471 std::vector<GLsizei> strides; 4472 4473 buffer_ids.resize(max_buffers); 4474 data.resize(max_buffers * 4); 4475 offsets.resize(max_buffers); 4476 strides.resize(max_buffers); 4477 4478 /* Prepare data */ 4479 const GLfloat value = 1.0f / (GLfloat)max_buffers; 4480 4481 for (GLint i = 0; i < max_buffers; ++i) 4482 { 4483 data[i * 4 + 0] = value; 4484 data[i * 4 + 1] = value; 4485 data[i * 4 + 2] = value; 4486 data[i * 4 + 3] = value; 4487 } 4488 4489 /* Prepare buffer */ 4490 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, data.size() * sizeof(GLfloat), &data[0]); 4491 4492 for (GLint i = 0; i < max_buffers; ++i) 4493 { 4494 buffer_ids[i] = buffer.m_id; 4495 offsets[i] = i * attribute_size; 4496 strides[i] = attribute_size; 4497 } 4498 4499 /* Prepare FBO */ 4500 Framebuffer framebuffer(m_context); 4501 Texture texture; 4502 4503 texture.InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 1 /* depth */); 4504 4505 /* */ 4506 Framebuffer::Generate(gl, framebuffer.m_id); 4507 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id); 4508 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width, 4509 height); 4510 4511 /* Prepare program */ 4512 size_t attr_position = 0; 4513 size_t sum_position = 0; 4514 std::string vs_source = vs; 4515 for (GLint i = 0; i < max_buffers; ++i) 4516 { 4517 size_t attr_start_position = attr_position; 4518 size_t sum_start_position = sum_position; 4519 4520 GLchar index[16]; 4521 4522 sprintf(index, "%d", i); 4523 4524 /* Add entry to ubo list */ 4525 replaceToken("ATTRIBUTE_LIST", attr_position, "ATTRIBUTE\nATTRIBUTE_LIST", vs_source); 4526 attr_position = attr_start_position; 4527 4528 replaceToken("ATTRIBUTE", attr_position, attribute, vs_source); 4529 attr_position = attr_start_position; 4530 4531 replaceToken("XXX", attr_position, index, vs_source); 4532 replaceToken("XXX", attr_position, index, vs_source); 4533 4534 /* Add entry to sum list */ 4535 replaceToken("SUM_LIST", sum_position, "aXXX + SUM_LIST", vs_source); 4536 sum_position = sum_start_position; 4537 4538 replaceToken("XXX", sum_position, index, vs_source); 4539 } 4540 4541 /* Remove token for lists */ 4542 replaceToken(" + SUM_LIST", sum_position, "", vs_source); 4543 replaceToken("ATTRIBUTE_LIST", attr_position, "", vs_source); 4544 4545 Program program(m_context); 4546 program.Init("" /* cs */, fs, gs, "" /* tcs */, "" /* tes */, vs_source.c_str()); 4547 4548 program.Use(); 4549 4550 gl.genVertexArrays(1, &vao); 4551 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 4552 4553 try 4554 { 4555 gl.bindVertexArray(vao); 4556 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays"); 4557 4558 for (GLint i = 0; i < max_buffers; ++i) 4559 { 4560 gl.enableVertexAttribArray(i); 4561 GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); 4562 } 4563 4564 /* */ 4565 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]); 4566 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers"); 4567 4568 /* */ 4569 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4570 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4571 4572 for (GLint i = 0; i < max_buffers; ++i) 4573 { 4574 gl.disableVertexAttribArray(i); 4575 GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray"); 4576 } 4577 } 4578 catch (const std::exception&) 4579 { 4580 gl.deleteVertexArrays(1, &vao); 4581 4582 TCU_FAIL("Unexpected error generated"); 4583 } 4584 4585 gl.deleteVertexArrays(1, &vao); 4586 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays"); 4587 4588 /* Verify results */ 4589 GLuint pixels[width * height]; 4590 for (GLuint i = 0; i < width * height; ++i) 4591 { 4592 pixels[i] = 0; 4593 } 4594 4595 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 4596 4597 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 4598 4599 /* Unbind */ 4600 Texture::Bind(gl, 0, GL_TEXTURE_2D); 4601 4602 /* Verify */ 4603 for (GLuint i = 0; i < width * height; ++i) 4604 { 4605 if (0xffffffff != pixels[i]) 4606 { 4607 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i] 4608 << " at offset: " << i << tcu::TestLog::EndMessage; 4609 4610 test_result = false; 4611 4612 break; 4613 } 4614 } 4615 4616 /* Set result */ 4617 if (true == test_result) 4618 { 4619 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4620 } 4621 else 4622 { 4623 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4624 } 4625 4626 /* Done */ 4627 return tcu::TestNode::STOP; 4628 } 4629 } /* MultiBind */ 4630 4631 /** Constructor. 4632 * 4633 * @param context Rendering context. 4634 **/ 4635 MultiBindTests::MultiBindTests(deqp::Context& context) 4636 : TestCaseGroup(context, "multi_bind", "Verifies \"multi bind\" functionality") 4637 { 4638 /* Left blank on purpose */ 4639 } 4640 4641 /** Initializes a multi_bind test group. 4642 * 4643 **/ 4644 void MultiBindTests::init(void) 4645 { 4646 addChild(new MultiBind::DispatchBindTexturesTest(m_context)); 4647 4648 addChild(new MultiBind::ErrorsBindBuffersTest(m_context)); 4649 addChild(new MultiBind::ErrorsBindTexturesTest(m_context)); 4650 addChild(new MultiBind::ErrorsBindSamplersTest(m_context)); 4651 addChild(new MultiBind::ErrorsBindImageTexturesTest(m_context)); 4652 addChild(new MultiBind::ErrorsBindVertexBuffersTest(m_context)); 4653 addChild(new MultiBind::FunctionalBindBuffersBaseTest(m_context)); 4654 addChild(new MultiBind::FunctionalBindBuffersRangeTest(m_context)); 4655 addChild(new MultiBind::FunctionalBindTexturesTest(m_context)); 4656 addChild(new MultiBind::FunctionalBindSamplersTest(m_context)); 4657 addChild(new MultiBind::FunctionalBindImageTexturesTest(m_context)); 4658 addChild(new MultiBind::FunctionalBindVertexBuffersTest(m_context)); 4659 addChild(new MultiBind::DispatchBindBuffersBaseTest(m_context)); 4660 addChild(new MultiBind::DispatchBindBuffersRangeTest(m_context)); 4661 4662 addChild(new MultiBind::DispatchBindImageTexturesTest(m_context)); 4663 addChild(new MultiBind::DispatchBindSamplersTest(m_context)); 4664 addChild(new MultiBind::DrawBindVertexBuffersTest(m_context)); 4665 } 4666 4667 } /* gl4cts namespace */ 4668