X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Fgraphicsbuffer.cpp;h=576c2d68668a1a7e1d81c129044452f448bd4e39;hp=fe5ae1c4600d339e5858defaaf2a38c09583328c;hb=c64ec8fda6d6ad1bb5bdc5f2edd7d1d47c2d2680;hpb=eff96d65bd1101083e04cb3ff2468b3feea3ff9e diff --git a/src/graphicsbuffer.cpp b/src/graphicsbuffer.cpp index fe5ae1c..576c2d6 100644 --- a/src/graphicsbuffer.cpp +++ b/src/graphicsbuffer.cpp @@ -1,8 +1,5 @@ #include "graphicsbuffer.h" #include "log.h" -#define GL_GLEXT_PROTOTYPES -#include -#include using namespace IPDF; @@ -39,7 +36,7 @@ static GLenum BufferUsageToGLUsage(GraphicsBuffer::BufferUsage buffer_usage) usage = GL_STREAM_COPY; break; default: - SDL_assert(false && "Unknown buffer usage type."); + SDL_assert(false && "Unknown buffer usage type."); //WTF? usage = GL_DYNAMIC_DRAW; } return usage; @@ -59,6 +56,8 @@ static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type) return GL_PIXEL_UNPACK_BUFFER; case GraphicsBuffer::BufferTypeUniform: return GL_UNIFORM_BUFFER; + case GraphicsBuffer::BufferTypeTexture: + return GL_TEXTURE_BUFFER; case GraphicsBuffer::BufferTypeDrawIndirect: return GL_DRAW_INDIRECT_BUFFER; default: @@ -69,9 +68,12 @@ static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type) GraphicsBuffer::GraphicsBuffer() { m_invalidated = true; - m_map_pointer = nullptr; + m_map_pointer = NULL; m_buffer_size = 0; m_buffer_shape_dirty = true; + m_buffer_handle = 0; + m_buffer_usage = BufferUsageDynamicDraw; + m_faking_map = false; SetUsage(BufferUsageStaticDraw); } @@ -101,18 +103,23 @@ void GraphicsBuffer::SetUsage(GraphicsBuffer::BufferUsage bufUsage) void GraphicsBuffer::Invalidate() { m_invalidated = true; + if (!m_buffer_shape_dirty) + { + // Orphan the block of memory we're pointing to. + Upload(m_buffer_size, NULL); + } // Apparently not supported. //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); @@ -120,7 +127,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) @@ -129,11 +137,26 @@ void* GraphicsBuffer::Map(bool read, bool write, bool invalidate) GLenum target = BufferTypeToGLType(m_buffer_type); if (invalidate) - m_invalidated = true; + { + m_invalidated = true; + + // Intel's Mesa driver does not rename the buffer when we map with GL_MAP_INVALIDATE_BUFFER_BIT, + // resulting in the CPU stalling waiting for rendering from the buffer to complete on the GPU. + // We manually force the buffer to be renamed here to avoid this. + m_buffer_shape_dirty = true; + } 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(); @@ -162,10 +185,21 @@ 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); m_map_pointer = nullptr; + m_invalidated = false; } void GraphicsBuffer::Upload(size_t length, const void* data) @@ -175,11 +209,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; } void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data) @@ -190,6 +227,7 @@ void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* dat Bind(); glBufferSubData(target, offset, length, data); + m_invalidated = false; } void GraphicsBuffer::Resize(size_t length) @@ -197,7 +235,6 @@ void GraphicsBuffer::Resize(size_t length) if (m_invalidated) { m_buffer_size = length; - RecreateBuffer(); } else { @@ -214,7 +251,7 @@ void GraphicsBuffer::Resize(size_t length) } } -void GraphicsBuffer::Bind() +void GraphicsBuffer::Bind() const { if (m_buffer_type == BufferTypeUniform) glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer_handle);