Accelerate VBO rendering (bareleye model goes from about 18fps to 34fps on a Macbook Pro)

Fix crashes related to VBO buffer expansion by reallocating the buffers when needed
This commit is contained in:
Jean-Marie Verdun
2017-06-04 09:32:38 -07:00
committed by wmayer
parent ed5155ac08
commit b9ba167d92

View File

@@ -90,6 +90,8 @@ class SoBrepFaceSet::VBO {
public:
struct Buffer {
uint32_t myvbo[2];
long vertex_array_size;
long index_array_size;
};
static SbBool vboAvailable;
@@ -464,7 +466,12 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
if (!this->shouldGLRender(action))
return;
SbBool hasVBO = PRIVATE(this)->vboAvailable;
SoState * state = action->getState();
if (hasVBO) {
// get the VBO status of the viewer
Gui::SoGLVBOActivatedElement::get(state, hasVBO);
}
Binding mbind = this->findMaterialBinding(state);
Binding nbind = this->findNormalBinding(state);
@@ -498,7 +505,7 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
if (!nindices) nindices = cindices;
pindices = this->partIndex.getValues(0);
numparts = this->partIndex.getNum();
SbBool hasVBO = PRIVATE(this)->vboAvailable;
if (hasVBO) {
// get the VBO status of the viewer
Gui::SoGLVBOActivatedElement::get(state, hasVBO);
@@ -510,12 +517,14 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
renderShape(action, hasVBO, static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices,
pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0);
// Disable caching for this node
SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
if (!hasVBO) {
// Disable caching for this node
SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
if (normalCacheUsed)
this->readUnlockNormalCache();
}
if (normalCacheUsed)
this->readUnlockNormalCache();
// Workaround for #0000433
//#if !defined(FC_OS_WIN32)
if (this->highlightIndex.getValue() >= 0)
@@ -1023,12 +1032,20 @@ void SoBrepFaceSet::VBO::render(SoGLRenderAction * action,
PFNGLGENBUFFERSPROC glGenBuffersARB = (PFNGLGENBUFFERSPROC)cc_glglue_getprocaddress(glue, "glGenBuffersARB");
#endif
glGenBuffersARB(2, buf.myvbo);
buf.vertex_array_size = 0;
buf.index_array_size = 0;
this->vbomap[contextId] = buf;
}
else {
buf = it->second;
}
if ((buf.vertex_array_size != (sizeof(float) * num_indices * 10)) ||
(buf.index_array_size != (sizeof(GLuint) * num_indices * 3))) {
if ((buf.vertex_array_size != 0 ) && ( buf.index_array_size != 0))
this->updateVbo = true;
}
// vbo loaded is defining if we must pre-load data into the VBO. When the variable is set to 0
// it means that the VBO has not been initialized
// updateVbo is tracking the need to update the content of the VBO which act as a buffer within
@@ -1038,27 +1055,23 @@ void SoBrepFaceSet::VBO::render(SoGLRenderAction * action,
if (!this->vboLoaded || this->updateVbo) {
#ifdef FC_OS_WIN32
const cc_glglue * glue = cc_glglue_instance(action->getCacheContext());
#endif
if (this->updateVbo && this->vboLoaded) {
// TODO
// We must remember the buffer size ... If it has to be extended we must
// take care of that
#ifdef FC_OS_WIN32
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glBindBufferARB");
PFNGLMAPBUFFERARBPROC glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glMapBufferARB");
#endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
vertex_array=(float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
index_array=(GLuint *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
this->indice_array=0;
}
else {
// We are allocating local buffer to transfer initial VBO content
vertex_array = ( float * ) malloc ( sizeof(float) * num_indices *10 );
index_array = ( GLuint *) malloc ( sizeof(GLuint) * num_indices *3 );
}
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glBindBufferARB");
PFNGLMAPBUFFERARBPROC glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glMapBufferARB");
PFNGLGENBUFFERSPROC glGenBuffersARB = (PFNGLGENBUFFERSPROC)cc_glglue_getprocaddress(glue, "glGenBuffersARB");
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)cc_glglue_getprocaddress(glue, "glDeleteBuffersARB");
PFNGLBUFFERDATAARBPROC glBufferDataARB = (PFNGLBUFFERDATAARBPROC)cc_glglue_getprocaddress(glue, "glBufferDataARB");
#endif
// We must manage buffer size increase let's clear everything and re-init to test the
// clearing process
glDeleteBuffersARB(2, buf.myvbo);
glGenBuffersARB(2, buf.myvbo);
vertex_array = ( float * ) malloc ( sizeof(float) * num_indices * 10 );
index_array = ( GLuint *) malloc ( sizeof(GLuint) * num_indices * 3 );
buf.vertex_array_size = sizeof(float) * num_indices * 10;
buf.index_array_size = sizeof(GLuint) * num_indices * 3;
this->vbomap[contextId] = buf;
this->indice_array = 0;
// Get the initial colors
SoState * state = action->getState();
@@ -1250,35 +1263,19 @@ void SoBrepFaceSet::VBO::render(SoGLRenderAction * action,
}
}
if (!this->updateVbo || !this->vboLoaded) {
// Push the content to the VBO
#ifdef FC_OS_WIN32
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC)cc_glglue_getprocaddress(glue, "glBindBufferARB");
PFNGLBUFFERDATAARBPROC glBufferDataARB = (PFNGLBUFFERDATAARBPROC)cc_glglue_getprocaddress(glue, "glBufferDataARB");
#endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float) * indice , vertex_array, GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float) * indice , vertex_array, GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLuint) * this->indice_array , &index_array[0], GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLuint) * this->indice_array , &index_array[0], GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
this->vboLoaded = true;
this->updateVbo = false;
free(vertex_array);
free(index_array);
}
else {
#ifdef FC_OS_WIN32
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)cc_glglue_getprocaddress(glue, "glUnmapBufferARB");
#endif
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
this->updateVbo = false;
}
this->vboLoaded = true;
this->updateVbo = false;
free(vertex_array);
free(index_array);
}
// This is the VBO rendering code
@@ -1287,8 +1284,11 @@ void SoBrepFaceSet::VBO::render(SoGLRenderAction * action,
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC)cc_glglue_getprocaddress(glue, "glBindBufferARB");
#endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
if (!this->updateVbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
@@ -1304,6 +1304,7 @@ void SoBrepFaceSet::VBO::render(SoGLRenderAction * action,
glDisableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
this->updateVbo = false;
// The data is within the VBO we can clear it at application level
}