BufferObject.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <cstring>
  2. #include "anki/gl/BufferObject.h"
  3. #include "anki/gl/GlException.h"
  4. #include "anki/util/Exception.h"
  5. /// Instead of map/unmap use glBufferSubData() when writing to the whole buffer
  6. #define USE_BUFFER_DATA_ON_WRITE 1
  7. namespace anki {
  8. //==============================================================================
  9. BufferObject& BufferObject::operator=(BufferObject&& b)
  10. {
  11. destroy();
  12. Base::operator=(std::forward<Base>(b));
  13. target = b.target;
  14. usage = b.usage;
  15. sizeInBytes = b.sizeInBytes;
  16. #if ANKI_DEBUG
  17. mapped = b.mapped;
  18. #endif
  19. return *this;
  20. }
  21. //==============================================================================
  22. void BufferObject::destroy()
  23. {
  24. if(isCreated())
  25. {
  26. unbind();
  27. glDeleteBuffers(1, &glId);
  28. glId = 0;
  29. }
  30. }
  31. //==============================================================================
  32. void BufferObject::create(GLenum target_, U32 sizeInBytes_,
  33. const void* dataPtr, GLenum usage_)
  34. {
  35. ANKI_ASSERT(!isCreated());
  36. ANKI_ASSERT(sizeInBytes_ > 0 && "Unacceptable sizeInBytes");
  37. usage = usage_;
  38. target = target_;
  39. sizeInBytes = sizeInBytes_;
  40. glGenBuffers(1, &glId);
  41. ANKI_ASSERT(glId != 0);
  42. bind();
  43. glBufferData(target, sizeInBytes, dataPtr, usage);
  44. // make a check
  45. GLint bufferSize = 0;
  46. glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufferSize);
  47. if(sizeInBytes != (U32)bufferSize)
  48. {
  49. destroy();
  50. throw ANKI_EXCEPTION("Data size mismatch");
  51. }
  52. unbind();
  53. ANKI_CHECK_GL_ERROR();
  54. }
  55. //==============================================================================
  56. void* BufferObject::map(U32 offset, U32 length, GLuint flags)
  57. {
  58. ANKI_ASSERT(isCreated());
  59. #if ANKI_DEBUG
  60. ANKI_ASSERT(mapped == false);
  61. #endif
  62. bind();
  63. ANKI_ASSERT(offset + length <= sizeInBytes);
  64. void* mappedMem = glMapBufferRange(target, offset, length, flags);
  65. ANKI_ASSERT(mappedMem != nullptr);
  66. #if ANKI_DEBUG
  67. mapped = true;
  68. #endif
  69. return mappedMem;
  70. }
  71. //==============================================================================
  72. void BufferObject::unmap()
  73. {
  74. ANKI_ASSERT(isCreated());
  75. #if ANKI_DEBUG
  76. ANKI_ASSERT(mapped == true);
  77. #endif
  78. bind();
  79. glUnmapBuffer(target);
  80. #if ANKI_DEBUG
  81. mapped = false;
  82. #endif
  83. }
  84. //==============================================================================
  85. void BufferObject::write(void* buff, U32 offset, U32 size)
  86. {
  87. ANKI_ASSERT(isCreated());
  88. ANKI_ASSERT(usage != GL_STATIC_DRAW);
  89. ANKI_ASSERT(offset + size <= sizeInBytes);
  90. bind();
  91. #if USE_BUFFER_DATA_ON_WRITE
  92. glBufferSubData(target, offset, sizeInBytes, buff);
  93. #else
  94. void* mapped = map(offset, size,
  95. GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT
  96. | GL_MAP_UNSYNCHRONIZED_BIT);
  97. memcpy(mapped, buff, size);
  98. unmap();
  99. #endif
  100. }
  101. //==============================================================================
  102. void BufferObject::read(void* outBuff, U32 offset, U32 size)
  103. {
  104. ANKI_ASSERT(isCreated());
  105. ANKI_ASSERT(usage != GL_STATIC_DRAW);
  106. ANKI_ASSERT(offset + size <= sizeInBytes);
  107. bind();
  108. void* mapped = map(offset, size, GL_MAP_READ_BIT);
  109. memcpy(outBuff, mapped, size);
  110. unmap();
  111. }
  112. } // end namespace anki