Hideously useless buffer perf optimization.
authorDavid Gow <[email protected]>
Tue, 22 Apr 2014 08:35:52 +0000 (16:35 +0800)
committerDavid Gow <[email protected]>
Tue, 22 Apr 2014 08:35:52 +0000 (16:35 +0800)
bin/ipdf
src/graphicsbuffer.cpp
src/graphicsbuffer.h
src/log.h
src/screen.cpp

index ce60299..bc85e7c 100755 (executable)
Binary files a/bin/ipdf and b/bin/ipdf differ
index 6f9ea9a..fe5ae1c 100644 (file)
@@ -69,7 +69,9 @@ static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type)
 GraphicsBuffer::GraphicsBuffer()
 {
        m_invalidated = true;
+       m_map_pointer = nullptr;
        m_buffer_size = 0;
+       m_buffer_shape_dirty = true;
        SetUsage(BufferUsageStaticDraw);
 }
 
@@ -84,13 +86,41 @@ GraphicsBuffer::~GraphicsBuffer()
 
 void GraphicsBuffer::SetType(GraphicsBuffer::BufferType bufType)
 {
-       glGenBuffers(1, &m_buffer_handle);
        m_buffer_type = bufType;
 }
 
 void GraphicsBuffer::SetUsage(GraphicsBuffer::BufferUsage bufUsage)
 {
-       m_buffer_usage = bufUsage;
+       if (bufUsage != m_buffer_usage)
+       {
+               m_buffer_usage = bufUsage;
+               m_buffer_shape_dirty = true;
+       }
+}
+
+void GraphicsBuffer::Invalidate()
+{
+       m_invalidated = true;
+       // Apparently not supported.
+       //glInvalidateBufferData(m_buffer_handle);
+}
+
+void GraphicsBuffer::RecreateBuffer()
+{
+       // If the buffer is not dirty, don't recreate it.
+       if (!m_buffer_shape_dirty) return;
+       // If the buffer is mapped, don't recreate it.
+       if (m_map_pointer) return;
+       // If the buffer has data in it we need, don't recreate it.
+       if (!m_invalidated) return;
+       if (m_buffer_handle)
+       {
+               glDeleteBuffers(1, &m_buffer_handle);
+       }
+       glGenBuffers(1, &m_buffer_handle);
+       m_buffer_shape_dirty = false;
+       if (m_buffer_size)
+               Upload(m_buffer_size, nullptr);
 }
 
 void* GraphicsBuffer::Map(bool read, bool write, bool invalidate)
@@ -98,12 +128,19 @@ void* GraphicsBuffer::Map(bool read, bool write, bool invalidate)
        GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_BUFFER_BIT:0);
        GLenum target = BufferTypeToGLType(m_buffer_type);
 
+       if (invalidate)
+              m_invalidated = true;
+
+       if (m_map_pointer)
+               Warn("Tried to map already mapped buffer!");    
+
+       RecreateBuffer();
+
        Bind();
        
-       return glMapBufferRange(target, 0, m_buffer_size, access);
+       m_map_pointer = glMapBufferRange(target, 0, m_buffer_size, access);
        
-       //TODO: Emulate DSA
-       //return glMapNamedBufferEXT(m_bufferHandle, access);
+       return m_map_pointer;
 }
 
 void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bool invalidate)
@@ -111,12 +148,15 @@ void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bo
        GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_RANGE_BIT:0);
        GLenum target = BufferTypeToGLType(m_buffer_type);
 
+       if (m_map_pointer)
+               Warn("Tried to map already mapped buffer!");    
+
+       RecreateBuffer();
+
        Bind();
        
-       return glMapBufferRange(target, offset, length, access);
-
-       //TODO: Emulate DSA
-       //return glMapNamedBufferRangeEXT(m_bufferHandle, offset, length, access);
+       m_map_pointer = glMapBufferRange(target, offset, length, access);
+       return m_map_pointer;
 }
 
 void GraphicsBuffer::UnMap()
@@ -125,7 +165,7 @@ void GraphicsBuffer::UnMap()
        
        Bind();
        glUnmapBuffer(target);
-       //glUnmapNamedBufferEXT(m_bufferHandle);
+       m_map_pointer = nullptr;
 }
 
 void GraphicsBuffer::Upload(size_t length, const void* data)
@@ -133,27 +173,31 @@ void GraphicsBuffer::Upload(size_t length, const void* data)
        GLenum target = BufferTypeToGLType(m_buffer_type);
        
        GLenum usage = BufferUsageToGLUsage(m_buffer_usage);
+
+       m_invalidated = true;
+       RecreateBuffer();
        
        Bind();
        glBufferData(target, length, data, usage);
        m_buffer_size = length;
-       //glNamedBufferDataEXT(m_bufferHandle, length, data, usage);
 }
 
 void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data)
 {
        GLenum target = BufferTypeToGLType(m_buffer_type);
+
+       RecreateBuffer();
        
        Bind();
        glBufferSubData(target, offset, length, data);
-       //glNamedBufferSubDataEXT(m_bufferHandle, offset, length, data);
 }
 
 void GraphicsBuffer::Resize(size_t length)
 {
        if (m_invalidated)
        {
-               Upload(length, nullptr);
+               m_buffer_size = length;
+               RecreateBuffer();       
        }
        else
        {
@@ -166,9 +210,8 @@ void GraphicsBuffer::Resize(size_t length)
                glBindBuffer(GL_COPY_WRITE_BUFFER, m_buffer_handle);
                glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, m_buffer_size);
                glDeleteBuffers(1, &old_buffer);
+               m_buffer_size = length;
        }
-       m_buffer_size = length;
-
 }
 
 void GraphicsBuffer::Bind()
index d74d344..47534c9 100644 (file)
@@ -9,7 +9,7 @@
 namespace IPDF
 {
        /*
-        * The "Screen" class handles managing the OS window (using SDL2).
+        * Implementation of an OpenGL buffer, with some extra cleverness.
         */
        class GraphicsBuffer
        {
@@ -53,15 +53,19 @@ namespace IPDF
 
                void Resize(size_t length);
                const size_t GetSize() const { return m_buffer_size; }
+
+               void Invalidate();
                
                void Bind();
        private:
+               void RecreateBuffer();
                GLuint m_buffer_handle;
                BufferType m_buffer_type;
                BufferUsage m_buffer_usage;
                void *m_map_pointer;
                size_t m_buffer_size;
                bool m_invalidated;
+               bool m_buffer_shape_dirty;
        };
 
 }
index 0dfedfd..a98a8cc 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -35,7 +35,7 @@ inline std::string methodName(const std::string& prettyFunction)
 
 #define Debug(...) LogEx(LOG_DEBUG, __func__, __FILE__, __LINE__, __VA_ARGS__)
 #define Error(...) LogEx(LOG_ERR, __func__, __FILE__, __LINE__, __VA_ARGS__)
-#define Warn(...) LogEx(LOG_WARN, __func__, __FILE__, __LINE__, __VA_ARGS__)
+#define Warn(...) LogEx(LOG_WARNING, __func__, __FILE__, __LINE__, __VA_ARGS__)
 
 
 extern void LogEx(int level, const char * funct, const char * file, int line,  ...); // General function for printing log messages to stderr
index 8adb195..ecc8c20 100644 (file)
@@ -255,7 +255,7 @@ void Screen::DebugFontInit(const char *name, float font_size)
 
        m_debug_font_vertices.SetUsage(GraphicsBuffer::BufferUsageStreamDraw);
        m_debug_font_vertices.SetType(GraphicsBuffer::BufferTypeVertex);
-       m_debug_font_vertices.Upload(512, nullptr);
+       m_debug_font_vertices.Upload(8192, nullptr);
        m_debug_font_vertex_head = 0;
 }
 
@@ -290,7 +290,6 @@ void Screen::DebugFontFlush()
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, 4*sizeof(float), (void*)(2*sizeof(float)));
        glTexCoordPointer(2, GL_FLOAT, 4*sizeof(float), 0);
-       Debug("Flushing Debug Font arrays, %d verts (%d floats)", m_debug_font_vertex_head/4, m_debug_font_vertex_head);
        glDrawArrays(GL_QUADS, 0, m_debug_font_vertex_head/4);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

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