From 56bc8825cc1e7a6b69854297fd0620fe18647cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Oct 2012 18:24:41 +0200 Subject: [PATCH] Mesh rework, part 5: tracking currently bound VAO. If the VAO is already bound, not calling glBindVertexArray() again. --- src/Implementation/MeshState.h | 30 ++++++++++++++++++++++++++++++ src/Implementation/State.cpp | 4 +++- src/Implementation/State.h | 2 ++ src/IndexedMesh.cpp | 3 +-- src/Mesh.cpp | 21 ++++++++++++++++++--- src/Mesh.h | 11 ++++++----- 6 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 src/Implementation/MeshState.h diff --git a/src/Implementation/MeshState.h b/src/Implementation/MeshState.h new file mode 100644 index 000000000..1e0b24328 --- /dev/null +++ b/src/Implementation/MeshState.h @@ -0,0 +1,30 @@ +#ifndef Magnum_Implementation_MeshState_h +#define Magnum_Implementation_MeshState_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Magnum.h" + +namespace Magnum { namespace Implementation { + +struct MeshState { + inline MeshState(): currentVAO(0) {} + + GLuint currentVAO; +}; + +}} + +#endif diff --git a/src/Implementation/State.cpp b/src/Implementation/State.cpp index b1cb03dd8..062a98a8c 100644 --- a/src/Implementation/State.cpp +++ b/src/Implementation/State.cpp @@ -16,16 +16,18 @@ #include "State.h" #include "BufferState.h" +#include "MeshState.h" #include "ShaderProgramState.h" #include "TextureState.h" namespace Magnum { namespace Implementation { -State::State(): buffer(new BufferState), shaderProgram(new ShaderProgramState), texture(new TextureState) {} +State::State(): buffer(new BufferState), mesh(new MeshState), shaderProgram(new ShaderProgramState), texture(new TextureState) {} State::~State() { delete texture; delete shaderProgram; + delete mesh; delete buffer; } diff --git a/src/Implementation/State.h b/src/Implementation/State.h index d655b3172..a264247d7 100644 --- a/src/Implementation/State.h +++ b/src/Implementation/State.h @@ -20,6 +20,7 @@ namespace Magnum { namespace Implementation { struct BufferState; +struct MeshState; struct ShaderProgramState; struct TextureState; @@ -28,6 +29,7 @@ struct State { ~State(); BufferState* const buffer; + MeshState* const mesh; ShaderProgramState* const shaderProgram; TextureState* const texture; }; diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index 5b8b3433d..9a8d0daa0 100644 --- a/src/IndexedMesh.cpp +++ b/src/IndexedMesh.cpp @@ -63,8 +63,7 @@ void IndexedMesh::bindIndexBufferImplementationDefault() {} #ifndef MAGNUM_TARGET_GLES void IndexedMesh::bindIndexBufferImplementationVAO() { - glBindVertexArray(vao); - + bindVAO(vao); _indexBuffer->bind(Buffer::Target::ElementArray); } #endif diff --git a/src/Mesh.cpp b/src/Mesh.cpp index d5931139d..719fc4b79 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -20,6 +20,8 @@ #include "Buffer.h" #include "Context.h" #include "Extensions.h" +#include "Implementation/MeshState.h" +#include "Implementation/State.h" using namespace std; @@ -31,6 +33,14 @@ Mesh::BindAttributeImplementation Mesh::bindAttributeImplementation = &Mesh::bin Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault; Mesh::UnbindImplementation Mesh::unbindImplementation = &Mesh::unbindImplementationDefault; +Mesh::~Mesh() { + /* Remove current vao from the state */ + GLuint& current = Context::current()->state()->mesh->currentVAO; + if(current == vao) current = 0; + + (this->*destroyImplementation)(); +} + Mesh::Mesh(Mesh&& other): vao(other.vao), _primitive(other._primitive), _vertexCount(other._vertexCount), attributes(other.attributes) { other.vao = 0; } @@ -57,6 +67,11 @@ void Mesh::draw() { unbind(); } +void Mesh::bindVAO(GLuint vao) { + GLuint& current = Context::current()->state()->mesh->currentVAO; + if(current != vao) glBindVertexArray(current = vao); +} + void Mesh::bind() { CORRADE_ASSERT((_vertexCount == 0) == attributes.empty(), "Mesh: vertex count is non-zero, but no attributes are bound", ); @@ -125,7 +140,7 @@ void Mesh::bindAttributeImplementationDefault(const Attribute&) {} #ifndef MAGNUM_TARGET_GLES void Mesh::bindAttributeImplementationVAO(const Attribute& attribute) { - glBindVertexArray(vao); + bindVAO(vao); vertexAttribPointer(attribute); } #endif @@ -137,7 +152,7 @@ void Mesh::bindImplementationDefault() { #ifndef MAGNUM_TARGET_GLES void Mesh::bindImplementationVAO() { - glBindVertexArray(vao); + bindVAO(vao); } #endif @@ -148,7 +163,7 @@ void Mesh::unbindImplementationDefault() { #ifndef MAGNUM_TARGET_GLES void Mesh::unbindImplementationVAO() { - glBindVertexArray(0); + bindVAO(0); } #endif diff --git a/src/Mesh.h b/src/Mesh.h index 1c8c0467d..d4f6c32ed 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -81,7 +81,8 @@ Basic workflow is to set up respective shader (see @ref AbstractShaderProgram-re If @extension{APPLE,vertex_array_object} is supported, VAOs are used instead of binding the buffers and specifying vertex attribute pointers in each -draw() call. +draw() call. The engine tracks currently bound VAO to avoid unnecessary calls +to @fn_gl{BindVertexArray}. @requires_gl30 Extension @extension{EXT,gpu_shader4} (for unsigned integer attributes) @@ -354,9 +355,7 @@ class MAGNUM_EXPORT Mesh { * @see @fn_gl{DeleteVertexArrays} (if * @extension{APPLE,vertex_array_object} is available) */ - inline virtual ~Mesh() { - (this->*destroyImplementation)(); - } + virtual ~Mesh(); /** @brief Move assignment */ Mesh& operator=(Mesh&& other); @@ -571,6 +570,8 @@ class MAGNUM_EXPORT Mesh { void MAGNUM_EXPORT addVertexAttribute(Buffer* buffer, GLuint location, GLint count, Type type, GLintptr offset, GLsizei stride); + static void MAGNUM_LOCAL bindVAO(GLuint vao); + void MAGNUM_LOCAL bind(); inline void unbind() { @@ -591,7 +592,7 @@ class MAGNUM_EXPORT Mesh { #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL destroyImplementationVAO(); #endif - static DestroyImplementation destroyImplementation; + static MAGNUM_LOCAL DestroyImplementation destroyImplementation; typedef void(Mesh::*BindAttributeImplementation)(const Attribute&); void MAGNUM_LOCAL bindAttributeImplementationDefault(const Attribute& attribute);