diff --git a/CMakeLists.txt b/CMakeLists.txt index 8600e85c..798a6646 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,7 @@ set(SOURCES "gl/postfx.cpp" "gl/cubemap.cpp" "gl/glsl_common.cpp" +"gl/buffer.cpp" "imgui/imgui.cpp" "imgui/imgui_demo.cpp" diff --git a/gl/buffer.cpp b/gl/buffer.cpp new file mode 100644 index 00000000..31fa9579 --- /dev/null +++ b/gl/buffer.cpp @@ -0,0 +1,67 @@ +#include "buffer.h" + +GLenum gl::buffer::glenum_target(gl::buffer::targets target) +{ + GLenum mapping[13] = + { + GL_ARRAY_BUFFER, + GL_ATOMIC_COUNTER_BUFFER, + GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, + GL_DISPATCH_INDIRECT_BUFFER, + GL_DRAW_INDIRECT_BUFFER, + GL_ELEMENT_ARRAY_BUFFER, + GL_PIXEL_PACK_BUFFER, + GL_PIXEL_UNPACK_BUFFER, + GL_SHADER_STORAGE_BUFFER, + GL_TEXTURE_BUFFER, + GL_TRANSFORM_FEEDBACK_BUFFER, + GL_UNIFORM_BUFFER + }; + return mapping[target]; +} + +void gl::buffer::bind(targets target) +{ + if (binding_points[target] == *this) + return; + + glBindBuffer(glenum_target(target), *this); + binding_points[target] = *this; +} + +void gl::buffer::bind_base(targets target, GLuint index) +{ + glBindBufferBase(glenum_target(target), index, *this); + binding_points[target] = *this; +} + +void gl::buffer::unbind(targets target) +{ + glBindBuffer(glenum_target(target), 0); + binding_points[target] = 0; +} + +gl::buffer::buffer() +{ + glGenBuffers(1, *this); +} + +gl::buffer::~buffer() +{ + glDeleteBuffers(1, *this); +} + +void gl::buffer::allocate(targets target, int size, GLenum hint) +{ + bind(target); + glBufferData(glenum_target(target), size, nullptr, hint); +} + +void gl::buffer::upload(targets target, const void *data, int offset, int size) +{ + bind(target); + glBufferSubData(glenum_target(target), offset, size, data); +} + +GLuint gl::buffer::binding_points[13]; diff --git a/gl/buffer.h b/gl/buffer.h new file mode 100644 index 00000000..0c82e255 --- /dev/null +++ b/gl/buffer.h @@ -0,0 +1,44 @@ +#pragma once + +#include "object.h" +#include "bindable.h" + +namespace gl +{ + class buffer : public object + { + static GLuint binding_points[13]; + + public: + enum targets + { + ARRAY_BUFFER = 0, + ATOMIC_COUNTER_BUFFER, + COPY_READ_BUFFER, + COPY_WRITE_BUFFER, + DISPATCH_INDIRECT_BUFFER, + DRAW_INDIRECT_BUFFER, + ELEMENT_ARRAY_BUFFER, + PIXEL_PACK_BUFFER, + PIXEL_UNPACK_BUFFER, + SHADER_STORAGE_BUFFER, + TEXTURE_BUFFER, + TRANSFORM_FEEDBACK_BUFFER, + UNIFORM_BUFFER + }; + + private: + static GLenum glenum_target(targets target); + + public: + buffer(); + ~buffer(); + + void bind(targets target); + void bind_base(targets target, GLuint index); + static void unbind(targets target); + + void allocate(targets target, int size, GLenum hint); + void upload(targets target, const void *data, int offset, int size); + }; +} diff --git a/gl/ubo.cpp b/gl/ubo.cpp index b221596f..1ef45198 100644 --- a/gl/ubo.cpp +++ b/gl/ubo.cpp @@ -3,31 +3,17 @@ gl::ubo::ubo(int size, int idx, GLenum hint) { - glGenBuffers(1, *this); - bind(); - glBufferData(GL_UNIFORM_BUFFER, size, nullptr, hint); + allocate(buffer::UNIFORM_BUFFER, size, hint); index = idx; bind_uniform(); } void gl::ubo::bind_uniform() { - glBindBufferBase(GL_UNIFORM_BUFFER, index, *this); - active = this; -} - -gl::ubo::~ubo() -{ - glDeleteBuffers(1, *this); -} - -void gl::ubo::bind(GLuint i) -{ - glBindBuffer(GL_UNIFORM_BUFFER, i); + bind_base(buffer::UNIFORM_BUFFER, index); } void gl::ubo::update(const uint8_t *data, int offset, int size) { - bind(); - glBufferSubData(GL_UNIFORM_BUFFER, offset, size, data); + upload(buffer::UNIFORM_BUFFER, data, offset, size); } diff --git a/gl/ubo.h b/gl/ubo.h index bee247f4..690f7c3e 100644 --- a/gl/ubo.h +++ b/gl/ubo.h @@ -2,24 +2,20 @@ #include "object.h" #include "bindable.h" +#include "buffer.h" #define UBS_PAD(x) uint8_t PAD[x] namespace gl { - static GLuint next_binding_point; - - class ubo : public object, public bindable + class ubo : public buffer { int index; public: ubo(int size, int index, GLenum hint = GL_DYNAMIC_DRAW); - ~ubo(); void bind_uniform(); - using bindable::bind; - static void bind(GLuint i); void update(const uint8_t *data, int offset, int size); template void update(const T &data, size_t offset = 0)