Refactoring of streamer code to integrate texture and vbo memory management in progress.

--HG--
branch : nfb
This commit is contained in:
2014-05-13 23:49:03 -07:00
parent dc9bec2766
commit e96c48b59e
2 changed files with 171 additions and 126 deletions

View File

@@ -39,10 +39,7 @@
#include "KRMeshSphere.h" #include "KRMeshSphere.h"
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) { KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
m_currentVBO.vbo_handle = -1; m_currentVBO = NULL;
m_currentVBO.vbo_handle_indexes = -1;
m_currentVBO.vao_handle = -1;
m_currentVBO.data = NULL;
m_vboMemUsed = 0; m_vboMemUsed = 0;
m_memoryTransferredThisFrame = 0; m_memoryTransferredThisFrame = 0;
@@ -140,24 +137,22 @@ unordered_multimap<std::string, KRMesh *> &KRMeshManager::getModels() {
} }
void KRMeshManager::unbindVBO() { void KRMeshManager::unbindVBO() {
if(m_currentVBO.data != NULL) { if(m_currentVBO != NULL) {
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, 0)); GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, 0));
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
m_currentVBO.size = 0; m_currentVBO = NULL;
m_currentVBO.data = NULL;
m_currentVBO.vbo_handle = -1;
m_currentVBO.vbo_handle_indexes = -1;
m_currentVBO.vao_handle = -1;
} }
} }
void KRMeshManager::releaseVBO(KRDataBlock &data) void KRMeshManager::releaseVBO(KRDataBlock &data)
{ {
if(m_currentVBO.data == &data) { if(m_currentVBO) {
unbindVBO(); if(m_currentVBO->m_data == &data) {
unbindVBO();
}
} }
vbo_info_type vbo_to_release; KRVBOData *vbo_to_release = NULL;
if(m_vbosActive.find(&data) != m_vbosActive.end()) { if(m_vbosActive.find(&data) != m_vbosActive.end()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "glFinish called due to releasing a VBO that is active in the current frame."); KRContext::Log(KRContext::LOG_LEVEL_WARNING, "glFinish called due to releasing a VBO that is active in the current frame.");
GLDEBUG(glFinish()); GLDEBUG(glFinish());
@@ -171,49 +166,40 @@ void KRMeshManager::releaseVBO(KRDataBlock &data)
m_vbosPool.erase(&data); m_vbosPool.erase(&data);
} }
m_vboMemUsed -= vbo_to_release.size; if(vbo_to_release) {
m_vboMemUsed -= vbo_to_release->m_size;
#if GL_OES_vertex_array_object
GLDEBUG(glDeleteVertexArraysOES(1, &vbo_to_release.vao_handle)); vbo_to_release->unload();
#endif delete vbo_to_release;
GLDEBUG(glDeleteBuffers(1, &vbo_to_release.vbo_handle));
if(vbo_to_release.vbo_handle_indexes != -1) {
GLDEBUG(glDeleteBuffers(1, &vbo_to_release.vbo_handle_indexes));
} }
} }
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo) {
if(m_currentVBO.data != &data) {
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo)
{
bool vbo_changed = false;
if(m_currentVBO == NULL) {
vbo_changed = true;
} else if(m_currentVBO->m_data != &data) {
vbo_changed = true;
}
if(vbo_changed) {
if(m_vbosActive.find(&data) != m_vbosActive.end()) { if(m_vbosActive.find(&data) != m_vbosActive.end()) {
m_currentVBO = m_vbosActive[&data]; m_currentVBO = m_vbosActive[&data];
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle)); m_currentVBO->bind();
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
configureAttribs(vertex_attrib_flags);
if(m_currentVBO.vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
}
#endif
} else if(m_vbosPool.find(&data) != m_vbosPool.end()) { } else if(m_vbosPool.find(&data) != m_vbosPool.end()) {
m_currentVBO = m_vbosPool[&data]; m_currentVBO = m_vbosPool[&data];
m_vbosPool.erase(&data); m_vbosPool.erase(&data);
m_vbosActive[&data] = m_currentVBO; m_vbosActive[&data] = m_currentVBO;
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle)); m_currentVBO->bind();
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
configureAttribs(vertex_attrib_flags);
if(m_currentVBO.vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
}
#endif
} else { } else {
@@ -222,75 +208,22 @@ void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vert
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "flushBuffers due to VBO exhaustion..."); KRContext::Log(KRContext::LOG_LEVEL_WARNING, "flushBuffers due to VBO exhaustion...");
m_pContext->rotateBuffers(false); m_pContext->rotateBuffers(false);
} }
unordered_map<KRDataBlock *, vbo_info_type>::iterator first_itr = m_vbosPool.begin(); unordered_map<KRDataBlock *, KRVBOData *>::iterator first_itr = m_vbosPool.begin();
vbo_info_type firstVBO = first_itr->second; KRVBOData *firstVBO = first_itr->second;
#if GL_OES_vertex_array_object
GLDEBUG(glDeleteVertexArraysOES(1, &firstVBO.vao_handle));
#endif
GLDEBUG(glDeleteBuffers(1, &firstVBO.vbo_handle));
if(firstVBO.vbo_handle_indexes != -1) {
GLDEBUG(glDeleteBuffers(1, &firstVBO.vbo_handle_indexes));
}
m_vboMemUsed -= firstVBO.size;
m_vbosPool.erase(first_itr); m_vbosPool.erase(first_itr);
m_vboMemUsed -= firstVBO->m_size;
firstVBO->unload();
delete firstVBO;
// fprintf(stderr, "VBO Swapping...\n"); // fprintf(stderr, "VBO Swapping...\n");
} }
m_currentVBO.vao_handle = -1; m_currentVBO = new KRVBOData();
m_currentVBO.vbo_handle = -1;
m_currentVBO.vbo_handle_indexes = -1;
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle));
if(index_data.getSize() > 0) {
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle_indexes));
}
#if GL_OES_vertex_array_object m_currentVBO->load(data, index_data, vertex_attrib_flags, static_vbo);
GLDEBUG(glGenVertexArraysOES(1, &m_currentVBO.vao_handle)); m_memoryTransferredThisFrame += m_currentVBO->m_size;
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle)); m_vboMemUsed += m_currentVBO->m_size;
#endif
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
data.copy(map_ptr);
//memcpy(map_ptr, data, size);
GLDEBUG(glUnmapBufferOES(GL_ARRAY_BUFFER));
#else
data.lock();
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
data.unlock();
#endif
m_memoryTransferredThisFrame += data.getSize();
m_vboMemUsed += data.getSize();
configureAttribs(vertex_attrib_flags);
m_currentVBO.size = data.getSize();
m_currentVBO.data = &data;
if(index_data.getSize() == 0) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
index_data.copy(map_ptr);
//memcpy(map_ptr, index_data, index_data.getSize());
GLDEBUG(glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER));
#else
index_data.lock();
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), index_data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
index_data.unlock();
#endif
m_memoryTransferredThisFrame += index_data.getSize();
m_vboMemUsed += index_data.getSize();
m_currentVBO.size += index_data.getSize();
}
m_vbosActive[&data] = m_currentVBO; m_vbosActive[&data] = m_currentVBO;
} }
@@ -374,8 +307,8 @@ long KRMeshManager::getMemUsed()
long KRMeshManager::getMemActive() long KRMeshManager::getMemActive()
{ {
long mem_active = 0; long mem_active = 0;
for(unordered_map<KRDataBlock *, vbo_info_type>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) { for(unordered_map<KRDataBlock *, KRVBOData *>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
mem_active += (*itr).second.size; mem_active += (*itr).second->m_size;
} }
return mem_active; return mem_active;
} }
@@ -384,12 +317,11 @@ void KRMeshManager::rotateBuffers(bool new_frame)
{ {
m_vbosPool.insert(m_vbosActive.begin(), m_vbosActive.end()); m_vbosPool.insert(m_vbosActive.begin(), m_vbosActive.end());
m_vbosActive.clear(); m_vbosActive.clear();
if(m_currentVBO.data != NULL) { if(m_currentVBO != NULL) {
// Ensure that the currently active VBO does not get flushed to free memory // Ensure that the currently active VBO does not get flushed to free memory
m_vbosPool.erase(m_currentVBO.data); m_vbosPool.erase(m_currentVBO->m_data);
m_vbosActive[m_currentVBO.data] = m_currentVBO; m_vbosActive[m_currentVBO->m_data] = m_currentVBO;
} }
} }
KRDataBlock &KRMeshManager::getVolumetricLightingVertexes() KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
@@ -531,3 +463,99 @@ void KRMeshManager::doStreaming(long &memoryRemaining, long &memoryRemainingThis
{ {
} }
KRMeshManager::KRVBOData::KRVBOData()
{
m_vbo_handle = -1;
m_vbo_handle_indexes = -1;
m_vao_handle = -1;
m_data = NULL;
}
KRMeshManager::KRVBOData::~KRVBOData()
{
}
void KRMeshManager::KRVBOData::unload()
{
#if GL_OES_vertex_array_object
GLDEBUG(glDeleteVertexArraysOES(1, &m_vao_handle));
#endif
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle));
if(m_vbo_handle_indexes != -1) {
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle_indexes));
}
}
void KRMeshManager::KRVBOData::bind()
{
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
KRMeshManager::configureAttribs(m_vertex_attrib_flags);
if(m_vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
}
#endif
}
void KRMeshManager::KRVBOData::load(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo)
{
m_vertex_attrib_flags = vertex_attrib_flags;
m_vao_handle = -1;
m_vbo_handle = -1;
m_vbo_handle_indexes = -1;
GLDEBUG(glGenBuffers(1, &m_vbo_handle));
if(index_data.getSize() > 0) {
GLDEBUG(glGenBuffers(1, &m_vbo_handle_indexes));
}
#if GL_OES_vertex_array_object
GLDEBUG(glGenVertexArraysOES(1, &m_vao_handle));
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
#endif
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
data.copy(map_ptr);
GLDEBUG(glUnmapBufferOES(GL_ARRAY_BUFFER));
#else
data.lock();
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
data.unlock();
#endif
configureAttribs(vertex_attrib_flags);
m_size = data.getSize();
m_data = &data;
if(index_data.getSize() == 0) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
index_data.copy(map_ptr);
GLDEBUG(glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER));
#else
index_data.lock();
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), index_data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
index_data.unlock();
#endif
m_size += index_data.getSize();
}
}

View File

@@ -65,7 +65,7 @@ public:
long getMemUsed(); long getMemUsed();
long getMemActive(); long getMemActive();
void configureAttribs(__int32_t attributes); static void configureAttribs(__int32_t attributes);
typedef struct { typedef struct {
GLfloat x; GLfloat x;
@@ -120,19 +120,36 @@ public:
private: private:
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
typedef struct vbo_info { class KRVBOData {
GLuint vbo_handle;
GLuint vbo_handle_indexes; public:
GLuint vao_handle;
GLsizeiptr size; KRVBOData();
KRDataBlock *data; ~KRVBOData();
} vbo_info_type;
GLsizeiptr m_size;
KRDataBlock *m_data;
void load(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo);
void unload();
void bind();
// Disable copy constructors
KRVBOData(const KRVBOData& o) = delete;
KRVBOData(KRVBOData& o) = delete;
private:
int m_vertex_attrib_flags;
GLuint m_vbo_handle;
GLuint m_vbo_handle_indexes;
GLuint m_vao_handle;
};
long m_vboMemUsed; long m_vboMemUsed;
vbo_info_type m_currentVBO; KRVBOData *m_currentVBO;
unordered_map<KRDataBlock *, vbo_info_type> m_vbosActive; unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
unordered_map<KRDataBlock *, vbo_info_type> m_vbosPool; unordered_map<KRDataBlock *, KRVBOData *> m_vbosPool;
KRDataBlock m_randomParticleVertexData; KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData; KRDataBlock m_volumetricLightingVertexData;