From: David Gow Date: Wed, 4 Jun 2014 14:34:02 +0000 (+0800) Subject: Minor perf improvement on nVidia X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=ddf7783ce69eb619f5a6b12e779c134279aa2ac6;p=ipdf%2Fcode.git Minor perf improvement on nVidia nVidia's driver does not like you mapping a STATIC buffer, as they're usually in parts of VRAM not directly accessible by the CPU. The driver therefore has to migrate the buffer somewhere slower. We initialize the object bounds buffer by mapping it and writing directly into it. This is good where we're doing coordinate transform on the CPU: we're changing it every frame and it can be a dynamic buffer, but we only need to do it once if the GPU is doing coordinate transforms so we make it a static buffer. This change "fakes" mapping a STATIC buffer for the first time by allocating some CPU-side memory, having the application write into that, and then initializing the buffer with that. This removes a performance warning on nVidia when switching to GPU-side coordinate transforms. --- diff --git a/bin/ipdf b/bin/ipdf index e0fb8e8..46b624c 100755 Binary files a/bin/ipdf and b/bin/ipdf differ diff --git a/src/graphicsbuffer.cpp b/src/graphicsbuffer.cpp index 37d9b12..82c6a30 100644 --- a/src/graphicsbuffer.cpp +++ b/src/graphicsbuffer.cpp @@ -71,6 +71,7 @@ GraphicsBuffer::GraphicsBuffer() m_buffer_shape_dirty = true; m_buffer_handle = 0; m_buffer_usage = BufferUsageDynamicDraw; + m_faking_map = false; SetUsage(BufferUsageStaticDraw); } @@ -109,14 +110,14 @@ void GraphicsBuffer::Invalidate() //glInvalidateBufferData(m_buffer_handle); } -void GraphicsBuffer::RecreateBuffer() +bool GraphicsBuffer::RecreateBuffer(const void *data) { // If the buffer is not dirty, don't recreate it. - if (!m_buffer_shape_dirty) return; + if (!m_buffer_shape_dirty) return false; // If the buffer is mapped, don't recreate it. - if (m_map_pointer) return; + if (!m_faking_map && m_map_pointer) return false; // If the buffer has data in it we need, don't recreate it. - if (!m_invalidated) return; + if (!m_invalidated) return false; if (m_buffer_handle) { glDeleteBuffers(1, &m_buffer_handle); @@ -124,7 +125,8 @@ void GraphicsBuffer::RecreateBuffer() glGenBuffers(1, &m_buffer_handle); m_buffer_shape_dirty = false; if (m_buffer_size) - Upload(m_buffer_size, nullptr); + Upload(m_buffer_size, data); + return true; } void* GraphicsBuffer::Map(bool read, bool write, bool invalidate) @@ -145,6 +147,14 @@ void* GraphicsBuffer::Map(bool read, bool write, bool invalidate) if (m_map_pointer) Warn("Tried to map already mapped buffer!"); + + if (!read && m_buffer_usage == BufferUsage::BufferUsageStaticDraw) + { + m_map_pointer = malloc(m_buffer_size); + m_faking_map = true; + return m_map_pointer; + } + RecreateBuffer(); Bind(); @@ -173,6 +183,16 @@ void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bo void GraphicsBuffer::UnMap() { GLenum target = BufferTypeToGLType(m_buffer_type); + + if (m_faking_map) + { + Upload(m_buffer_size, m_map_pointer); + free(m_map_pointer); + m_map_pointer = nullptr; + m_invalidated = false; + m_faking_map = false; + return; + } Bind(); glUnmapBuffer(target); @@ -187,13 +207,14 @@ void GraphicsBuffer::Upload(size_t length, const void* data) GLenum usage = BufferUsageToGLUsage(m_buffer_usage); m_invalidated = true; - RecreateBuffer(); - - Bind(); - glBufferData(target, length, data, usage); + m_buffer_size = length; + if (!RecreateBuffer(data)) + { + Bind(); + glBufferData(target, length, data, usage); + } if (data != nullptr) m_invalidated = false; - m_buffer_size = length; } void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data) @@ -212,7 +233,6 @@ void GraphicsBuffer::Resize(size_t length) if (m_invalidated) { m_buffer_size = length; - RecreateBuffer(); } else { diff --git a/src/graphicsbuffer.h b/src/graphicsbuffer.h index 7cec235..dd25617 100644 --- a/src/graphicsbuffer.h +++ b/src/graphicsbuffer.h @@ -57,7 +57,7 @@ namespace IPDF void Bind() const; private: - void RecreateBuffer(); + bool RecreateBuffer(const void *data = nullptr); GLuint m_buffer_handle; BufferType m_buffer_type; BufferUsage m_buffer_usage; @@ -65,6 +65,7 @@ namespace IPDF size_t m_buffer_size; bool m_invalidated; bool m_buffer_shape_dirty; + bool m_faking_map; }; }