From 35b01fc3a901165335a2bf9561f9bcf2276b7671 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 4 Jun 2014 18:59:54 +0200 Subject: [PATCH] Implement volatile vertex buffer for opengl driver, should provide considerable performance improvements for particle systems. Needs additional testing. --- .../driver/opengl/driver_opengl_extension.cpp | 20 +++++++++ .../driver/opengl/driver_opengl_extension.h | 7 ++- .../3d/driver/opengl/driver_opengl_vertex.cpp | 15 +++++-- .../driver_opengl_vertex_buffer_hard.cpp | 45 ++++++++++++++----- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_extension.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_extension.cpp index 3ded67d62..ecb4a3a05 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_extension.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_extension.cpp @@ -372,6 +372,10 @@ PFNGLUNMAPBUFFERARBPROC nglUnmapBufferARB; PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB; PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB; +// GL_ARB_map_buffer_range +PFNGLMAPBUFFERRANGEPROC nglMapBufferRange; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC nglFlushMappedBufferRange; + // GL_ARB_vertex_program PFNGLVERTEXATTRIB1SARBPROC nglVertexAttrib1sARB; PFNGLVERTEXATTRIB1FARBPROC nglVertexAttrib1fARB; @@ -1259,6 +1263,21 @@ static bool setupARBVertexBufferObject(const char *glext) return true; } +// *************************************************************************** +static bool setupARBMapBufferRange(const char *glext) +{ + H_AUTO_OGL(setupARBMapBufferRange); + +#ifndef USE_OPENGLES + CHECK_EXT("GL_ARB_map_buffer_range"); + + CHECK_ADDRESS(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange); + CHECK_ADDRESS(PFNGLFLUSHMAPPEDBUFFERRANGEPROC, glFlushMappedBufferRange); +#endif + + return true; +} + // *************************************************************************** static bool setupARBVertexProgram(const char *glext) { @@ -1695,6 +1714,7 @@ void registerGlExtensions(CGlExtensions &ext) if(!ext.DisableHardwareVertexArrayAGP) { ext.ARBVertexBufferObject = setupARBVertexBufferObject(glext); + ext.ARBMapBufferRange = setupARBMapBufferRange(glext); } // fix for radeon 7200 -> disable agp diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h index 938473029..7ed761aff 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h @@ -99,6 +99,7 @@ struct CGlExtensions bool ARBTextureCompression; bool ARBFragmentProgram; bool ARBVertexBufferObject; + bool ARBMapBufferRange; bool ARBVertexProgram; bool ARBTextureNonPowerOfTwo; bool ARBMultisample; @@ -262,6 +263,7 @@ public: result += ATIVertexArrayObject ? "ATIVertexArrayObject " : ""; result += ATIVertexAttribArrayObject ? "ATIVertexAttribArrayObject " : ""; result += ARBVertexBufferObject ? "ARBVertexBufferObject " : ""; + result += ARBMapBufferRange ? "ARBMapBufferRange " : ""; result += ATIMapObjectBuffer ? "ATIMapObjectBuffer " : ""; result += "\n FBO: "; @@ -654,7 +656,10 @@ extern PFNGLUNMAPBUFFERARBPROC nglUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB; - +// GL_ARB_map_buffer_range +//================================== +extern PFNGLMAPBUFFERRANGEPROC nglMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC nglFlushMappedBufferRange; // GL_ARB_vertex_program //================================== diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp index c71e82ce4..cab62f094 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp @@ -147,9 +147,9 @@ bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB) CVBDrvInfosGL *info = new CVBDrvInfosGL(this, it, &VB); *it= VB.DrvInfos = info; - // Preferred memory + // Preferred memory, AGPVolatile only goes through when ARBMapBufferRange is available CVertexBuffer::TPreferredMemory preferred = VB.getPreferredMemory (); - if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile)) + if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile && !_Extensions.ARBMapBufferRange)) preferred = CVertexBuffer::RAMPreferred; const uint size = VB.capacity()*VB.getVertexSize(); uint preferredMemory = _Extensions.DisableHardwareVertexArrayAGP ? CVertexBuffer::RAMPreferred : preferred; @@ -159,6 +159,12 @@ bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB) info->_VBHard = createVertexBufferHard(size, VB.capacity(), (CVertexBuffer::TPreferredMemory)preferredMemory, &VB); if (info->_VBHard) break; + + if ((CVertexBuffer::TPreferredMemory)preferredMemory == CVertexBuffer::AGPVolatile) + { + preferredMemory = CVertexBuffer::RAMPreferred; + break; + } preferredMemory--; } @@ -170,7 +176,7 @@ bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB) } // Upload the data - VB.setLocation ((CVertexBuffer::TLocation)preferredMemory); + VB.setLocation(preferredMemory == CVertexBuffer::AGPVolatile ? CVertexBuffer::AGPResident : (CVertexBuffer::TLocation)preferredMemory); } } @@ -740,7 +746,7 @@ bool CDriverGL::supportVertexBufferHard() const bool CDriverGL::supportVolatileVertexBuffer() const { H_AUTO_OGL(CDriverGL_supportVolatileVertexBuffer) - return false; + return _Extensions.ARBMapBufferRange; } @@ -769,6 +775,7 @@ IVertexBufferHardGL *CDriverGL::createVertexBufferHard(uint size, uint numVertic IVertexArrayRange *vertexArrayRange= NULL; switch(vbType) { + case CVertexBuffer::AGPVolatile: case CVertexBuffer::AGPPreferred: vertexArrayRange= _AGPVertexArrayRange; break; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_vertex_buffer_hard.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_vertex_buffer_hard.cpp index 79c55ea16..0556fad3e 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_vertex_buffer_hard.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_vertex_buffer_hard.cpp @@ -1174,6 +1174,9 @@ bool CVertexArrayRangeARB::allocate(uint32 size, CVertexBuffer::TPreferredMemory switch(vbType) { + case CVertexBuffer::AGPVolatile: + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB); + break; case CVertexBuffer::AGPPreferred: glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); break; @@ -1221,13 +1224,14 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff if (glGetError() != GL_NO_ERROR) return NULL; _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID); - switch(_VBType) + CVertexBuffer::TPreferredMemory preferred = vb->getPreferredMemory(); + switch (preferred) { - case CVertexBuffer::AGPPreferred: + case CVertexBuffer::AGPVolatile: #ifdef USE_OPENGLES - glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STREAM_DRAW); #else - nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); + nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB); #endif break; case CVertexBuffer::StaticPreferred: @@ -1244,8 +1248,13 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); #endif break; + // case CVertexBuffer::AGPPreferred: default: - nlassert(0); +#ifdef USE_OPENGLES + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); +#else + nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); +#endif break; } if (glGetError() != GL_NO_ERROR) @@ -1259,7 +1268,7 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff return NULL; } CVertexBufferHardARB *newVbHard= new CVertexBufferHardARB(_Driver, vb); - newVbHard->initGL(vertexBufferID, this, _VBType); + newVbHard->initGL(vertexBufferID, this, preferred); _Driver->_DriverGLStates.forceBindARBVertexBuffer(0); return newVbHard; } @@ -1393,6 +1402,7 @@ void *CVertexBufferHardARB::lock() H_AUTO_OGL(CVertexBufferHardARB_lock); if (_VertexPtr) return _VertexPtr; // already locked + const uint size = VB->getNumVertices() * VB->getVertexSize(); if (_Invalid) { if (VB->getLocation() != CVertexBuffer::NotResident) @@ -1414,15 +1424,14 @@ void *CVertexBufferHardARB::lock() _Driver->incrementResetCounter(); return &_DummyVB[0]; } - const uint size = VB->getNumVertices() * VB->getVertexSize(); _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID); switch(_MemType) { - case CVertexBuffer::AGPPreferred: + case CVertexBuffer::AGPVolatile: #ifdef USE_OPENGLES - glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STREAM_DRAW); #else - nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); + nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB); #endif break; case CVertexBuffer::StaticPreferred: @@ -1439,8 +1448,13 @@ void *CVertexBufferHardARB::lock() nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); #endif break; + // case CVertexBuffer::AGPPreferred: default: - nlassert(0); +#ifdef USE_OPENGLES + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); +#else + nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); +#endif break; } if (glGetError() != GL_NO_ERROR) @@ -1499,7 +1513,14 @@ void *CVertexBufferHardARB::lock() _LastBufferSize = size; } #else - _VertexPtr = nglMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + if (_MemType == CVertexBuffer::AGPVolatile) + { + _VertexPtr = nglMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + else + { + _VertexPtr = nglMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } if (!_VertexPtr) { nglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);