aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/gl/GrGLConfig.h4
-rw-r--r--src/gpu/gl/GrGLBufferImpl.cpp4
-rw-r--r--src/gpu/gl/GrGLGpu.cpp18
3 files changed, 25 insertions, 1 deletions
diff --git a/include/gpu/gl/GrGLConfig.h b/include/gpu/gl/GrGLConfig.h
index b9769ea7e7..c91537cc38 100644
--- a/include/gpu/gl/GrGLConfig.h
+++ b/include/gpu/gl/GrGLConfig.h
@@ -111,6 +111,10 @@
#define GR_GL_CHECK_ERROR_START 1
#endif
+#if !defined(GR_GL_USE_BUFFER_DATA_NULL_HINT)
+ #define GR_GL_USE_BUFFER_DATA_NULL_HINT 1
+#endif
+
#if !defined(GR_GL_PER_GL_FUNC_CALLBACK)
#define GR_GL_PER_GL_FUNC_CALLBACK 0
#endif
diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp
index becc55ae69..6cbf4e0d0e 100644
--- a/src/gpu/gl/GrGLBufferImpl.cpp
+++ b/src/gpu/gl/GrGLBufferImpl.cpp
@@ -99,7 +99,11 @@ bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInB
}
gpu->bufferData(fDesc.fID, fBufferType, fDesc.fDynamic, fDesc.fSizeInBytes, src,
srcSizeInBytes);
+#if GR_GL_USE_BUFFER_DATA_NULL_HINT
+ fGLSizeInBytes = fDesc.fSizeInBytes;
+#else
fGLSizeInBytes = srcSizeInBytes;
+#endif
VALIDATE();
return true;
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 645a508e6c..ce02fe8ea9 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1596,7 +1596,7 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, bool dynamic, size_t curren
case GrGLCaps::kMapBuffer_MapBufferType:
this->bindBuffer(id, type);
// Let driver know it can discard the old data
- if (currentSize != requestedSize) {
+ if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize) {
GL_CALL(BufferData(type, requestedSize, nullptr,
dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
}
@@ -1634,10 +1634,26 @@ void GrGLGpu::bufferData(GrGLuint id, GrGLenum type, bool dynamic, size_t curren
this->bindBuffer(id, type);
GrGLenum usage = dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW;
+#if GR_GL_USE_BUFFER_DATA_NULL_HINT
+ if (currentSize == srcSizeInBytes) {
+ GL_CALL(BufferData(type, (GrGLsizeiptr) srcSizeInBytes, src, usage));
+ } else {
+ // Before we call glBufferSubData we give the driver a hint using
+ // glBufferData with nullptr. This makes the old buffer contents
+ // inaccessible to future draws. The GPU may still be processing
+ // draws that reference the old contents. With this hint it can
+ // assign a different allocation for the new contents to avoid
+ // flushing the gpu past draws consuming the old contents.
+ // TODO I think we actually want to try calling bufferData here
+ GL_CALL(BufferData(type, currentSize, nullptr, usage));
+ GL_CALL(BufferSubData(type, 0, (GrGLsizeiptr) srcSizeInBytes, src));
+ }
+#else
// Note that we're cheating on the size here. Currently no methods
// allow a partial update that preserves contents of non-updated
// portions of the buffer (map() does a glBufferData(..size, nullptr..))
GL_CALL(BufferData(type, srcSizeInBytes, src, usage));
+#endif
}
void GrGLGpu::unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr) {