From Tim Moore, "Here is initial support for uniform buffer objects. The binding between a buffer object and an indexed target is implemented as a new StateAttribute, UniformBufferBinding. I've included an example program based on the code in the ARB_uniform_buffer_object specification.
A few things remain to do: * The binding between a uniform block in a shader program and a buffer indexed target number is fixed, like a vertex attribute binding. This is too restrictive because that binding can be changed without relinking the program. This mapping should be done by name in the same way that uniform values are handled i.e., like a pseudo state attribute; * There's no direct way yet to query for the offset of uniforms in uniform block, so only the std140 layout is really usable. A helper class that implemented the std140 rules would be quite helpful for setting up uniform blocks without having to link a program first; * There's no direct support for querying parameters such as the maximum block length, minimum offset alignment, etc. Having that information available outside of the draw thread would make certain instancing techniques easier to implement."
This commit is contained in:
@@ -386,6 +386,21 @@ void Program::removeBindFragDataLocation( const std::string& name )
|
||||
dirtyProgram();
|
||||
}
|
||||
|
||||
void Program::addBindUniformBlock(const std::string& name, GLuint index)
|
||||
{
|
||||
_uniformBlockBindingList[name] = index;
|
||||
dirtyProgram(); // XXX
|
||||
}
|
||||
|
||||
void Program::removeBindUniformBlock(const std::string& name)
|
||||
{
|
||||
_uniformBlockBindingList.erase(name);
|
||||
dirtyProgram(); // XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Program::apply( osg::State& state ) const
|
||||
{
|
||||
const unsigned int contextID = state.getContextID();
|
||||
@@ -589,6 +604,58 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
|
||||
}
|
||||
}
|
||||
|
||||
if (_extensions->isUniformBufferObjectSupported())
|
||||
{
|
||||
GLuint activeUniformBlocks = 0;
|
||||
GLsizei maxBlockNameLen = 0;
|
||||
_extensions->glGetProgramiv(_glProgramHandle, GL_ACTIVE_UNIFORM_BLOCKS,
|
||||
reinterpret_cast<GLint*>(&activeUniformBlocks));
|
||||
_extensions->glGetProgramiv(_glProgramHandle,
|
||||
GL_ACTIVE_UNIFORM_MAX_LENGTH,
|
||||
&maxBlockNameLen);
|
||||
if (maxBlockNameLen > 0)
|
||||
{
|
||||
std::vector<GLchar> blockName(maxBlockNameLen);
|
||||
for (GLuint i = 0; i < activeUniformBlocks; ++i)
|
||||
{
|
||||
GLsizei len = 0;
|
||||
GLint blockSize = 0;
|
||||
_extensions->glGetActiveUniformBlockName(_glProgramHandle, i,
|
||||
maxBlockNameLen, &len,
|
||||
&blockName[0]);
|
||||
_extensions->glGetActiveUniformBlockiv(_glProgramHandle, i,
|
||||
GL_UNIFORM_BLOCK_DATA_SIZE,
|
||||
&blockSize);
|
||||
_uniformBlockMap
|
||||
.insert(UniformBlockMap::value_type(&blockName[0],
|
||||
UniformBlockInfo(i, blockSize)));
|
||||
}
|
||||
}
|
||||
// Bind any uniform blocks
|
||||
const UniformBlockBindingList& bindingList = _program->getUniformBlockBindingList();
|
||||
for (UniformBlockMap::iterator itr = _uniformBlockMap.begin(),
|
||||
end = _uniformBlockMap.end();
|
||||
itr != end;
|
||||
++itr)
|
||||
{
|
||||
const std::string& blockName = itr->first;
|
||||
UniformBlockBindingList::const_iterator bitr = bindingList.find(blockName);
|
||||
if (bitr != bindingList.end())
|
||||
{
|
||||
_extensions->glUniformBlockBinding(_glProgramHandle, itr->second._index,
|
||||
bitr->second);
|
||||
OSG_INFO << "uniform block " << blockName << ": " << itr->second._index
|
||||
<< " binding: " << bitr->second << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN << "uniform block " << blockName << " has no binding.\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build _uniformInfoMap
|
||||
GLint numUniforms = 0;
|
||||
GLsizei maxLen = 0;
|
||||
|
||||
Reference in New Issue
Block a user