Refactored osg::TextureBuffer to support assigning any type of osg::BufferData rather than just osg::Image as was previously required.
Refactored osgforest and osggpucull examples to take account of changes to TextureBuffer. Added osg::DrawIndirectBufferBinding.
This commit is contained in:
committed by
Robert Osfield
parent
7d66a57bc0
commit
78b99c7143
@@ -476,6 +476,8 @@ osg::Geode* ForestTechniqueManager::createTerrain(const osg::Vec3& origin, const
|
||||
geometry->setVertexArray(&v);
|
||||
geometry->setColorArray(&color, osg::Array::BIND_OVERALL);
|
||||
geometry->setTexCoordArray(0,&t);
|
||||
geometry->setUseDisplayList(false);
|
||||
geometry->setUseVertexBufferObjects(true);
|
||||
|
||||
for(r=0;r<numRows-1;++r)
|
||||
{
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
|
||||
void DrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
|
||||
{
|
||||
if( !_buffer.valid() )
|
||||
return;
|
||||
_buffer->bindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER );
|
||||
|
||||
// if you want to see how many primitives were rendered - uncomment code below, but
|
||||
// be warned : it is a serious performance killer ( because of GPU->CPU roundtrip )
|
||||
|
||||
@@ -34,106 +30,12 @@ void DrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/
|
||||
// OSG_WARN<<"DrawArraysIndirect ("<<val<<"): "<< tab[val] << " " << tab[val+1] << " " << tab[val+2] << " " << tab[val+3] << std::endl;
|
||||
// dext->glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
||||
|
||||
DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
|
||||
ext->glDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect) );
|
||||
_buffer->unbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER );
|
||||
state.get<osg::GLExtensions>()->glDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect) );
|
||||
|
||||
}
|
||||
|
||||
void MultiDrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
|
||||
void MultiDrawArraysIndirect::draw(osg::State& state, bool useVertexBufferObjects) const
|
||||
{
|
||||
if( !_buffer.valid() )
|
||||
return;
|
||||
_buffer->bindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER );
|
||||
|
||||
DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
|
||||
ext->glMultiDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect), _drawcount, _stride );
|
||||
_buffer->unbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER );
|
||||
}
|
||||
|
||||
DrawIndirectGLExtensions::DrawIndirectGLExtensions( unsigned int contextID )
|
||||
{
|
||||
setupGLExtensions( contextID );
|
||||
}
|
||||
|
||||
DrawIndirectGLExtensions::DrawIndirectGLExtensions( const DrawIndirectGLExtensions &rhs )
|
||||
: Referenced()
|
||||
{
|
||||
_glDrawArraysIndirect = rhs._glDrawArraysIndirect;
|
||||
_glMultiDrawArraysIndirect = rhs._glMultiDrawArraysIndirect;
|
||||
_glMemoryBarrier = rhs._glMemoryBarrier;
|
||||
}
|
||||
|
||||
|
||||
void DrawIndirectGLExtensions::lowestCommonDenominator( const DrawIndirectGLExtensions &rhs )
|
||||
{
|
||||
if ( !rhs._glDrawArraysIndirect )
|
||||
{
|
||||
_glDrawArraysIndirect = rhs._glDrawArraysIndirect;
|
||||
}
|
||||
if ( !rhs._glMultiDrawArraysIndirect )
|
||||
{
|
||||
_glMultiDrawArraysIndirect = rhs._glMultiDrawArraysIndirect;
|
||||
}
|
||||
if ( !rhs._glMemoryBarrier )
|
||||
{
|
||||
_glMemoryBarrier = rhs._glMemoryBarrier;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawIndirectGLExtensions::setupGLExtensions( unsigned int /*contextID*/ )
|
||||
{
|
||||
_glDrawArraysIndirect = 0;
|
||||
_glMultiDrawArraysIndirect = 0;
|
||||
osg::setGLExtensionFuncPtr( _glDrawArraysIndirect, "glDrawArraysIndirect" );
|
||||
osg::setGLExtensionFuncPtr( _glMultiDrawArraysIndirect, "glMultiDrawArraysIndirect" );
|
||||
osg::setGLExtensionFuncPtr( _glMemoryBarrier, "glMemoryBarrier" );
|
||||
}
|
||||
|
||||
void DrawIndirectGLExtensions::glDrawArraysIndirect(GLenum mode, const void * indirect) const
|
||||
{
|
||||
if ( _glDrawArraysIndirect )
|
||||
{
|
||||
_glDrawArraysIndirect( mode, indirect );
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN<<"Error: glDrawArraysIndirect not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawIndirectGLExtensions::glMultiDrawArraysIndirect(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride)
|
||||
{
|
||||
if ( _glMultiDrawArraysIndirect )
|
||||
{
|
||||
_glMultiDrawArraysIndirect( mode, indirect, drawcount, stride );
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN<<"Error: glMultiDrawArraysIndirect not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawIndirectGLExtensions::glMemoryBarrier(GLbitfield barriers)
|
||||
{
|
||||
if ( _glMemoryBarrier )
|
||||
{
|
||||
_glMemoryBarrier( barriers );
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN<<"Error: glMemoryBarrier not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef osg::buffered_value< osg::ref_ptr<DrawIndirectGLExtensions> > BufferedDrawIndirectGLExtensions;
|
||||
static BufferedDrawIndirectGLExtensions bdiExtensions;
|
||||
|
||||
DrawIndirectGLExtensions* DrawIndirectGLExtensions::getExtensions( unsigned int contextID,bool createIfNotInitalized )
|
||||
{
|
||||
if ( !bdiExtensions[contextID] && createIfNotInitalized )
|
||||
{
|
||||
bdiExtensions[contextID] = new DrawIndirectGLExtensions( contextID );
|
||||
}
|
||||
return bdiExtensions[contextID].get();
|
||||
// DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
|
||||
state.get<osg::GLExtensions>()->glMultiDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect), _drawcount, _stride );
|
||||
}
|
||||
|
||||
@@ -20,21 +20,12 @@
|
||||
#include <osg/BufferObject>
|
||||
#include <osg/TextureBuffer>
|
||||
|
||||
#ifndef GL_ARB_draw_indirect
|
||||
#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
|
||||
#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
|
||||
#endif
|
||||
|
||||
#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
|
||||
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
|
||||
#endif
|
||||
|
||||
|
||||
class DrawArraysIndirect : public osg::DrawArrays
|
||||
{
|
||||
public:
|
||||
DrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0)
|
||||
: osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect)
|
||||
DrawArraysIndirect(GLenum mode=0, unsigned int indirect=0)
|
||||
: osg::DrawArrays(mode), _indirect(indirect)
|
||||
{
|
||||
}
|
||||
virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); }
|
||||
@@ -45,15 +36,14 @@ public:
|
||||
|
||||
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
||||
protected:
|
||||
osg::ref_ptr<osg::TextureBuffer> _buffer;
|
||||
unsigned int _indirect;
|
||||
};
|
||||
|
||||
class MultiDrawArraysIndirect : public osg::DrawArrays
|
||||
{
|
||||
public:
|
||||
MultiDrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0)
|
||||
: osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect), _drawcount(drawcount), _stride(stride)
|
||||
MultiDrawArraysIndirect(GLenum mode=0, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0)
|
||||
: osg::DrawArrays(mode), _indirect(indirect), _drawcount(drawcount), _stride(stride)
|
||||
{
|
||||
}
|
||||
virtual osg::Object* cloneType() const { return new MultiDrawArraysIndirect(); }
|
||||
@@ -64,37 +54,10 @@ public:
|
||||
|
||||
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
||||
protected:
|
||||
osg::ref_ptr<osg::TextureBuffer> _buffer;
|
||||
unsigned int _indirect;
|
||||
GLsizei _drawcount;
|
||||
GLsizei _stride;
|
||||
};
|
||||
|
||||
class DrawIndirectGLExtensions : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
DrawIndirectGLExtensions( unsigned int contextID );
|
||||
DrawIndirectGLExtensions( const DrawIndirectGLExtensions &rhs );
|
||||
void lowestCommonDenominator( const DrawIndirectGLExtensions &rhs );
|
||||
void setupGLExtensions( unsigned int contextID );
|
||||
|
||||
void glDrawArraysIndirect(GLenum mode, const void * indirect) const;
|
||||
void glMultiDrawArraysIndirect(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
|
||||
void glMemoryBarrier(GLbitfield barriers);
|
||||
|
||||
static DrawIndirectGLExtensions* getExtensions( unsigned int contextID,bool createIfNotInitalized );
|
||||
protected:
|
||||
|
||||
typedef void ( GL_APIENTRY *DrawArraysIndirectProc ) (GLenum mode, const void * indirect);
|
||||
typedef void ( GL_APIENTRY *MultiDrawArraysIndirectProc ) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
|
||||
typedef void ( GL_APIENTRY *MemoryBarrierProc ) (GLbitfield barriers);
|
||||
|
||||
DrawArraysIndirectProc _glDrawArraysIndirect;
|
||||
MultiDrawArraysIndirectProc _glMultiDrawArraysIndirect;
|
||||
MemoryBarrierProc _glMemoryBarrier;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -189,36 +189,55 @@ struct IndirectTarget
|
||||
{
|
||||
osg::Image* indirectCommandImage = new osg::Image;
|
||||
indirectCommandImage->setImage( indirectCommands->getTotalDataSize()/sizeof(unsigned int), 1, 1, GL_R32I, GL_RED, GL_UNSIGNED_INT, (unsigned char*)indirectCommands->getDataPointer(), osg::Image::NO_DELETE );
|
||||
|
||||
osg::VertexBufferObject * indirectCommandImagebuffer=new osg::VertexBufferObject();
|
||||
indirectCommandImagebuffer->setUsage(GL_DYNAMIC_DRAW);
|
||||
indirectCommandImage->setBufferObject(indirectCommandImagebuffer);
|
||||
|
||||
indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommandImage);
|
||||
indirectCommandTextureBuffer->setInternalFormat( GL_R32I );
|
||||
indirectCommandTextureBuffer->setUsageHint(GL_DYNAMIC_DRAW);
|
||||
indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE);
|
||||
indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false);
|
||||
|
||||
|
||||
// add proper primitivesets to geometryAggregators
|
||||
if( !useMultiDrawArraysIndirect ) // use glDrawArraysIndirect()
|
||||
{
|
||||
std::vector<DrawArraysIndirect*> newPrimitiveSets;
|
||||
|
||||
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
|
||||
newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, indirectCommandTextureBuffer.get(), j*sizeof( DrawArraysIndirectCommand ) ) );
|
||||
newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, j*sizeof( DrawArraysIndirectCommand ) ) );
|
||||
|
||||
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
|
||||
|
||||
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
|
||||
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( newPrimitiveSets[j] );
|
||||
|
||||
|
||||
}
|
||||
else // use glMultiDrawArraysIndirect()
|
||||
{
|
||||
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
|
||||
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( new MultiDrawArraysIndirect( GL_TRIANGLES, indirectCommandTextureBuffer.get(), 0, indirectCommands->getData().size(), 0 ) );
|
||||
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( new MultiDrawArraysIndirect( GL_TRIANGLES, 0, indirectCommands->getData().size(), 0 ) );
|
||||
}
|
||||
geometryAggregator->getAggregatedGeometry()->setUseVertexBufferObjects(true);
|
||||
|
||||
///attach a DrawIndirect buffer binding to the stateset
|
||||
osg::ref_ptr<osg::DrawIndirectBufferBinding> bb=new osg::DrawIndirectBufferBinding();
|
||||
bb->setBufferObject(indirectCommandImage->getBufferObject());
|
||||
geometryAggregator->getAggregatedGeometry()->getOrCreateStateSet()->setAttribute(bb );
|
||||
geometryAggregator->getAggregatedGeometry()->setUseDisplayList(false);
|
||||
geometryAggregator->getAggregatedGeometry()->setUseVertexBufferObjects(true);
|
||||
|
||||
|
||||
osg::Image* instanceTargetImage = new osg::Image;
|
||||
instanceTargetImage->allocateImage( maxTargetQuantity*rowsPerInstance, 1, 1, pixelFormat, type );
|
||||
|
||||
osg::VertexBufferObject * instanceTargetImageBuffer=new osg::VertexBufferObject();
|
||||
instanceTargetImageBuffer->setUsage(GL_DYNAMIC_DRAW);
|
||||
instanceTargetImage->setBufferObject(instanceTargetImageBuffer);
|
||||
|
||||
instanceTarget = new osg::TextureBuffer(instanceTargetImage);
|
||||
instanceTarget->setInternalFormat( internalFormat );
|
||||
instanceTarget->setUsageHint(GL_DYNAMIC_DRAW);
|
||||
instanceTarget->bindToImageUnit(OSGGPUCULL_MAXIMUM_INDIRECT_TARGET_NUMBER+index, osg::Texture::READ_WRITE);
|
||||
|
||||
}
|
||||
@@ -228,6 +247,8 @@ struct IndirectTarget
|
||||
osg::Uniform* uniform = new osg::Uniform(uniformName.c_str(), (int)index );
|
||||
stateset->addUniform( uniform );
|
||||
stateset->setTextureAttribute( index, indirectCommandTextureBuffer.get() );
|
||||
|
||||
|
||||
}
|
||||
void addIndirectTargetData( bool cullPhase, const std::string& uniformNamePrefix, int index, osg::StateSet* stateset )
|
||||
{
|
||||
@@ -617,6 +638,9 @@ osg::Geometry* buildGPUCullGeometry( const std::vector<StaticInstance>& instance
|
||||
|
||||
geom->setInitialBound( bbox );
|
||||
|
||||
geom->setUseDisplayList(false);
|
||||
geom->setUseVertexBufferObjects(true);
|
||||
|
||||
return geom.release();
|
||||
}
|
||||
|
||||
@@ -643,6 +667,9 @@ osg::Node* createInstanceGraph(InstanceCell<T>* cell, const osg::BoundingBox& ob
|
||||
bbox.zMax() += objectsBBox.zMax();
|
||||
geometry->setInitialBound(bbox);
|
||||
geode = new osg::Geode;
|
||||
geometry->setUseDisplayList(false);
|
||||
geometry->setUseVertexBufferObjects(true);
|
||||
|
||||
geode->addDrawable( geometry );
|
||||
}
|
||||
|
||||
@@ -728,8 +755,8 @@ struct InvokeMemoryBarrier : public osg::Drawable::DrawCallback
|
||||
}
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
||||
{
|
||||
DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true );
|
||||
ext->glMemoryBarrier( _barriers );
|
||||
//DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true );
|
||||
renderInfo.getState()->get<osg::GLExtensions>()->glMemoryBarrier( _barriers );
|
||||
drawable->drawImplementation(renderInfo);
|
||||
}
|
||||
GLbitfield _barriers;
|
||||
@@ -1333,8 +1360,12 @@ void createDynamicRendering( osg::Group* root, GPUCullData& gpuData, osg::Buffer
|
||||
// all data about instances is stored in texture buffer ( compare it with static rendering )
|
||||
osg::Image* instancesImage = new osg::Image;
|
||||
instancesImage->setImage( instances->getTotalDataSize() / sizeof(osg::Vec4f), 1, 1, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, (unsigned char*)instances->getDataPointer(), osg::Image::NO_DELETE );
|
||||
|
||||
osg::VertexBufferObject *instancesBuffer =new osg::VertexBufferObject;
|
||||
instancesBuffer->setUsage(GL_STATIC_DRAW);
|
||||
instancesImage->setBufferObject(instancesBuffer);
|
||||
|
||||
osg::TextureBuffer* instancesTextureBuffer = new osg::TextureBuffer(instancesImage);
|
||||
instancesTextureBuffer->setUsageHint(GL_STATIC_DRAW);
|
||||
instancesTextureBuffer->setUnRefImageDataAfterApply(false);
|
||||
|
||||
osg::Uniform* dynamicInstancesDataUniform = new osg::Uniform( "dynamicInstancesData", 8 );
|
||||
|
||||
Reference in New Issue
Block a user