From ba67fcd830d41399ec8d225fd9536a4f780056ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 15 Aug 2014 13:37:19 +0200 Subject: [PATCH] refactor vao object to use acutal OpenGL IDs rather than object pointers --- include/mbgl/geometry/buffer.hpp | 8 +- include/mbgl/geometry/vao.hpp | 114 +++++++++--------------- include/mbgl/geometry/vertex_buffer.hpp | 5 ++ include/mbgl/shader/shader.hpp | 7 +- src/geometry/vao.cpp | 46 ++++++++++ src/geometry/vertex_buffer.cpp | 4 + src/shader/composite_shader.cpp | 1 + src/shader/dot_shader.cpp | 1 + src/shader/gaussian_shader.cpp | 1 + src/shader/icon_shader.cpp | 1 + src/shader/line_shader.cpp | 1 + src/shader/linejoin_shader.cpp | 1 + src/shader/outline_shader.cpp | 1 + src/shader/pattern_shader.cpp | 1 + src/shader/plain_shader.cpp | 1 + src/shader/raster_shader.cpp | 1 + src/shader/shader.cpp | 5 +- src/shader/text_shader.cpp | 1 + 18 files changed, 123 insertions(+), 77 deletions(-) create mode 100644 src/geometry/vao.cpp diff --git a/include/mbgl/geometry/buffer.hpp b/include/mbgl/geometry/buffer.hpp index 20489cb33..446177d44 100644 --- a/include/mbgl/geometry/buffer.hpp +++ b/include/mbgl/geometry/buffer.hpp @@ -62,6 +62,10 @@ public: } } + inline GLuint getID() const { + return buffer; + } + protected: // increase the buffer size by at least /required/ bytes. inline void *addElement() { @@ -72,7 +76,7 @@ protected: while (length < pos + itemSize) length += defaultLength; array = realloc(array, length); if (array == nullptr) { - throw std::runtime_error("Buffer reallocation failed¯"); + throw std::runtime_error("Buffer reallocation failed"); } } pos += itemSize; @@ -106,7 +110,7 @@ private: size_t length = 0; // GL buffer ID - uint32_t buffer = 0; + GLuint buffer = 0; }; } diff --git a/include/mbgl/geometry/vao.hpp b/include/mbgl/geometry/vao.hpp index 1023fc118..87408ddba 100644 --- a/include/mbgl/geometry/vao.hpp +++ b/include/mbgl/geometry/vao.hpp @@ -1,104 +1,74 @@ #ifndef MBGL_GEOMETRY_VAO #define MBGL_GEOMETRY_VAO +#include #include #include namespace mbgl { +#if GL_ARB_vertex_array_object class VertexArrayObject { public: template - void bind(Shader& shader, VertexBuffer& vertex_buffer, char *offset) { -#if GL_ARB_vertex_array_object - if (!vao) { - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - } else { - // We have been given the correct information. - glBindVertexArray(vao); - } - - if (shader_ptr != &shader) { - if (shader_ptr != nullptr) { - throw std::runtime_error("shader rebind!"); - } -#endif - vertex_buffer.bind(); + inline void bind(Shader& shader, VertexBuffer &vertexBuffer, char *offset) { + bindVertexArrayObject(); + if (bound_shader == 0) { + vertexBuffer.bind(); shader.bind(offset); - -#if GL_ARB_vertex_array_object - shader_ptr = &shader; - vertex_buffer_ptr = &vertex_buffer; - elements_buffer_ptr = nullptr; - offset_ptr = offset; - } else if (vertex_buffer_ptr != &vertex_buffer) { - throw std::runtime_error("trying to bind VAO to another vertex buffer"); - } else if (elements_buffer_ptr != nullptr) { - throw std::runtime_error("trying to bind VAO to another elements buffer"); - } else if (offset_ptr != offset) { - throw std::runtime_error("trying to bind VAO to another offset"); + storeBinding(shader, vertexBuffer.getID(), 0, offset); + } else { + verifyBinding(shader, vertexBuffer.getID(), 0, offset); } -#endif } template - void bind(Shader& shader, VertexBuffer& vertex_buffer, ElementsBuffer& elements_buffer, char *offset) { -#if GL_ARB_vertex_array_object - if (!vao) { - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - } else { - // We have been given the correct information. - glBindVertexArray(vao); - } - - if (shader_ptr != &shader) { - if (shader_ptr != nullptr) { - throw std::runtime_error("shader rebind!"); - } -#endif - vertex_buffer.bind(); - elements_buffer.bind(); + inline void bind(Shader& shader, VertexBuffer &vertexBuffer, ElementsBuffer &elementsBuffer, char *offset) { + bindVertexArrayObject(); + if (bound_shader == 0) { + vertexBuffer.bind(); + elementsBuffer.bind(); shader.bind(offset); - -#if GL_ARB_vertex_array_object - shader_ptr = &shader; - vertex_buffer_ptr = &vertex_buffer; - elements_buffer_ptr = &elements_buffer; - offset_ptr = offset; - } else if (vertex_buffer_ptr != &vertex_buffer) { - throw std::runtime_error("trying to bind VAO to another vertex buffer"); - } else if (elements_buffer_ptr != &elements_buffer) { - throw std::runtime_error("trying to bind VAO to another elements buffer"); - } else if (offset_ptr != offset) { - throw std::runtime_error("trying to bind VAO to another offset"); + storeBinding(shader, vertexBuffer.getID(), elementsBuffer.getID(), offset); + } else { + verifyBinding(shader, vertexBuffer.getID(), elementsBuffer.getID(), offset); } -#endif } - ~VertexArrayObject() { -#if GL_ARB_vertex_array_object - if (vao) { - glDeleteVertexArrays(1, &vao); - } -#endif - } + ~VertexArrayObject(); private: -#if GL_ARB_vertex_array_object + void bindVertexArrayObject(); + void storeBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, char *offset); + void verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, char *offset); + GLuint vao = 0; // For debug reasons, we're storing the bind information so that we can // detect errors and report - void *shader_ptr = nullptr; - void *vertex_buffer_ptr = nullptr; - void *elements_buffer_ptr = nullptr; - char *offset_ptr = 0; -#endif + GLuint bound_shader = 0; + const char *bound_shader_name = ""; + GLuint bound_vertex_buffer = 0; + GLuint bound_elements_buffer = 0; + char *bound_offset = 0; }; +#else + +class VertexArrayObject { +public: + template + void bind(Shader& shader, Buffers& buffers, char *offset) { + for (auto &buffer : buffers) { + buffer.bind(); + } + shader.bind(offset); + } +}; + +#endif + } #endif diff --git a/include/mbgl/geometry/vertex_buffer.hpp b/include/mbgl/geometry/vertex_buffer.hpp index 58fd4a9d0..05cda9424 100644 --- a/include/mbgl/geometry/vertex_buffer.hpp +++ b/include/mbgl/geometry/vertex_buffer.hpp @@ -25,6 +25,11 @@ public: */ void bind(); + /* + * Returns the OpenGL ID of the buffer object. + */ + uint32_t getID() const; + private: const std::vector array; uint32_t buffer = 0; diff --git a/include/mbgl/shader/shader.hpp b/include/mbgl/shader/shader.hpp index 2398cb12e..fa2d5a0a8 100644 --- a/include/mbgl/shader/shader.hpp +++ b/include/mbgl/shader/shader.hpp @@ -9,13 +9,18 @@ namespace mbgl { class Shader : private util::noncopyable { public: - Shader(const char *vertex, const char *fragment); + Shader(const char *name, const char *vertex, const char *fragment); ~Shader(); + const char *name; bool valid; uint32_t program; void setMatrix(const std::array& matrix); + inline uint32_t getID() const { + return program; + } + private: bool compileShader(uint32_t *shader, uint32_t type, const char *source); diff --git a/src/geometry/vao.cpp b/src/geometry/vao.cpp new file mode 100644 index 000000000..4c459c436 --- /dev/null +++ b/src/geometry/vao.cpp @@ -0,0 +1,46 @@ +#include + +namespace mbgl { + +#if GL_ARB_vertex_array_object + +VertexArrayObject::~VertexArrayObject() { + if (vao) { + glDeleteVertexArrays(1, &vao); + } +} + +void VertexArrayObject::bindVertexArrayObject() { + if (!vao) { + glGenVertexArrays(1, &vao); + } + glBindVertexArray(vao); +} + +void VertexArrayObject::verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, + char *offset) { + if (bound_shader != shader.getID()) { + throw std::runtime_error(std::string("trying to rebind VAO to another shader from " + + std::to_string(bound_shader) + "(" + bound_shader_name + ") to " + + std::to_string(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, GLuint vertexBuffer, GLuint elementsBuffer, + char *offset) { + bound_shader = shader.getID(); + bound_shader_name = shader.name; + bound_offset = offset; + bound_vertex_buffer = vertexBuffer; + bound_elements_buffer = elementsBuffer; +} + +#endif + +} diff --git a/src/geometry/vertex_buffer.cpp b/src/geometry/vertex_buffer.cpp index 56072e161..888cc57a9 100644 --- a/src/geometry/vertex_buffer.cpp +++ b/src/geometry/vertex_buffer.cpp @@ -26,3 +26,7 @@ void VertexBuffer::bind() { glBindBuffer(GL_ARRAY_BUFFER, buffer); } } + +uint32_t VertexBuffer::getID() const { + return buffer; +} \ No newline at end of file diff --git a/src/shader/composite_shader.cpp b/src/shader/composite_shader.cpp index 07fe0c074..9ed0a1b83 100644 --- a/src/shader/composite_shader.cpp +++ b/src/shader/composite_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; CompositeShader::CompositeShader() : Shader( + "composite", shaders[COMPOSITE_SHADER].vertex, shaders[COMPOSITE_SHADER].fragment ) { diff --git a/src/shader/dot_shader.cpp b/src/shader/dot_shader.cpp index 8e2837f2c..54163d698 100644 --- a/src/shader/dot_shader.cpp +++ b/src/shader/dot_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; DotShader::DotShader() : Shader( + "dot", shaders[DOT_SHADER].vertex, shaders[DOT_SHADER].fragment ) { diff --git a/src/shader/gaussian_shader.cpp b/src/shader/gaussian_shader.cpp index eb8867756..d22006020 100644 --- a/src/shader/gaussian_shader.cpp +++ b/src/shader/gaussian_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; GaussianShader::GaussianShader() : Shader( + "gaussian", shaders[GAUSSIAN_SHADER].vertex, shaders[GAUSSIAN_SHADER].fragment ) { diff --git a/src/shader/icon_shader.cpp b/src/shader/icon_shader.cpp index 6455d870a..4973dc411 100644 --- a/src/shader/icon_shader.cpp +++ b/src/shader/icon_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; IconShader::IconShader() : Shader( + "icon", shaders[ICON_SHADER].vertex, shaders[ICON_SHADER].fragment ) { diff --git a/src/shader/line_shader.cpp b/src/shader/line_shader.cpp index 529ab0d31..1b0527366 100644 --- a/src/shader/line_shader.cpp +++ b/src/shader/line_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; LineShader::LineShader() : Shader( + "line", shaders[LINE_SHADER].vertex, shaders[LINE_SHADER].fragment ) { diff --git a/src/shader/linejoin_shader.cpp b/src/shader/linejoin_shader.cpp index 73b7a1e74..e8ec306ed 100644 --- a/src/shader/linejoin_shader.cpp +++ b/src/shader/linejoin_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; LinejoinShader::LinejoinShader() : Shader( + "linejoin", shaders[LINEJOIN_SHADER].vertex, shaders[LINEJOIN_SHADER].fragment ) { diff --git a/src/shader/outline_shader.cpp b/src/shader/outline_shader.cpp index b1e57bf0f..d9c19fa80 100644 --- a/src/shader/outline_shader.cpp +++ b/src/shader/outline_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; OutlineShader::OutlineShader() : Shader( + "outline", shaders[OUTLINE_SHADER].vertex, shaders[OUTLINE_SHADER].fragment ) { diff --git a/src/shader/pattern_shader.cpp b/src/shader/pattern_shader.cpp index ec604290a..8fe6a34e9 100644 --- a/src/shader/pattern_shader.cpp +++ b/src/shader/pattern_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; PatternShader::PatternShader() : Shader( + "pattern", shaders[PATTERN_SHADER].vertex, shaders[PATTERN_SHADER].fragment ) { diff --git a/src/shader/plain_shader.cpp b/src/shader/plain_shader.cpp index 3abc57eaa..bb0c22899 100644 --- a/src/shader/plain_shader.cpp +++ b/src/shader/plain_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; PlainShader::PlainShader() : Shader( + "plain", shaders[PLAIN_SHADER].vertex, shaders[PLAIN_SHADER].fragment ) { diff --git a/src/shader/raster_shader.cpp b/src/shader/raster_shader.cpp index 51b328fa8..60d81c61b 100644 --- a/src/shader/raster_shader.cpp +++ b/src/shader/raster_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; RasterShader::RasterShader() : Shader( + "raster", shaders[RASTER_SHADER].vertex, shaders[RASTER_SHADER].fragment ) { diff --git a/src/shader/shader.cpp b/src/shader/shader.cpp index fa073c42d..171ce9b7c 100644 --- a/src/shader/shader.cpp +++ b/src/shader/shader.cpp @@ -8,8 +8,9 @@ using namespace mbgl; -Shader::Shader(const GLchar *vertSource, const GLchar *fragSource) - : valid(false), +Shader::Shader(const char *name, const GLchar *vertSource, const GLchar *fragSource) + : name(name), + valid(false), program(0) { util::timer timer("shader compilation", Event::Shader); diff --git a/src/shader/text_shader.cpp b/src/shader/text_shader.cpp index c9e70825c..f6de934e2 100644 --- a/src/shader/text_shader.cpp +++ b/src/shader/text_shader.cpp @@ -8,6 +8,7 @@ using namespace mbgl; TextShader::TextShader() : Shader( + "text", shaders[TEXT_SHADER].vertex, shaders[TEXT_SHADER].fragment ) {