From 97cd6e0695f69f3d404e22a6c831aee22d3f0987 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 24 Aug 2012 10:29:08 +0300 Subject: [PATCH] Add the uniform buffer type --- source/buffer.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++-- source/buffer.h | 43 ++++++++++++++++++++++++-- 2 files changed, 118 insertions(+), 4 deletions(-) diff --git a/source/buffer.cpp b/source/buffer.cpp index 1762b204..f0926874 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -1,14 +1,16 @@ #include +#include "arb_uniform_buffer_object.h" #include "arb_vertex_buffer_object.h" -#include "extension.h" #include "buffer.h" +#include "extension.h" +#include "misc.h" using namespace std; namespace Msp { namespace GL { -const Buffer *Buffer::bound[4] = { 0, 0, 0, 0 }; +const Buffer *Buffer::bound[5] = { 0, 0, 0, 0, 0 }; Buffer::Buffer(BufferType t): type(t), @@ -30,6 +32,8 @@ void Buffer::require_buffer_type(BufferType type) static RequireExtension _req_vbo("GL_ARB_vertex_buffer_object"); if(type==PIXEL_PACK_BUFFER || type==PIXEL_UNPACK_BUFFER) static RequireExtension _req_pbo("GL_ARB_pixel_buffer_object"); + else if(type==UNIFORM_BUFFER) + static RequireExtension _req_ubo("GL_ARB_uniform_buffer_object"); } void Buffer::set_usage(BufferUsage u) @@ -54,6 +58,11 @@ void Buffer::sub_data(unsigned off, unsigned sz, const void *d) restore(old, type); } +BufferRange *Buffer::create_range(unsigned s, unsigned o) +{ + return new BufferRange(*this, s, o); +} + void Buffer::bind_to(BufferType t) const { if(t!=type) @@ -76,6 +85,7 @@ const Buffer *&Buffer::binding(BufferType type) case ELEMENT_ARRAY_BUFFER: return bound[1]; case PIXEL_PACK_BUFFER: return bound[2]; case PIXEL_UNPACK_BUFFER: return bound[3]; + case UNIFORM_BUFFER: return bound[4]; default: throw invalid_argument("Buffer::binding"); } } @@ -101,5 +111,70 @@ void Buffer::restore(const Buffer *buf, BufferType type) } } + +vector BufferRange::bound_uniform; + +BufferRange::BufferRange(Buffer &b, unsigned o, unsigned s): + buffer(b), + offset(o), + size(s) +{ + if(o>buffer.get_size() || o+s>buffer.get_size()) + throw out_of_range("BufferRange::BufferRange"); +} + +void BufferRange::data(const void *d) +{ + buffer.sub_data(offset, size, d); +} + +void BufferRange::bind_to(BufferType t, unsigned i) +{ + if(t!=buffer.type) + Buffer::require_buffer_type(t); + // Intentionally using bitwise | to avoid short-circuiting + if(Buffer::set_current(t, &buffer) | set_current(t, i, this)) + glBindBufferRange(t, i, buffer.id, offset, size); +} + +void BufferRange::unbind_from(BufferType t, unsigned i) +{ + if(set_current(t, i, 0)) + { + Buffer::set_current(t, 0); + glBindBufferBase(t, i, 0); + } +} + +const BufferRange *&BufferRange::binding(BufferType type, unsigned index) +{ + if(type==UNIFORM_BUFFER) + { + if(index>=get_n_uniform_buffer_bindings()) + throw out_of_range("Buffer::binding"); + if(bound_uniform.size()<=index) + bound_uniform.resize(index+1); + return bound_uniform[index]; + } + else + throw invalid_argument("Buffer::binding"); +} + +bool BufferRange::set_current(BufferType type, unsigned index, const BufferRange *buf) +{ + const BufferRange *&ptr = binding(type, index); + if(ptr==buf) + return false; + + ptr = buf; + return true; +} + +unsigned BufferRange::get_n_uniform_buffer_bindings() +{ + static unsigned count = get_i(GL_MAX_UNIFORM_BUFFER_BINDINGS); + return count; +} + } // namespace GL } // namespace Msp diff --git a/source/buffer.h b/source/buffer.h index 117f4ea6..bd3a999e 100644 --- a/source/buffer.h +++ b/source/buffer.h @@ -1,6 +1,7 @@ #ifndef MSP_GL_BUFFER_H_ #define MSP_GL_BUFFER_H_ +#include #include "gl.h" namespace Msp { @@ -11,7 +12,8 @@ enum BufferType ARRAY_BUFFER = GL_ARRAY_BUFFER_ARB, ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER_ARB, PIXEL_PACK_BUFFER = GL_PIXEL_PACK_BUFFER_ARB, - PIXEL_UNPACK_BUFFER = GL_PIXEL_UNPACK_BUFFER_ARB + PIXEL_UNPACK_BUFFER = GL_PIXEL_UNPACK_BUFFER_ARB, + UNIFORM_BUFFER = GL_UNIFORM_BUFFER }; enum BufferUsage @@ -27,6 +29,8 @@ enum BufferUsage DYNAMIC_COPY = GL_DYNAMIC_COPY_ARB }; +class BufferRange; + /** A buffer for storing data in GL memory. Putting vertex and index data in buffers can improve rendering performance. The VertexArray and Mesh classes @@ -34,13 +38,15 @@ contain built-in support for buffers. */ class Buffer { + friend class BufferRange; + private: BufferType type; BufferUsage usage; unsigned id; unsigned size; - static const Buffer *bound[4]; + static const Buffer *bound[5]; public: Buffer(BufferType); @@ -64,6 +70,8 @@ public: unsigned get_size() const { return size; } + BufferRange *create_range(unsigned, unsigned); + /** Binds the buffer in its default slot. */ void bind() const { bind_to(type); } @@ -81,6 +89,7 @@ private: static void restore(const Buffer *, BufferType); }; + /** An adaptor for Buffer to make it compatible with Bind. */ @@ -98,6 +107,36 @@ public: static void unbind() { Buffer::unbind_from(T); } }; + +/** +A proxy for a subset of a buffer. Can be bound for use with uniform blocks. +*/ +class BufferRange +{ +private: + Buffer &buffer; + unsigned offset; + unsigned size; + + static std::vector bound_uniform; + +public: + BufferRange(Buffer &, unsigned, unsigned); + + void data(const void *); + + void bind_to(BufferType, unsigned); + + static const BufferRange *current(BufferType t, unsigned i) { return binding(t, i); } + static void unbind_from(BufferType, unsigned); +private: + static const BufferRange *&binding(BufferType, unsigned); + static bool set_current(BufferType, unsigned, const BufferRange *); + +public: + static unsigned get_n_uniform_buffer_bindings(); +}; + } // namespace GL } // namespace Msp -- 2.45.2