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