BsGLHardwareBufferManager.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "BsGLHardwareBufferManager.h"
  2. #include "BsGLVertexBuffer.h"
  3. #include "BsGLIndexBuffer.h"
  4. #include "BsGLGpuBuffer.h"
  5. #include "BsHardwareBuffer.h"
  6. #include "BsGLGpuParamBlockBuffer.h"
  7. #include "BsRenderSystem.h"
  8. #include "BsRenderSystemCapabilities.h"
  9. namespace BansheeEngine
  10. {
  11. struct GLScratchBufferAlloc
  12. {
  13. /// Size in bytes
  14. UINT32 size: 31;
  15. /// Free? (pack with size)
  16. UINT32 free: 1;
  17. };
  18. #define SCRATCH_POOL_SIZE 1 * 1024 * 1024
  19. #define SCRATCH_ALIGNMENT 32
  20. GLHardwareBufferManager::GLHardwareBufferManager()
  21. : mScratchBufferPool(NULL), mMapBufferThreshold(BS_GL_DEFAULT_MAP_BUFFER_THRESHOLD)
  22. {
  23. // Init scratch pool
  24. // TODO make it a configurable size?
  25. // 32-bit aligned buffer
  26. mScratchBufferPool = static_cast<char*>(_aligned_malloc(SCRATCH_POOL_SIZE, SCRATCH_ALIGNMENT));
  27. GLScratchBufferAlloc* ptrAlloc = (GLScratchBufferAlloc*)mScratchBufferPool;
  28. ptrAlloc->size = SCRATCH_POOL_SIZE - sizeof(GLScratchBufferAlloc);
  29. ptrAlloc->free = 1;
  30. // non-Win32 machines are having issues glBufferSubData, looks like buffer corruption
  31. // disable for now until we figure out where the problem lies
  32. # if BS_PLATFORM != BS_PLATFORM_WIN32
  33. mMapBufferThreshold = 0;
  34. # endif
  35. // Win32 machines with ATI GPU are having issues glMapBuffer, looks like buffer corruption
  36. // disable for now until we figure out where the problem lies
  37. # if BS_PLATFORM == BS_PLATFORM_WIN32
  38. if (BansheeEngine::RenderSystem::instancePtr()->getCapabilities()->getVendor() == GPU_AMD)
  39. {
  40. mMapBufferThreshold = 0xffffffffUL /* maximum unsigned long value */;
  41. }
  42. # endif
  43. }
  44. GLHardwareBufferManager::~GLHardwareBufferManager()
  45. {
  46. _aligned_free(mScratchBufferPool);
  47. }
  48. VertexBufferPtr GLHardwareBufferManager::createVertexBufferImpl(
  49. UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
  50. {
  51. return bs_core_ptr<GLVertexBuffer, PoolAlloc>(new (bs_alloc<GLVertexBuffer, PoolAlloc>()) GLVertexBuffer(vertexSize, numVerts, usage));
  52. }
  53. IndexBufferPtr GLHardwareBufferManager::createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
  54. {
  55. return bs_core_ptr<GLIndexBuffer, PoolAlloc>(new (bs_alloc<GLIndexBuffer, PoolAlloc>()) GLIndexBuffer(itype, numIndexes, usage));
  56. }
  57. GpuParamBlockBufferPtr GLHardwareBufferManager::createGpuParamBlockBufferImpl()
  58. {
  59. return bs_core_ptr<GLGpuParamBlockBuffer, PoolAlloc>(new (bs_alloc<GLGpuParamBlockBuffer, PoolAlloc>()) GLGpuParamBlockBuffer());
  60. }
  61. GpuBufferPtr GLHardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize,
  62. GpuBufferType type, GpuBufferUsage usage, bool randomGpuWrite, bool useCounter)
  63. {
  64. return bs_core_ptr<GLGpuBuffer, PoolAlloc>(new (bs_alloc<GLGpuBuffer, PoolAlloc>()) GLGpuBuffer(elementCount, elementSize, type, usage, randomGpuWrite, useCounter));
  65. }
  66. GLenum GLHardwareBufferManager::getGLUsage(unsigned int usage)
  67. {
  68. switch(usage)
  69. {
  70. case GBU_STATIC:
  71. return GL_STATIC_DRAW;
  72. case GBU_DYNAMIC:
  73. return GL_DYNAMIC_DRAW;
  74. default:
  75. return GL_DYNAMIC_DRAW;
  76. };
  77. }
  78. GLenum GLHardwareBufferManager::getGLType(unsigned int type)
  79. {
  80. switch(type)
  81. {
  82. case VET_FLOAT1:
  83. case VET_FLOAT2:
  84. case VET_FLOAT3:
  85. case VET_FLOAT4:
  86. return GL_FLOAT;
  87. case VET_SHORT1:
  88. case VET_SHORT2:
  89. case VET_SHORT3:
  90. case VET_SHORT4:
  91. return GL_SHORT;
  92. case VET_COLOR:
  93. case VET_COLOR_ABGR:
  94. case VET_COLOR_ARGB:
  95. case VET_UBYTE4:
  96. return GL_UNSIGNED_BYTE;
  97. default:
  98. return 0;
  99. };
  100. }
  101. void* GLHardwareBufferManager::allocateScratch(UINT32 size)
  102. {
  103. // simple forward link search based on alloc sizes
  104. // not that fast but the list should never get that long since not many
  105. // locks at once (hopefully)
  106. BS_LOCK_MUTEX(mScratchMutex)
  107. // Alignment - round up the size to 32 bits
  108. // control blocks are 32 bits too so this packs nicely
  109. if (size % 4 != 0)
  110. {
  111. size += 4 - (size % 4);
  112. }
  113. UINT32 bufferPos = 0;
  114. while (bufferPos < SCRATCH_POOL_SIZE)
  115. {
  116. GLScratchBufferAlloc* pNext = (GLScratchBufferAlloc*)(mScratchBufferPool + bufferPos);
  117. // Big enough?
  118. if (pNext->free && pNext->size >= size)
  119. {
  120. // split? And enough space for control block
  121. if(pNext->size > size + sizeof(GLScratchBufferAlloc))
  122. {
  123. UINT32 offset = (UINT32)sizeof(GLScratchBufferAlloc) + size;
  124. GLScratchBufferAlloc* pSplitAlloc = (GLScratchBufferAlloc*)
  125. (mScratchBufferPool + bufferPos + offset);
  126. pSplitAlloc->free = 1;
  127. // split size is remainder minus new control block
  128. pSplitAlloc->size = pNext->size - size - sizeof(GLScratchBufferAlloc);
  129. // New size of current
  130. pNext->size = size;
  131. }
  132. // allocate and return
  133. pNext->free = 0;
  134. // return pointer just after this control block (++ will do that for us)
  135. return ++pNext;
  136. }
  137. bufferPos += (UINT32)sizeof(GLScratchBufferAlloc) + pNext->size;
  138. }
  139. // no available alloc
  140. return 0;
  141. }
  142. void GLHardwareBufferManager::deallocateScratch(void* ptr)
  143. {
  144. BS_LOCK_MUTEX(mScratchMutex)
  145. // Simple linear search dealloc
  146. UINT32 bufferPos = 0;
  147. GLScratchBufferAlloc* pLast = 0;
  148. while (bufferPos < SCRATCH_POOL_SIZE)
  149. {
  150. GLScratchBufferAlloc* pCurrent = (GLScratchBufferAlloc*)(mScratchBufferPool + bufferPos);
  151. // Pointers match?
  152. if ((mScratchBufferPool + bufferPos + sizeof(GLScratchBufferAlloc))
  153. == ptr)
  154. {
  155. // dealloc
  156. pCurrent->free = 1;
  157. // merge with previous
  158. if (pLast && pLast->free)
  159. {
  160. // adjust buffer pos
  161. bufferPos -= (pLast->size + (UINT32)sizeof(GLScratchBufferAlloc));
  162. // merge free space
  163. pLast->size += pCurrent->size + sizeof(GLScratchBufferAlloc);
  164. pCurrent = pLast;
  165. }
  166. // merge with next
  167. UINT32 offset = bufferPos + pCurrent->size + (UINT32)sizeof(GLScratchBufferAlloc);
  168. if (offset < SCRATCH_POOL_SIZE)
  169. {
  170. GLScratchBufferAlloc* pNext = (GLScratchBufferAlloc*)(
  171. mScratchBufferPool + offset);
  172. if (pNext->free)
  173. {
  174. pCurrent->size += pNext->size + sizeof(GLScratchBufferAlloc);
  175. }
  176. }
  177. // done
  178. return;
  179. }
  180. bufferPos += (UINT32)sizeof(GLScratchBufferAlloc) + pCurrent->size;
  181. pLast = pCurrent;
  182. }
  183. // Should never get here unless there's a corruption
  184. assert (false && "Memory deallocation error");
  185. }
  186. const UINT32 GLHardwareBufferManager::getGLMapBufferThreshold() const
  187. {
  188. return mMapBufferThreshold;
  189. }
  190. void GLHardwareBufferManager::setGLMapBufferThreshold(const UINT32 value)
  191. {
  192. mMapBufferThreshold = value;
  193. }
  194. }