Minor perf improvement on nVidia
authorDavid Gow <david@ingeniumdigital.com>
Wed, 4 Jun 2014 14:34:02 +0000 (22:34 +0800)
committerDavid Gow <david@ingeniumdigital.com>
Wed, 4 Jun 2014 14:34:02 +0000 (22:34 +0800)
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.

bin/ipdf
src/graphicsbuffer.cpp
src/graphicsbuffer.h

index e0fb8e8..46b624c 100755 (executable)
Binary files a/bin/ipdf and b/bin/ipdf differ
index 37d9b12..82c6a30 100644 (file)
@@ -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
        {
index 7cec235..dd25617 100644 (file)
@@ -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;
        };
 
 }

UCC git Repository :: git.ucc.asn.au