Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Use VAOs internally
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh committed Oct 29, 2016
1 parent 0e57d10 commit 39d5cb3
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 26 deletions.
82 changes: 64 additions & 18 deletions src/mbgl/gl/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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();
Expand All @@ -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();
Expand Down
16 changes: 15 additions & 1 deletion src/mbgl/gl/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#include <array>
#include <unordered_map>

namespace mbgl {

Expand All @@ -31,7 +32,6 @@ class Context : private util::noncopyable {
UniqueShader createVertexShader();
UniqueShader createFragmentShader();
UniqueTexture createTexture();
UniqueVertexArray createVertexArray();

template <class V>
VertexBuffer<V> createVertexBuffer(std::vector<V>&& v) {
Expand Down Expand Up @@ -174,6 +174,20 @@ class Context : private util::noncopyable {
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
Expand Down
7 changes: 0 additions & 7 deletions test/gl/object.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,6 @@ TEST(GLObject, Store) {
context.reset();
EXPECT_TRUE(context.empty());

mbgl::gl::UniqueVertexArray vao = context.createVertexArray();
EXPECT_NE(vao.get(), 0u);
vao.reset();
EXPECT_FALSE(context.empty());
context.performCleanup();
EXPECT_TRUE(context.empty());

context.reset();
EXPECT_TRUE(context.empty());

Expand Down

0 comments on commit 39d5cb3

Please sign in to comment.