[core] Use VAOs internally
This commit is contained in:
@@ -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;
|
||||
auto needAttributeBindings = [&] () {
|
||||
if (!gl::GenVertexArrays || !gl::BindVertexArray) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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))));
|
||||
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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user