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 gl4cBufferStorageTests.cpp 26 * \brief Implements conformance tests for "Buffer storage" functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29#include "gl4cBufferStorageTests.hpp" 30 31#include "gluContextInfo.hpp" 32#include "gluDefs.hpp" 33#include "gluStrUtil.hpp" 34#include "glwEnums.hpp" 35#include "glwFunctions.hpp" 36#include "tcuImageIO.hpp" 37#include "tcuTestLog.hpp" 38#include "tcuTexture.hpp" 39 40#include <iomanip> 41#include <string> 42 43using namespace glw; 44 45namespace gl4cts 46{ 47namespace BufferStorage 48{ 49/* Enums */ 50 51/* Represents how functionality is supported */ 52enum FUNCTIONALITY_SUPPORT 53{ 54 FUNCTIONALITY_SUPPORT_NONE = 0, 55 FUNCTIONALITY_SUPPORT_EXTENSION, 56 FUNCTIONALITY_SUPPORT_CORE, 57 FUNCTIONALITY_SUPPORT_NOT_DETERMINED, 58}; 59 60/* Prototypes of functions */ 61FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context& context); 62bool isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor); 63 64/* Classes */ 65 66/** Represents buffer instance 67 * Provides basic buffer functionality 68 **/ 69class Buffer 70{ 71public: 72 // I don't quite understand how the old code *ever* worked... 73 // This is uglyish hack to make it actually compile on any sane 74 // compiler, and not crash. 75 struct MoveMapOwner 76 { 77 MoveMapOwner(Buffer* buffer_, glw::GLvoid* data_) : buffer(buffer_), data(data_) 78 { 79 } 80 81 Buffer* buffer; 82 glw::GLvoid* data; 83 }; 84 85 /* Public classes */ 86 class MapOwner 87 { 88 friend class Buffer; 89 90 public: 91 MapOwner(MapOwner& map_owner); 92 MapOwner(const MoveMapOwner& moveOwner); 93 ~MapOwner(); 94 95 glw::GLvoid* m_data; 96 97 private: 98 MapOwner(Buffer& buffer, glw::GLvoid* data); 99 100 Buffer* m_buffer; 101 }; 102 103 /* Public methods */ 104 /* Ctr & Dtr */ 105 Buffer(deqp::Context& context); 106 ~Buffer(); 107 108 /* Init & Release */ 109 void InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data); 110 111 void InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid* data); 112 113 void Release(); 114 115 /* Functionality */ 116 void Bind() const; 117 void BindBase(glw::GLuint index) const; 118 119 void BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const; 120 121 MoveMapOwner MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access); 122 123 void UnMap(); 124 125 /* Public static routines */ 126 /* Extensions */ 127 static void LoadExtDirectStateAccess(deqp::Context& context); 128 129 /* Functionality */ 130 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 131 132 static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index); 133 134 static void BindRange(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index, 135 glw::GLintptr offset, glw::GLsizeiptr size); 136 137 static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 138 const glw::GLvoid* data); 139 140 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 141 142 static void GetNamedParameter(const glw::Functions& gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint* data); 143 144 static void GetParameter(const glw::Functions& gl, glw::GLenum target, glw::GLenum value, glw::GLint* data); 145 146 static void GetSubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 147 glw::GLvoid* data); 148 149 static void* Map(const glw::Functions& gl, glw::GLenum target, glw::GLenum access); 150 151 static void* MapRange(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length, 152 glw::GLenum access); 153 154 static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, 155 const glw::GLvoid* data); 156 157 static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 158 glw::GLvoid* data); 159 160 static void UnMap(const glw::Functions& gl, glw::GLenum target); 161 162 /* Public fields */ 163 glw::GLuint m_id; 164 165 /* Public constants */ 166 static const glw::GLuint m_invalid_id; 167 static const glw::GLuint m_n_targets = 13; 168 static const glw::GLenum m_targets[m_n_targets]; 169 170private: 171 /* Private enums */ 172 173 /* Private fields */ 174 deqp::Context& m_context; 175 glw::GLenum m_target; 176}; 177 178/** Represents framebuffer 179 * Provides basic functionality 180 **/ 181class Framebuffer 182{ 183public: 184 /* Public methods */ 185 /* Ctr & Dtr */ 186 Framebuffer(deqp::Context& context); 187 ~Framebuffer(); 188 189 /* Init & Release */ 190 void Release(); 191 192 /* Public static routines */ 193 static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment, 194 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height); 195 196 static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id); 197 198 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 199 200 /* Public fields */ 201 glw::GLuint m_id; 202 203 /* Public constants */ 204 static const glw::GLuint m_invalid_id; 205 206private: 207 /* Private fields */ 208 deqp::Context& m_context; 209}; 210 211/** Represents shader instance. 212 * Provides basic functionality for shaders. 213 **/ 214class Shader 215{ 216public: 217 /* Public methods */ 218 /* Ctr & Dtr */ 219 Shader(deqp::Context& context); 220 ~Shader(); 221 222 /* Init & Realese */ 223 void Init(glw::GLenum stage, const std::string& source); 224 void Release(); 225 226 /* Public static routines */ 227 /* Functionality */ 228 static void Compile(const glw::Functions& gl, glw::GLuint id); 229 230 static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id); 231 232 static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source); 233 234 /* Public fields */ 235 glw::GLuint m_id; 236 237 /* Public constants */ 238 static const glw::GLuint m_invalid_id; 239 240private: 241 /* Private fields */ 242 deqp::Context& m_context; 243}; 244 245/** Represents program instance. 246 * Provides basic functionality 247 **/ 248class Program 249{ 250public: 251 /* Public methods */ 252 /* Ctr & Dtr */ 253 Program(deqp::Context& context); 254 ~Program(); 255 256 /* Init & Release */ 257 void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader, 258 const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader, 259 const std::string& vertex_shader); 260 261 void Release(); 262 263 /* Public static routines */ 264 /* Functionality */ 265 static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id); 266 267 static void Create(const glw::Functions& gl, glw::GLuint& out_id); 268 269 static void Link(const glw::Functions& gl, glw::GLuint id); 270 271 static void Use(const glw::Functions& gl, glw::GLuint id); 272 273 /* Public fields */ 274 glw::GLuint m_id; 275 276 Shader m_compute; 277 Shader m_fragment; 278 Shader m_geometry; 279 Shader m_tess_ctrl; 280 Shader m_tess_eval; 281 Shader m_vertex; 282 283 /* Public constants */ 284 static const glw::GLuint m_invalid_id; 285 286private: 287 /* Private fields */ 288 deqp::Context& m_context; 289}; 290 291/** Represents texture instance 292 **/ 293class Texture 294{ 295public: 296 /* Public types */ 297 /* Public methods */ 298 /* Ctr & Dtr */ 299 Texture(deqp::Context& context); 300 ~Texture(); 301 302 /* Init & Release */ 303 void Release(); 304 305 /* Public static routines */ 306 /* Extensions */ 307 static void LoadExtDirectStateAccess(deqp::Context& context); 308 309 /* Functionality */ 310 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 311 312 static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, 313 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth, 314 glw::GLsizei image_size, const glw::GLvoid* data); 315 316 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 317 318 static void GetData(const glw::Functions& gl, glw::GLenum target, glw::GLenum format, glw::GLenum type, 319 glw::GLvoid* out_data); 320 321 static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname, 322 glw::GLint* param); 323 324 static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format, 325 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, 326 const glw::GLvoid* data); 327 328 static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 329 glw::GLuint width, glw::GLuint height, glw::GLuint depth); 330 331 static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y, 332 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format, 333 glw::GLenum type, const glw::GLvoid* pixels); 334 335 /* Public fields */ 336 glw::GLuint m_id; 337 338 /* Public constants */ 339 static const glw::GLuint m_invalid_id; 340 341private: 342 /* Private fields */ 343 deqp::Context& m_context; 344 345 /* Private static fields */ 346 static FUNCTIONALITY_SUPPORT m_direct_state_access_support; 347}; 348 349/** Represents Vertex array object 350 * Provides basic functionality 351 **/ 352class VertexArray 353{ 354public: 355 /* Public methods */ 356 /* Ctr & Dtr */ 357 VertexArray(deqp::Context& Context); 358 ~VertexArray(); 359 360 /* Init & Release */ 361 void Release(); 362 363 /* Public static methods */ 364 static void Bind(const glw::Functions& gl, glw::GLuint id); 365 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 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/* Global variables */ 379static FUNCTIONALITY_SUPPORT m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED; 380 381/* Implementations of functions */ 382/** Get support for direct state access 383 * 384 * @param context CTS context 385 **/ 386FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context& context) 387{ 388 if (FUNCTIONALITY_SUPPORT_NOT_DETERMINED == m_direct_state_access_support) 389 { 390 const Functions& gl = context.getRenderContext().getFunctions(); 391 392 if (true == isGLVersionAtLeast(gl, 4, 5)) 393 { 394 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_CORE; 395 } 396 else 397 { 398 bool is_supported = context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 399 400 if (true == is_supported) 401 { 402 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_EXTENSION; 403 } 404 else 405 { 406 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NONE; 407 } 408 } 409 } 410 411 return m_direct_state_access_support; 412} 413 414/** Check if GL context meets version requirements 415 * 416 * @param gl Functions 417 * @param required_major Minimum required MAJOR_VERSION 418 * @param required_minor Minimum required MINOR_VERSION 419 * 420 * @return true if GL context version is at least as requested, false otherwise 421 **/ 422bool isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor) 423{ 424 glw::GLint major = 0; 425 glw::GLint minor = 0; 426 427 gl.getIntegerv(GL_MAJOR_VERSION, &major); 428 gl.getIntegerv(GL_MINOR_VERSION, &minor); 429 430 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 431 432 if (major > required_major) 433 { 434 /* Major is higher than required one */ 435 return true; 436 } 437 else if (major == required_major) 438 { 439 if (minor >= required_minor) 440 { 441 /* Major is equal to required one */ 442 /* Minor is higher than or equal to required one */ 443 return true; 444 } 445 else 446 { 447 /* Major is equal to required one */ 448 /* Minor is lower than required one */ 449 return false; 450 } 451 } 452 else 453 { 454 /* Major is lower than required one */ 455 return false; 456 } 457} 458 459/* Buffer constants */ 460const GLuint Buffer::m_invalid_id = -1; 461 462const GLenum Buffer::m_targets[Buffer::m_n_targets] = { 463 GL_ARRAY_BUFFER, /* 0 */ 464 GL_ATOMIC_COUNTER_BUFFER, /* 1 */ 465 GL_COPY_READ_BUFFER, /* 2 */ 466 GL_COPY_WRITE_BUFFER, /* 3 */ 467 GL_DISPATCH_INDIRECT_BUFFER, /* 4 */ 468 GL_DRAW_INDIRECT_BUFFER, /* 5 */ 469 GL_ELEMENT_ARRAY_BUFFER, /* 6 */ 470 GL_PIXEL_PACK_BUFFER, /* 7 */ 471 GL_PIXEL_UNPACK_BUFFER, /* 8 */ 472 GL_QUERY_BUFFER, /* 9 */ 473 GL_SHADER_STORAGE_BUFFER, /* 10 */ 474 GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */ 475 GL_UNIFORM_BUFFER, /* 12 */ 476}; 477 478/** Constructor. 479 * 480 * @param context CTS context. 481 **/ 482Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER) 483{ 484} 485 486/** Destructor 487 * 488 **/ 489Buffer::~Buffer() 490{ 491 Release(); 492} 493 494/** Initialize buffer instance 495 * 496 * @param target Buffer target 497 * @param usage Buffer usage enum 498 * @param size <size> parameter 499 * @param data <data> parameter 500 **/ 501void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data) 502{ 503 /* Delete previous buffer instance */ 504 Release(); 505 506 m_target = target; 507 508 const Functions& gl = m_context.getRenderContext().getFunctions(); 509 510 Generate(gl, m_id); 511 Bind(gl, m_id, m_target); 512 Data(gl, m_target, usage, size, data); 513} 514 515/** Initialize buffer instance 516 * 517 * @param target Buffer target 518 * @param usage Buffer usage enum 519 * @param size <size> parameter 520 * @param data <data> parameter 521 **/ 522void Buffer::InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid* data) 523{ 524 /* Delete previous buffer instance */ 525 Release(); 526 527 m_target = target; 528 529 const Functions& gl = m_context.getRenderContext().getFunctions(); 530 531 Generate(gl, m_id); 532 Bind(gl, m_id, m_target); 533 Storage(gl, m_target, flags, size, data); 534} 535 536/** Release buffer instance 537 * 538 **/ 539void Buffer::Release() 540{ 541 if (m_invalid_id != m_id) 542 { 543 const Functions& gl = m_context.getRenderContext().getFunctions(); 544 545 gl.deleteBuffers(1, &m_id); 546 m_id = m_invalid_id; 547 } 548} 549 550/** Binds buffer to its target 551 * 552 **/ 553void Buffer::Bind() const 554{ 555 const Functions& gl = m_context.getRenderContext().getFunctions(); 556 557 Bind(gl, m_id, m_target); 558} 559 560/** Binds indexed buffer 561 * 562 * @param index <index> parameter 563 **/ 564void Buffer::BindBase(glw::GLuint index) const 565{ 566 const Functions& gl = m_context.getRenderContext().getFunctions(); 567 568 BindBase(gl, m_id, m_target, index); 569} 570 571/** Binds range of buffer 572 * 573 * @param index <index> parameter 574 * @param offset <offset> parameter 575 * @param size <size> parameter 576 **/ 577void Buffer::BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const 578{ 579 const Functions& gl = m_context.getRenderContext().getFunctions(); 580 581 BindRange(gl, m_id, m_target, index, offset, size); 582} 583 584/** Maps contents of buffer into CPU space 585 * 586 * @param access Requested access 587 * 588 * @return Pointer to memory region available for CPU 589 **/ 590Buffer::MoveMapOwner Buffer::MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access) 591{ 592 const Functions& gl = m_context.getRenderContext().getFunctions(); 593 594 Bind(gl, m_id, m_target); 595 596 void* data = MapRange(gl, m_target, offset, length, access); 597 598 MoveMapOwner map(this, data); 599 600 return map; 601} 602 603/** Unmaps contents of buffer 604 * 605 **/ 606void Buffer::UnMap() 607{ 608 const Functions& gl = m_context.getRenderContext().getFunctions(); 609 610 UnMap(gl, m_target); 611} 612 613/** Loads entry points for direct state access extension 614 * 615 * @param context CTS context 616 **/ 617void Buffer::LoadExtDirectStateAccess(deqp::Context& context) 618{ 619 FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context); 620 621 switch (support) 622 { 623 case FUNCTIONALITY_SUPPORT_NONE: 624 /* Nothing to be done */ 625 break; 626 case FUNCTIONALITY_SUPPORT_CORE: 627 case FUNCTIONALITY_SUPPORT_EXTENSION: 628 break; 629 default: 630 TCU_FAIL("Invalid enum"); 631 break; 632 } 633} 634 635/** Bind buffer to given target 636 * 637 * @param gl GL functions 638 * @param id Id of buffer 639 * @param target Buffer target 640 **/ 641void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target) 642{ 643 gl.bindBuffer(target, id); 644 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 645} 646 647/** Binds indexed buffer 648 * 649 * @param gl GL functions 650 * @param id Id of buffer 651 * @param target Buffer target 652 * @param index <index> parameter 653 **/ 654void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index) 655{ 656 gl.bindBufferBase(target, index, id); 657 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase"); 658} 659 660/** Binds buffer range 661 * 662 * @param gl GL functions 663 * @param id Id of buffer 664 * @param target Buffer target 665 * @param index <index> parameter 666 * @param offset <offset> parameter 667 * @param size <size> parameter 668 **/ 669void Buffer::BindRange(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index, 670 glw::GLintptr offset, glw::GLsizeiptr size) 671{ 672 gl.bindBufferRange(target, index, id, offset, size); 673 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 674} 675 676/** Allocate memory for buffer and sends initial content 677 * 678 * @param gl GL functions 679 * @param target Buffer target 680 * @param usage Buffer usage enum 681 * @param size <size> parameter 682 * @param data <data> parameter 683 **/ 684void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 685 const glw::GLvoid* data) 686{ 687 gl.bufferData(target, size, data, usage); 688 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 689} 690 691/** Generate buffer 692 * 693 * @param gl GL functions 694 * @param out_id Id of buffer 695 **/ 696void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id) 697{ 698 GLuint id = m_invalid_id; 699 700 gl.genBuffers(1, &id); 701 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 702 703 if (m_invalid_id == id) 704 { 705 TCU_FAIL("Got invalid id"); 706 } 707 708 out_id = id; 709} 710 711/** Query parameter of named buffer 712 * 713 * @param gl GL functions 714 * @param buffer Buffer name 715 * @param pname Parameter name 716 * @param data Storage for queried results 717 **/ 718void Buffer::GetNamedParameter(const glw::Functions& gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint* data) 719{ 720 gl.getNamedBufferParameteriv(buffer, pname, data); 721 GLU_EXPECT_NO_ERROR(gl.getError(), "GetNameBufferParameteriv"); 722} 723 724/** Query parameter of bound buffer 725 * 726 * @param gl GL functions 727 * @param Target Buffer target 728 * @param pname Parameter name 729 * @param data Storage for queried results 730 **/ 731void Buffer::GetParameter(const glw::Functions& gl, glw::GLenum target, glw::GLenum value, glw::GLint* data) 732{ 733 gl.getBufferParameteriv(target, value, data); 734 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferParameteriv"); 735} 736 737/** Get contents of buffer's region 738 * 739 * @param gl GL functions 740 * @param target Buffer target 741 * @param offset Offset in buffer 742 * @param size <size> parameter 743 * @param data <data> parameter 744 **/ 745void Buffer::GetSubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 746 glw::GLvoid* data) 747{ 748 gl.getBufferSubData(target, offset, size, data); 749 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferSubData"); 750} 751 752/** Maps buffer content 753 * 754 * @param gl GL functions 755 * @param target Buffer target 756 * @param access Access rights for mapped region 757 * 758 * @return Mapped memory 759 **/ 760void* Buffer::Map(const glw::Functions& gl, glw::GLenum target, glw::GLenum access) 761{ 762 void* result = gl.mapBuffer(target, access); 763 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 764 765 return result; 766} 767 768/** Maps buffer content 769 * 770 * @param gl GL functions 771 * @param target Buffer target 772 * @param access Access rights for mapped region 773 * 774 * @return Mapped memory 775 **/ 776void* Buffer::MapRange(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length, 777 glw::GLenum access) 778{ 779 void* result = gl.mapBufferRange(target, offset, length, access); 780 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange"); 781 782 return result; 783} 784 785/** Allocate immutable memory for buffer and sends initial content 786 * 787 * @param gl GL functions 788 * @param target Buffer target 789 * @param flags Buffer flags 790 * @param size <size> parameter 791 * @param data <data> parameter 792 **/ 793void Buffer::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, 794 const glw::GLvoid* data) 795{ 796 gl.bufferStorage(target, size, data, flags); 797 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage"); 798} 799 800/** Update range of buffer 801 * 802 * @param gl GL functions 803 * @param target Buffer target 804 * @param offset Offset in buffer 805 * @param size <size> parameter 806 * @param data <data> parameter 807 **/ 808void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 809 glw::GLvoid* data) 810{ 811 gl.bufferSubData(target, offset, size, data); 812 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData"); 813} 814 815/** Unmaps buffer 816 * 817 * @param gl GL functions 818 * @param target Buffer target 819 **/ 820void Buffer::UnMap(const glw::Functions& gl, glw::GLenum target) 821{ 822 gl.unmapBuffer(target); 823 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 824} 825 826/** Constructor 827 * Takes ownership of mapped region 828 * 829 * @param buffer Mapped buffer 830 * @param data Mapped data 831 **/ 832Buffer::MapOwner::MapOwner(Buffer& buffer, glw::GLvoid* data) : m_data(data), m_buffer(&buffer) 833{ 834 /* Nothing to be done */ 835} 836 837Buffer::MapOwner::MapOwner(const Buffer::MoveMapOwner& moveOwner) : m_data(moveOwner.data), m_buffer(moveOwner.buffer) 838{ 839} 840 841/** Move constructor 842 * Transfer ownership of mapped region. 843 * 844 * @param map_owner Map owner 845 **/ 846Buffer::MapOwner::MapOwner(MapOwner& map_owner) : m_data(map_owner.m_data), m_buffer(map_owner.m_buffer) 847{ 848 map_owner.m_data = 0; 849 map_owner.m_buffer = 0; 850} 851 852/** Destructor 853 * Unmaps buffer 854 **/ 855Buffer::MapOwner::~MapOwner() 856{ 857 m_data = 0; 858 if (0 != m_buffer) 859 { 860 m_buffer->Bind(); 861 m_buffer->UnMap(); 862 m_buffer = 0; 863 } 864} 865 866/* Framebuffer constants */ 867const GLuint Framebuffer::m_invalid_id = -1; 868 869/** Constructor. 870 * 871 * @param context CTS context. 872 **/ 873Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 874{ 875 /* Nothing to done here */ 876} 877 878/** Destructor 879 * 880 **/ 881Framebuffer::~Framebuffer() 882{ 883 Release(); 884} 885 886/** Release texture instance 887 * 888 **/ 889void Framebuffer::Release() 890{ 891 if (m_invalid_id != m_id) 892 { 893 const Functions& gl = m_context.getRenderContext().getFunctions(); 894 895 gl.deleteFramebuffers(1, &m_id); 896 m_id = m_invalid_id; 897 } 898} 899 900/** Attach texture to specified attachment 901 * 902 * @param gl GL functions 903 * @param target Framebuffer target 904 * @param attachment Attachment 905 * @param texture_id Texture id 906 * @param width Texture width 907 * @param height Texture height 908 **/ 909void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment, 910 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height) 911{ 912 gl.framebufferTexture(target, attachment, texture_id, 0 /* level */); 913 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture"); 914 915 gl.viewport(0 /* x */, 0 /* y */, width, height); 916 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 917} 918 919/** Binds framebuffer to DRAW_FRAMEBUFFER 920 * 921 * @param gl GL functions 922 * @param target Framebuffer target 923 * @param id ID of framebuffer 924 **/ 925void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id) 926{ 927 gl.bindFramebuffer(target, id); 928 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 929} 930 931/** Generate framebuffer 932 * 933 **/ 934void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id) 935{ 936 GLuint id = m_invalid_id; 937 938 gl.genFramebuffers(1, &id); 939 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 940 941 if (m_invalid_id == id) 942 { 943 TCU_FAIL("Invalid id"); 944 } 945 946 out_id = id; 947} 948 949/* Program constants */ 950const GLuint Program::m_invalid_id = 0; 951 952/** Constructor. 953 * 954 * @param context CTS context. 955 **/ 956Program::Program(deqp::Context& context) 957 : m_id(m_invalid_id) 958 , m_compute(context) 959 , m_fragment(context) 960 , m_geometry(context) 961 , m_tess_ctrl(context) 962 , m_tess_eval(context) 963 , m_vertex(context) 964 , m_context(context) 965{ 966 /* Nothing to be done here */ 967} 968 969/** Destructor 970 * 971 **/ 972Program::~Program() 973{ 974 Release(); 975} 976 977/** Initialize program instance 978 * 979 * @param compute_shader Compute shader source code 980 * @param fragment_shader Fragment shader source code 981 * @param geometry_shader Geometry shader source code 982 * @param tesselation_control_shader Tesselation control shader source code 983 * @param tesselation_evaluation_shader Tesselation evaluation shader source code 984 * @param vertex_shader Vertex shader source code 985 **/ 986void Program::Init(const std::string& compute_shader, const std::string& fragment_shader, 987 const std::string& geometry_shader, const std::string& tesselation_control_shader, 988 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader) 989{ 990 /* Delete previous program */ 991 Release(); 992 993 /* GL entry points */ 994 const Functions& gl = m_context.getRenderContext().getFunctions(); 995 996 /* Initialize shaders */ 997 m_compute.Init(GL_COMPUTE_SHADER, compute_shader); 998 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader); 999 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader); 1000 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader); 1001 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader); 1002 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader); 1003 1004 /* Create program, set up transform feedback and attach shaders */ 1005 Create(gl, m_id); 1006 Attach(gl, m_id, m_compute.m_id); 1007 Attach(gl, m_id, m_fragment.m_id); 1008 Attach(gl, m_id, m_geometry.m_id); 1009 Attach(gl, m_id, m_tess_ctrl.m_id); 1010 Attach(gl, m_id, m_tess_eval.m_id); 1011 Attach(gl, m_id, m_vertex.m_id); 1012 1013 /* Link program */ 1014 Link(gl, m_id); 1015} 1016 1017/** Release program instance 1018 * 1019 **/ 1020void Program::Release() 1021{ 1022 const Functions& gl = m_context.getRenderContext().getFunctions(); 1023 1024 if (m_invalid_id != m_id) 1025 { 1026 Use(gl, m_invalid_id); 1027 1028 gl.deleteProgram(m_id); 1029 m_id = m_invalid_id; 1030 } 1031 1032 m_compute.Release(); 1033 m_fragment.Release(); 1034 m_geometry.Release(); 1035 m_tess_ctrl.Release(); 1036 m_tess_eval.Release(); 1037 m_vertex.Release(); 1038} 1039 1040/** Attach shader to program 1041 * 1042 * @param gl GL functions 1043 * @param program_id Id of program 1044 * @param shader_id Id of shader 1045 **/ 1046void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id) 1047{ 1048 /* Sanity checks */ 1049 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id)) 1050 { 1051 return; 1052 } 1053 1054 gl.attachShader(program_id, shader_id); 1055 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 1056} 1057 1058/** Create program instance 1059 * 1060 * @param gl GL functions 1061 * @param out_id Id of program 1062 **/ 1063void Program::Create(const glw::Functions& gl, glw::GLuint& out_id) 1064{ 1065 const GLuint id = gl.createProgram(); 1066 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 1067 1068 if (m_invalid_id == id) 1069 { 1070 TCU_FAIL("Failed to create program"); 1071 } 1072 1073 out_id = id; 1074} 1075 1076/** Link program 1077 * 1078 * @param gl GL functions 1079 * @param id Id of program 1080 **/ 1081void Program::Link(const glw::Functions& gl, glw::GLuint id) 1082{ 1083 GLint status = GL_FALSE; 1084 1085 gl.linkProgram(id); 1086 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); 1087 1088 /* Get link status */ 1089 gl.getProgramiv(id, GL_LINK_STATUS, &status); 1090 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 1091 1092 /* Log link error */ 1093 if (GL_TRUE != status) 1094 { 1095 glw::GLint length = 0; 1096 std::string message; 1097 1098 /* Get error log length */ 1099 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length); 1100 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 1101 1102 message.resize(length, 0); 1103 1104 /* Get error log */ 1105 gl.getProgramInfoLog(id, length, 0, &message[0]); 1106 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); 1107 1108 TCU_FAIL(message.c_str()); 1109 } 1110} 1111 1112/** Use program 1113 * 1114 * @param gl GL functions 1115 * @param id Id of program 1116 **/ 1117void Program::Use(const glw::Functions& gl, glw::GLuint id) 1118{ 1119 gl.useProgram(id); 1120 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 1121} 1122 1123/* Shader's constants */ 1124const GLuint Shader::m_invalid_id = 0; 1125 1126/** Constructor. 1127 * 1128 * @param context CTS context. 1129 **/ 1130Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 1131{ 1132 /* Nothing to be done here */ 1133} 1134 1135/** Destructor 1136 * 1137 **/ 1138Shader::~Shader() 1139{ 1140 Release(); 1141} 1142 1143/** Initialize shader instance 1144 * 1145 * @param stage Shader stage 1146 * @param source Source code 1147 **/ 1148void Shader::Init(glw::GLenum stage, const std::string& source) 1149{ 1150 if (true == source.empty()) 1151 { 1152 /* No source == no shader */ 1153 return; 1154 } 1155 1156 /* Delete any previous shader */ 1157 Release(); 1158 1159 /* Create, set source and compile */ 1160 const Functions& gl = m_context.getRenderContext().getFunctions(); 1161 1162 Create(gl, stage, m_id); 1163 Source(gl, m_id, source); 1164 1165 Compile(gl, m_id); 1166} 1167 1168/** Release shader instance 1169 * 1170 **/ 1171void Shader::Release() 1172{ 1173 if (m_invalid_id != m_id) 1174 { 1175 const Functions& gl = m_context.getRenderContext().getFunctions(); 1176 1177 gl.deleteShader(m_id); 1178 m_id = m_invalid_id; 1179 } 1180} 1181 1182/** Compile shader 1183 * 1184 * @param gl GL functions 1185 * @param id Shader id 1186 **/ 1187void Shader::Compile(const glw::Functions& gl, glw::GLuint id) 1188{ 1189 GLint status = GL_FALSE; 1190 1191 /* Compile */ 1192 gl.compileShader(id); 1193 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); 1194 1195 /* Get compilation status */ 1196 gl.getShaderiv(id, GL_COMPILE_STATUS, &status); 1197 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 1198 1199 /* Log compilation error */ 1200 if (GL_TRUE != status) 1201 { 1202 glw::GLint length = 0; 1203 std::string message; 1204 1205 /* Error log length */ 1206 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length); 1207 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 1208 1209 /* Prepare storage */ 1210 message.resize(length, 0); 1211 1212 /* Get error log */ 1213 gl.getShaderInfoLog(id, length, 0, &message[0]); 1214 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); 1215 1216 TCU_FAIL(message.c_str()); 1217 } 1218} 1219 1220/** Create shader 1221 * 1222 * @param gl GL functions 1223 * @param stage Shader stage 1224 * @param out_id Shader id 1225 **/ 1226void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id) 1227{ 1228 const GLuint id = gl.createShader(stage); 1229 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 1230 1231 if (m_invalid_id == id) 1232 { 1233 TCU_FAIL("Failed to create shader"); 1234 } 1235 1236 out_id = id; 1237} 1238 1239/** Set shader's source code 1240 * 1241 * @param gl GL functions 1242 * @param id Shader id 1243 * @param source Shader source code 1244 **/ 1245void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source) 1246{ 1247 const GLchar* code = source.c_str(); 1248 1249 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */); 1250 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); 1251} 1252 1253/* Texture static fields */ 1254 1255FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED; 1256 1257/* Texture constants */ 1258const GLuint Texture::m_invalid_id = -1; 1259 1260/** Constructor. 1261 * 1262 * @param context CTS context. 1263 **/ 1264Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 1265{ 1266 /* Nothing to done here */ 1267} 1268 1269/** Destructor 1270 * 1271 **/ 1272Texture::~Texture() 1273{ 1274 Release(); 1275} 1276 1277/** Release texture instance 1278 * 1279 **/ 1280void Texture::Release() 1281{ 1282 if (m_invalid_id != m_id) 1283 { 1284 const Functions& gl = m_context.getRenderContext().getFunctions(); 1285 1286 gl.deleteTextures(1, &m_id); 1287 m_id = m_invalid_id; 1288 } 1289} 1290 1291/** Loads entry points for direct state access extension 1292 * 1293 * @param context CTS context 1294 **/ 1295void Texture::LoadExtDirectStateAccess(deqp::Context& context) 1296{ 1297 FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context); 1298 1299 switch (support) 1300 { 1301 case FUNCTIONALITY_SUPPORT_NONE: 1302 /* Nothing to be done */ 1303 break; 1304 case FUNCTIONALITY_SUPPORT_CORE: 1305 case FUNCTIONALITY_SUPPORT_EXTENSION: 1306 break; 1307 default: 1308 TCU_FAIL("Invalid enum"); 1309 break; 1310 } 1311} 1312 1313/** Bind texture to target 1314 * 1315 * @param gl GL functions 1316 * @param id Id of texture 1317 * @param tex_type Type of texture 1318 **/ 1319void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target) 1320{ 1321 gl.bindTexture(target, id); 1322 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 1323} 1324 1325/** Set contents of compressed texture 1326 * 1327 * @param gl GL functions 1328 * @param target Texture target 1329 * @param level Mipmap level 1330 * @param internal_format Format of data 1331 * @param width Width of texture 1332 * @param height Height of texture 1333 * @param depth Depth of texture 1334 * @param image_size Size of data 1335 * @param data Buffer with image data 1336 **/ 1337void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, 1338 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth, 1339 glw::GLsizei image_size, const glw::GLvoid* data) 1340{ 1341 switch (target) 1342 { 1343 case GL_TEXTURE_1D: 1344 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data); 1345 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D"); 1346 break; 1347 case GL_TEXTURE_1D_ARRAY: 1348 case GL_TEXTURE_2D: 1349 case GL_TEXTURE_RECTANGLE: 1350 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data); 1351 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D"); 1352 break; 1353 case GL_TEXTURE_CUBE_MAP: 1354 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, 1355 image_size, data); 1356 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, 1357 image_size, data); 1358 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, 1359 image_size, data); 1360 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, 1361 image_size, data); 1362 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, 1363 image_size, data); 1364 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, 1365 image_size, data); 1366 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D"); 1367 break; 1368 case GL_TEXTURE_3D: 1369 case GL_TEXTURE_2D_ARRAY: 1370 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data); 1371 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D"); 1372 break; 1373 default: 1374 TCU_FAIL("Invliad enum"); 1375 break; 1376 } 1377} 1378 1379/** Generate texture instance 1380 * 1381 * @param gl GL functions 1382 * @param out_id Id of texture 1383 **/ 1384void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id) 1385{ 1386 GLuint id = m_invalid_id; 1387 1388 gl.genTextures(1, &id); 1389 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 1390 1391 if (m_invalid_id == id) 1392 { 1393 TCU_FAIL("Invalid id"); 1394 } 1395 1396 out_id = id; 1397} 1398 1399/** Get texture data 1400 * 1401 * @param gl GL functions 1402 * @param target Texture target 1403 * @param format Format of data 1404 * @param type Type of data 1405 * @param out_data Buffer for data 1406 **/ 1407void Texture::GetData(const glw::Functions& gl, glw::GLenum target, glw::GLenum format, glw::GLenum type, 1408 glw::GLvoid* out_data) 1409{ 1410 gl.getTexImage(target, 0 /* level */, format, type, out_data); 1411 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); 1412} 1413 1414/** Generate texture instance 1415 * 1416 * @param gl GL functions 1417 * @param target Texture target 1418 * @param level Mipmap level 1419 * @param pname Parameter to query 1420 * @param param Result of query 1421 **/ 1422void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname, 1423 glw::GLint* param) 1424{ 1425 gl.getTexLevelParameteriv(target, level, pname, param); 1426 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv"); 1427} 1428 1429/** Set contents of texture 1430 * 1431 * @param gl GL functions 1432 * @param target Texture target 1433 * @param level Mipmap level 1434 * @param internal_format Format of data 1435 * @param width Width of texture 1436 * @param height Height of texture 1437 * @param depth Depth of texture 1438 * @param format Format of data 1439 * @param type Type of data 1440 * @param data Buffer with image data 1441 **/ 1442void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format, 1443 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, 1444 const glw::GLvoid* data) 1445{ 1446 switch (target) 1447 { 1448 case GL_TEXTURE_1D: 1449 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data); 1450 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D"); 1451 break; 1452 case GL_TEXTURE_1D_ARRAY: 1453 case GL_TEXTURE_2D: 1454 case GL_TEXTURE_RECTANGLE: 1455 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data); 1456 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D"); 1457 break; 1458 case GL_TEXTURE_CUBE_MAP: 1459 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format, 1460 type, data); 1461 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format, 1462 type, data); 1463 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format, 1464 type, data); 1465 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format, 1466 type, data); 1467 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format, 1468 type, data); 1469 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format, 1470 type, data); 1471 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D"); 1472 break; 1473 case GL_TEXTURE_3D: 1474 case GL_TEXTURE_2D_ARRAY: 1475 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data); 1476 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D"); 1477 break; 1478 default: 1479 TCU_FAIL("Invliad enum"); 1480 break; 1481 } 1482} 1483 1484/** Allocate storage for texture 1485 * 1486 * @param gl GL functions 1487 * @param target Texture target 1488 * @param levels Number of levels 1489 * @param internal_format Internal format of texture 1490 * @param width Width of texture 1491 * @param height Height of texture 1492 * @param depth Depth of texture 1493 **/ 1494void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 1495 glw::GLuint width, glw::GLuint height, glw::GLuint depth) 1496{ 1497 switch (target) 1498 { 1499 case GL_TEXTURE_1D: 1500 gl.texStorage1D(target, levels, internal_format, width); 1501 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D"); 1502 break; 1503 case GL_TEXTURE_1D_ARRAY: 1504 case GL_TEXTURE_2D: 1505 case GL_TEXTURE_RECTANGLE: 1506 case GL_TEXTURE_CUBE_MAP: 1507 gl.texStorage2D(target, levels, internal_format, width, height); 1508 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); 1509 break; 1510 case GL_TEXTURE_3D: 1511 case GL_TEXTURE_2D_ARRAY: 1512 gl.texStorage3D(target, levels, internal_format, width, height, depth); 1513 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D"); 1514 break; 1515 default: 1516 TCU_FAIL("Invliad enum"); 1517 break; 1518 } 1519} 1520 1521/** Set contents of texture 1522 * 1523 * @param gl GL functions 1524 * @param target Texture target 1525 * @param level Mipmap level 1526 * @param x X offset 1527 * @param y Y offset 1528 * @param z Z offset 1529 * @param width Width of texture 1530 * @param height Height of texture 1531 * @param depth Depth of texture 1532 * @param format Format of data 1533 * @param type Type of data 1534 * @param pixels Buffer with image data 1535 **/ 1536void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y, 1537 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format, 1538 glw::GLenum type, const glw::GLvoid* pixels) 1539{ 1540 switch (target) 1541 { 1542 case GL_TEXTURE_1D: 1543 gl.texSubImage1D(target, level, x, width, format, type, pixels); 1544 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D"); 1545 break; 1546 case GL_TEXTURE_1D_ARRAY: 1547 case GL_TEXTURE_2D: 1548 case GL_TEXTURE_RECTANGLE: 1549 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels); 1550 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 1551 break; 1552 case GL_TEXTURE_CUBE_MAP: 1553 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels); 1554 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels); 1555 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels); 1556 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels); 1557 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels); 1558 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels); 1559 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 1560 break; 1561 case GL_TEXTURE_3D: 1562 case GL_TEXTURE_2D_ARRAY: 1563 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels); 1564 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D"); 1565 break; 1566 default: 1567 TCU_FAIL("Invliad enum"); 1568 break; 1569 } 1570} 1571 1572/* VertexArray constants */ 1573const GLuint VertexArray::m_invalid_id = -1; 1574 1575/** Constructor. 1576 * 1577 * @param context CTS context. 1578 **/ 1579VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context) 1580{ 1581} 1582 1583/** Destructor 1584 * 1585 **/ 1586VertexArray::~VertexArray() 1587{ 1588 Release(); 1589} 1590 1591/** Release vertex array object instance 1592 * 1593 **/ 1594void VertexArray::Release() 1595{ 1596 if (m_invalid_id != m_id) 1597 { 1598 const Functions& gl = m_context.getRenderContext().getFunctions(); 1599 1600 Bind(gl, 0); 1601 1602 gl.deleteVertexArrays(1, &m_id); 1603 1604 m_id = m_invalid_id; 1605 } 1606} 1607 1608/** Binds Vertex array object 1609 * 1610 * @param gl GL functions 1611 * @param id ID of vertex array object 1612 **/ 1613void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id) 1614{ 1615 gl.bindVertexArray(id); 1616 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); 1617} 1618 1619/** Generates Vertex array object 1620 * 1621 * @param gl GL functions 1622 * @param out_id ID of vertex array object 1623 **/ 1624void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id) 1625{ 1626 GLuint id = m_invalid_id; 1627 1628 gl.genVertexArrays(1, &id); 1629 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 1630 1631 if (m_invalid_id == id) 1632 { 1633 TCU_FAIL("Invalid id"); 1634 } 1635 1636 out_id = id; 1637} 1638 1639/** Constructor 1640 * 1641 * @param context Test context 1642 **/ 1643ErrorsTest::ErrorsTest(deqp::Context& context) 1644 : TestCase(context, "errors", "Test if errors are generated as specified") 1645{ 1646 /* Nothing to be done here */ 1647} 1648 1649/** Execute test 1650 * 1651 * @return tcu::TestNode::STOP otherwise 1652 **/ 1653tcu::TestNode::IterateResult ErrorsTest::iterate() 1654{ 1655 const Functions& gl = m_context.getRenderContext().getFunctions(); 1656 1657 bool test_result = true; 1658 1659 Buffer::LoadExtDirectStateAccess(m_context); 1660 1661 // No GL45 or GL_ARB_direct_state_access support 1662 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE) 1663 { 1664 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported"); 1665 return tcu::TestNode::STOP; 1666 } 1667 1668 /* 1669 * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to 1670 * <target>; Check all targets; 1671 */ 1672 for (GLuint i = 0; i < Buffer::m_n_targets; ++i) 1673 { 1674 const GLenum target = Buffer::m_targets[i]; 1675 std::string message = "BufferStorage was executed for id 0, target: "; 1676 1677 message.append(glu::getBufferTargetStr(target).toString().c_str()); 1678 1679 Buffer::Bind(gl, 0 /* id */, target); 1680 gl.bufferStorage(target, 0 /* size */, 0 /* data */, GL_DYNAMIC_STORAGE_BIT /* flags */); 1681 1682 verifyError(GL_INVALID_OPERATION, message.c_str(), test_result); 1683 } 1684 1685 /* 1686 * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and 1687 * BufferData if buffer already have immutable store; 1688 */ 1689 { 1690 static const GLsizeiptr data_size = 32; 1691 static GLubyte data[data_size]; 1692 1693 Buffer buffer(m_context); 1694 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data); 1695 1696 /* NamedBufferStorage */ 1697 if (0 != gl.namedBufferStorage) 1698 { 1699 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_DYNAMIC_STORAGE_BIT); 1700 verifyError(GL_INVALID_OPERATION, "NamedBufferStorage was executed for id with immutable storage", 1701 test_result); 1702 } 1703 1704 /* BufferStorage */ 1705 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1706 1707 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_DYNAMIC_STORAGE_BIT); 1708 verifyError(GL_INVALID_OPERATION, "BufferStorage was executed for target with immutable storage", test_result); 1709 1710 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1711 } 1712 1713 /* 1714 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when 1715 * <size> is less or equal to zero; 1716 */ 1717 { 1718 static const GLsizeiptr data_size = 32; 1719 static GLubyte data[data_size]; 1720 1721 Buffer buffer(m_context); 1722 gl.createBuffers(1, &buffer.m_id); 1723 1724 /* NamedBufferStorage */ 1725 if (0 != gl.namedBufferStorage) 1726 { 1727 gl.namedBufferStorage(buffer.m_id, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT); 1728 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == 0", test_result); 1729 1730 gl.namedBufferStorage(buffer.m_id, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT); 1731 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == -16", test_result); 1732 } 1733 1734 /* BufferStorage */ 1735 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1736 1737 gl.bufferStorage(GL_ARRAY_BUFFER, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT); 1738 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == 0", test_result); 1739 1740 gl.bufferStorage(GL_ARRAY_BUFFER, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT); 1741 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == -16", test_result); 1742 1743 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1744 } 1745 1746 /* 1747 * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when 1748 * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor 1749 * MAP_WRITE_BIT; 1750 */ 1751 { 1752 static const GLsizeiptr data_size = 32; 1753 static GLubyte data[data_size]; 1754 1755 Buffer buffer(m_context); 1756 gl.createBuffers(1, &buffer.m_id); 1757 1758 /* NamedBufferStorage */ 1759 if (0 != gl.namedBufferStorage) 1760 { 1761 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_PERSISTENT_BIT); 1762 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", 1763 test_result); 1764 } 1765 1766 /* BufferStorage */ 1767 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1768 1769 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_PERSISTENT_BIT); 1770 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", test_result); 1771 1772 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1773 } 1774 1775 /* 1776 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when 1777 * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT; 1778 */ 1779 { 1780 static const GLsizeiptr data_size = 32; 1781 static GLubyte data[data_size]; 1782 1783 Buffer buffer(m_context); 1784 gl.createBuffers(1, &buffer.m_id); 1785 1786 /* NamedBufferStorage */ 1787 if (0 != gl.namedBufferStorage) 1788 { 1789 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_COHERENT_BIT); 1790 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_COHERENT_BIT", 1791 test_result); 1792 } 1793 1794 /* BufferStorage */ 1795 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1796 1797 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_COHERENT_BIT); 1798 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_COHERENT_BIT", test_result); 1799 1800 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1801 } 1802 1803 /* 1804 * - INVALID_OPERATION is generated by MapBufferRange if any of: 1805 * * MAP_COHERENT_BIT, 1806 * * MAP_PERSISTENT_BIT, 1807 * * MAP_READ_BIT, 1808 * * MAP_WRITE_BIT 1809 * is included in <access> and not in buffer's storage flags; 1810 */ 1811 { 1812 static const GLsizeiptr data_size = 32; 1813 static GLubyte data[data_size]; 1814 1815 Buffer buffer(m_context); 1816 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data); 1817 1818 /* MapNamedBufferRange */ 1819 if (0 != gl.mapNamedBufferRange) 1820 { 1821 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_READ_BIT); 1822 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, " 1823 "storage flags == GL_DYNAMIC_STORAGE_BIT", 1824 test_result); 1825 1826 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT); 1827 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, " 1828 "storage flags == GL_DYNAMIC_STORAGE_BIT", 1829 test_result); 1830 1831 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT); 1832 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, " 1833 "storage flags == GL_DYNAMIC_STORAGE_BIT", 1834 test_result); 1835 1836 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT); 1837 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, " 1838 "storage flags == GL_DYNAMIC_STORAGE_BIT", 1839 test_result); 1840 } 1841 1842 /* BufferStorage */ 1843 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1844 1845 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT); 1846 verifyError( 1847 GL_INVALID_OPERATION, 1848 "MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT", 1849 test_result); 1850 1851 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT); 1852 verifyError( 1853 GL_INVALID_OPERATION, 1854 "MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT", 1855 test_result); 1856 1857 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT); 1858 verifyError( 1859 GL_INVALID_OPERATION, 1860 "MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT", 1861 test_result); 1862 1863 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT); 1864 verifyError( 1865 GL_INVALID_OPERATION, 1866 "MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT", 1867 test_result); 1868 1869 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1870 } 1871 1872 /* 1873 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData 1874 * when buffer has immutable store but its flags does not include 1875 * DYNAMIC_STORAGE. 1876 */ 1877 { 1878 static const GLsizeiptr data_size = 32; 1879 static GLubyte data[data_size]; 1880 1881 Buffer buffer(m_context); 1882 buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size, 1883 data); 1884 1885 /* NamedBufferSubData */ 1886 if (0 != gl.namedBufferSubData) 1887 { 1888 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data); 1889 verifyError(GL_INVALID_OPERATION, 1890 "NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result); 1891 } 1892 1893 /* BufferStorage */ 1894 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 1895 1896 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data); 1897 verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", 1898 test_result); 1899 1900 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER); 1901 } 1902 1903 /* Set result */ 1904 if (true == test_result) 1905 { 1906 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1907 } 1908 else 1909 { 1910 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1911 } 1912 1913 /* Done */ 1914 return tcu::TestNode::STOP; 1915} 1916 1917/** Verifies that expected error was generated 1918 * 1919 * @param expected_error Expected error 1920 * @param error_message Message that will be logged in case of wrong error 1921 * @param out_test_result Set to false if worng error was generated, not modified otherwise 1922 **/ 1923void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result) 1924{ 1925 const Functions& gl = m_context.getRenderContext().getFunctions(); 1926 1927 const GLenum error = gl.getError(); 1928 1929 if (error != expected_error) 1930 { 1931 out_test_result = false; 1932 1933 m_context.getTestContext().getLog() 1934 << tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error) 1935 << ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message 1936 << tcu::TestLog::EndMessage; 1937 } 1938} 1939 1940/** Constructor 1941 * 1942 * @param context Test context 1943 **/ 1944GetBufferParameterTest::GetBufferParameterTest(deqp::Context& context) 1945 : TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers") 1946{ 1947 static const GLenum s_mapping_bits[] = { 0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT }; 1948 static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]); 1949 1950 GLenum flags = 0; 1951 1952 for (GLuint dynamic = 0; dynamic < 2; ++dynamic) 1953 { 1954 flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT; 1955 1956 for (GLuint client = 0; client < 2; ++client) 1957 { 1958 flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT; 1959 1960 /* No "map" bits */ 1961 if (0 != flags) 1962 { 1963 m_test_cases.push_back(testCase(flags, 0)); 1964 } 1965 1966 for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx) 1967 { 1968 const GLenum flag_mapping_bits = s_mapping_bits[flag_idx]; 1969 const GLenum flags_with_mapping = flags | flag_mapping_bits; 1970 1971 for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx) 1972 { 1973 const GLenum access = s_mapping_bits[access_idx]; 1974 1975 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT)); 1976 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT)); 1977 m_test_cases.push_back( 1978 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT)); 1979 m_test_cases.push_back( 1980 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT)); 1981 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, 1982 access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT)); 1983 } 1984 } 1985 } 1986 } 1987} 1988 1989/** Execute test 1990 * 1991 * @return tcu::TestNode::STOP otherwise 1992 **/ 1993tcu::TestNode::IterateResult GetBufferParameterTest::iterate() 1994{ 1995 static const GLsizeiptr data_size = 32; 1996 static GLubyte data[data_size]; 1997 1998 Buffer::LoadExtDirectStateAccess(m_context); 1999 2000 // No GL45 or GL_ARB_direct_state_access support 2001 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE) 2002 { 2003 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported"); 2004 return tcu::TestNode::STOP; 2005 } 2006 2007 const Functions& gl = m_context.getRenderContext().getFunctions(); 2008 2009 bool test_result = true; 2010 2011 for (GLuint i = 0; i < m_test_cases.size(); ++i) 2012 { 2013 const testCase& test_case = m_test_cases[i]; 2014 const GLenum access = test_case.m_access; 2015 const GLenum flags = test_case.m_flags; 2016 2017 GLint queried_flags = -1; 2018 GLint queried_immutable = -1; 2019 GLint queried_size = -1; 2020 2021 Buffer buffer(m_context); 2022 2023 buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data); 2024 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER); 2025 2026 if (0 != gl.getNamedBufferParameteriv) 2027 { 2028 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags); 2029 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable); 2030 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size); 2031 2032 if (queried_flags != (GLint)flags) 2033 { 2034 test_result = false; 2035 m_context.getTestContext().getLog() 2036 << tcu::TestLog::Message 2037 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags 2038 << " expected: " << flags << tcu::TestLog::EndMessage; 2039 } 2040 } 2041 2042 if (queried_flags != (GLint)flags) 2043 { 2044 test_result = false; 2045 m_context.getTestContext().getLog() 2046 << tcu::TestLog::Message 2047 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags 2048 << " expected: " << flags << tcu::TestLog::EndMessage; 2049 } 2050 2051 if (queried_immutable != GL_TRUE) 2052 { 2053 test_result = false; 2054 m_context.getTestContext().getLog() 2055 << tcu::TestLog::Message 2056 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " 2057 << queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage; 2058 } 2059 2060 if (queried_size != data_size) 2061 { 2062 test_result = false; 2063 m_context.getTestContext().getLog() 2064 << tcu::TestLog::Message 2065 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size 2066 << " expected: " << data_size << tcu::TestLog::EndMessage; 2067 } 2068 2069 queried_flags = -1; 2070 queried_immutable = -1; 2071 queried_size = -1; 2072 2073 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags); 2074 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable); 2075 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size); 2076 2077 if (queried_flags != (GLint)flags) 2078 { 2079 test_result = false; 2080 m_context.getTestContext().getLog() 2081 << tcu::TestLog::Message 2082 << "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags 2083 << " expected: " << flags << tcu::TestLog::EndMessage; 2084 } 2085 2086 if (queried_immutable != GL_TRUE) 2087 { 2088 test_result = false; 2089 m_context.getTestContext().getLog() 2090 << tcu::TestLog::Message 2091 << "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable 2092 << " expected: " << GL_TRUE << tcu::TestLog::EndMessage; 2093 } 2094 2095 if (queried_size != data_size) 2096 { 2097 test_result = false; 2098 m_context.getTestContext().getLog() 2099 << tcu::TestLog::Message 2100 << "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size 2101 << " expected: " << data_size << tcu::TestLog::EndMessage; 2102 } 2103 2104 if (0 != access) 2105 { 2106 GLint queried_access = -1; 2107 2108 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access)); 2109 2110 if (0 != gl.getNamedBufferParameteriv) 2111 { 2112 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access); 2113 } 2114 2115 if (queried_access != (GLint)access) 2116 { 2117 test_result = false; 2118 m_context.getTestContext().getLog() 2119 << tcu::TestLog::Message 2120 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access 2121 << " expected: " << access << tcu::TestLog::EndMessage; 2122 } 2123 2124 queried_access = -1; 2125 2126 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access); 2127 2128 if (queried_access != (GLint)access) 2129 { 2130 test_result = false; 2131 m_context.getTestContext().getLog() 2132 << tcu::TestLog::Message 2133 << "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access 2134 << " expected: " << access << tcu::TestLog::EndMessage; 2135 } 2136 } 2137 2138 Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER); 2139 } 2140 2141 /* Set result */ 2142 if (true == test_result) 2143 { 2144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2145 } 2146 else 2147 { 2148 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2149 } 2150 2151 /* Done */ 2152 return tcu::TestNode::STOP; 2153} 2154 2155/** Constructor 2156 * 2157 * @param context Test context 2158 **/ 2159GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access) 2160{ 2161} 2162 2163/** Constructor 2164 * 2165 * @param context Test context 2166 **/ 2167DynamicStorageTest::DynamicStorageTest(deqp::Context& context) 2168 : TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected") 2169{ 2170 /* Nothing to be done here */ 2171} 2172 2173/** Execute test 2174 * 2175 * @return tcu::TestNode::STOP otherwise 2176 **/ 2177tcu::TestNode::IterateResult DynamicStorageTest::iterate() 2178{ 2179 static const size_t data_size = 64; 2180 2181 const Functions& gl = m_context.getRenderContext().getFunctions(); 2182 2183 bool test_result = true; 2184 2185 /* 2186 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to 2187 * COPY_READ_BUFFER; 2188 * - prepare 64 bytes immutable buffer filled with value 2; Do not set 2189 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER; 2190 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes 2191 * filled with value 3; INVLIAD_OPERATION error should be generated; 2192 * - inspect contents of buffer to verify it is filled with 2; 2193 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to 2194 * COPY_WRITE_BUFFER; No error should be generated; 2195 * - inspect contents of buffer to verify it is filled with 1; 2196 */ 2197 { 2198 /* Prepare buffers */ 2199 GLubyte read_data[data_size]; 2200 GLubyte temp_data[data_size]; 2201 GLubyte update_data[data_size]; 2202 GLubyte write_data[data_size]; 2203 2204 for (size_t i = 0; i < data_size; ++i) 2205 { 2206 read_data[i] = 1; 2207 temp_data[i] = 0; 2208 update_data[i] = 3; 2209 write_data[i] = 2; 2210 } 2211 2212 Buffer read_buffer(m_context); 2213 Buffer write_buffer(m_context); 2214 2215 read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data); 2216 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data); 2217 2218 /* Check bufferSubData */ 2219 write_buffer.Bind(); 2220 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data); 2221 2222 GLenum error = gl.getError(); 2223 if (GL_INVALID_OPERATION != error) 2224 { 2225 test_result = false; 2226 2227 m_context.getTestContext().getLog() 2228 << tcu::TestLog::Message << "Invalid error was generated. BufferSubData was executed on store without " 2229 "DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: " 2230 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage; 2231 } 2232 2233 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data); 2234 2235 if (0 != memcmp(temp_data, write_data, data_size)) 2236 { 2237 test_result = false; 2238 2239 m_context.getTestContext().getLog() 2240 << tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT." 2241 << tcu::TestLog::EndMessage; 2242 } 2243 2244 /* Check copyBufferSubData */ 2245 read_buffer.Bind(); 2246 gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */, 2247 data_size); 2248 GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData"); 2249 2250 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data); 2251 2252 if (0 != memcmp(temp_data, read_data, data_size)) 2253 { 2254 test_result = false; 2255 2256 m_context.getTestContext().getLog() << tcu::TestLog::Message 2257 << "CopyBufferSubData stored invalid contents in write target buffer." 2258 << tcu::TestLog::EndMessage; 2259 } 2260 } 2261 2262 /* 2263 * - delete buffer and create new one; This time <flags> should contain 2264 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER; 2265 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes 2266 * filled with value 3; No error should be generated; 2267 * - inspect contents of buffer to verify it is filled with 3; 2268 */ 2269 { 2270 /* Prepare buffers */ 2271 GLubyte temp_data[data_size]; 2272 GLubyte update_data[data_size]; 2273 GLubyte write_data[data_size]; 2274 2275 for (size_t i = 0; i < data_size; ++i) 2276 { 2277 temp_data[i] = 0; 2278 update_data[i] = 3; 2279 write_data[i] = 2; 2280 } 2281 2282 Buffer write_buffer(m_context); 2283 2284 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data); 2285 2286 /* Check bufferSubData */ 2287 write_buffer.Bind(); 2288 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data); 2289 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData"); 2290 2291 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data); 2292 2293 if (0 != memcmp(temp_data, update_data, data_size)) 2294 { 2295 test_result = false; 2296 2297 m_context.getTestContext().getLog() << tcu::TestLog::Message 2298 << "BufferSubData stored invalid contents in write target buffer." 2299 << tcu::TestLog::EndMessage; 2300 } 2301 } 2302 2303 /* Set result */ 2304 if (true == test_result) 2305 { 2306 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2307 } 2308 else 2309 { 2310 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2311 } 2312 2313 /* Done */ 2314 return tcu::TestNode::STOP; 2315} 2316 2317/** Constructor 2318 * 2319 * @param context Test context 2320 **/ 2321MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context& context) 2322 : TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer") 2323{ 2324 /* Nothing to be done here */ 2325} 2326 2327/** Execute test 2328 * 2329 * @return tcu::TestNode::STOP otherwise 2330 **/ 2331tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate() 2332{ 2333 static const size_t data_size = 64; 2334 static const GLintptr mapped_region_offset = 16; 2335 static const GLsizeiptr mapped_region_size = 16; 2336 static const testCase test_cases[] = { 2337 { 0, 16, false }, /* before mapped region */ 2338 { 32, 16, false }, /* after mapped region */ 2339 { 8, 16, true }, /* at the beginning */ 2340 { 24, 16, true }, /* at the end */ 2341 { 12, 8, true }, /* in the middle */ 2342 }; 2343 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); 2344 2345 const Functions& gl = m_context.getRenderContext().getFunctions(); 2346 2347 bool test_result = true; 2348 2349 /* Storage for data */ 2350 GLubyte incrementing_data[data_size]; 2351 2352 /* Prepare data */ 2353 for (size_t i = 0; i < data_size; ++i) 2354 { 2355 incrementing_data[i] = (glw::GLubyte)i; 2356 } 2357 2358 /* Load DSA */ 2359 Buffer::LoadExtDirectStateAccess(m_context); 2360 2361 // No GL45 or GL_ARB_direct_state_access support 2362 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE) 2363 { 2364 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported"); 2365 return tcu::TestNode::STOP; 2366 } 2367 2368 /* Prepare buffer */ 2369 Buffer buffer(m_context); 2370 buffer.InitStorage(GL_ARRAY_BUFFER, 2371 GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size, 2372 0 /* data */); 2373 buffer.Bind(); 2374 2375 /* 2376 * - execute tested operation, to update whole buffer with incrementing values 2377 * starting from 0; No error should be generated; 2378 */ 2379 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data); 2380 GLenum error = gl.getError(); 2381 2382 if (GL_NO_ERROR != error) 2383 { 2384 test_result = false; 2385 2386 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: " 2387 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage; 2388 } 2389 2390 if (0 != gl.namedBufferSubData) 2391 { 2392 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data); 2393 error = gl.getError(); 2394 } 2395 2396 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data); 2397 error = gl.getError(); 2398 2399 if (GL_NO_ERROR != error) 2400 { 2401 test_result = false; 2402 2403 m_context.getTestContext().getLog() 2404 << tcu::TestLog::Message 2405 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str() 2406 << tcu::TestLog::EndMessage; 2407 } 2408 2409 /* 2410 * - map buffer contents with MapBufferRange; <access> should contain 2411 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset> 2412 * and <size>; 2413 * - mapped region should contain values from 16 to 31; 2414 * - execute tested operation, to update portions of buffer specified below; 2415 * No error should be generated; 2416 */ 2417 { 2418 const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size, 2419 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); 2420 2421 if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size)) 2422 { 2423 test_result = false; 2424 2425 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Mapped region contains unexpected data" 2426 << tcu::TestLog::EndMessage; 2427 } 2428 2429 for (size_t i = 0; i < n_test_cases; ++i) 2430 { 2431 const GLintptr offset = test_cases[i].m_offset; 2432 const GLsizeiptr size = test_cases[i].m_size; 2433 2434 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data); 2435 error = gl.getError(); 2436 2437 if (GL_NO_ERROR != error) 2438 { 2439 test_result = false; 2440 2441 m_context.getTestContext().getLog() 2442 << tcu::TestLog::Message 2443 << "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str() 2444 << tcu::TestLog::EndMessage; 2445 } 2446 2447 if (0 != gl.namedBufferSubData) 2448 { 2449 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data); 2450 error = gl.getError(); 2451 } 2452 2453 if (GL_NO_ERROR != error) 2454 { 2455 test_result = false; 2456 2457 m_context.getTestContext().getLog() 2458 << tcu::TestLog::Message 2459 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str() 2460 << tcu::TestLog::EndMessage; 2461 } 2462 } 2463 } 2464 2465 /* 2466 * - unmap buffer; 2467 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; 2468 * - execute tested operation to update regions specified below; It is expected 2469 * that INVALID_OPERATION will be generated for cases that cross mapped region; 2470 * No error should be generated for other cases. 2471 */ 2472 { 2473 Buffer::MapOwner tmp( 2474 buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); 2475 2476 for (size_t i = 0; i < n_test_cases; ++i) 2477 { 2478 const GLintptr offset = test_cases[i].m_offset; 2479 const GLsizeiptr size = test_cases[i].m_size; 2480 const bool is_error_expected = test_cases[i].m_cross_mapped_region; 2481 const GLenum expected_error = (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR; 2482 2483 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data); 2484 error = gl.getError(); 2485 2486 if (expected_error != error) 2487 { 2488 test_result = false; 2489 2490 m_context.getTestContext().getLog() 2491 << tcu::TestLog::Message 2492 << "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str() 2493 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str() 2494 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size 2495 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage; 2496 } 2497 2498 if (0 != gl.namedBufferSubData) 2499 { 2500 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data); 2501 error = gl.getError(); 2502 } 2503 2504 if (expected_error != error) 2505 { 2506 test_result = false; 2507 2508 m_context.getTestContext().getLog() 2509 << tcu::TestLog::Message 2510 << "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str() 2511 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str() 2512 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size 2513 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage; 2514 } 2515 } 2516 } 2517 2518 /* Set result */ 2519 if (true == test_result) 2520 { 2521 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2522 } 2523 else 2524 { 2525 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2526 } 2527 2528 /* Done */ 2529 return tcu::TestNode::STOP; 2530} 2531 2532/** Constructor 2533 * 2534 * @param context Test context 2535 **/ 2536MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context& context) 2537 : TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer") 2538 , m_compressed_image_size(0) 2539 , m_compressed_internal_format(0) 2540{ 2541 /* Nothing to be done here */ 2542} 2543 2544/** Execute test 2545 * 2546 * @return tcu::TestNode::STOP otherwise 2547 **/ 2548tcu::TestNode::IterateResult MapPersistentTextureTest::iterate() 2549{ 2550 static const size_t data_size = 256; 2551 2552 const Functions& gl = m_context.getRenderContext().getFunctions(); 2553 2554 bool test_result = true; 2555 2556 /* Storage for data */ 2557 GLubyte data[data_size]; 2558 2559 /* Prepare data */ 2560 for (size_t i = 0; i < data_size; ++i) 2561 { 2562 data[i] = (glw::GLubyte)i; 2563 } 2564 2565 /* Load DSA */ 2566 Buffer::LoadExtDirectStateAccess(m_context); 2567 Texture::LoadExtDirectStateAccess(m_context); 2568 2569 /* Get info about compressed image */ 2570 getCompressedInfo(); 2571 2572 /* Prepare buffer */ 2573 Buffer buffer(m_context); 2574 buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size, 2575 data); 2576 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER); 2577 2578 /* 2579 * - prepare texture in a way that is relevant for tested operation; 2580 * - execute tested operation, no error should be generated; 2581 * - delete texture and prepare next one; 2582 */ 2583 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i) 2584 { 2585 const TESTED_OPERATION operation = (TESTED_OPERATION)i; 2586 2587 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR); 2588 2589 if (false == result) 2590 { 2591 test_result = false; 2592 2593 m_context.getTestContext().getLog() << tcu::TestLog::Message 2594 << "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped" 2595 << tcu::TestLog::EndMessage; 2596 } 2597 } 2598 2599 /* 2600 * - map buffer contents with MapBufferRange, <access> should contain 2601 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 2602 * - execute tested operation, no error should be generated; 2603 */ 2604 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i) 2605 { 2606 const TESTED_OPERATION operation = (TESTED_OPERATION)i; 2607 2608 { 2609 Buffer::MapOwner tmp( 2610 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); 2611 } 2612 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER); 2613 2614 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR); 2615 2616 if (false == result) 2617 { 2618 test_result = false; 2619 2620 m_context.getTestContext().getLog() << tcu::TestLog::Message 2621 << "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped" 2622 << tcu::TestLog::EndMessage; 2623 } 2624 } 2625 2626 /* Set result */ 2627 if (true == test_result) 2628 { 2629 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2630 } 2631 else 2632 { 2633 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2634 } 2635 2636 /* Done */ 2637 return tcu::TestNode::STOP; 2638} 2639 2640/** Return name of operation 2641 * 2642 * @param operation Operation which name will be returned 2643 * 2644 * @return Name of operation or 0 in case of invalid enum 2645 **/ 2646const char* MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation) 2647{ 2648 const char* name = 0; 2649 2650 switch (operation) 2651 { 2652 case OP_COMPRESSED_TEX_IMAGE: 2653 name = "CompressedTexImage"; 2654 break; 2655 case OP_COMPRESSED_TEX_SUB_IMAGE: 2656 name = "CompressedTexSubImage"; 2657 break; 2658 case OP_COMPRESSED_TEXTURE_SUB_IMAGE: 2659 name = "CompressedTextureSubImage"; 2660 break; 2661 case OP_TEX_IMAGE: 2662 name = "TexImage"; 2663 break; 2664 case OP_TEX_SUB_IMAGE: 2665 name = "TexSubImage"; 2666 break; 2667 default: 2668 TCU_FAIL("Invalid enum"); 2669 } 2670 2671 return name; 2672} 2673 2674/** Check format and size of compressed image 2675 * 2676 **/ 2677void MapPersistentTextureTest::getCompressedInfo() 2678{ 2679 const Functions& gl = m_context.getRenderContext().getFunctions(); 2680 2681 /* Texture creation */ 2682 Texture texture(m_context); 2683 Texture::Generate(gl, texture.m_id); 2684 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 2685 Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE, 2686 0); // glspec 4.5 pg 216 2687 2688 /* Queries */ 2689 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, 2690 &m_compressed_image_size); 2691 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT, 2692 &m_compressed_internal_format); 2693} 2694 2695/** Verifies results of tested operation 2696 * 2697 * @param operation Operation to be tested 2698 * @param buffer Buffer that will be used as GL_PIXEL_UNPACK_BUFFER 2699 * @param expected_error Expected error 2700 * 2701 * @return false in case of any error, true otherwise 2702 **/ 2703bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer, 2704 glw::GLenum expected_error) 2705{ 2706 const Functions& gl = m_context.getRenderContext().getFunctions(); 2707 2708 bool result = true; 2709 2710 GLenum error = GL_NO_ERROR; 2711 Texture texture(m_context); 2712 2713 /* Prepare texture */ 2714 Texture::Generate(gl, texture.m_id); 2715 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 2716 2717 switch (operation) 2718 { 2719 case OP_COMPRESSED_TEX_IMAGE: 2720 case OP_TEX_IMAGE: 2721 break; 2722 case OP_COMPRESSED_TEX_SUB_IMAGE: 2723 case OP_COMPRESSED_TEXTURE_SUB_IMAGE: 2724 Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */, 2725 8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */, 2726 0 /* empty image */); 2727 break; 2728 case OP_TEX_SUB_IMAGE: 2729 Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED, 2730 GL_UNSIGNED_BYTE, 0 /* empty image */); 2731 break; 2732 default: 2733 TCU_FAIL("Invalid enum"); 2734 } 2735 2736 /* Bind buffer to PIXEL_UNPACK */ 2737 Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER); 2738 2739 /* Execute operation */ 2740 switch (operation) 2741 { 2742 case OP_COMPRESSED_TEX_IMAGE: 2743 gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */, 2744 8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */, 2745 0 /* offset to pixel unpack buffer */); 2746 error = gl.getError(); 2747 break; 2748 case OP_COMPRESSED_TEX_SUB_IMAGE: 2749 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, 2750 m_compressed_internal_format, m_compressed_image_size, 2751 0 /* offset to pixel unpack buffer */); 2752 error = gl.getError(); 2753 break; 2754 case OP_COMPRESSED_TEXTURE_SUB_IMAGE: 2755 if (0 != gl.compressedTextureSubImage2D) 2756 { 2757 gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 2758 8 /* height */, m_compressed_internal_format, m_compressed_image_size, 2759 0 /* offset to pixel unpack buffer */); 2760 error = gl.getError(); 2761 } 2762 else 2763 { 2764 /* Not supported, ignore */ 2765 error = expected_error; 2766 } 2767 break; 2768 case OP_TEX_IMAGE: 2769 gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED, 2770 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */); 2771 error = gl.getError(); 2772 break; 2773 case OP_TEX_SUB_IMAGE: 2774 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED, 2775 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */); 2776 error = gl.getError(); 2777 break; 2778 default: 2779 TCU_FAIL("Invalid enum"); 2780 } 2781 2782 /* Unbind buffer */ 2783 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER); 2784 2785 /* Check result */ 2786 if (expected_error != error) 2787 { 2788 result = false; 2789 2790 m_context.getTestContext().getLog() << tcu::TestLog::Message << getOperationName(operation) 2791 << " generated wrong error: " << glu::getErrorStr(error).toString().c_str() 2792 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str() 2793 << tcu::TestLog::EndMessage; 2794 } 2795 2796 /* Done */ 2797 return result; 2798} 2799 2800/** Constructor 2801 * 2802 * @param context Test context 2803 **/ 2804MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context& context) 2805 : TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer") 2806{ 2807 /* Nothing to be done here */ 2808} 2809 2810/** Execute test 2811 * 2812 * @return tcu::TestNode::STOP otherwise 2813 **/ 2814tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate() 2815{ 2816 static const GLuint height = 8; 2817 static const GLuint width = 8; 2818 static const size_t data_size = width * height; 2819 2820 const Functions& gl = m_context.getRenderContext().getFunctions(); 2821 2822 bool test_result = true; 2823 2824 /* Prepare data */ 2825 GLubyte initial_texture_data[data_size]; 2826 GLubyte updated_texture_data[data_size]; 2827 2828 for (size_t i = 0; i < data_size; ++i) 2829 { 2830 initial_texture_data[i] = (glw::GLubyte)i; 2831 updated_texture_data[i] = (glw::GLubyte)(data_size - i); 2832 } 2833 2834 /* Prepare GL objects */ 2835 Buffer buffer(m_context); 2836 Framebuffer framebuffer(m_context); 2837 Texture texture(m_context); 2838 2839 buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size, 2840 0 /* data */); 2841 2842 Texture::Generate(gl, texture.m_id); 2843 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 2844 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */); 2845 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */, 2846 GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data); 2847 2848 Framebuffer::Generate(gl, framebuffer.m_id); 2849 Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id); 2850 Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height); 2851 2852 /* 2853 * - execute ReadPixels to transfer texture contents to buffer, no error should 2854 * be generated; 2855 */ 2856 buffer.Bind(); 2857 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 2858 0 /* offset in PIXEL_PACK_BUFFER */); 2859 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer"); 2860 2861 /* 2862 * - update contents of texture with different image; 2863 * - map buffer contents with MapBufferRange, <access> should contain 2864 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 2865 * - execute ReadPixels to transfer texture contents to buffer, no error should 2866 * be generated; 2867 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish; 2868 * - inspect contents of mapped buffer, to verify that latest data transfer was 2869 * successful; 2870 * - unmap buffer 2871 */ 2872 { 2873 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 2874 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data); 2875 2876 const Buffer::MapOwner map( 2877 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); 2878 2879 buffer.Bind(); 2880 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 2881 0 /* offset in PIXEL_PACK_BUFFER */); 2882 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer"); 2883 2884 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); 2885 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 2886 2887 gl.finish(); 2888 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish"); 2889 2890 if (0 != memcmp(updated_texture_data, map.m_data, data_size)) 2891 { 2892 test_result = false; 2893 2894 m_context.getTestContext().getLog() 2895 << tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels" 2896 << tcu::TestLog::EndMessage; 2897 } 2898 } 2899 2900 /* 2901 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; 2902 * - execute ReadPixels to transfer texture contents to buffer, 2903 * INVALID_OPERATION error should be generated. 2904 */ 2905 { 2906 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); 2907 2908 buffer.Bind(); 2909 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 2910 0 /* offset in PIXEL_PACK_BUFFER */); 2911 GLenum error = gl.getError(); 2912 2913 if (GL_INVALID_OPERATION != error) 2914 { 2915 test_result = false; 2916 2917 m_context.getTestContext().getLog() 2918 << tcu::TestLog::Message << "Wrong error was generated by ReadPixels. Expected INVALID_OPERATION as " 2919 "PIXEL_PACK buffer is mapped. Got: " 2920 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage; 2921 } 2922 } 2923 2924 /* Set result */ 2925 if (true == test_result) 2926 { 2927 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2928 } 2929 else 2930 { 2931 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2932 } 2933 2934 /* Done */ 2935 return tcu::TestNode::STOP; 2936} 2937 2938/** Constructor 2939 * 2940 * @param context Test context 2941 **/ 2942MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context) 2943 : TestCase(context, "map_persistent_dispatch", "test dispatch operation against mapped buffer") 2944{ 2945 /* Nothing to be done here */ 2946} 2947 2948/** Constructor 2949 * 2950 * @param context Test context 2951 * @param test_name Test name 2952 * @param test_description Test description 2953 **/ 2954MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context, const GLchar* test_name, 2955 const GLchar* test_description) 2956 : TestCase(context, test_name, test_description) 2957{ 2958 /* Nothing to be done here */ 2959} 2960 2961/** Execute test 2962 * 2963 * @return tcu::TestNode::STOP otherwise 2964 **/ 2965tcu::TestNode::IterateResult MapPersistentDispatchTest::iterate() 2966{ 2967 static const GLchar* compute_shader = "#version 430 core\n" 2968 "\n" 2969 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 2970 "\n" 2971 "layout (binding = 0, std430) buffer DestinationData {\n" 2972 " uint values[];\n" 2973 "} destination;\n" 2974 "\n" 2975 "layout (binding = 1, std430) buffer SourceData {\n" 2976 " uint values[];\n" 2977 "} source;\n" 2978 "\n" 2979 "void main()\n" 2980 "{\n" 2981 " uint index = gl_GlobalInvocationID.x;\n" 2982 " uint sum = 0u;\n" 2983 "\n" 2984 " for (uint i = 0u; i <= index; ++i)\n" 2985 " {\n" 2986 " sum += source.values[i];\n" 2987 " }\n" 2988 "\n" 2989 " destination.values[index] = sum;\n" 2990 "}\n" 2991 "\n"; 2992 static const GLuint data_size = 16; 2993 static const GLuint destination_binding = 0; 2994 static const GLuint source_binding = 1; 2995 2996 const Functions& gl = m_context.getRenderContext().getFunctions(); 2997 2998 bool test_result = true; 2999 3000 /* Prepare data */ 3001 GLuint destination_data[data_size]; 3002 GLuint modified_source_data[data_size]; 3003 GLuint modified_sum_data[data_size]; 3004 GLuint source_data[data_size]; 3005 GLuint sum_data[data_size]; 3006 3007 GLuint modified_sum = 0; 3008 GLuint sum = 0; 3009 3010 for (GLuint i = 0; i < data_size; ++i) 3011 { 3012 destination_data[i] = 0; 3013 modified_source_data[i] = data_size - i; 3014 source_data[i] = i; 3015 3016 modified_sum += modified_source_data[i]; 3017 sum += source_data[i]; 3018 3019 modified_sum_data[i] = modified_sum; 3020 sum_data[i] = sum; 3021 } 3022 3023 /* Prepare buffers */ 3024 Buffer destination(m_context); 3025 Buffer source(m_context); 3026 3027 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT, 3028 data_size * sizeof(GLuint), destination_data); 3029 3030 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, 3031 data_size * sizeof(GLuint), source_data); 3032 3033 /* Prepare program */ 3034 Program program(m_context); 3035 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 3036 3037 /* 3038 * - bind buffers to SHADER_STORAGE_BUFFER; 3039 * - use MapBufferRange to map both buffers; <access> shall be set as follows: 3040 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both 3041 * * MAP_WRITE_BIT flag shall be set for source; 3042 * * MAP_READ_BIT flag shall be set for destination; 3043 * - dispatch program for 16x1x1 groups; 3044 * - modify contents of source buffer via mapped memory; 3045 * - execute Finish; 3046 * - inspect contents of destination buffer via mapped memory; It is expected 3047 * that it will contain results based on original content of source buffer; 3048 * - dispatch program for 16x1x1 groups; 3049 * - execute Finish; 3050 * - inspect contents of destination buffer via mapped memory; It is expected 3051 * that it will contain results based on modified content of source buffer. 3052 */ 3053 { 3054 /* Set program */ 3055 Program::Use(gl, program.m_id); 3056 3057 /* Map buffers */ 3058 destination.Bind(); 3059 const Buffer::MapOwner destination_map(destination.MapRange( 3060 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT)); 3061 3062 source.Bind(); 3063 const Buffer::MapOwner source_map( 3064 source.MapRange(0 /* offset */, data_size * sizeof(GLuint), 3065 GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT)); 3066 3067 /* Clear binding point */ 3068 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER); 3069 3070 /* Bind buffers */ 3071 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding); 3072 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding); 3073 3074 /* Execute program for 16x1x1 groups */ 3075 gl.dispatchCompute(16, 1, 1); 3076 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers"); 3077 3078 /* Make sure that program executed */ 3079 gl.finish(); 3080 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish"); 3081 3082 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint))) 3083 { 3084 test_result = false; 3085 3086 m_context.getTestContext().getLog() << tcu::TestLog::Message 3087 << "Contents of mapped region does not correspond with expected results" 3088 << tcu::TestLog::EndMessage; 3089 } 3090 3091 /* Modify source buffer via mapped area */ 3092 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint)); 3093 3094 /* Execute program for 16x1x1 groups */ 3095 gl.dispatchCompute(16, 1, 1); 3096 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers"); 3097 3098 /* Make sure that program executed */ 3099 gl.finish(); 3100 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish"); 3101 3102 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint))) 3103 { 3104 test_result = false; 3105 3106 m_context.getTestContext().getLog() << tcu::TestLog::Message 3107 << "Contents of mapped region does not correspond with expected results" 3108 << tcu::TestLog::EndMessage; 3109 } 3110 } 3111 3112 /* Set result */ 3113 if (true == test_result) 3114 { 3115 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3116 } 3117 else 3118 { 3119 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3120 } 3121 3122 /* Done */ 3123 return tcu::TestNode::STOP; 3124} 3125 3126/** Constructor 3127 * 3128 * @param context Test context 3129 **/ 3130MapPersistentFlushTest::MapPersistentFlushTest(deqp::Context& context) 3131 : TestCase(context, "map_persistent_flush", "Test mapped buffer against flushing") 3132{ 3133 /* Nothing to be done here */ 3134} 3135 3136/** Execute test 3137 * 3138 * @return tcu::TestNode::STOP otherwise 3139 **/ 3140tcu::TestNode::IterateResult MapPersistentFlushTest::iterate() 3141{ 3142 static const GLchar* compute_shader = "#version 430 core\n" 3143 "\n" 3144 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3145 "\n" 3146 "layout (binding = 0, std430) buffer DestinationData {\n" 3147 " uint values[];\n" 3148 "} destination;\n" 3149 "\n" 3150 "layout (binding = 1, std430) buffer SourceData {\n" 3151 " uint values[];\n" 3152 "} source;\n" 3153 "\n" 3154 "void main()\n" 3155 "{\n" 3156 " uint index = gl_GlobalInvocationID.x;\n" 3157 " uint sum = 0u;\n" 3158 "\n" 3159 " for (uint i = 0u; i <= index; ++i)\n" 3160 " {\n" 3161 " sum += source.values[i];\n" 3162 " }\n" 3163 "\n" 3164 " destination.values[index] = sum;\n" 3165 "}\n" 3166 "\n"; 3167 static const GLuint data_size = 16; 3168 static const GLuint destination_binding = 0; 3169 static const GLuint source_binding = 1; 3170 3171 const Functions& gl = m_context.getRenderContext().getFunctions(); 3172 3173 bool test_result = true; 3174 3175 /* Prepare data */ 3176 GLuint destination_data[data_size]; 3177 GLuint modified_source_data[data_size]; 3178 GLuint modified_sum_data[data_size]; 3179 GLuint source_data[data_size]; 3180 GLuint sum_data[data_size]; 3181 3182 GLuint modified_sum = 0; 3183 GLuint sum = 0; 3184 3185 for (GLuint i = 0; i < data_size; ++i) 3186 { 3187 destination_data[i] = 0; 3188 modified_source_data[i] = data_size - i; 3189 source_data[i] = i; 3190 3191 modified_sum += modified_source_data[i]; 3192 sum += source_data[i]; 3193 3194 modified_sum_data[i] = modified_sum; 3195 sum_data[i] = sum; 3196 } 3197 3198 /* Prepare buffers */ 3199 Buffer destination(m_context); 3200 Buffer source(m_context); 3201 3202 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT, 3203 data_size * sizeof(GLuint), destination_data); 3204 3205 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, 3206 data_size * sizeof(GLuint), source_data); 3207 3208 /* Prepare program */ 3209 Program program(m_context); 3210 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 3211 3212 /* 3213 * - bind buffers to SHADER_STORAGE_BUFFER; 3214 * - use MapBufferRange to map both buffers; <access> shall be set as follows: 3215 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both 3216 * * MAP_WRITE_BIT flag shall be set for source; 3217 * * MAP_READ_BIT flag shall be set for destination; 3218 * - dispatch program for 16x1x1 groups; 3219 * - modify contents of source buffer via mapped memory; 3220 * - execute Finish; 3221 * - inspect contents of destination buffer via mapped memory; It is expected 3222 * that it will contain results based on original content of source buffer; 3223 * - dispatch program for 16x1x1 groups; 3224 * - execute Finish; 3225 * - inspect contents of destination buffer via mapped memory; It is expected 3226 * that it will contain results based on modified content of source buffer. 3227 */ 3228 { 3229 /* Set program */ 3230 Program::Use(gl, program.m_id); 3231 3232 /* Map buffers */ 3233 destination.Bind(); 3234 const Buffer::MapOwner destination_map(destination.MapRange( 3235 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT)); 3236 3237 source.Bind(); 3238 const Buffer::MapOwner source_map( 3239 source.MapRange(0 /* offset */, data_size * sizeof(GLuint), 3240 GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT)); 3241 3242 /* Clear binding point */ 3243 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER); 3244 3245 /* Bind buffers */ 3246 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding); 3247 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding); 3248 3249 /* Execute program for 16x1x1 groups */ 3250 gl.dispatchCompute(16, 1, 1); 3251 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers"); 3252 3253 /* Make sure that program executed */ 3254 gl.finish(); 3255 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish"); 3256 3257 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint))) 3258 { 3259 test_result = false; 3260 3261 m_context.getTestContext().getLog() << tcu::TestLog::Message 3262 << "Contents of mapped region does not correspond with expected results" 3263 << tcu::TestLog::EndMessage; 3264 } 3265 3266 /* Modify source buffer via mapped area */ 3267 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint)); 3268 3269 /* 3270 * - apply FlushMappedBufferRange to ensure that modifications of source buffer 3271 * are visible to server. 3272 */ 3273 source.Bind(); 3274 gl.flushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /* offset */, data_size * sizeof(GLuint)); 3275 GLU_EXPECT_NO_ERROR(gl.getError(), "FlushMappedBufferRange"); 3276 3277 /* Clear binding point */ 3278 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER); 3279 3280 /* Execute program for 16x1x1 groups */ 3281 gl.dispatchCompute(16, 1, 1); 3282 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers"); 3283 3284 /* Make sure that program executed */ 3285 gl.finish(); 3286 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish"); 3287 3288 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint))) 3289 { 3290 test_result = false; 3291 3292 m_context.getTestContext().getLog() << tcu::TestLog::Message 3293 << "Contents of mapped region does not correspond with expected results" 3294 << tcu::TestLog::EndMessage; 3295 } 3296 } 3297 3298 /* Set result */ 3299 if (true == test_result) 3300 { 3301 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3302 } 3303 else 3304 { 3305 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3306 } 3307 3308 /* Done */ 3309 return tcu::TestNode::STOP; 3310} 3311 3312/** Constructor 3313 * 3314 * @param context Test context 3315 **/ 3316MapPersistentDrawTest::MapPersistentDrawTest(deqp::Context& context) 3317 : TestCase(context, "map_persistent_draw", "Test draw operation against mapped buffer") 3318{ 3319 /* Nothing to be done here */ 3320} 3321 3322/** Execute test 3323 * 3324 * @return tcu::TestNode::STOP otherwise 3325 **/ 3326tcu::TestNode::IterateResult MapPersistentDrawTest::iterate() 3327{ 3328 /* 3329 * * fragment shader should pass value of "gs_fs_color" varying to red 3330 * channel of output color; 3331 */ 3332 static const GLchar* fragment_shader = "#version 440 core\n" 3333 "\n" 3334 "in float gs_fs_color;\n" 3335 "out vec4 fs_out_color;\n" 3336 "\n" 3337 "void main()\n" 3338 "{\n" 3339 " fs_out_color = vec4(gs_fs_color, 0, 0, 1);\n" 3340 "}\n" 3341 "\n"; 3342 3343 /* 3344 * * geometry shader should: 3345 * - define single uniform buffer array "rectangles" with unspecified size; 3346 * Rectangles should have two vec2 fields: position and size; 3347 * - define single atomic_uint "atom_color"; 3348 * - increment "atom_color" once per execution; 3349 * - output a quad that is placed at rectangles[vs_gs_index].position and 3350 * has size equal rectangles[vs_gs_index].size; 3351 * - define output float varying "gs_fs_color" equal to "atom_color" / 255; 3352 */ 3353 static const GLchar* geometry_shader = 3354 "#version 440 core\n" 3355 "\n" 3356 "layout(points) in;\n" 3357 "layout(triangle_strip, max_vertices = 4) out;\n" 3358 "\n" 3359 "struct Rectangle {\n" 3360 " vec2 position;\n" 3361 " vec2 size;\n" 3362 "};\n" 3363 "\n" 3364 "layout (std140, binding = 0) uniform Rectangles {\n" 3365 " Rectangle rectangle[2];\n" 3366 "} rectangles;\n" 3367 "\n" 3368 "layout (binding = 0) uniform atomic_uint atom_color;\n" 3369 "\n" 3370 "in uint vs_gs_index[];\n" 3371 "out float gs_fs_color;\n" 3372 "\n" 3373 "void main()\n" 3374 "{\n" 3375 " const uint atom_color_value = atomicCounterIncrement(atom_color);\n" 3376 " //const uint atom_color_value = vs_gs_index[0];\n" 3377 " const float color = float(atom_color_value) / 255.0;\n" 3378 " //const float color = rectangles.rectangle[1].size.x;\n" 3379 "\n" 3380 " const float left = rectangles.rectangle[vs_gs_index[0]].position.x;\n" 3381 " const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n" 3382 " const float right = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n" 3383 " const float top = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n" 3384 "\n" 3385 " //const float left = rectangles.rectangle[0].position.x;\n" 3386 " //const float bottom = rectangles.rectangle[0].position.y;\n" 3387 " //const float right = rectangles.rectangle[0].size.x + left;\n" 3388 " //const float top = rectangles.rectangle[0].size.y + bottom;\n" 3389 "\n" 3390 " gs_fs_color = color;\n" 3391 " gl_Position = vec4(left, bottom, 0, 1);\n" 3392 " EmitVertex();\n" 3393 "\n" 3394 " gs_fs_color = color;\n" 3395 " gl_Position = vec4(left, top, 0, 1);\n" 3396 " EmitVertex();\n" 3397 "\n" 3398 " gs_fs_color = color;\n" 3399 " gl_Position = vec4(right, bottom, 0, 1);\n" 3400 " EmitVertex();\n" 3401 "\n" 3402 " gs_fs_color = color;\n" 3403 " gl_Position = vec4(right, top, 0, 1);\n" 3404 " EmitVertex();\n" 3405 "}\n" 3406 "\n"; 3407 3408 /* 3409 * * vertex shader should output single varying "vs_gs_index" of type uint, 3410 * equal to gl_VertexID; 3411 */ 3412 static const GLchar* vertex_shader = "#version 440 core\n" 3413 "\n" 3414 "out uint vs_gs_index;\n" 3415 "\n" 3416 "void main()\n" 3417 "{\n" 3418 " vs_gs_index = gl_VertexID;\n" 3419 "}\n" 3420 "\n"; 3421 3422 static const GLuint atom_binding = 0; 3423 static const size_t atom_data_size = 1 * sizeof(GLuint); 3424 static const GLuint expected_atom_first = 3; 3425 static const GLuint expected_atom_second = 7; 3426 static const GLuint expected_pixel = 0xff000003; 3427 static const GLuint height = 16; 3428 static const GLuint n_rectangles = 2; 3429 static const GLuint pixel_size = 4 * sizeof(GLubyte); 3430 static const GLuint rectangles_binding = 0; 3431 static const size_t rectangle_size = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */ 3432 static const size_t rectangles_data_size = n_rectangles * rectangle_size; 3433 static const GLuint width = 16; 3434 static const GLuint line_size = width * pixel_size; 3435 static const GLuint pixel_offset = 8 * line_size + 7 * pixel_size; 3436 static const size_t texture_data_size = height * line_size; 3437 3438 const Functions& gl = m_context.getRenderContext().getFunctions(); 3439 3440 bool test_result = true; 3441 3442 /* Prepare data */ 3443 GLuint atom_first_data[1]; 3444 GLuint atom_second_data[1]; 3445 GLubyte rectangles_first_data[rectangles_data_size]; 3446 GLubyte rectangles_second_data[rectangles_data_size]; 3447 GLubyte texture_data[texture_data_size]; 3448 3449 atom_first_data[0] = 1; 3450 atom_second_data[0] = 5; 3451 3452 { 3453 GLfloat* ptr = (GLfloat*)rectangles_first_data; 3454 3455 /* First.position*/ 3456 ptr[0] = -0.5f; 3457 ptr[1] = -0.5f; 3458 3459 /* First.size*/ 3460 ptr[2] = 1.0f; 3461 ptr[3] = 1.0f; 3462 3463 /* Second.position*/ 3464 ptr[4 + 0] = -0.75f; 3465 ptr[4 + 1] = -0.75f; 3466 3467 /* Second.size*/ 3468 ptr[4 + 2] = 1.5f; 3469 ptr[4 + 3] = 1.5f; 3470 } 3471 3472 { 3473 GLfloat* ptr = (GLfloat*)rectangles_second_data; 3474 3475 /* First.position*/ 3476 ptr[0] = -1.0f; 3477 ptr[1] = -1.0f; 3478 3479 /* First.size*/ 3480 ptr[2] = 0.5f; 3481 ptr[3] = 0.5f; 3482 3483 /* Second.position*/ 3484 ptr[4 + 0] = 0.5f; 3485 ptr[4 + 1] = 0.5f; 3486 3487 /* Second.size*/ 3488 ptr[4 + 2] = 0.5f; 3489 ptr[4 + 3] = 0.5f; 3490 } 3491 3492 /* Prepare buffers */ 3493 Buffer atom(m_context); 3494 Buffer rectangles(m_context); 3495 3496 atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, 3497 atom_data_size, 0); 3498 3499 rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0); 3500 3501 /* Prepare framebuffer */ 3502 Framebuffer framebuffer(m_context); 3503 Texture texture(m_context); 3504 3505 Texture::Generate(gl, texture.m_id); 3506 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 3507 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */); 3508 3509 Framebuffer::Generate(gl, framebuffer.m_id); 3510 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id); 3511 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height); 3512 3513 /* Prepare VAO */ 3514 VertexArray vao(m_context); 3515 3516 VertexArray::Generate(gl, vao.m_id); 3517 VertexArray::Bind(gl, vao.m_id); 3518 3519 /* Prepare program */ 3520 Program program(m_context); 3521 program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader); 3522 Program::Use(gl, program.m_id); 3523 3524 /* 3525 * - make persistent mapping of both buffers for reads and writes; 3526 * - modify "rectangles" buffer via mapped memory with the following two sets 3527 * * position [-0.5,-0.5], size [1.0,1.0], 3528 * * position [-0.25,-0.25], size [1.5,1.5]; 3529 * - modify "atom_color" buffer via mapped memory to value 1; 3530 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; 3531 * - enable blending with functions ONE for both source and destination; 3532 * - execute DrawArrays for two vertices; 3533 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; 3534 * - inspect contents of: 3535 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), 3536 * * "atom_color" - to verify that it is equal to 3; 3537 * - modify "rectangles" buffer via mapped memory with the following two sets 3538 * * position [-1.0,-1.0], size [0.5,0.5], 3539 * * position [0.5,0.5], size [0.5,0.5]; 3540 * - modify "atom_color" buffer via mapped memory to value 5; 3541 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; 3542 * - execute DrawArrays for two vertices; 3543 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; 3544 * - inspect contents of: 3545 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), 3546 * * "atom_color" - to verify that it is equal to 7; 3547 * 3548 * Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile. 3549 */ 3550 { 3551 /* Choose specification */ 3552 const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 3553 3554 /* Map buffers */ 3555 atom.Bind(); 3556 const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size, 3557 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | 3558 (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0))); 3559 3560 rectangles.Bind(); 3561 const Buffer::MapOwner rectangles_map( 3562 rectangles.MapRange(0 /* offset */, rectangles_data_size, 3563 GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0))); 3564 3565 /* Clear binding points */ 3566 Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER); 3567 Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER); 3568 3569 /* Bind buffers */ 3570 Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding); 3571 Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding); 3572 3573 /* Set up blending */ 3574 gl.enable(GL_BLEND); 3575 gl.blendFunc(GL_ONE, GL_ONE); 3576 3577 /* Modify buffers */ 3578 memcpy(atom_map.m_data, atom_first_data, atom_data_size); 3579 memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size); 3580 3581 /* Execute barrier or flush content. */ 3582 if (is_gl_45) 3583 { 3584 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size); 3585 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange"); 3586 3587 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size); 3588 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange"); 3589 } 3590 else 3591 { 3592 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); 3593 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3594 } 3595 3596 /* Clear drawbuffer */ 3597 GLint clear_color[4] = { 0, 0, 0, 0 }; 3598 gl.clearBufferiv(GL_COLOR, 0, clear_color); 3599 3600 /* Execute program for 2 vertices */ 3601 gl.drawArrays(GL_POINTS, 0, 2); 3602 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers"); 3603 3604 /* Execute barrier */ 3605 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 3606 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3607 3608 /* Inspect texture */ 3609 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data); 3610 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size)) 3611 { 3612 test_result = false; 3613 3614 m_context.getTestContext().getLog() << tcu::TestLog::Message 3615 << "Contents of framebuffer does not correspond with expected results" 3616 << tcu::TestLog::EndMessage; 3617 tcu::ConstPixelBufferAccess img( 3618 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height, 3619 1 /* depth */, texture_data); 3620 m_context.getTestContext().getLog() 3621 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img); 3622 } 3623 3624 /* Inspect atom */ 3625 if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint))) 3626 { 3627 test_result = false; 3628 3629 m_context.getTestContext().getLog() << tcu::TestLog::Message 3630 << "Contents of ATOMIC_COUNTER buffer are invalid." 3631 << tcu::TestLog::EndMessage; 3632 } 3633 3634 /* Modify buffers */ 3635 memcpy(atom_map.m_data, atom_second_data, atom_data_size); 3636 memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size); 3637 3638 /* Execute barrier or flush content. */ 3639 if (is_gl_45) 3640 { 3641 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size); 3642 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange"); 3643 3644 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size); 3645 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange"); 3646 } 3647 else 3648 { 3649 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); 3650 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3651 } 3652 3653 /* Execute program for 2 vertices */ 3654 gl.drawArrays(GL_POINTS, 0, 2); 3655 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers"); 3656 3657 /* Execute barrier */ 3658 gl.memoryBarrier(GL_ALL_BARRIER_BITS); 3659 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); 3660 3661 /* Inspect texture */ 3662 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data); 3663 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size)) 3664 { 3665 test_result = false; 3666 3667 m_context.getTestContext().getLog() << tcu::TestLog::Message 3668 << "Contents of framebuffer does not correspond with expected results" 3669 << tcu::TestLog::EndMessage; 3670 tcu::ConstPixelBufferAccess img( 3671 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height, 3672 1 /* depth */, texture_data); 3673 m_context.getTestContext().getLog() 3674 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img); 3675 } 3676 3677 /* Inspect atom */ 3678 if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint))) 3679 { 3680 test_result = false; 3681 3682 m_context.getTestContext().getLog() << tcu::TestLog::Message 3683 << "Contents of ATOMIC_COUNTER buffer are invalid." 3684 << tcu::TestLog::EndMessage; 3685 } 3686 } 3687 3688 /* Set result */ 3689 if (true == test_result) 3690 { 3691 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3692 } 3693 else 3694 { 3695 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3696 } 3697 3698 /* Done */ 3699 return tcu::TestNode::STOP; 3700} 3701} /* BufferStorage */ 3702 3703/** Constructor. 3704 * 3705 * @param context Rendering context. 3706 **/ 3707BufferStorageTests::BufferStorageTests(deqp::Context& context) 3708 : TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality") 3709{ 3710 /* Left blank on purpose */ 3711} 3712 3713/** Initializes a texture_storage_multisample test group. 3714 * 3715 **/ 3716void BufferStorageTests::init(void) 3717{ 3718 addChild(new BufferStorage::ErrorsTest(m_context)); 3719 addChild(new BufferStorage::GetBufferParameterTest(m_context)); 3720 addChild(new BufferStorage::DynamicStorageTest(m_context)); 3721 addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context)); 3722 addChild(new BufferStorage::MapPersistentTextureTest(m_context)); 3723 addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context)); 3724 addChild(new BufferStorage::MapPersistentDispatchTest(m_context)); 3725 addChild(new BufferStorage::MapPersistentFlushTest(m_context)); 3726 addChild(new BufferStorage::MapPersistentDrawTest(m_context)); 3727} 3728} /* gl4cts namespace */ 3729