Commit 604d84b1 authored by Christopher Tenter's avatar Christopher Tenter

add uniform buffer object

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@19914 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 2a3a9ba2
......@@ -43,6 +43,7 @@
#include <ACG/GL/acg_glew.hh>
#include <ACG/GL/globjects.hh>
#include <ACG/GL/GLFormatInfo.hh>
#include <ACG/ShaderUtils/GLSLShader.hh>
#include <QImage>
#include <QGLWidget>
......@@ -326,6 +327,13 @@ void VertexBufferObject::gen() {
valid = true;
}
int VertexBufferObject::size() {
bind();
int bufsize = 0;
glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufsize);
return bufsize;
}
#endif
......@@ -799,6 +807,144 @@ bool QueryCounter::isSupported()
//-----------------------------------------------------------------------------
// support state unknown : -1
int UniformBufferObject::supportStatus_ = -1;
int UniformBufferObject::maxBlockSize_ = -1;
int UniformBufferObject::maxBindings_ = -1;
int UniformBufferObject::maxCombinedShaderBlocks_ = -1;
int UniformBufferObject::offsetAlignment_ = -1;
UniformBufferObject::UniformBufferObject()
: VertexBufferObject(
#ifndef GL_ARB_uniform_buffer_object
GL_NONE
#else
GL_UNIFORM_BUFFER
#endif
),
data_(0)
{
}
UniformBufferObject::~UniformBufferObject()
{
}
void UniformBufferObject::bind( GLuint _index )
{
#ifdef GL_ARB_uniform_buffer_object
glBindBufferBase(GL_UNIFORM_BUFFER, _index, id());
#endif
}
bool UniformBufferObject::isSupported()
{
#ifndef GL_ARB_uniform_buffer_object
// missing definition in gl header!
supportStatus_ = 0;
#else
if (supportStatus_ < 0)
supportStatus_ = checkExtensionSupported("GL_ARB_uniform_buffer_object") ? 1 : 0;
#endif
return supportStatus_ > 0;
}
void UniformBufferObject::queryCaps()
{
#ifdef GL_ARB_uniform_buffer_object
if (isSupported())
{
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxBindings_);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBlockSize_);
glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxCombinedShaderBlocks_);
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment_);
}
#endif
}
int UniformBufferObject::getMaxBindings()
{
if (maxBindings_ < 0)
queryCaps();
return maxBindings_;
}
int UniformBufferObject::getMaxBlocksize()
{
if (maxBlockSize_ < 0)
queryCaps();
return maxBlockSize_;
}
int UniformBufferObject::getMaxCombinedShaderBlocks()
{
if (maxCombinedShaderBlocks_ < 0)
queryCaps();
return maxCombinedShaderBlocks_;
}
int UniformBufferObject::getOffsetAlignment()
{
if (offsetAlignment_ < 0)
queryCaps();
return offsetAlignment_;
}
void UniformBufferObject::setUniformData( GLSL::Program* _prog, const char* _bufferName, const char* _uniformName, const void* _data, int _datasize, bool _delay )
{
if (_prog && _bufferName && _uniformName && _data)
{
GLuint idx = _prog->getUniformBlockIndex(_bufferName);
if (idx != GL_INVALID_INDEX)
{
size_t bufsize = size_t(_prog->getUniformBlockSize(idx));
if (data_.size() != bufsize)
data_.resize(bufsize, 0);
int offset = -1;
_prog->getUniformBlockOffsets(1, &_uniformName, &offset);
if (offset >= 0)
{
memcpy(&data_[offset], _data, _datasize);
if (!_delay)
{
VertexBufferObject::bind();
if (size() != int(bufsize))
VertexBufferObject::upload(bufsize, &data_[0], GL_DYNAMIC_DRAW);
else
uploadSubData(offset, _datasize, _data);
}
}
}
}
}
void UniformBufferObject::upload()
{
if (!data_.empty())
{
VertexBufferObject::bind();
VertexBufferObject::upload(data_.size(), &data_[0], GL_DYNAMIC_DRAW);
}
}
//-----------------------------------------------------------------------------
// support state unknown : -1
int ShaderStorageBufferObject::supportStatus_ = -1;
......
......@@ -64,6 +64,7 @@
#include <fstream>
#include <string>
#include <map>
#include <vector>
// C
#include <cstdio>
......@@ -80,6 +81,10 @@
//== NAMESPACES ===============================================================
namespace GLSL {
class Program; // prototype
}
namespace ACG {
......@@ -144,6 +149,8 @@ public:
GLuint id() const {return vbo;}
int size();
private:
void gen();
......@@ -762,6 +769,80 @@ private:
};
//== CLASS DEFINITION =========================================================
/*
Uniform buffer object:
https://www.opengl.org/wiki/Uniform_Buffer_Object
Grouping shader uniforms into a buffer allows to reuse
the same set of uniforms across multiple shaders.
Also avoids having to call lots of setUniform functions.
extension: https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
opengl-core: 3.1
usage:
ACG::Vec4f vec0 = ..;
ubo.setUniformData(shader, "blockName", "uniformName0", vec0.data());
bind to a binding index:
ubo.bind(idx);
shader->setUniformBlockBinding(idx);
in shader:
uniform blockName
{
vec4 uniformName0;
vec4 uniformName1;
..
};
*/
class ACGDLLEXPORT UniformBufferObject : public VertexBufferObject
{
public:
UniformBufferObject();
virtual ~UniformBufferObject();
// set data for a uniform (makes a byte-wise)
// if _delay is true, the buffer is only locally changed and must be updated later via upload().
// otherwise, the buffer is immediately updated via glBufferSubData
void setUniformData(GLSL::Program* _prog, const char* _bufferName, const char* _uniformName, const void* _data, int _datasize, bool _delay = false);
// upload the buffer after delayed initialization via setUniformData
void upload();
// use this to bind to a shader binding point
void bind(GLuint _index);
// check hardware support
static bool isSupported();
// get hw caps
static int getMaxBindings();
static int getMaxBlocksize();
static int getMaxCombinedShaderBlocks();
static int getOffsetAlignment();
private:
// buffer data (optional)
std::vector<char> data_;
static void queryCaps();
// hw caps
static int supportStatus_;
static int maxBlockSize_;
static int maxBindings_;
static int maxCombinedShaderBlocks_;
static int offsetAlignment_;
};
//== CLASS DEFINITION =========================================================
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment