BsGLBuffer.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsGLBuffer.h"
  4. #include "BsGLHardwareBufferManager.h"
  5. #include "Error/BsException.h"
  6. namespace bs { namespace ct
  7. {
  8. GLBuffer::GLBuffer()
  9. :mTarget(0), mBufferId(0), mZeroLocked(false)
  10. {
  11. }
  12. GLBuffer::GLBuffer(GLenum target, UINT32 size, GpuBufferUsage usage)
  13. :mTarget(target), mBufferId(0), mZeroLocked(false)
  14. {
  15. initialize(target, size, usage);
  16. }
  17. GLBuffer::~GLBuffer()
  18. {
  19. if (mBufferId != 0)
  20. {
  21. glDeleteBuffers(1, &mBufferId);
  22. BS_CHECK_GL_ERROR();
  23. }
  24. }
  25. void GLBuffer::initialize(GLenum target, UINT32 size, GpuBufferUsage usage)
  26. {
  27. assert(mBufferId == 0 && "Buffer already initialized");
  28. mTarget = target;
  29. glGenBuffers(1, &mBufferId);
  30. BS_CHECK_GL_ERROR();
  31. if (!mBufferId)
  32. BS_EXCEPT(InternalErrorException, "Cannot create GL buffer");
  33. glBindBuffer(target, mBufferId);
  34. BS_CHECK_GL_ERROR();
  35. glBufferData(target, size, nullptr, GLHardwareBufferManager::getGLUsage(usage));
  36. BS_CHECK_GL_ERROR();
  37. }
  38. void* GLBuffer::lock(UINT32 offset, UINT32 length, GpuLockOptions options)
  39. {
  40. // If no buffer ID it's assumed this type of buffer is unsupported and we silently fail (it's up to the creator
  41. // if the buffer to check for support and potentially print a warning)
  42. if(mBufferId == 0)
  43. return nullptr;
  44. GLenum access = 0;
  45. glBindBuffer(mTarget, mBufferId);
  46. BS_CHECK_GL_ERROR();
  47. if ((options == GBL_WRITE_ONLY) || (options == GBL_WRITE_ONLY_NO_OVERWRITE) || (options == GBL_WRITE_ONLY_DISCARD))
  48. {
  49. access = GL_MAP_WRITE_BIT;
  50. if (options == GBL_WRITE_ONLY_DISCARD)
  51. access |= GL_MAP_INVALIDATE_BUFFER_BIT;
  52. else if (options == GBL_WRITE_ONLY_NO_OVERWRITE)
  53. access |= GL_MAP_UNSYNCHRONIZED_BIT;
  54. }
  55. else if (options == GBL_READ_ONLY)
  56. access = GL_MAP_READ_BIT;
  57. else
  58. access = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
  59. void* buffer = nullptr;
  60. if (length > 0)
  61. {
  62. buffer = glMapBufferRange(mTarget, offset, length, access);
  63. BS_CHECK_GL_ERROR();
  64. if (buffer == nullptr)
  65. BS_EXCEPT(InternalErrorException, "Cannot map OpenGL buffer.");
  66. mZeroLocked = false;
  67. }
  68. else
  69. mZeroLocked = true;
  70. return static_cast<void*>(static_cast<unsigned char*>(buffer));
  71. }
  72. void GLBuffer::unlock()
  73. {
  74. if(mBufferId == 0)
  75. return;
  76. glBindBuffer(mTarget, mBufferId);
  77. BS_CHECK_GL_ERROR();
  78. if (!mZeroLocked)
  79. {
  80. if (!glUnmapBuffer(mTarget))
  81. {
  82. BS_CHECK_GL_ERROR();
  83. BS_EXCEPT(InternalErrorException, "Buffer data corrupted, please reload.");
  84. }
  85. }
  86. }
  87. void GLBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
  88. {
  89. if(mBufferId == 0)
  90. return;
  91. void* bufferData = lock(offset, length, GBL_READ_ONLY);
  92. memcpy(pDest, bufferData, length);
  93. unlock();
  94. }
  95. void GLBuffer::writeData(UINT32 offset, UINT32 length,
  96. const void* pSource, BufferWriteType writeFlags)
  97. {
  98. if(mBufferId == 0)
  99. return;
  100. GpuLockOptions lockOption = GBL_WRITE_ONLY;
  101. if (writeFlags == BWT_DISCARD)
  102. lockOption = GBL_WRITE_ONLY_DISCARD;
  103. else if (writeFlags == BTW_NO_OVERWRITE)
  104. lockOption = GBL_WRITE_ONLY_NO_OVERWRITE;
  105. void* bufferData = lock(offset, length, lockOption);
  106. memcpy(bufferData, pSource, length);
  107. unlock();
  108. }
  109. void GLBuffer::copyData(GLBuffer& dstBuffer, UINT32 srcOffset, UINT32 dstOffset, UINT32 length)
  110. {
  111. if(mBufferId == 0)
  112. return;
  113. glBindBuffer(GL_COPY_READ_BUFFER, mBufferId);
  114. BS_CHECK_GL_ERROR();
  115. glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer.getGLBufferId());
  116. BS_CHECK_GL_ERROR();
  117. glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, dstOffset, length);
  118. BS_CHECK_GL_ERROR();
  119. }
  120. }}