(view as text)
diff --git a/Source/Core/VideoBackends/OGL/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/StreamBuffer.cpp
index 71bfa40..f21ab60 100644
--- a/Source/Core/VideoBackends/OGL/StreamBuffer.cpp
+++ b/Source/Core/VideoBackends/OGL/StreamBuffer.cpp
@@ -152,7 +152,7 @@ public:
m_iterator = 0;
}
u8* pointer = (u8*)glMapBufferRange(m_buffertype, m_iterator, size,
- GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
return std::make_pair(pointer, m_iterator);
}
@@ -187,7 +187,7 @@ public:
Align(stride);
AllocMemory(size);
u8* pointer = (u8*)glMapBufferRange(m_buffertype, m_iterator, size,
- GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
return std::make_pair(pointer, m_iterator);
}
@@ -346,24 +346,40 @@ public:
// choose best streaming library based on the supported extensions and known issues
StreamBuffer* StreamBuffer::Create(u32 type, size_t size)
{
- bool nvidia = !strcmp(g_ogl_config.gl_vendor, "NVIDIA Corporation");
-
- if (g_ogl_config.bSupportsGLBufferStorage &&
- !(DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTORAGE) && type == GL_ARRAY_BUFFER))
- return new BufferStorage(type, size);
- else if(!g_ogl_config.bSupportsGLBaseVertex && !DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTREAM))
- return new BufferSubData(type, size);
- else if(!g_ogl_config.bSupportsGLBaseVertex)
+ // without basevertex support, only streaming methods whith uploads everything to zero works fine:
+ if(!g_ogl_config.bSupportsGLBaseVertex)
+ {
+ if(!DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTREAM))
+ return new BufferSubData(type, size);
+
+ // BufferData is by far the worst way, only use it if needed
return new BufferData(type, size);
- else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory &&
- !(DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) && type == GL_ELEMENT_ARRAY_BUFFER))
- return new PinnedMemory(type, size);
- else if(nvidia)
- return new BufferSubData(type, size);
- else if(g_ogl_config.bSupportsGLSync)
- return new MapAndSync(type, size);
- else
- return new MapAndOrphan(type, size);
+ }
+
+ // Prefer the syncing buffers over the orphaning one
+ if(g_ogl_config.bSupportsGLSync)
+ {
+ // try to use buffer storage whenever possible
+ if (g_ogl_config.bSupportsGLBufferStorage &&
+ !(DriverDetails::HasBug(DriverDetails::BUG_BROKENBUFFERSTORAGE) && type == GL_ARRAY_BUFFER))
+ return new BufferStorage(type, size);
+
+ // pinned memory is almost as fine
+ if(g_ogl_config.bSupportsGLPinnedMemory &&
+ !(DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) && type == GL_ELEMENT_ARRAY_BUFFER))
+ return new PinnedMemory(type, size);
+
+ // don't fall back to MapAnd* for nvidia drivers
+ if(DriverDetails::HasBug(DriverDetails::BUG_BROKENUNSYNCMAPPING))
+ return new BufferSubData(type, size);
+
+ // mapping fallback
+ if(g_ogl_config.bSupportsGLSync)
+ return new MapAndSync(type, size);
+ }
+
+ // default fallback, should work everywhere, but isn't the best way to do this job
+ return new MapAndOrphan(type, size);
}
}
diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp
index 3f90b2f..37b5c3c 100644
--- a/Source/Core/VideoCommon/DriverDetails.cpp
+++ b/Source/Core/VideoCommon/DriverDetails.cpp
@@ -55,6 +55,8 @@ namespace DriverDetails
{OS_WINDOWS,VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENBUFFERSTORAGE, -1.0, 33220.0, true},
{OS_LINUX, VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENBUFFERSTORAGE, -1.0, 33138.0, true},
{OS_OSX, VENDOR_INTEL, DRIVER_INTEL, 3000, BUG_PRIMITIVERESTART, -1.0, -1.0, true},
+ {OS_WINDOWS,VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENUNSYNCMAPPING, -1.0, -1.0, true},
+ {OS_LINUX, VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENUNSYNCMAPPING, -1.0, -1.0, true},
};
std::map<Bug, BugInfo> m_bugs;
diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h
index 384e372..07c8dc5 100644
--- a/Source/Core/VideoCommon/DriverDetails.h
+++ b/Source/Core/VideoCommon/DriverDetails.h
@@ -154,6 +154,15 @@ namespace DriverDetails
// The drivers on OS X has broken primitive restart.
// Intel HD 4000 series isn't affected by the bug
BUG_PRIMITIVERESTART,
+ // Bug: unsync mapping doesn't work fine
+ // Affected devices: nvidia driver
+ // Started Version: -1
+ // Ended Version: -1
+ // The nvidia driver (both windows + linux) doesn't like unsync mapping performance wise.
+ // Because of their threaded behavoir, they seem not to handle unsync mapping complete unsync,
+ // in fact, they serialize the driver which adds a much bigger overhead.
+ // Workaround: Use BufferSubData
+ BUG_BROKENUNSYNCMAPPING,
};
// Initializes our internal vendor, device family, and driver version