diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-10-10 15:58:04 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-10-28 17:14:07 -0700 |
commit | 39d5cb325012a5675676c81153c5e95d29fbc357 (patch) | |
tree | 214ad773048a0ae1e0492573ba9bb21716c4d881 /src/mbgl | |
parent | 0e57d10d77e555a9229f7d522d83f87df7d5180d (diff) | |
download | qtlocation-mapboxgl-39d5cb325012a5675676c81153c5e95d29fbc357.tar.gz |
[core] Use VAOs internally
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/gl/context.cpp | 82 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 16 |
2 files changed, 79 insertions, 19 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 26a8e299ec..acecf2b698 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -3,6 +3,9 @@ #include <mbgl/gl/gl.hpp> #include <mbgl/gl/vertex_array.hpp> #include <mbgl/util/traits.hpp> +#include <mbgl/util/std.hpp> + +#include <boost/functional/hash.hpp> namespace mbgl { namespace gl { @@ -68,12 +71,6 @@ UniqueTexture Context::createTexture() { return UniqueTexture{ std::move(id), { this } }; } -UniqueVertexArray Context::createVertexArray() { - VertexArrayID id = 0; - MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); - return UniqueVertexArray{ std::move(id), { this } }; -} - UniqueFramebuffer Context::createFramebuffer() { FramebufferID id = 0; MBGL_CHECK_ERROR(glGenFramebuffers(1, &id)); @@ -319,6 +316,15 @@ PrimitiveType Context::operator()(const TriangleStrip&) { return PrimitiveType::TriangleStrip; } +std::size_t Context::VertexArrayObjectHash::operator()(const VertexArrayObjectKey& key) const { + std::size_t seed = 0; + boost::hash_combine(seed, std::get<0>(key)); + boost::hash_combine(seed, std::get<1>(key)); + boost::hash_combine(seed, std::get<2>(key)); + boost::hash_combine(seed, std::get<3>(key)); + return seed; +} + void Context::setDepthMode(const DepthMode& depth) { if (depth.func == DepthMode::Always && !depth.mask) { depthTest = false; @@ -374,18 +380,51 @@ void Context::draw(const Drawable& drawable) { drawable.bindUniforms(); for (const auto& segment : drawable.segments) { - vertexBuffer = drawable.vertexBuffer; - elementBuffer = drawable.indexBuffer; - - for (const auto& binding : drawable.attributeBindings) { - MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); - MBGL_CHECK_ERROR(glVertexAttribPointer( - binding.location, - binding.count, - static_cast<GLenum>(binding.type), - GL_FALSE, - static_cast<GLsizei>(drawable.vertexSize), - reinterpret_cast<GLvoid*>(binding.offset + (drawable.vertexSize * segment.vertexOffset)))); + auto needAttributeBindings = [&] () { + if (!gl::GenVertexArrays || !gl::BindVertexArray) { + return true; + } + + VertexArrayObjectKey vaoKey { + drawable.program, + drawable.vertexBuffer, + drawable.indexBuffer, + segment.vertexOffset + }; + + auto it = vaos.find(vaoKey); + if (it != vaos.end()) { + vertexArrayObject = it->second; + return false; + } + + VertexArrayID id = 0; + MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); + vertexArrayObject = id; + vaos.emplace(vaoKey, UniqueVertexArray(std::move(id), { this })); + + // If we are initializing a new VAO, we need to force the buffers + // to be rebound. VAOs don't inherit the existing buffer bindings. + vertexBuffer.setDirty(); + elementBuffer.setDirty(); + + return true; + }; + + if (needAttributeBindings()) { + vertexBuffer = drawable.vertexBuffer; + elementBuffer = drawable.indexBuffer; + + for (const auto& binding : drawable.attributeBindings) { + MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); + MBGL_CHECK_ERROR(glVertexAttribPointer( + binding.location, + binding.count, + static_cast<GLenum>(binding.type), + GL_FALSE, + static_cast<GLsizei>(drawable.vertexSize), + reinterpret_cast<GLvoid*>(binding.offset + (drawable.vertexSize * segment.vertexOffset)))); + } } if (drawable.indexBuffer) { @@ -408,6 +447,9 @@ void Context::performCleanup() { if (program == id) { program.setDirty(); } + mbgl::util::erase_if(vaos, [&] (const VertexArrayObjectMap::value_type& kv) { + return std::get<0>(kv.first) == id; + }); MBGL_CHECK_ERROR(glDeleteProgram(id)); } abandonedPrograms.clear(); @@ -424,6 +466,10 @@ void Context::performCleanup() { } else if (elementBuffer == id) { elementBuffer.setDirty(); } + mbgl::util::erase_if(vaos, [&] (const VertexArrayObjectMap::value_type& kv) { + return std::get<1>(kv.first) == id + || std::get<2>(kv.first) == id; + }); } MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data())); abandonedBuffers.clear(); diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 74c1bcba56..84c83f8d31 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -14,6 +14,7 @@ #include <memory> #include <vector> #include <array> +#include <unordered_map> namespace mbgl { @@ -31,7 +32,6 @@ public: UniqueShader createVertexShader(); UniqueShader createFragmentShader(); UniqueTexture createTexture(); - UniqueVertexArray createVertexArray(); template <class V> VertexBuffer<V> createVertexBuffer(std::vector<V>&& v) { @@ -174,6 +174,20 @@ private: std::vector<VertexArrayID> abandonedVertexArrays; std::vector<FramebufferID> abandonedFramebuffers; std::vector<RenderbufferID> abandonedRenderbuffers; + + using VertexArrayObjectKey = std::tuple< + ProgramID, // Program + BufferID, // Vertex buffer + BufferID, // Index buffer + std::size_t // Vertex buffer offset + >; + + struct VertexArrayObjectHash { + std::size_t operator()(const VertexArrayObjectKey&) const; + }; + + using VertexArrayObjectMap = std::unordered_map<VertexArrayObjectKey, UniqueVertexArray, VertexArrayObjectHash>; + VertexArrayObjectMap vaos; }; } // namespace gl |