DynamicMemoryManager.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/gr/gl/DynamicMemoryManager.h>
  6. #include <anki/gr/gl/Error.h>
  7. #include <anki/core/Config.h>
  8. #include <anki/core/Trace.h>
  9. namespace anki
  10. {
  11. //==============================================================================
  12. DynamicMemoryManager::~DynamicMemoryManager()
  13. {
  14. for(PerFrameBuffer& buff : m_perFrameBuffers)
  15. {
  16. ANKI_ASSERT(buff.m_name == 0);
  17. (void)buff;
  18. }
  19. for(PersistentBuffer& buff : m_persistentBuffers)
  20. {
  21. ANKI_ASSERT(buff.m_name == 0);
  22. (void)buff;
  23. }
  24. }
  25. //==============================================================================
  26. void DynamicMemoryManager::destroyRenderThread()
  27. {
  28. for(PerFrameBuffer& buff : m_perFrameBuffers)
  29. {
  30. if(buff.m_name != 0)
  31. {
  32. glDeleteBuffers(1, &buff.m_name);
  33. buff.m_name = 0;
  34. }
  35. buff.m_cpuBuff.destroy(m_alloc);
  36. }
  37. for(PersistentBuffer& buff : m_persistentBuffers)
  38. {
  39. if(buff.m_name != 0)
  40. {
  41. glDeleteBuffers(1, &buff.m_name);
  42. buff.m_name = 0;
  43. }
  44. buff.m_cpuBuff.destroy(m_alloc);
  45. }
  46. }
  47. //==============================================================================
  48. void DynamicMemoryManager::initMainThread(
  49. GenericMemoryPoolAllocator<U8> alloc, const ConfigSet& cfg)
  50. {
  51. m_alloc = alloc;
  52. m_perFrameBuffers[BufferUsage::UNIFORM].m_size =
  53. cfg.getNumber("gr.uniformPerFrameMemorySize");
  54. m_perFrameBuffers[BufferUsage::STORAGE].m_size =
  55. cfg.getNumber("gr.storagePerFrameMemorySize");
  56. m_perFrameBuffers[BufferUsage::VERTEX].m_size =
  57. cfg.getNumber("gr.vertexPerFrameMemorySize");
  58. m_perFrameBuffers[BufferUsage::TRANSFER].m_size =
  59. cfg.getNumber("gr.transferPerFrameMemorySize");
  60. m_persistentBuffers[BufferUsage::TRANSFER].m_size =
  61. cfg.getNumber("gr.transferPersistentMemorySize");
  62. }
  63. //==============================================================================
  64. void DynamicMemoryManager::initRenderThread()
  65. {
  66. const U BUFF_FLAGS = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
  67. // Uniform
  68. {
  69. // Create buffer
  70. PerFrameBuffer& buff = m_perFrameBuffers[BufferUsage::UNIFORM];
  71. PtrSize size = buff.m_size;
  72. glGenBuffers(1, &buff.m_name);
  73. glBindBuffer(GL_UNIFORM_BUFFER, buff.m_name);
  74. // Map it
  75. glBufferStorage(GL_UNIFORM_BUFFER, size, nullptr, BUFF_FLAGS);
  76. buff.m_mappedMem = static_cast<U8*>(
  77. glMapBufferRange(GL_UNIFORM_BUFFER, 0, size, BUFF_FLAGS));
  78. ANKI_ASSERT(buff.m_mappedMem);
  79. // Create the allocator
  80. GLint64 blockAlignment;
  81. glGetInteger64v(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &blockAlignment);
  82. buff.m_alloc.init(size, blockAlignment, MAX_UNIFORM_BLOCK_SIZE);
  83. }
  84. // Storage
  85. {
  86. // Create buffer
  87. PerFrameBuffer& buff = m_perFrameBuffers[BufferUsage::STORAGE];
  88. PtrSize size = buff.m_size;
  89. glGenBuffers(1, &buff.m_name);
  90. glBindBuffer(GL_SHADER_STORAGE_BUFFER, buff.m_name);
  91. // Map it
  92. glBufferStorage(GL_SHADER_STORAGE_BUFFER, size, nullptr, BUFF_FLAGS);
  93. buff.m_mappedMem = static_cast<U8*>(
  94. glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size, BUFF_FLAGS));
  95. ANKI_ASSERT(buff.m_mappedMem);
  96. // Create the allocator
  97. GLint64 blockAlignment;
  98. glGetInteger64v(
  99. GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &blockAlignment);
  100. buff.m_alloc.init(size, blockAlignment, MAX_STORAGE_BLOCK_SIZE);
  101. }
  102. // Vertex
  103. {
  104. // Create buffer
  105. PerFrameBuffer& buff = m_perFrameBuffers[BufferUsage::VERTEX];
  106. PtrSize size = buff.m_size;
  107. glGenBuffers(1, &buff.m_name);
  108. glBindBuffer(GL_ARRAY_BUFFER, buff.m_name);
  109. // Map it
  110. glBufferStorage(GL_ARRAY_BUFFER, size, nullptr, BUFF_FLAGS);
  111. buff.m_mappedMem = static_cast<U8*>(
  112. glMapBufferRange(GL_ARRAY_BUFFER, 0, size, BUFF_FLAGS));
  113. ANKI_ASSERT(buff.m_mappedMem);
  114. // Create the allocator
  115. buff.m_alloc.init(size, 16, MAX_U32);
  116. }
  117. // Transfer
  118. {
  119. PerFrameBuffer& buff = m_perFrameBuffers[BufferUsage::TRANSFER];
  120. PtrSize size = buff.m_size;
  121. buff.m_cpuBuff.create(m_alloc, size);
  122. buff.m_mappedMem = reinterpret_cast<U8*>(&buff.m_cpuBuff[0]);
  123. buff.m_alloc.init(size, 16, MAX_U32);
  124. }
  125. {
  126. const U BLOCK_SIZE = (4096 * 4096) / 4 * 16;
  127. PersistentBuffer& buff = m_persistentBuffers[BufferUsage::TRANSFER];
  128. PtrSize size = getAlignedRoundUp(BLOCK_SIZE, buff.m_size);
  129. size = max(size, 2 * BLOCK_SIZE);
  130. buff.m_cpuBuff.create(m_alloc, size);
  131. buff.m_mappedMem = reinterpret_cast<U8*>(&buff.m_cpuBuff[0]);
  132. buff.m_alloc.init(m_alloc, size, BLOCK_SIZE);
  133. buff.m_alignment = 16;
  134. }
  135. }
  136. //==============================================================================
  137. void DynamicMemoryManager::allocate(PtrSize size,
  138. BufferUsage usage,
  139. TransientMemoryTokenLifetime lifespan,
  140. TransientMemoryToken& token,
  141. void*& ptr,
  142. Error* outErr)
  143. {
  144. Error err = ErrorCode::NONE;
  145. ptr = nullptr;
  146. U8* mappedMemBase;
  147. if(lifespan == TransientMemoryTokenLifetime::PER_FRAME)
  148. {
  149. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  150. err = buff.m_alloc.allocate(size, token.m_offset);
  151. mappedMemBase = buff.m_mappedMem;
  152. }
  153. else
  154. {
  155. PersistentBuffer& buff = m_persistentBuffers[usage];
  156. err = buff.m_alloc.allocate(size, buff.m_alignment, token.m_offset);
  157. mappedMemBase = buff.m_mappedMem;
  158. }
  159. if(!err)
  160. {
  161. token.m_usage = usage;
  162. token.m_range = size;
  163. token.m_lifetime = lifespan;
  164. ptr = mappedMemBase + token.m_offset;
  165. }
  166. else if(outErr)
  167. {
  168. *outErr = err;
  169. }
  170. else
  171. {
  172. ANKI_LOGF("Out of transient GPU memory");
  173. }
  174. }
  175. //==============================================================================
  176. void DynamicMemoryManager::endFrame()
  177. {
  178. for(BufferUsage usage = BufferUsage::FIRST; usage < BufferUsage::COUNT;
  179. ++usage)
  180. {
  181. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  182. if(buff.m_mappedMem)
  183. {
  184. // Increase the counters
  185. switch(usage)
  186. {
  187. case BufferUsage::UNIFORM:
  188. ANKI_TRACE_INC_COUNTER(GR_DYNAMIC_UNIFORMS_SIZE,
  189. buff.m_alloc.getUnallocatedMemorySize());
  190. break;
  191. case BufferUsage::STORAGE:
  192. ANKI_TRACE_INC_COUNTER(GR_DYNAMIC_STORAGE_SIZE,
  193. buff.m_alloc.getUnallocatedMemorySize());
  194. break;
  195. default:
  196. break;
  197. }
  198. buff.m_alloc.endFrame();
  199. }
  200. }
  201. }
  202. } // end namespace anki