From 4e50aeee31f8251cccd73ab47f31eadfd258c987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 10 May 2014 20:04:09 +0200 Subject: [PATCH] Ability to reset internal state tracker. --- src/Magnum/AbstractFramebuffer.cpp | 2 + src/Magnum/AbstractShaderProgram.cpp | 4 +- src/Magnum/AbstractTexture.cpp | 1 + src/Magnum/Buffer.cpp | 1 + src/Magnum/Context.cpp | 24 +++++++++++ src/Magnum/Context.h | 43 +++++++++++++++++++ src/Magnum/Framebuffer.cpp | 1 + src/Magnum/Implementation/BufferState.cpp | 6 +++ src/Magnum/Implementation/BufferState.h | 2 + .../Implementation/FramebufferState.cpp | 7 +++ src/Magnum/Implementation/FramebufferState.h | 2 + src/Magnum/Implementation/MeshState.cpp | 6 +++ src/Magnum/Implementation/MeshState.h | 2 + .../Implementation/ShaderProgramState.cpp | 6 +++ .../Implementation/ShaderProgramState.h | 2 + src/Magnum/Implementation/State.h | 3 ++ src/Magnum/Implementation/TextureState.cpp | 6 +++ src/Magnum/Implementation/TextureState.h | 2 + src/Magnum/Mesh.cpp | 1 + 19 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index 9500c4b7f..c0c5f2f7e 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -158,6 +158,8 @@ AbstractFramebuffer& AbstractFramebuffer::setViewport(const Range2Di& rectangle) void AbstractFramebuffer::setViewportInternal() { Implementation::FramebufferState* state = Context::current()->state().framebuffer; + /* We are using empty viewport to indicate disengaged state */ + CORRADE_INTERNAL_ASSERT(_viewport != Range2Di{}); CORRADE_INTERNAL_ASSERT(state->drawBinding == _id); /* Already up-to-date, nothing to do */ diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index b72dcf562..572fc72ba 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -196,7 +196,9 @@ Int AbstractShaderProgram::maxTexelOffset() { } #endif -AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {} +AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) { + CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); +} AbstractShaderProgram::AbstractShaderProgram(AbstractShaderProgram&& other) noexcept: _id(other._id) { other._id = 0; diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 6e9049a4f..56b005e64 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -171,6 +171,7 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, std: AbstractTexture::AbstractTexture(GLenum target): _target(target) { glGenTextures(1, &_id); + CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } AbstractTexture::~AbstractTexture() { diff --git a/src/Magnum/Buffer.cpp b/src/Magnum/Buffer.cpp index d37f253ae..37d96f8fc 100644 --- a/src/Magnum/Buffer.cpp +++ b/src/Magnum/Buffer.cpp @@ -114,6 +114,7 @@ Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) #endif { glGenBuffers(1, &_id); + CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } Buffer::~Buffer() { diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index e835284ae..ad57fa6be 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -45,6 +45,11 @@ #include "Magnum/Renderer.h" #include "Implementation/State.h" +#include "Implementation/BufferState.h" +#include "Implementation/FramebufferState.h" +#include "Implementation/MeshState.h" +#include "Implementation/ShaderProgramState.h" +#include "Implementation/TextureState.h" namespace Magnum { @@ -526,6 +531,25 @@ Version Context::supportedVersion(std::initializer_list versions) const #endif } +void Context::resetState(const States states) { + if(states & State::Buffers) + _state->buffer->reset(); + if(states & State::Framebuffers) + _state->framebuffer->reset(); + if(states & State::Meshes) + _state->mesh->reset(); + + /* Nothing to reset for renderer yet */ + + if(states & State::Shaders) { + /* Nothing to reset for shaders */ + _state->shaderProgram->reset(); + } + + if(states & State::Textures) + _state->texture->reset(); +} + #ifndef DOXYGEN_GENERATING_OUTPUT Debug operator<<(Debug debug, const Context::Flag value) { switch(value) { diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index f74fd887e..df00aa1dc 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -137,6 +137,38 @@ class MAGNUM_EXPORT Context { #endif }; + /** + * @brief State to reset + * + * @see @ref States, @ref resetState() + */ + enum class State: UnsignedInt { + /** Reset tracked buffer-related bindings and state */ + Buffers = 1 << 0, + + /** Reset tracked framebuffer-related bindings and state */ + Framebuffers = 1 << 1, + + /** Reset tracked mesh-related bindings */ + Meshes = 1 << 2, + + /** Reset tracked renderer-related state */ + Renderer = 1 << 3, + + /** Reset tracked shader-related bindings */ + Shaders = 1 << 4, + + /** Reset tracked texture-related bindings and state */ + Textures = 1 << 5 + }; + + /** + * @brief States to reset + * + * @see @ref resetState() + */ + typedef Containers::EnumSet States; + /** * @brief Context flags * @@ -382,6 +414,17 @@ class MAGNUM_EXPORT Context { return isVersionSupported(extension._requiredVersion) && extensionStatus[extension._index] && !isVersionSupported(_extensionRequiredVersion[extension._index]); } + /** + * @brief Reset internal state tracker + * @param states Tracked states to reset. Default is all state. + * + * The engine internally tracks object bindings and other state to + * avoid redundant OpenGL calls. In some cases (e.g. when non-Magnum + * code makes GL calls) the internal tracker no longer reflects actual + * state and needs to be reset to avoid strange issues. + */ + void resetState(States states = ~States{}); + #ifndef DOXYGEN_GENERATING_OUTPUT Implementation::State& state() { return *_state; } #endif diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index d0fd4ef75..1c707507e 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -82,6 +82,7 @@ Framebuffer::Framebuffer(const Range2Di& viewport) { _viewport = viewport; glGenFramebuffers(1, &_id); + CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } Framebuffer::~Framebuffer() { diff --git a/src/Magnum/Implementation/BufferState.cpp b/src/Magnum/Implementation/BufferState.cpp index 6be8f2945..d9e0b1d3d 100644 --- a/src/Magnum/Implementation/BufferState.cpp +++ b/src/Magnum/Implementation/BufferState.cpp @@ -30,6 +30,8 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" +#include "State.h" + namespace Magnum { namespace Implementation { const Buffer::Target BufferState::targetForIndex[] = { @@ -136,4 +138,8 @@ BufferState::BufferState(Context& context, std::vector& extensions) #endif } +void BufferState::reset() { + std::fill_n(bindings, TargetCount, State::DisengagedBinding); +} + }} diff --git a/src/Magnum/Implementation/BufferState.h b/src/Magnum/Implementation/BufferState.h index 4e16abb18..9c255c37a 100644 --- a/src/Magnum/Implementation/BufferState.h +++ b/src/Magnum/Implementation/BufferState.h @@ -46,6 +46,8 @@ struct BufferState { explicit BufferState(Context& context, std::vector& extensions); + void reset(); + #ifndef MAGNUM_TARGET_GLES2 void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); #endif diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 4b6a99803..0f6f3c121 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -29,6 +29,8 @@ #include "Magnum/Extensions.h" #include "Magnum/Renderbuffer.h" +#include "State.h" + namespace Magnum { namespace Implementation { FramebufferState::FramebufferState(Context& context, std::vector& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0) @@ -138,4 +140,9 @@ FramebufferState::FramebufferState(Context& context, std::vector& e } } +void FramebufferState::reset() { + readBinding = drawBinding = renderbufferBinding = State::DisengagedBinding; + viewport = {}; +} + }} diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index f8ecde63c..25c55fe29 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -35,6 +35,8 @@ namespace Magnum { namespace Implementation { struct FramebufferState { explicit FramebufferState(Context& context, std::vector& extensions); + void reset(); + GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); diff --git a/src/Magnum/Implementation/MeshState.cpp b/src/Magnum/Implementation/MeshState.cpp index 66d56fb57..9af9a0d76 100644 --- a/src/Magnum/Implementation/MeshState.cpp +++ b/src/Magnum/Implementation/MeshState.cpp @@ -28,6 +28,8 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" +#include "State.h" + namespace Magnum { namespace Implementation { MeshState::MeshState(Context& context, std::vector& extensions): currentVAO(0) @@ -138,4 +140,8 @@ MeshState::MeshState(Context& context, std::vector& extensions): cu #endif } +void MeshState::reset() { + currentVAO = State::DisengagedBinding; +} + }} diff --git a/src/Magnum/Implementation/MeshState.h b/src/Magnum/Implementation/MeshState.h index 2c39037fc..c5ba22bef 100644 --- a/src/Magnum/Implementation/MeshState.h +++ b/src/Magnum/Implementation/MeshState.h @@ -35,6 +35,8 @@ namespace Magnum { namespace Implementation { struct MeshState { explicit MeshState(Context& context, std::vector& extensions); + void reset(); + void(Mesh::*createImplementation)(); void(Mesh::*destroyImplementation)(); void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&); diff --git a/src/Magnum/Implementation/ShaderProgramState.cpp b/src/Magnum/Implementation/ShaderProgramState.cpp index 3e375e8c0..680ad4bad 100644 --- a/src/Magnum/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/Implementation/ShaderProgramState.cpp @@ -29,6 +29,8 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" +#include "State.h" + namespace Magnum { namespace Implementation { ShaderProgramState::ShaderProgramState(Context& context, std::vector& extensions): current(0), maxVertexAttributes(0) @@ -185,4 +187,8 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector& extensions); + void reset(); + void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); diff --git a/src/Magnum/Implementation/State.h b/src/Magnum/Implementation/State.h index 207594cd2..f8e9c6a7f 100644 --- a/src/Magnum/Implementation/State.h +++ b/src/Magnum/Implementation/State.h @@ -26,6 +26,7 @@ */ #include "Magnum/Magnum.h" +#include "Magnum/OpenGL.h" namespace Magnum { namespace Implementation { @@ -44,6 +45,8 @@ struct State { ~State(); + enum: GLuint { DisengagedBinding = ~0u }; + BufferState* buffer; DebugState* debug; FramebufferState* framebuffer; diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 0e5c5e23b..60c031784 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -34,6 +34,8 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" +#include "State.h" + namespace Magnum { namespace Implementation { TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, max3DSize{}, maxCubeMapSize{}, @@ -228,4 +230,8 @@ TextureState::TextureState(Context& context, std::vector& extension TextureState::~TextureState() = default; +void TextureState::reset() { + std::fill_n(bindings.begin(), bindings.size(), std::pair{{}, State::DisengagedBinding}); +} + }} diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 9075a58f8..c4acf3e5d 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -37,6 +37,8 @@ struct TextureState { explicit TextureState(Context& context, std::vector& extensions); ~TextureState(); + void reset(); + void(*unbindImplementation)(GLint); void(*bindMultiImplementation)(GLint, std::initializer_list); void(AbstractTexture::*bindImplementation)(GLint); diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 219b004ff..c91a8059f 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -307,6 +307,7 @@ void Mesh::createImplementationVAO() { //glGenVertexArraysOES(1, &_id); CORRADE_INTERNAL_ASSERT(false); #endif + CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } void Mesh::destroyImplementationDefault() {}