From: David Gow Date: Mon, 21 Apr 2014 05:46:46 +0000 (+0800) Subject: Store everything in a VBO, making things faster. X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=81786f2f649a1d73ef8d4e40dc03beec4fd53698 Store everything in a VBO, making things faster. Also 1024*1024 grid of boxes, for extreme slowness. Yay! --- diff --git a/bin/ipdf b/bin/ipdf index 10e25fe..7e9fdb3 100755 Binary files a/bin/ipdf and b/bin/ipdf differ diff --git a/src/Makefile b/src/Makefile index 90adae9..0b3be85 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ ARCH := $(shell uname -m) CXX = g++ -std=gnu++0x -g # -Wall -Werror -Wshadow -pedantic MAIN = main.o -OBJ = log.o real.o document.o view.o screen.o vfpu.o stb_truetype.o +OBJ = log.o real.o document.o view.o screen.o vfpu.o graphicsbuffer.o stb_truetype.o LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL diff --git a/src/graphicsbuffer.cpp b/src/graphicsbuffer.cpp new file mode 100644 index 0000000..906226e --- /dev/null +++ b/src/graphicsbuffer.cpp @@ -0,0 +1,137 @@ +#include "graphicsbuffer.h" +#define GL_GLEXT_PROTOTYPES +#include +#include + +using namespace IPDF; + +GraphicsBuffer::GraphicsBuffer() +{ + SetUsage(BufferUsageStaticDraw); +} + +GraphicsBuffer::~GraphicsBuffer() +{ + if (m_map_pointer) + { + UnMap(); + } + glDeleteBuffers(1, &m_buffer_handle); +} + +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; +} + +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 = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER; + + Bind(); + + return glMapBufferRange(target, 0, m_buffer_size, access); + + //TODO: Emulate DSA + //return glMapNamedBufferEXT(m_bufferHandle, access); +} + +void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bool invalidate) +{ + GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_RANGE_BIT:0); + GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER; + + Bind(); + + return glMapBufferRange(target, offset, length, access); + + //TODO: Emulate DSA + //return glMapNamedBufferRangeEXT(m_bufferHandle, offset, length, access); +} + +void GraphicsBuffer::UnMap() +{ + GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER; + + Bind(); + glUnmapBuffer(target); + //glUnmapNamedBufferEXT(m_bufferHandle); +} + +void GraphicsBuffer::Upload(size_t length, const void* data) +{ + GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER; + + GLenum usage; + switch (m_buffer_usage) + { + case BufferUsageStaticDraw: + usage = GL_STATIC_DRAW; + break; + case BufferUsageStaticRead: + usage = GL_STATIC_READ; + break; + case BufferUsageStaticCopy: + usage = GL_STATIC_COPY; + break; + case BufferUsageDynamicDraw: + usage = GL_DYNAMIC_DRAW; + break; + case BufferUsageDynamicRead: + usage = GL_DYNAMIC_READ; + break; + case BufferUsageDynamicCopy: + usage = GL_DYNAMIC_COPY; + break; + case BufferUsageStreamDraw: + usage = GL_STREAM_DRAW; + break; + case BufferUsageStreamRead: + usage = GL_STREAM_READ; + break; + case BufferUsageStreamCopy: + usage = GL_STREAM_COPY; + break; + default: + SDL_assert(false && "Unknown buffer usage type."); + usage = GL_DYNAMIC_DRAW; + } + + 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 = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER; + + Bind(); + glBufferSubData(target, offset, length, data); + //glNamedBufferSubDataEXT(m_bufferHandle, offset, length, data); +} + +void GraphicsBuffer::Bind() +{ + if (m_buffer_type == BufferTypeVertex) + glBindBuffer(GL_ARRAY_BUFFER, m_buffer_handle); + else if (m_buffer_type == BufferTypeIndex) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer_handle); + else if (m_buffer_type == BufferTypePixelPack) + glBindBuffer(GL_PIXEL_PACK_BUFFER, m_buffer_handle); + else if (m_buffer_type == BufferTypePixelUnpack) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_buffer_handle); + else if (m_buffer_type == BufferTypeUniform) + glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer_handle); + else if (m_buffer_type == BufferTypeDrawIndirect) + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_buffer_handle); +} + diff --git a/src/graphicsbuffer.h b/src/graphicsbuffer.h new file mode 100644 index 0000000..15e5b42 --- /dev/null +++ b/src/graphicsbuffer.h @@ -0,0 +1,68 @@ +#ifndef _GRAPHICSBUFFER_H +#define _GRAPHICSBUFFER_H + +#include +#define GL_GLEXT_PROTOTYPES +#include + + +namespace IPDF +{ + /* + * The "Screen" class handles managing the OS window (using SDL2). + */ + class GraphicsBuffer + { + public: + enum BufferType + { + BufferTypeVertex, // A Vertex Buffer + BufferTypeIndex, // An Index Buffer + BufferTypePixelPack, // Pixel Pack buffer + BufferTypePixelUnpack, + BufferTypeUniform, // Uniform/Constant buffer + BufferTypeDrawIndirect, + }; + + enum BufferUsage + { + BufferUsageStaticDraw, + BufferUsageStaticRead, + BufferUsageStaticCopy, + BufferUsageDynamicDraw, + BufferUsageDynamicRead, + BufferUsageDynamicCopy, + BufferUsageStreamDraw, + BufferUsageStreamRead, + BufferUsageStreamCopy + }; + + GraphicsBuffer(); + ~GraphicsBuffer(); + + void SetType(BufferType bufType); + void SetUsage(BufferUsage bufUsage); + + void *Map(bool read, bool write, bool invalidate); + void *MapRange(int offset, int length, bool read, bool write, bool invalidate); + + void UnMap(); + + void Upload(size_t length, const void *data); + void UploadRange(size_t length, intptr_t offset, const void *data); + + void Resize(size_t length); + + void Bind(); + private: + GLuint m_buffer_handle; + BufferType m_buffer_type; + BufferUsage m_buffer_usage; + void *m_map_pointer; + size_t m_buffer_size; + bool m_invalidated; + }; + +} + +#endif // _SCREEN_H diff --git a/src/main.cpp b/src/main.cpp index 9cf0c68..d9f2a7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,7 +76,14 @@ int main(int argc, char ** argv) } else { - doc.Add(RECT_OUTLINE, Rect(0.5,0.5,1,1)); + for(int i = 0; i < 1024; ++i) + { + for (int j = 0; j < 1024; ++j) + { + doc.Add(((i^j)&1)?RECT_OUTLINE:RECT_FILLED, Rect(0.2+i-512.0,0.2+j-512.0,0.6,0.6)); + } + } + } Rect bounds(b[0],b[1],b[2],b[3]); diff --git a/src/screen.cpp b/src/screen.cpp index 07d3f94..5c3957c 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -293,7 +293,7 @@ void Screen::DebugFontPrint(const char* str) glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + glMatrixMode(GL_PROJECTION); glPopMatrix(); } diff --git a/src/view.cpp b/src/view.cpp index 26e9507..bda0faa 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -12,6 +12,8 @@ void View::Translate(Real x, Real y) m_bounds.x += x; m_bounds.y += y; Debug("View Bounds => %s", m_bounds.Str().c_str()); + if (!m_use_gpu_transform) + m_bounds_dirty = true; } void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt) @@ -36,6 +38,8 @@ void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt) m_bounds.w *= scaleAmt; m_bounds.h *= scaleAmt; Debug("View Bounds => %s", m_bounds.Str().c_str()); + if (!m_use_gpu_transform) + m_bounds_dirty = true; } Rect View::TransformToViewCoords(const Rect& inp) const @@ -74,18 +78,11 @@ void View::DrawGrid() } } +void glPrimitiveRestartIndex(GLuint index); + void View::Render() { - static bool debug_output_done = false; - if (!debug_output_done) - { - m_document.DebugDumpObjects(); - debug_output_done = true; - } - - - //DrawGrid(); // Draw the gridlines - + glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (m_use_gpu_transform) @@ -96,16 +93,70 @@ void View::Render() { glOrtho(0,1,1,0,-1,1); } + + if (m_bounds_dirty) + ReRender(); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - if (m_colour.a < 1.0f) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glColor4f(m_colour.r, m_colour.g, m_colour.b, m_colour.a); - glBegin(GL_QUADS); + m_vertex_buffer.Bind(); + m_index_buffer.Bind(); + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(0xFFFFFFFF); + glVertexPointer(2, GL_FLOAT, 0, 0); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawElements(GL_TRIANGLE_STRIP, m_rendered_filled * 5, GL_UNSIGNED_INT, 0); + glDrawElements(GL_LINE_LOOP, m_rendered_outline*5, GL_UNSIGNED_INT,(void*)(sizeof(uint32_t)*m_rendered_filled*5)); + glDisable(GL_PRIMITIVE_RESTART); + if (m_colour.a < 1.0f) + { + glDisable(GL_BLEND); + } + + +} + +void View::ReRender() +{ + static bool debug_output_done = false; + if (!debug_output_done) + { + m_document.DebugDumpObjects(); + debug_output_done = true; + + m_vertex_buffer.SetType(GraphicsBuffer::BufferTypeVertex); + m_index_buffer.SetUsage(GraphicsBuffer::BufferUsageStaticDraw); + m_index_buffer.SetType(GraphicsBuffer::BufferTypeIndex); + + m_vertex_buffer.Upload(m_document.ObjectCount() * 8 * sizeof(float), NULL); + m_index_buffer.Upload(m_document.ObjectCount() * 5 * sizeof(uint32_t), NULL); + } + m_rendered_filled = m_rendered_outline = 0; + + if (m_use_gpu_transform) + { + m_vertex_buffer.SetUsage(GraphicsBuffer::BufferUsageStaticDraw); + } + else + { + m_vertex_buffer.SetUsage(GraphicsBuffer::BufferUsageDynamicDraw); + } + + + //DrawGrid(); // Draw the gridlines + + + + float *vertexData = (float*)m_vertex_buffer.Map(false, true, true); + uint32_t *indexData = (uint32_t*)m_index_buffer.Map(false, true, true); + + uint32_t currentIndex = 0; for (unsigned id = 0; id < m_document.ObjectCount(); ++id) { if (m_document.m_objects.types[id] != RECT_FILLED) @@ -119,13 +170,25 @@ void View::Render() { obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]); } - glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y)); - glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y)); - glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y) + Float(obj_bounds.h)); - glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y) + Float(obj_bounds.h)); - } - glEnd(); + *vertexData = Float(obj_bounds.x); vertexData++; + *vertexData = Float(obj_bounds.y); vertexData++; + *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++; + *vertexData = Float(obj_bounds.y); vertexData++; + *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++; + *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++; + *vertexData = Float(obj_bounds.x); vertexData++; + *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++; + + *indexData = currentIndex; indexData++; + *indexData = currentIndex+1; indexData++; + *indexData = currentIndex+3; indexData++; + *indexData = currentIndex+2; indexData++; + *indexData = 0xFFFFFFFF; // Primitive restart. + indexData++; + currentIndex += 4; + m_rendered_filled++; + } for (unsigned id = 0; id < m_document.ObjectCount(); ++id) { @@ -140,17 +203,27 @@ void View::Render() { obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]); } - glBegin(GL_LINE_LOOP); - glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y)); - glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y)); - glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y) + Float(obj_bounds.h)); - glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y) + Float(obj_bounds.h)); - glEnd(); + *vertexData = Float(obj_bounds.x); vertexData++; + *vertexData = Float(obj_bounds.y); vertexData++; + *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++; + *vertexData = Float(obj_bounds.y); vertexData++; + *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++; + *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++; + *vertexData = Float(obj_bounds.x); vertexData++; + *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++; + + *indexData = currentIndex; indexData++; + *indexData = currentIndex+1; indexData++; + *indexData = currentIndex+2; indexData++; + *indexData = currentIndex+3; indexData++; + *indexData = 0xFFFFFFFF; // Primitive restart. + indexData++; + currentIndex += 4; + m_rendered_outline++; } + m_vertex_buffer.UnMap(); + m_index_buffer.UnMap(); - if (m_colour.a < 1.0f) - { - glDisable(GL_BLEND); - } + m_bounds_dirty = false; } diff --git a/src/view.h b/src/view.h index c6c230d..172b5e7 100644 --- a/src/view.h +++ b/src/view.h @@ -3,6 +3,7 @@ #include "ipdf.h" #include "document.h" +#include "graphicsbuffer.h" namespace IPDF { @@ -10,7 +11,7 @@ namespace IPDF { public: View(Document & document, const Rect & bounds = Rect(0,0,1,1), const Colour & colour = Colour(0.f,0.f,0.f,1.f)) - : m_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false) + : m_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false), m_bounds_dirty(true) { Debug("View Created - Bounds => {%s}", m_bounds.Str().c_str()); } @@ -26,14 +27,20 @@ namespace IPDF const Rect& GetBounds() const { return m_bounds; } const bool UsingGPUTransform() const { return m_use_gpu_transform; } - void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); } + void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); m_bounds_dirty = true; } private: + void ReRender(); void DrawGrid(); bool m_use_gpu_transform; + bool m_bounds_dirty; + GraphicsBuffer m_vertex_buffer; + GraphicsBuffer m_index_buffer; Document & m_document; Rect m_bounds; Colour m_colour; + uint32_t m_rendered_filled; + uint32_t m_rendered_outline; }; }