Browse Source

Tracking Buffer state.

Reduces OpenGL call count if subsequently binding the same Buffer into
the same Target.
vectorfields
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 "Extensions.h"
#include "Implementation/State.h"
#include "Implementation/BufferState.h"
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) {
read->bind(Target::CopyRead);
write->bind(Target::CopyWrite);
glCopyBufferSubData(static_cast<GLenum>(Target::CopyRead), static_cast<GLenum>(Target::CopyWrite), readOffset, writeOffset, size);
glCopyBufferSubData(static_cast<GLenum>(read->bindInternal(Target::CopyRead)), static_cast<GLenum>(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, 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) {
bind();
glBufferData(static_cast<GLenum>(_defaultTarget), size, data, static_cast<GLenum>(usage));
glBufferData(static_cast<GLenum>(bindInternal(_defaultTarget)), size, data, static_cast<GLenum>(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) {
bind();
glBufferSubData(static_cast<GLenum>(_defaultTarget), offset, size, data);
glBufferSubData(static_cast<GLenum>(bindInternal(_defaultTarget)), offset, size, 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}
*/
inline static void unbind(Target target) {
glBindBuffer(static_cast<GLenum>(target), 0);
}
inline static void unbind(Target target) { bind(target, 0); }
/**
* @brief Copy one buffer to another
@ -277,9 +275,7 @@ class MAGNUM_EXPORT Buffer {
* Deletes associated OpenGL buffer.
* @see @fn_gl{DeleteBuffers}
*/
inline virtual ~Buffer() {
glDeleteBuffers(1, &_id);
}
virtual ~Buffer();
/** @brief Default bind type */
inline Target defaultTarget() const { return _defaultTarget; }
@ -301,9 +297,7 @@ class MAGNUM_EXPORT Buffer {
*
* @see @fn_gl{BindBuffer}
*/
inline void bind(Target target) {
glBindBuffer(static_cast<GLenum>(target), _id);
}
inline void bind(Target target) { bind(target, _id); }
/**
* @brief Set buffer data
@ -390,6 +384,9 @@ class MAGNUM_EXPORT Buffer {
private:
static void initializeContextBasedFunctionality(Context* context);
static void bind(Target hint, GLuint id);
Target bindInternal(Target hint);
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 copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);

1
src/CMakeLists.txt

@ -37,6 +37,7 @@ set(Magnum_SRCS
Timeline.cpp
TypeTraits.cpp
Implementation/BufferState.cpp
Implementation/State.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 "BufferState.h"
namespace Magnum { namespace Implementation {
State::State() {}
State::State(): buffer(new BufferState) {}
State::~State() {
delete buffer;
}
}}

4
src/Implementation/State.h

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

Loading…
Cancel
Save