Implement volatile vertex buffer for opengl driver, should provide considerable performance improvements for particle systems. Needs additional testing.

This commit is contained in:
kaetemi 2014-06-04 18:59:54 +02:00
parent bc0258d826
commit 944058c61e
4 changed files with 70 additions and 17 deletions

View file

@ -372,6 +372,10 @@ PFNGLUNMAPBUFFERARBPROC nglUnmapBufferARB;
PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB; PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB;
PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB; PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB;
// GL_ARB_map_buffer_range
PFNGLMAPBUFFERRANGEPROC nglMapBufferRange;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC nglFlushMappedBufferRange;
// GL_ARB_vertex_program // GL_ARB_vertex_program
PFNGLVERTEXATTRIB1SARBPROC nglVertexAttrib1sARB; PFNGLVERTEXATTRIB1SARBPROC nglVertexAttrib1sARB;
PFNGLVERTEXATTRIB1FARBPROC nglVertexAttrib1fARB; PFNGLVERTEXATTRIB1FARBPROC nglVertexAttrib1fARB;
@ -1259,6 +1263,21 @@ static bool setupARBVertexBufferObject(const char *glext)
return true; 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) static bool setupARBVertexProgram(const char *glext)
{ {
@ -1695,6 +1714,7 @@ void registerGlExtensions(CGlExtensions &ext)
if(!ext.DisableHardwareVertexArrayAGP) if(!ext.DisableHardwareVertexArrayAGP)
{ {
ext.ARBVertexBufferObject = setupARBVertexBufferObject(glext); ext.ARBVertexBufferObject = setupARBVertexBufferObject(glext);
ext.ARBMapBufferRange = setupARBMapBufferRange(glext);
} }
// fix for radeon 7200 -> disable agp // fix for radeon 7200 -> disable agp

View file

@ -99,6 +99,7 @@ struct CGlExtensions
bool ARBTextureCompression; bool ARBTextureCompression;
bool ARBFragmentProgram; bool ARBFragmentProgram;
bool ARBVertexBufferObject; bool ARBVertexBufferObject;
bool ARBMapBufferRange;
bool ARBVertexProgram; bool ARBVertexProgram;
bool ARBTextureNonPowerOfTwo; bool ARBTextureNonPowerOfTwo;
bool ARBMultisample; bool ARBMultisample;
@ -262,6 +263,7 @@ public:
result += ATIVertexArrayObject ? "ATIVertexArrayObject " : ""; result += ATIVertexArrayObject ? "ATIVertexArrayObject " : "";
result += ATIVertexAttribArrayObject ? "ATIVertexAttribArrayObject " : ""; result += ATIVertexAttribArrayObject ? "ATIVertexAttribArrayObject " : "";
result += ARBVertexBufferObject ? "ARBVertexBufferObject " : ""; result += ARBVertexBufferObject ? "ARBVertexBufferObject " : "";
result += ARBMapBufferRange ? "ARBMapBufferRange " : "";
result += ATIMapObjectBuffer ? "ATIMapObjectBuffer " : ""; result += ATIMapObjectBuffer ? "ATIMapObjectBuffer " : "";
result += "\n FBO: "; result += "\n FBO: ";
@ -654,7 +656,10 @@ extern PFNGLUNMAPBUFFERARBPROC nglUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC nglGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB; extern PFNGLGETBUFFERPOINTERVARBPROC nglGetBufferPointervARB;
// GL_ARB_map_buffer_range
//==================================
extern PFNGLMAPBUFFERRANGEPROC nglMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC nglFlushMappedBufferRange;
// GL_ARB_vertex_program // GL_ARB_vertex_program
//================================== //==================================

View file

@ -147,9 +147,9 @@ bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB)
CVBDrvInfosGL *info = new CVBDrvInfosGL(this, it, &VB); CVBDrvInfosGL *info = new CVBDrvInfosGL(this, it, &VB);
*it= VB.DrvInfos = info; *it= VB.DrvInfos = info;
// Preferred memory // Preferred memory, AGPVolatile only goes through when ARBMapBufferRange is available
CVertexBuffer::TPreferredMemory preferred = VB.getPreferredMemory (); CVertexBuffer::TPreferredMemory preferred = VB.getPreferredMemory ();
if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile)) if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile && !_Extensions.ARBMapBufferRange))
preferred = CVertexBuffer::RAMPreferred; preferred = CVertexBuffer::RAMPreferred;
const uint size = VB.capacity()*VB.getVertexSize(); const uint size = VB.capacity()*VB.getVertexSize();
uint preferredMemory = _Extensions.DisableHardwareVertexArrayAGP ? CVertexBuffer::RAMPreferred : preferred; 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); info->_VBHard = createVertexBufferHard(size, VB.capacity(), (CVertexBuffer::TPreferredMemory)preferredMemory, &VB);
if (info->_VBHard) if (info->_VBHard)
break; break;
if ((CVertexBuffer::TPreferredMemory)preferredMemory == CVertexBuffer::AGPVolatile)
{
preferredMemory = CVertexBuffer::RAMPreferred;
break;
}
preferredMemory--; preferredMemory--;
} }
@ -170,7 +176,7 @@ bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB)
} }
// Upload the data // 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 bool CDriverGL::supportVolatileVertexBuffer() const
{ {
H_AUTO_OGL(CDriverGL_supportVolatileVertexBuffer) H_AUTO_OGL(CDriverGL_supportVolatileVertexBuffer)
return false; return _Extensions.ARBMapBufferRange;
} }
@ -769,6 +775,7 @@ IVertexBufferHardGL *CDriverGL::createVertexBufferHard(uint size, uint numVertic
IVertexArrayRange *vertexArrayRange= NULL; IVertexArrayRange *vertexArrayRange= NULL;
switch(vbType) switch(vbType)
{ {
case CVertexBuffer::AGPVolatile:
case CVertexBuffer::AGPPreferred: case CVertexBuffer::AGPPreferred:
vertexArrayRange= _AGPVertexArrayRange; vertexArrayRange= _AGPVertexArrayRange;
break; break;

View file

@ -1174,6 +1174,9 @@ bool CVertexArrayRangeARB::allocate(uint32 size, CVertexBuffer::TPreferredMemory
switch(vbType) switch(vbType)
{ {
case CVertexBuffer::AGPVolatile:
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB);
break;
case CVertexBuffer::AGPPreferred: case CVertexBuffer::AGPPreferred:
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
break; break;
@ -1221,13 +1224,14 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff
if (glGetError() != GL_NO_ERROR) return NULL; if (glGetError() != GL_NO_ERROR) return NULL;
_Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID); _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
switch(_VBType) CVertexBuffer::TPreferredMemory preferred = vb->getPreferredMemory();
switch (preferred)
{ {
case CVertexBuffer::AGPPreferred: case CVertexBuffer::AGPVolatile:
#ifdef USE_OPENGLES #ifdef USE_OPENGLES
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STREAM_DRAW);
#else #else
nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB);
#endif #endif
break; break;
case CVertexBuffer::StaticPreferred: case CVertexBuffer::StaticPreferred:
@ -1244,8 +1248,13 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff
nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
#endif #endif
break; break;
// case CVertexBuffer::AGPPreferred:
default: 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; break;
} }
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
@ -1259,7 +1268,7 @@ IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuff
return NULL; return NULL;
} }
CVertexBufferHardARB *newVbHard= new CVertexBufferHardARB(_Driver, vb); CVertexBufferHardARB *newVbHard= new CVertexBufferHardARB(_Driver, vb);
newVbHard->initGL(vertexBufferID, this, _VBType); newVbHard->initGL(vertexBufferID, this, preferred);
_Driver->_DriverGLStates.forceBindARBVertexBuffer(0); _Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
return newVbHard; return newVbHard;
} }
@ -1393,6 +1402,7 @@ void *CVertexBufferHardARB::lock()
H_AUTO_OGL(CVertexBufferHardARB_lock); H_AUTO_OGL(CVertexBufferHardARB_lock);
if (_VertexPtr) return _VertexPtr; // already locked if (_VertexPtr) return _VertexPtr; // already locked
const uint size = VB->getNumVertices() * VB->getVertexSize();
if (_Invalid) if (_Invalid)
{ {
if (VB->getLocation() != CVertexBuffer::NotResident) if (VB->getLocation() != CVertexBuffer::NotResident)
@ -1414,15 +1424,14 @@ void *CVertexBufferHardARB::lock()
_Driver->incrementResetCounter(); _Driver->incrementResetCounter();
return &_DummyVB[0]; return &_DummyVB[0];
} }
const uint size = VB->getNumVertices() * VB->getVertexSize();
_Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID); _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
switch(_MemType) switch(_MemType)
{ {
case CVertexBuffer::AGPPreferred: case CVertexBuffer::AGPVolatile:
#ifdef USE_OPENGLES #ifdef USE_OPENGLES
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STREAM_DRAW);
#else #else
nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB);
#endif #endif
break; break;
case CVertexBuffer::StaticPreferred: case CVertexBuffer::StaticPreferred:
@ -1439,8 +1448,13 @@ void *CVertexBufferHardARB::lock()
nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB); nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
#endif #endif
break; break;
// case CVertexBuffer::AGPPreferred:
default: 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; break;
} }
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
@ -1499,7 +1513,14 @@ void *CVertexBufferHardARB::lock()
_LastBufferSize = size; _LastBufferSize = size;
} }
#else #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) if (!_VertexPtr)
{ {
nglUnmapBufferARB(GL_ARRAY_BUFFER_ARB); nglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);