[buffer_storage] Implement ARB_buffer_storage. Disable it for GL_ARRAY_BUFFER due to a bug in Nvidia's drivers that causes black screen with it.

This commit is contained in:
Ryan Houdek 2013-12-27 10:56:03 -06:00
parent 4d1f113ab1
commit ce99921c20
6 changed files with 56 additions and 13 deletions

View File

@ -478,6 +478,7 @@ Renderer::Renderer()
g_ogl_config.bSupportsGLSync = TO_BOOL(GLEW_ARB_sync);
g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex) &&
!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY);
g_ogl_config.bSupportsGLBufferStorage = TO_BOOL(GLEW_ARB_buffer_storage);
g_ogl_config.bSupportCoverageMSAA = TO_BOOL(GLEW_NV_framebuffer_multisample_coverage);
g_ogl_config.bSupportSampleShading = TO_BOOL(GLEW_ARB_sample_shading);
g_ogl_config.bSupportOGL31 = TO_BOOL(GLEW_VERSION_3_1);
@ -554,6 +555,7 @@ Renderer::Renderer()
g_ogl_config.bSupportsGLPinnedMemory ? "" : "PinnedMemory ",
g_ogl_config.bSupportsGLSLCache ? "" : "ShaderCache ",
g_ogl_config.bSupportsGLBaseVertex ? "" : "BaseVertex ",
g_ogl_config.bSupportsGLBufferStorage ? "" : "BufferStorage ",
g_ogl_config.bSupportsGLSync ? "" : "Sync ",
g_ogl_config.bSupportCoverageMSAA ? "" : "CSAA ",
g_ogl_config.bSupportSampleShading ? "" : "SSAA "

View File

@ -22,6 +22,7 @@ extern struct VideoConfig {
bool bSupportsGLPinnedMemory;
bool bSupportsGLSync;
bool bSupportsGLBaseVertex;
bool bSupportsGLBufferStorage;
bool bSupportCoverageMSAA;
bool bSupportSampleShading;
GLSL_VERSION eSupportedGLSLVersion;

View File

@ -33,7 +33,11 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType)
g_Config.bHackedBufferUpload = false;
}
if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA)
if (g_ogl_config.bSupportsGLBufferStorage &&
!(DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTORAGE) && type == GL_ARRAY_BUFFER) &&
(m_uploadtype & BUFFERSTORAGE))
m_uploadtype = BUFFERSTORAGE;
else if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA)
&& !DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTREAM))
m_uploadtype = BUFFERSUBDATA;
else if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERDATA))
@ -79,9 +83,9 @@ void StreamBuffer::Alloc ( size_t size, u32 stride )
break;
case MAP_AND_SYNC:
case PINNED_MEMORY:
case BUFFERSTORAGE:
// insert waiting slots for used memory
for(size_t i=SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
for (size_t i = SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
{
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
@ -96,7 +100,7 @@ void StreamBuffer::Alloc ( size_t size, u32 stride )
m_free_iterator = iter_end;
// if buffer is full
if(iter_end >= m_size) {
if (iter_end >= m_size) {
// insert waiting slots in unused space at the end of the buffer
for (size_t i = SLOT(m_used_iterator); i < SYNC_POINTS; i++)
@ -109,7 +113,7 @@ void StreamBuffer::Alloc ( size_t size, u32 stride )
iter_end = size;
// wait for space at the start
for(u32 i=0; i<=SLOT(iter_end); i++)
for (u32 i = 0; i <= SLOT(iter_end); i++)
{
glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
glDeleteSync(fences[i]);
@ -128,7 +132,7 @@ void StreamBuffer::Alloc ( size_t size, u32 stride )
m_iterator_aligned = 0;
break;
case STREAM_DETECT:
case DETECT_MASK: // Just to shutup warnings
case DETECT_MASK: // To shutup compiler warnings
break;
}
m_iterator = m_iterator_aligned;
@ -149,8 +153,9 @@ size_t StreamBuffer::Upload ( u8* data, size_t size )
break;
case PINNED_MEMORY:
case MAP_AND_RISK:
if(pointer)
memcpy(pointer+m_iterator, data, size);
case BUFFERSTORAGE:
if (pointer)
memcpy(pointer + m_iterator, data, size);
break;
case BUFFERSUBDATA:
glBufferSubData(m_buffertype, m_iterator, size, data);
@ -159,7 +164,7 @@ size_t StreamBuffer::Upload ( u8* data, size_t size )
glBufferData(m_buffertype, size, data, GL_STREAM_DRAW);
break;
case STREAM_DETECT:
case DETECT_MASK: // Just to shutup warnings
case DETECT_MASK: // To shutup compiler warnings
break;
}
size_t ret = m_iterator;
@ -204,6 +209,25 @@ void StreamBuffer::Init()
Init();
}
break;
case BUFFERSTORAGE:
glGetError(); // errors before this allocation should be ignored
fences = new GLsync[SYNC_POINTS];
for (u32 i = 0; i<SYNC_POINTS; i++)
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glBindBuffer(m_buffertype, m_buffer);
// PERSISTANT_BIT to make sure that the buffer can be used while mapped
// COHERENT_BIT is set so we don't have to use a MemoryBarrier on write
glBufferStorage(m_buffertype, m_size, NULL,
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
pointer = (u8*)glMapBufferRange(m_buffertype, 0, m_size,
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
if(!pointer)
ERROR_LOG(VIDEO, "Buffer allocation failed");
break;
case MAP_AND_RISK:
glBindBuffer(m_buffertype, m_buffer);
glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
@ -216,7 +240,7 @@ void StreamBuffer::Init()
glBindBuffer(m_buffertype, m_buffer);
break;
case STREAM_DETECT:
case DETECT_MASK: // Just to shutup warnings
case DETECT_MASK: // To shutup compiler warnings
break;
}
}
@ -238,8 +262,14 @@ void StreamBuffer::Shutdown()
glFinish(); // ogl pipeline must be flushed, else this buffer can be in use
FreeAlignedMemory(pointer);
break;
case BUFFERSTORAGE:
DeleteFences();
glUnmapBuffer(m_buffertype);
glBindBuffer(m_buffertype, 0);
glFinish(); // ogl pipeline must be flushed, else this buffer can be in use
break;
case STREAM_DETECT:
case DETECT_MASK: // Just to shutup warnings
case DETECT_MASK: // To shutup compiler warnings
break;
}
}

View File

@ -18,14 +18,15 @@
namespace OGL
{
enum StreamType {
DETECT_MASK = 0x7F,
DETECT_MASK = 0xFF,
STREAM_DETECT = (1 << 0),
MAP_AND_ORPHAN = (1 << 1),
MAP_AND_SYNC = (1 << 2),
MAP_AND_RISK = (1 << 3),
PINNED_MEMORY = (1 << 4),
BUFFERSUBDATA = (1 << 5),
BUFFERDATA = (1 << 6)
BUFFERDATA = (1 << 6),
BUFFERSTORAGE = (1 << 7),
};
class StreamBuffer {

View File

@ -52,6 +52,7 @@ namespace DriverDetails
{OS_ALL, VENDOR_ATI, DRIVER_ATI, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true},
{OS_LINUX, VENDOR_ATI, DRIVER_ATI, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true},
{OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true},
{OS_ALL, VENDOR_NVIDIA, DRIVER_NVIDIA, BUG_BROKENBUFFERSTORAGE, -1.0, -1.0, true},
};
std::map<Bug, BugInfo> m_bugs;

View File

@ -141,6 +141,14 @@ namespace DriverDetails
// Ended Version: -1
// If a shader includes a textureSize function call then the shader compiler will call abort()
BUG_BROKENTEXTURESIZE,
// Bug: ARB_buffer_storage doesn't work with ARRAY_BUFFER type streams
// Affected devices: Geforce 4xx+
// Started Version: -1
// Ended Version: -1
// The buffer_storage streaming method is required for greater speed gains in our buffer streaming
// It reduces what is needed for streaming to basically a memcpy call
// It seems to work for all buffer types except GL_ARRAY_BUFFER
BUG_BROKENBUFFERSTORAGE,
};
// Initializes our internal vendor, device family, and driver version