summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2013-12-27 10:56:03 -0600
committerRyan Houdek <Sonicadvance1@gmail.com>2013-12-27 10:56:03 -0600
commitce99921c20ef63ea7ed1361a6453bc6384ab0748 (patch)
tree8ae82bdbc4b58171ec33563ff0dc784d471755dc /Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp
parent4d1f113ab15c051368d4de9c50c0f4e8188f25f1 (diff)
[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.
Diffstat (limited to 'Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp52
1 files changed, 41 insertions, 11 deletions
diff --git a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp
index 8ec9c3c1cb..5e3d4dfd38 100644
--- a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp
+++ b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp
@@ -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;
}
}