|
@@ -4,7 +4,9 @@
|
|
|
// http://www.anki3d.org/LICENSE
|
|
// http://www.anki3d.org/LICENSE
|
|
|
|
|
|
|
|
#include <anki/gr/gl/DynamicMemoryManager.h>
|
|
#include <anki/gr/gl/DynamicMemoryManager.h>
|
|
|
|
|
+#include <anki/gr/gl/Error.h>
|
|
|
#include <anki/core/Config.h>
|
|
#include <anki/core/Config.h>
|
|
|
|
|
+#include <anki/core/Trace.h>
|
|
|
|
|
|
|
|
namespace anki
|
|
namespace anki
|
|
|
{
|
|
{
|
|
@@ -19,13 +21,14 @@ DynamicMemoryManager::~DynamicMemoryManager()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
|
-void DynamicMemoryManager::destroy()
|
|
|
|
|
|
|
+void DynamicMemoryManager::destroyRenderThread()
|
|
|
{
|
|
{
|
|
|
for(DynamicBuffer& buff : m_buffers)
|
|
for(DynamicBuffer& buff : m_buffers)
|
|
|
{
|
|
{
|
|
|
if(buff.m_name != 0)
|
|
if(buff.m_name != 0)
|
|
|
{
|
|
{
|
|
|
glDeleteBuffers(1, &buff.m_name);
|
|
glDeleteBuffers(1, &buff.m_name);
|
|
|
|
|
+ buff.m_name = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
buff.m_cpuBuff.destroy(m_alloc);
|
|
buff.m_cpuBuff.destroy(m_alloc);
|
|
@@ -33,24 +36,41 @@ void DynamicMemoryManager::destroy()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
|
-void DynamicMemoryManager::init(
|
|
|
|
|
|
|
+void DynamicMemoryManager::initMainThread(
|
|
|
GenericMemoryPoolAllocator<U8> alloc, const ConfigSet& cfg)
|
|
GenericMemoryPoolAllocator<U8> alloc, const ConfigSet& cfg)
|
|
|
{
|
|
{
|
|
|
- const U BUFF_FLAGS = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
|
|
|
|
|
-
|
|
|
|
|
m_alloc = alloc;
|
|
m_alloc = alloc;
|
|
|
|
|
|
|
|
|
|
+ m_buffers[BufferUsage::UNIFORM].m_size =
|
|
|
|
|
+ cfg.getNumber("gr.uniformPerFrameMemorySize");
|
|
|
|
|
+
|
|
|
|
|
+ m_buffers[BufferUsage::STORAGE].m_size =
|
|
|
|
|
+ cfg.getNumber("gr.storagePerFrameMemorySize");
|
|
|
|
|
+
|
|
|
|
|
+ m_buffers[BufferUsage::VERTEX].m_size =
|
|
|
|
|
+ cfg.getNumber("gr.vertexPerFrameMemorySize");
|
|
|
|
|
+
|
|
|
|
|
+ m_buffers[BufferUsage::TRANSFER].m_size =
|
|
|
|
|
+ cfg.getNumber("gr.transferPerFrameMemorySize");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//==============================================================================
|
|
|
|
|
+void DynamicMemoryManager::initRenderThread()
|
|
|
|
|
+{
|
|
|
|
|
+ const U BUFF_FLAGS = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
|
|
|
|
|
+
|
|
|
// Uniform
|
|
// Uniform
|
|
|
{
|
|
{
|
|
|
// Create buffer
|
|
// Create buffer
|
|
|
- PtrSize size = cfg.getNumber("gr.uniformPerFrameMemorySize");
|
|
|
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::UNIFORM];
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::UNIFORM];
|
|
|
|
|
+ PtrSize size = buff.m_size;
|
|
|
glGenBuffers(1, &buff.m_name);
|
|
glGenBuffers(1, &buff.m_name);
|
|
|
|
|
+ glBindBuffer(GL_UNIFORM_BUFFER, buff.m_name);
|
|
|
|
|
|
|
|
// Map it
|
|
// Map it
|
|
|
- glNamedBufferStorage(buff.m_name, size, nullptr, BUFF_FLAGS);
|
|
|
|
|
|
|
+ glBufferStorage(GL_UNIFORM_BUFFER, size, nullptr, BUFF_FLAGS);
|
|
|
buff.m_mappedMem = static_cast<U8*>(
|
|
buff.m_mappedMem = static_cast<U8*>(
|
|
|
- glMapNamedBufferRange(buff.m_name, 0, size, BUFF_FLAGS));
|
|
|
|
|
|
|
+ glMapBufferRange(GL_UNIFORM_BUFFER, 0, size, BUFF_FLAGS));
|
|
|
ANKI_ASSERT(buff.m_mappedMem);
|
|
ANKI_ASSERT(buff.m_mappedMem);
|
|
|
|
|
|
|
|
// Create the allocator
|
|
// Create the allocator
|
|
@@ -62,14 +82,15 @@ void DynamicMemoryManager::init(
|
|
|
// Storage
|
|
// Storage
|
|
|
{
|
|
{
|
|
|
// Create buffer
|
|
// Create buffer
|
|
|
- PtrSize size = cfg.getNumber("gr.storagePerFrameMemorySize");
|
|
|
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::STORAGE];
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::STORAGE];
|
|
|
|
|
+ PtrSize size = buff.m_size;
|
|
|
glGenBuffers(1, &buff.m_name);
|
|
glGenBuffers(1, &buff.m_name);
|
|
|
|
|
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, buff.m_name);
|
|
|
|
|
|
|
|
// Map it
|
|
// Map it
|
|
|
- glNamedBufferStorage(buff.m_name, size, nullptr, BUFF_FLAGS);
|
|
|
|
|
|
|
+ glBufferStorage(GL_SHADER_STORAGE_BUFFER, size, nullptr, BUFF_FLAGS);
|
|
|
buff.m_mappedMem = static_cast<U8*>(
|
|
buff.m_mappedMem = static_cast<U8*>(
|
|
|
- glMapNamedBufferRange(buff.m_name, 0, size, BUFF_FLAGS));
|
|
|
|
|
|
|
+ glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size, BUFF_FLAGS));
|
|
|
ANKI_ASSERT(buff.m_mappedMem);
|
|
ANKI_ASSERT(buff.m_mappedMem);
|
|
|
|
|
|
|
|
// Create the allocator
|
|
// Create the allocator
|
|
@@ -79,17 +100,32 @@ void DynamicMemoryManager::init(
|
|
|
buff.m_frameAlloc.init(size, blockAlignment, MAX_STORAGE_BLOCK_SIZE);
|
|
buff.m_frameAlloc.init(size, blockAlignment, MAX_STORAGE_BLOCK_SIZE);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Transfer
|
|
|
|
|
|
|
+ // Vertex
|
|
|
{
|
|
{
|
|
|
- // Big enough block to hold a texture surface
|
|
|
|
|
- const PtrSize BLOCK_SIZE = (4096 * 4096) / 4 * 16 + 512;
|
|
|
|
|
|
|
+ // Create buffer
|
|
|
|
|
+ DynamicBuffer& buff = m_buffers[BufferUsage::VERTEX];
|
|
|
|
|
+ PtrSize size = buff.m_size;
|
|
|
|
|
+ glGenBuffers(1, &buff.m_name);
|
|
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, buff.m_name);
|
|
|
|
|
+
|
|
|
|
|
+ // Map it
|
|
|
|
|
+ glBufferStorage(GL_ARRAY_BUFFER, size, nullptr, BUFF_FLAGS);
|
|
|
|
|
+ buff.m_mappedMem = static_cast<U8*>(
|
|
|
|
|
+ glMapBufferRange(GL_ARRAY_BUFFER, 0, size, BUFF_FLAGS));
|
|
|
|
|
+ ANKI_ASSERT(buff.m_mappedMem);
|
|
|
|
|
|
|
|
- PtrSize size = cfg.getNumber("gr.transferPersistentMemorySize");
|
|
|
|
|
|
|
+ // Create the allocator
|
|
|
|
|
+ buff.m_frameAlloc.init(size, 16, MAX_U32);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Transfer
|
|
|
|
|
+ {
|
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::TRANSFER];
|
|
DynamicBuffer& buff = m_buffers[BufferUsage::TRANSFER];
|
|
|
|
|
+ PtrSize size = buff.m_size;
|
|
|
buff.m_cpuBuff.create(m_alloc, size);
|
|
buff.m_cpuBuff.create(m_alloc, size);
|
|
|
|
|
|
|
|
buff.m_mappedMem = reinterpret_cast<U8*>(&buff.m_cpuBuff[0]);
|
|
buff.m_mappedMem = reinterpret_cast<U8*>(&buff.m_cpuBuff[0]);
|
|
|
- buff.m_persistentAlloc.init(m_alloc, size, BLOCK_SIZE);
|
|
|
|
|
|
|
+ buff.m_frameAlloc.init(size, 16, MAX_U32);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -98,34 +134,47 @@ void* DynamicMemoryManager::allocatePerFrame(
|
|
|
BufferUsage usage, PtrSize size, DynamicBufferToken& handle)
|
|
BufferUsage usage, PtrSize size, DynamicBufferToken& handle)
|
|
|
{
|
|
{
|
|
|
DynamicBuffer& buff = m_buffers[usage];
|
|
DynamicBuffer& buff = m_buffers[usage];
|
|
|
- Error err = buff.m_frameAlloc.allocate(size, handle, true);
|
|
|
|
|
- (void)err;
|
|
|
|
|
- return buff.m_mappedMem + handle.m_offset;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//==============================================================================
|
|
|
|
|
-void* DynamicMemoryManager::allocatePersistent(
|
|
|
|
|
- BufferUsage usage, PtrSize size, DynamicBufferToken& handle)
|
|
|
|
|
-{
|
|
|
|
|
- DynamicBuffer& buff = m_buffers[usage];
|
|
|
|
|
- Error err = buff.m_persistentAlloc.allocate(size, 16, handle, false);
|
|
|
|
|
|
|
+ Error err = buff.m_frameAlloc.allocate(size, handle, false);
|
|
|
if(!err)
|
|
if(!err)
|
|
|
{
|
|
{
|
|
|
return buff.m_mappedMem + handle.m_offset;
|
|
return buff.m_mappedMem + handle.m_offset;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- ANKI_LOGW("Out of persistent dynamic memory. Someone should serialize");
|
|
|
|
|
|
|
+ ANKI_LOGW(
|
|
|
|
|
+ "Out of per-frame GPU memory. Someone will have to handle this");
|
|
|
return nullptr;
|
|
return nullptr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
|
-void DynamicMemoryManager::freePersistent(
|
|
|
|
|
- BufferUsage usage, const DynamicBufferToken& handle)
|
|
|
|
|
|
|
+void DynamicMemoryManager::endFrame()
|
|
|
{
|
|
{
|
|
|
- DynamicBuffer& buff = m_buffers[usage];
|
|
|
|
|
- buff.m_persistentAlloc.free(handle);
|
|
|
|
|
|
|
+ for(BufferUsage usage = BufferUsage::FIRST; usage < BufferUsage::COUNT;
|
|
|
|
|
+ ++usage)
|
|
|
|
|
+ {
|
|
|
|
|
+ DynamicBuffer& buff = m_buffers[usage];
|
|
|
|
|
+
|
|
|
|
|
+ if(buff.m_mappedMem)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Increase the counters
|
|
|
|
|
+ switch(usage)
|
|
|
|
|
+ {
|
|
|
|
|
+ case BufferUsage::UNIFORM:
|
|
|
|
|
+ ANKI_TRACE_INC_COUNTER(GR_DYNAMIC_UNIFORMS_SIZE,
|
|
|
|
|
+ buff.m_frameAlloc.getUnallocatedMemorySize());
|
|
|
|
|
+ break;
|
|
|
|
|
+ case BufferUsage::STORAGE:
|
|
|
|
|
+ ANKI_TRACE_INC_COUNTER(GR_DYNAMIC_STORAGE_SIZE,
|
|
|
|
|
+ buff.m_frameAlloc.getUnallocatedMemorySize());
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ buff.m_frameAlloc.endFrame();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // end namespace anki
|
|
} // end namespace anki
|