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 0d67c420cd
commit 766cace955
4 changed files with 70 additions and 17 deletions

View file

@ -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

View file

@ -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
//==================================

View file

@ -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;

View file

@ -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);