Browse Source

GL: put texture/image state trackers into the single allocation also.

euler-xxx
Vladimír Vondruš 5 years ago
parent
commit
bf802b7ad9
  1. 3
      doc/changelog.dox
  2. 4
      src/Magnum/GL/Implementation/MeshState.cpp
  3. 2
      src/Magnum/GL/Implementation/MeshState.h
  4. 42
      src/Magnum/GL/Implementation/State.cpp
  5. 43
      src/Magnum/GL/Implementation/TextureState.cpp
  6. 20
      src/Magnum/GL/Implementation/TextureState.h

3
doc/changelog.dox

@ -186,6 +186,9 @@ See also:
@subsubsection changelog-latest-changes-gl GL library
- The @ref GL::Context class got significantly optimized in terms of compile
time, header size and runtime as well, significantly reducing the amount of
allocations done at startup.
- Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum
isn't available on ES3 or desktop GL, but NVidia drivers are known to emit
it, which is why it got added.

4
src/Magnum/GL/Implementation/MeshState.cpp

@ -405,15 +405,15 @@ MeshState::MeshState(Context& context, ContextState& contextState, Containers::S
#endif
}
#ifndef MAGNUM_TARGET_GLES
MeshState::~MeshState() {
#ifndef MAGNUM_TARGET_GLES
/* If the default VAO was created, we need to delete it to avoid leaks.
Delete also the scratch VAO if the engine was so unlucky to have to run
awful external GL code (it was created in Context::resetState()). */
if(defaultVAO) glDeleteVertexArrays(1, &defaultVAO);
if(scratchVAO) glDeleteVertexArrays(1, &scratchVAO);
#endif
}
#endif
void MeshState::reset() {
currentVAO = State::DisengagedBinding;

2
src/Magnum/GL/Implementation/MeshState.h

@ -33,7 +33,9 @@ struct ContextState;
struct MeshState {
explicit MeshState(Context& context, ContextState& contextState, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
#ifndef MAGNUM_TARGET_GLES
~MeshState();
#endif
void reset();

42
src/Magnum/GL/Implementation/State.cpp

@ -25,7 +25,9 @@
#include "State.h"
#include <tuple>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
@ -48,6 +50,26 @@
namespace Magnum { namespace GL { namespace Implementation {
std::pair<Containers::ArrayTuple, State&> State::allocate(Context& context, std::ostream* const out) {
/* TextureState needs to track state per texture / image binding, fetch
how many of them is there and allocate here as well so we don't need to
do another nested allocation */
GLint maxTextureUnits{};
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
GLint maxImageUnits{};
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::shader_image_load_store>())
#else
if(context.isVersionSupported(Version::GLES310))
#endif
{
glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits);
CORRADE_INTERNAL_ASSERT(maxImageUnits > 0);
}
#endif
/* I have to say, the ArrayTuple is quite a crazy thing */
Containers::ArrayView<State> stateView;
Containers::ArrayView<BufferState> bufferStateView;
@ -62,6 +84,10 @@ std::pair<Containers::ArrayTuple, State&> State::allocate(Context& context, std:
Containers::ArrayView<ShaderState> shaderStateView;
Containers::ArrayView<ShaderProgramState> shaderProgramStateView;
Containers::ArrayView<TextureState> textureStateView;
Containers::ArrayView<std::pair<GLenum, GLuint>> textureBindings;
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::ArrayView<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings;
#endif
#ifndef MAGNUM_TARGET_GLES2
Containers::ArrayView<TransformFeedbackState> transformFeedbackStateView;
#endif
@ -79,11 +105,21 @@ std::pair<Containers::ArrayTuple, State&> State::allocate(Context& context, std:
{Containers::NoInit, 1, shaderStateView},
{Containers::NoInit, 1, shaderProgramStateView},
{Containers::NoInit, 1, textureStateView},
{Containers::ValueInit, std::size_t(maxTextureUnits), textureBindings},
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
{Containers::ValueInit, std::size_t(maxImageUnits), imageBindings},
#endif
#ifndef MAGNUM_TARGET_GLES2
{Containers::NoInit, 1, transformFeedbackStateView}
#endif
};
#ifdef MAGNUM_TARGET_GLES
/* This whole thing would be trivially destructible except for MeshState
which has to delete scratch VAOs on desktop in a custom destructor. */
CORRADE_INTERNAL_ASSERT(!data.deleter());
#endif
/* Extensions that might get used by current context. The State classes
will set strings based on Extension::index() and then we'll go through
the list and print ones that aren't null. It's 1.5 kB of temporary data
@ -120,7 +156,11 @@ std::pair<Containers::ArrayTuple, State&> State::allocate(Context& context, std:
new(&state.renderer) RendererState{context, stateView.front().context, extensions};
new(&state.shader) ShaderState(context, extensions);
new(&state.shaderProgram) ShaderProgramState{context, extensions};
new(&state.texture) TextureState{context, extensions};
new(&state.texture) TextureState{context, textureBindings,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
imageBindings,
#endif
extensions};
#ifndef MAGNUM_TARGET_GLES2
new(&state.transformFeedback) TransformFeedbackState{context, extensions};
#endif

43
src/Magnum/GL/Implementation/TextureState.cpp

@ -43,7 +43,13 @@ namespace Magnum { namespace GL { namespace Implementation {
using namespace Containers::Literals;
TextureState::TextureState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions): maxSize{},
TextureState::TextureState(Context& context,
Containers::ArrayView<std::pair<GLenum, GLuint>> bindings,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::ArrayView<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings,
#endif
Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions):
maxSize{},
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
max3DSize{},
#endif
@ -54,16 +60,22 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView<Impleme
#ifndef MAGNUM_TARGET_GLES
maxRectangleSize{}, maxBufferSize{},
#endif
maxTextureUnits(0),
/* This value got queried in State already to allocate the bindings array,
reuse it here */
maxTextureUnits{GLint(bindings.size())},
#ifndef MAGNUM_TARGET_GLES2
maxLodBias{0.0f},
#endif
maxMaxAnisotropy(0.0f), currentTextureUnit(0)
maxMaxAnisotropy(0.0f), currentTextureUnit(0),
#ifndef MAGNUM_TARGET_GLES2
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0)
maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0),
#endif
#ifndef MAGNUM_TARGET_GLES
, bufferOffsetAlignment(0)
bufferOffsetAlignment(0),
#endif
bindings{bindings}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
, imageBindings{imageBindings}
#endif
{
/* Create implementation */
@ -517,11 +529,6 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView<Impleme
}
#endif
/* Allocate texture bindings array to hold all possible texture units */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);
bindings = Containers::Array<std::pair<GLenum, GLuint>>{Containers::ValueInit, std::size_t(maxTextureUnits)};
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) {
CORRADE_INTERNAL_ASSERT(std::size_t(maxTextureUnits) <= decltype(bufferTextureBound)::Size);
@ -536,24 +543,8 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView<Impleme
/* bindImplementation already set above */
bindInternalImplementation = &AbstractTexture::bindImplementationDefault;
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Allocate image bindings array to hold all possible image units */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::shader_image_load_store>())
#else
if(context.isVersionSupported(Version::GLES310))
#endif
{
GLint maxImageUnits;
glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits);
imageBindings = Containers::Array<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>>{Containers::ValueInit, std::size_t(maxImageUnits)};
}
#endif
}
TextureState::~TextureState() = default;
void TextureState::reset() {
std::fill_n(bindings.begin(), bindings.size(), std::pair<GLenum, GLuint>{{}, State::DisengagedBinding});
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)

20
src/Magnum/GL/Implementation/TextureState.h

@ -25,7 +25,7 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Utility/StlForwardTuple.h>
#include "Magnum/Magnum.h"
@ -51,8 +51,12 @@
namespace Magnum { namespace GL { namespace Implementation {
struct TextureState {
explicit TextureState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
~TextureState();
explicit TextureState(Context& context,
Containers::ArrayView<std::pair<GLenum, GLuint>> bindings,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::ArrayView<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings,
#endif
Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
void reset();
@ -155,13 +159,19 @@ struct TextureState {
GLint bufferOffsetAlignment;
#endif
Containers::Array<std::pair<GLenum, GLuint>> bindings;
/* These arrays get allocated in State in a single allocation and views to
them are passed here via the constructor. */
/* Texture type, texture object ID. While not true, for simplicity this
assumes that each slot can have just one ID bound, not one ID per
texture type. */
Containers::ArrayView<std::pair<GLenum, GLuint>> bindings;
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
Math::BoolVector<80> bufferTextureBound;
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Texture object ID, level, layered, layer, access */
Containers::Array<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings;
Containers::ArrayView<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings;
#endif
};

Loading…
Cancel
Save