Browse Source

Tracking Buffer state.

Reduces OpenGL call count if subsequently binding the same Buffer into
the same Target.
pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
6b3781b97f
  1. 50
      src/Buffer.cpp
  2. 15
      src/Buffer.h
  3. 1
      src/CMakeLists.txt
  4. 63
      src/Implementation/BufferState.cpp
  5. 43
      src/Implementation/BufferState.h
  6. 5
      src/Implementation/State.cpp
  7. 4
      src/Implementation/State.h

50
src/Buffer.cpp

@ -19,6 +19,8 @@
#include "Context.h" #include "Context.h"
#include "Extensions.h" #include "Extensions.h"
#include "Implementation/State.h"
#include "Implementation/BufferState.h"
namespace Magnum { namespace Magnum {
@ -36,10 +38,46 @@ void Buffer::initializeContextBasedFunctionality(Context* context) {
} }
} }
Buffer::~Buffer() {
GLuint* bindings = Context::current()->state()->buffer->bindings;
/* Remove all current bindings from the state */
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
if(bindings[i] == _id) bindings[i] = 0;
glDeleteBuffers(1, &_id);
}
void Buffer::bind(Target target, GLuint id) {
GLuint& bound = Context::current()->state()->buffer->bindings[Implementation::BufferState::indexForTarget(target)];
/* Already bound, nothing to do */
if(bound == id) return;
/* Bind the buffer otherwise */
bound = id;
glBindBuffer(static_cast<GLenum>(target), id);
}
Buffer::Target Buffer::bindInternal(Target hint) {
GLuint* bindings = Context::current()->state()->buffer->bindings;
GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)];
/* Shortcut - if already bound to hint, return */
if(hintBinding == _id) return hint;
/* Return first target in which the buffer is bound */
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
if(bindings[i] == _id) return Implementation::BufferState::targetForIndex[i];
/* Bind the buffer to hint target otherwise */
hintBinding = _id;
glBindBuffer(static_cast<GLenum>(hint), _id);
return hint;
}
void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
read->bind(Target::CopyRead); glCopyBufferSubData(static_cast<GLenum>(read->bindInternal(Target::CopyRead)), static_cast<GLenum>(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, size);
write->bind(Target::CopyWrite);
glCopyBufferSubData(static_cast<GLenum>(Target::CopyRead), static_cast<GLenum>(Target::CopyWrite), readOffset, writeOffset, size);
} }
void Buffer::copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { void Buffer::copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
@ -47,8 +85,7 @@ void Buffer::copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOff
} }
void Buffer::setDataImplementationDefault(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { void Buffer::setDataImplementationDefault(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) {
bind(); glBufferData(static_cast<GLenum>(bindInternal(_defaultTarget)), size, data, static_cast<GLenum>(usage));
glBufferData(static_cast<GLenum>(_defaultTarget), size, data, static_cast<GLenum>(usage));
} }
void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) {
@ -56,8 +93,7 @@ void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffe
} }
void Buffer::setSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) { void Buffer::setSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
bind(); glBufferSubData(static_cast<GLenum>(bindInternal(_defaultTarget)), offset, size, data);
glBufferSubData(static_cast<GLenum>(_defaultTarget), offset, size, data);
} }
void Buffer::setSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) { void Buffer::setSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) {

15
src/Buffer.h

@ -236,9 +236,7 @@ class MAGNUM_EXPORT Buffer {
* *
* @see @fn_gl{BindBuffer} * @see @fn_gl{BindBuffer}
*/ */
inline static void unbind(Target target) { inline static void unbind(Target target) { bind(target, 0); }
glBindBuffer(static_cast<GLenum>(target), 0);
}
/** /**
* @brief Copy one buffer to another * @brief Copy one buffer to another
@ -277,9 +275,7 @@ class MAGNUM_EXPORT Buffer {
* Deletes associated OpenGL buffer. * Deletes associated OpenGL buffer.
* @see @fn_gl{DeleteBuffers} * @see @fn_gl{DeleteBuffers}
*/ */
inline virtual ~Buffer() { virtual ~Buffer();
glDeleteBuffers(1, &_id);
}
/** @brief Default bind type */ /** @brief Default bind type */
inline Target defaultTarget() const { return _defaultTarget; } inline Target defaultTarget() const { return _defaultTarget; }
@ -301,9 +297,7 @@ class MAGNUM_EXPORT Buffer {
* *
* @see @fn_gl{BindBuffer} * @see @fn_gl{BindBuffer}
*/ */
inline void bind(Target target) { inline void bind(Target target) { bind(target, _id); }
glBindBuffer(static_cast<GLenum>(target), _id);
}
/** /**
* @brief Set buffer data * @brief Set buffer data
@ -390,6 +384,9 @@ class MAGNUM_EXPORT Buffer {
private: private:
static void initializeContextBasedFunctionality(Context* context); static void initializeContextBasedFunctionality(Context* context);
static void bind(Target hint, GLuint id);
Target bindInternal(Target hint);
typedef void(*CopyImplementation)(Buffer*, Buffer*, GLintptr, GLintptr, GLsizeiptr); typedef void(*CopyImplementation)(Buffer*, Buffer*, GLintptr, GLintptr, GLsizeiptr);
static void MAGNUM_LOCAL copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); static void MAGNUM_LOCAL copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
static void MAGNUM_LOCAL copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); static void MAGNUM_LOCAL copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);

1
src/CMakeLists.txt

@ -37,6 +37,7 @@ set(Magnum_SRCS
Timeline.cpp Timeline.cpp
TypeTraits.cpp TypeTraits.cpp
Implementation/BufferState.cpp
Implementation/State.cpp Implementation/State.cpp
Trade/AbstractImporter.cpp Trade/AbstractImporter.cpp

63
src/Implementation/BufferState.cpp

@ -0,0 +1,63 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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 "BufferState.h"
#include <Utility/Debug.h>
namespace Magnum { namespace Implementation {
const Buffer::Target BufferState::targetForIndex[] = {
Buffer::Target::Array,
Buffer::Target::CopyRead,
Buffer::Target::CopyWrite,
Buffer::Target::ElementArray,
Buffer::Target::PixelPack,
Buffer::Target::PixelUnpack,
Buffer::Target::TransformFeedback,
Buffer::Target::Uniform,
#ifndef MAGNUM_TARGET_GLES
Buffer::Target::AtomicCounter,
Buffer::Target::DispatchIndirect,
Buffer::Target::DrawIndirect,
Buffer::Target::ShaderStorage,
Buffer::Target::Texture
#endif
};
std::size_t BufferState::indexForTarget(Buffer::Target target) {
switch(target) {
case Buffer::Target::Array: return 1;
case Buffer::Target::CopyRead: return 2;
case Buffer::Target::CopyWrite: return 3;
case Buffer::Target::ElementArray: return 4;
case Buffer::Target::PixelPack: return 5;
case Buffer::Target::PixelUnpack: return 6;
case Buffer::Target::TransformFeedback: return 7;
case Buffer::Target::Uniform: return 8;
#ifndef MAGNUM_TARGET_GLES
case Buffer::Target::AtomicCounter: return 9;
case Buffer::Target::DispatchIndirect: return 10;
case Buffer::Target::DrawIndirect: return 11;
case Buffer::Target::ShaderStorage: return 12;
case Buffer::Target::Texture: return 13;
#endif
}
CORRADE_ASSERT(false, "Unknown Buffer target", 0);
return 0;
}
}}

43
src/Implementation/BufferState.h

@ -0,0 +1,43 @@
#ifndef Magnum_Implementation_BufferState_h
#define Magnum_Implementation_BufferState_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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"
#include "Buffer.h"
namespace Magnum { namespace Implementation {
struct BufferState {
#ifndef MAGNUM_TARGET_GLES
static const std::size_t TargetCount = 13+1;
#else
static const std::size_t TargetCount = 8+1;
#endif
/* Target <-> index mapping */
static std::size_t indexForTarget(Buffer::Target target);
static const Buffer::Target targetForIndex[TargetCount-1];
inline constexpr BufferState(): bindings() {}
/* Currently bound buffer for all targets */
GLuint bindings[TargetCount];
};
}}
#endif

5
src/Implementation/State.cpp

@ -15,11 +15,14 @@
#include "State.h" #include "State.h"
#include "BufferState.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
State::State() {} State::State(): buffer(new BufferState) {}
State::~State() { State::~State() {
delete buffer;
} }
}} }}

4
src/Implementation/State.h

@ -19,11 +19,13 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
class BufferState; struct BufferState;
struct State { struct State {
State(); State();
~State(); ~State();
BufferState* const buffer;
}; };
}} }}

Loading…
Cancel
Save