From 7a3bef091e7390fa57bf33f1a704c893768b5625 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 26 Sep 2016 12:53:32 -0700 Subject: [core] Refactor Buffer --- src/mbgl/gl/context.cpp | 20 +++++++---- src/mbgl/gl/context.hpp | 21 ++++++++++-- src/mbgl/gl/element_group.hpp | 25 ++++++++++++++ src/mbgl/gl/index_buffer.hpp | 41 ++++++++++++++++++++++ src/mbgl/gl/vao.cpp | 61 +++++++++++++++++++++++++++++++++ src/mbgl/gl/vao.hpp | 80 +++++++++++++++++++++++++++++++++++++++++++ src/mbgl/gl/vertex_buffer.hpp | 17 +++++++++ 7 files changed, 256 insertions(+), 9 deletions(-) create mode 100644 src/mbgl/gl/element_group.hpp create mode 100644 src/mbgl/gl/index_buffer.hpp create mode 100644 src/mbgl/gl/vao.cpp create mode 100644 src/mbgl/gl/vao.hpp create mode 100644 src/mbgl/gl/vertex_buffer.hpp (limited to 'src/mbgl/gl') diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index ded7936feb..5837aa3399 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -91,10 +91,22 @@ UniqueShader Context::createFragmentShader() { return UniqueShader{ MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER)), { this } }; } -UniqueBuffer Context::createBuffer() { +UniqueBuffer Context::createVertexBuffer(const void* data, std::size_t size) { BufferID id = 0; MBGL_CHECK_ERROR(glGenBuffers(1, &id)); - return UniqueBuffer{ std::move(id), { this } }; + UniqueBuffer result { std::move(id), { this } }; + vertexBuffer = result; + MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); + return result; +} + +UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size) { + BufferID id = 0; + MBGL_CHECK_ERROR(glGenBuffers(1, &id)); + UniqueBuffer result { std::move(id), { this } }; + elementBuffer = result; + MBGL_CHECK_ERROR(glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); + return result; } UniqueTexture Context::createTexture() { @@ -120,10 +132,6 @@ UniqueFramebuffer Context::createFramebuffer() { return UniqueFramebuffer{ std::move(id), { this } }; } -void Context::uploadBuffer(BufferType type, size_t size, void* data) { - MBGL_CHECK_ERROR(glBufferData(static_cast(type), size, data, GL_STATIC_DRAW)); -} - UniqueTexture Context::createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit unit) { auto obj = createTexture(); diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 0ec846033a..e26b35e7c0 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -22,12 +24,24 @@ public: UniqueProgram createProgram(); UniqueShader createVertexShader(); UniqueShader createFragmentShader(); - UniqueBuffer createBuffer(); UniqueTexture createTexture(); UniqueVertexArray createVertexArray(); UniqueFramebuffer createFramebuffer(); - void uploadBuffer(BufferType, size_t, void*); + template + VertexBuffer createVertexBuffer(std::vector&& v) { + return VertexBuffer { + v.size(), + createVertexBuffer(v.data(), v.size() * sizeof(V)) + }; + } + + template + IndexBuffer

createIndexBuffer(std::vector

&& v) { + return IndexBuffer

{ + createIndexBuffer(v.data(), v.size() * sizeof(P)) + }; + } // Create a texture from an image with data. template @@ -98,9 +112,10 @@ public: State vertexArrayObject; private: + UniqueBuffer createVertexBuffer(const void* data, std::size_t size); + UniqueBuffer createIndexBuffer(const void* data, std::size_t size); UniqueTexture createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit); -private: friend detail::ProgramDeleter; friend detail::ShaderDeleter; friend detail::BufferDeleter; diff --git a/src/mbgl/gl/element_group.hpp b/src/mbgl/gl/element_group.hpp new file mode 100644 index 0000000000..f99a03b679 --- /dev/null +++ b/src/mbgl/gl/element_group.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace gl { + +template +struct ElementGroup : public util::noncopyable { + std::array array; + uint32_t vertex_length; + uint32_t elements_length; + + ElementGroup(uint32_t vertex_length_ = 0, uint32_t elements_length_ = 0) + : vertex_length(vertex_length_) + , elements_length(elements_length_) + { + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp new file mode 100644 index 0000000000..f38d7fd4f5 --- /dev/null +++ b/src/mbgl/gl/index_buffer.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace mbgl { +namespace gl { + +class Line { +public: + Line(uint16_t a_, uint16_t b_) + : a(a_), b(b_) {} + + uint16_t a; + uint16_t b; + + static constexpr std::size_t IndexCount = 2; +}; + +class Triangle { +public: + Triangle(uint16_t a_, uint16_t b_, uint16_t c_) + : a(a_), b(b_), c(c_) {} + + uint16_t a; + uint16_t b; + uint16_t c; + + static constexpr std::size_t IndexCount = 3; +}; + +template +class IndexBuffer { +public: + static_assert(std::is_same::value || std::is_same::value, + "primitive must be Line or Triangle"); + static constexpr std::size_t primitiveSize = sizeof(Primitive); + UniqueBuffer buffer; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/vao.cpp b/src/mbgl/gl/vao.cpp new file mode 100644 index 0000000000..527dd214fb --- /dev/null +++ b/src/mbgl/gl/vao.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +namespace mbgl { + +VertexArrayObject::VertexArrayObject() { +} + +VertexArrayObject::~VertexArrayObject() = default; + +void VertexArrayObject::bindVertexArrayObject(gl::Context& context) { + if (!gl::GenVertexArrays || !gl::BindVertexArray) { + static bool reported = false; + if (!reported) { + Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); + reported = true; + } + return; + } + + if (!vertexArray) { + vertexArray = context.createVertexArray(); + context.vertexBuffer.setDirty(); + context.elementBuffer.setDirty(); + } + + context.vertexArrayObject = *vertexArray; +} + +void VertexArrayObject::verifyBinding(Shader& shader, + gl::BufferID vertexBuffer, + gl::BufferID elementsBuffer, + int8_t* offset) { + if (bound_shader != shader.getID()) { + throw std::runtime_error(std::string("trying to rebind VAO to another shader from " + + util::toString(bound_shader) + "(" + bound_shader_name + ") to " + + util::toString(shader.getID()) + "(" + shader.name + ")" )); + } else if (bound_offset != offset) { + throw std::runtime_error("trying to bind VAO to another offset"); + } else if (bound_vertex_buffer != vertexBuffer) { + throw std::runtime_error("trying to bind VAO to another vertex buffer"); + } else if (bound_elements_buffer != elementsBuffer) { + throw std::runtime_error("trying to bind VAO to another elements buffer"); + } +} + +void VertexArrayObject::storeBinding(Shader& shader, + gl::BufferID vertexBuffer, + gl::BufferID elementsBuffer, + int8_t* offset) { + bound_shader = shader.getID(); + bound_shader_name = shader.name; + bound_offset = offset; + bound_vertex_buffer = vertexBuffer; + bound_elements_buffer = elementsBuffer; +} + +} // namespace mbgl diff --git a/src/mbgl/gl/vao.hpp b/src/mbgl/gl/vao.hpp new file mode 100644 index 0000000000..c2e3470367 --- /dev/null +++ b/src/mbgl/gl/vao.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +class VertexArrayObject : public util::noncopyable { +public: + VertexArrayObject(); + ~VertexArrayObject(); + + template + void bind(Shader& shader, + const gl::VertexBuffer& vertexBuffer, + int8_t* offset, + gl::Context& context) { + bindVertexArrayObject(context); + if (bound_shader == 0) { + context.vertexBuffer = vertexBuffer.buffer; + shader.bind(vertexBuffer, offset); + if (vertexArray) { + storeBinding(shader, vertexBuffer.buffer, 0, offset); + } + } else { + verifyBinding(shader, vertexBuffer.buffer, 0, offset); + } + } + + template + void bind(Shader& shader, + const gl::VertexBuffer& vertexBuffer, + const gl::IndexBuffer

& indexBuffer, + int8_t* offset, + gl::Context& context) { + bindVertexArrayObject(context); + if (bound_shader == 0) { + context.vertexBuffer = vertexBuffer.buffer; + context.elementBuffer = indexBuffer.buffer; + shader.bind(vertexBuffer, offset); + if (vertexArray) { + storeBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); + } + } else { + verifyBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); + } + } + + gl::VertexArrayID getID() const { + return *vertexArray; + } + +private: + void bindVertexArrayObject(gl::Context&); + void storeBinding(Shader& shader, + gl::BufferID vertexBuffer, + gl::BufferID elementsBuffer, + int8_t* offset); + void verifyBinding(Shader& shader, + gl::BufferID vertexBuffer, + gl::BufferID elementsBuffer, + int8_t* offset); + + mbgl::optional vertexArray; + + // For debug reasons, we're storing the bind information so that we can + // detect errors and report + gl::ProgramID bound_shader = 0; + const char* bound_shader_name = ""; + gl::BufferID bound_vertex_buffer = 0; + gl::BufferID bound_elements_buffer = 0; + int8_t *bound_offset = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/gl/vertex_buffer.hpp b/src/mbgl/gl/vertex_buffer.hpp new file mode 100644 index 0000000000..c77a9a4213 --- /dev/null +++ b/src/mbgl/gl/vertex_buffer.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace mbgl { +namespace gl { + +template +class VertexBuffer { +public: + static constexpr std::size_t vertexSize = sizeof(Vertex); + std::size_t vertexCount; + UniqueBuffer buffer; +}; + +} // namespace gl +} // namespace mbgl -- cgit v1.2.1