From 2dde4b9bf8bd7f479e60fbd4a6251c4e5997575c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 8 Oct 2012 00:17:27 +0200 Subject: [PATCH] Tracking AbstractShaderProgram state. Reduces OpenGL call count when subsequently using the same shader for rendering. --- src/AbstractShaderProgram.cpp | 18 +++++++++++++- src/AbstractShaderProgram.h | 2 -- src/Implementation/ShaderProgramState.h | 31 +++++++++++++++++++++++++ src/Implementation/State.cpp | 4 +++- src/Implementation/State.h | 2 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/Implementation/ShaderProgramState.h diff --git a/src/AbstractShaderProgram.cpp b/src/AbstractShaderProgram.cpp index 0dccdc4a3..feddb2c8a 100644 --- a/src/AbstractShaderProgram.cpp +++ b/src/AbstractShaderProgram.cpp @@ -18,6 +18,8 @@ #include #include "Shader.h" +#include "Implementation/State.h" +#include "Implementation/ShaderProgramState.h" #define LINKER_MESSAGE_MAX_LENGTH 1024 @@ -25,10 +27,24 @@ using namespace std; namespace Magnum { +AbstractShaderProgram::~AbstractShaderProgram() { + /* Remove current usage from the state */ + GLuint& current = Context::current()->state()->shaderProgram->current; + if(current == _id) + current = 0; + + glDeleteProgram(_id); +} + bool AbstractShaderProgram::use() { if(state != Linked) return false; - glUseProgram(_id); + /* Use only if the program isn't already in use */ + GLuint& current = Context::current()->state()->shaderProgram->current; + if(current != _id) { + current = _id; + glUseProgram(_id); + } return true; } diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index d9140fdf9..fbe4dcb9b 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -642,8 +642,6 @@ class MAGNUM_EXPORT AbstractShaderProgram { State state; }; -inline AbstractShaderProgram::~AbstractShaderProgram() { glDeleteProgram(_id); } - } #endif diff --git a/src/Implementation/ShaderProgramState.h b/src/Implementation/ShaderProgramState.h new file mode 100644 index 000000000..d81af0aca --- /dev/null +++ b/src/Implementation/ShaderProgramState.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Implementation_ShaderProgramState_h +#define Magnum_Implementation_ShaderProgramState_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 ShaderProgramState { + inline constexpr ShaderProgramState(): current(0) {} + + /* Currently used program */ + GLuint current; +}; + +}} + +#endif diff --git a/src/Implementation/State.cpp b/src/Implementation/State.cpp index daf8b4cab..5c3ead774 100644 --- a/src/Implementation/State.cpp +++ b/src/Implementation/State.cpp @@ -16,12 +16,14 @@ #include "State.h" #include "BufferState.h" +#include "ShaderProgramState.h" namespace Magnum { namespace Implementation { -State::State(): buffer(new BufferState) {} +State::State(): buffer(new BufferState), shaderProgram(new ShaderProgramState) {} State::~State() { + delete shaderProgram; delete buffer; } diff --git a/src/Implementation/State.h b/src/Implementation/State.h index a3438b028..8330fb7bd 100644 --- a/src/Implementation/State.h +++ b/src/Implementation/State.h @@ -20,12 +20,14 @@ namespace Magnum { namespace Implementation { struct BufferState; +struct ShaderProgramState; struct State { State(); ~State(); BufferState* const buffer; + ShaderProgramState* const shaderProgram; }; }}