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:
parent
7d66a57bc0
commit
78b99c7143
@ -476,6 +476,8 @@ osg::Geode* ForestTechniqueManager::createTerrain(const osg::Vec3& origin, const
|
|||||||
geometry->setVertexArray(&v);
|
geometry->setVertexArray(&v);
|
||||||
geometry->setColorArray(&color, osg::Array::BIND_OVERALL);
|
geometry->setColorArray(&color, osg::Array::BIND_OVERALL);
|
||||||
geometry->setTexCoordArray(0,&t);
|
geometry->setTexCoordArray(0,&t);
|
||||||
|
geometry->setUseDisplayList(false);
|
||||||
|
geometry->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
for(r=0;r<numRows-1;++r)
|
for(r=0;r<numRows-1;++r)
|
||||||
{
|
{
|
||||||
|
@ -21,10 +21,6 @@
|
|||||||
|
|
||||||
void DrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
|
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
|
// 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 )
|
// 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;
|
// OSG_WARN<<"DrawArraysIndirect ("<<val<<"): "<< tab[val] << " " << tab[val+1] << " " << tab[val+2] << " " << tab[val+3] << std::endl;
|
||||||
// dext->glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
// dext->glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
||||||
|
|
||||||
DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
|
state.get<osg::GLExtensions>()->glDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect) );
|
||||||
ext->glDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect) );
|
|
||||||
_buffer->unbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiDrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
|
void MultiDrawArraysIndirect::draw(osg::State& state, bool useVertexBufferObjects) const
|
||||||
{
|
{
|
||||||
if( !_buffer.valid() )
|
// DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
|
||||||
return;
|
state.get<osg::GLExtensions>()->glMultiDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect), _drawcount, _stride );
|
||||||
_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();
|
|
||||||
}
|
}
|
||||||
|
@ -20,21 +20,12 @@
|
|||||||
#include <osg/BufferObject>
|
#include <osg/BufferObject>
|
||||||
#include <osg/TextureBuffer>
|
#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
|
class DrawArraysIndirect : public osg::DrawArrays
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0)
|
DrawArraysIndirect(GLenum mode=0, unsigned int indirect=0)
|
||||||
: osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect)
|
: osg::DrawArrays(mode), _indirect(indirect)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); }
|
virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); }
|
||||||
@ -45,15 +36,14 @@ public:
|
|||||||
|
|
||||||
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osg::TextureBuffer> _buffer;
|
|
||||||
unsigned int _indirect;
|
unsigned int _indirect;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MultiDrawArraysIndirect : public osg::DrawArrays
|
class MultiDrawArraysIndirect : public osg::DrawArrays
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MultiDrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0)
|
MultiDrawArraysIndirect(GLenum mode=0, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0)
|
||||||
: osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect), _drawcount(drawcount), _stride(stride)
|
: osg::DrawArrays(mode), _indirect(indirect), _drawcount(drawcount), _stride(stride)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual osg::Object* cloneType() const { return new MultiDrawArraysIndirect(); }
|
virtual osg::Object* cloneType() const { return new MultiDrawArraysIndirect(); }
|
||||||
@ -64,37 +54,10 @@ public:
|
|||||||
|
|
||||||
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osg::TextureBuffer> _buffer;
|
|
||||||
unsigned int _indirect;
|
unsigned int _indirect;
|
||||||
GLsizei _drawcount;
|
GLsizei _drawcount;
|
||||||
GLsizei _stride;
|
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
|
#endif
|
||||||
|
@ -189,36 +189,55 @@ struct IndirectTarget
|
|||||||
{
|
{
|
||||||
osg::Image* indirectCommandImage = new osg::Image;
|
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 );
|
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 = new osg::TextureBuffer(indirectCommandImage);
|
||||||
indirectCommandTextureBuffer->setInternalFormat( GL_R32I );
|
indirectCommandTextureBuffer->setInternalFormat( GL_R32I );
|
||||||
indirectCommandTextureBuffer->setUsageHint(GL_DYNAMIC_DRAW);
|
|
||||||
indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE);
|
indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE);
|
||||||
indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false);
|
indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false);
|
||||||
|
|
||||||
|
|
||||||
// add proper primitivesets to geometryAggregators
|
// add proper primitivesets to geometryAggregators
|
||||||
if( !useMultiDrawArraysIndirect ) // use glDrawArraysIndirect()
|
if( !useMultiDrawArraysIndirect ) // use glDrawArraysIndirect()
|
||||||
{
|
{
|
||||||
std::vector<DrawArraysIndirect*> newPrimitiveSets;
|
std::vector<DrawArraysIndirect*> newPrimitiveSets;
|
||||||
|
|
||||||
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
|
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() );
|
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
|
||||||
|
|
||||||
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
|
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
|
||||||
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( newPrimitiveSets[j] );
|
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( newPrimitiveSets[j] );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else // use glMultiDrawArraysIndirect()
|
else // use glMultiDrawArraysIndirect()
|
||||||
{
|
{
|
||||||
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
|
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()->setUseDisplayList(false);
|
||||||
|
geometryAggregator->getAggregatedGeometry()->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
|
|
||||||
osg::Image* instanceTargetImage = new osg::Image;
|
osg::Image* instanceTargetImage = new osg::Image;
|
||||||
instanceTargetImage->allocateImage( maxTargetQuantity*rowsPerInstance, 1, 1, pixelFormat, type );
|
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 = new osg::TextureBuffer(instanceTargetImage);
|
||||||
instanceTarget->setInternalFormat( internalFormat );
|
instanceTarget->setInternalFormat( internalFormat );
|
||||||
instanceTarget->setUsageHint(GL_DYNAMIC_DRAW);
|
|
||||||
instanceTarget->bindToImageUnit(OSGGPUCULL_MAXIMUM_INDIRECT_TARGET_NUMBER+index, osg::Texture::READ_WRITE);
|
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 );
|
osg::Uniform* uniform = new osg::Uniform(uniformName.c_str(), (int)index );
|
||||||
stateset->addUniform( uniform );
|
stateset->addUniform( uniform );
|
||||||
stateset->setTextureAttribute( index, indirectCommandTextureBuffer.get() );
|
stateset->setTextureAttribute( index, indirectCommandTextureBuffer.get() );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
void addIndirectTargetData( bool cullPhase, const std::string& uniformNamePrefix, int index, osg::StateSet* stateset )
|
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->setInitialBound( bbox );
|
||||||
|
|
||||||
|
geom->setUseDisplayList(false);
|
||||||
|
geom->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
return geom.release();
|
return geom.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,6 +667,9 @@ osg::Node* createInstanceGraph(InstanceCell<T>* cell, const osg::BoundingBox& ob
|
|||||||
bbox.zMax() += objectsBBox.zMax();
|
bbox.zMax() += objectsBBox.zMax();
|
||||||
geometry->setInitialBound(bbox);
|
geometry->setInitialBound(bbox);
|
||||||
geode = new osg::Geode;
|
geode = new osg::Geode;
|
||||||
|
geometry->setUseDisplayList(false);
|
||||||
|
geometry->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
geode->addDrawable( geometry );
|
geode->addDrawable( geometry );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,8 +755,8 @@ struct InvokeMemoryBarrier : public osg::Drawable::DrawCallback
|
|||||||
}
|
}
|
||||||
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
||||||
{
|
{
|
||||||
DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true );
|
//DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true );
|
||||||
ext->glMemoryBarrier( _barriers );
|
renderInfo.getState()->get<osg::GLExtensions>()->glMemoryBarrier( _barriers );
|
||||||
drawable->drawImplementation(renderInfo);
|
drawable->drawImplementation(renderInfo);
|
||||||
}
|
}
|
||||||
GLbitfield _barriers;
|
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 )
|
// all data about instances is stored in texture buffer ( compare it with static rendering )
|
||||||
osg::Image* instancesImage = new osg::Image;
|
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 );
|
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);
|
osg::TextureBuffer* instancesTextureBuffer = new osg::TextureBuffer(instancesImage);
|
||||||
instancesTextureBuffer->setUsageHint(GL_STATIC_DRAW);
|
|
||||||
instancesTextureBuffer->setUnRefImageDataAfterApply(false);
|
instancesTextureBuffer->setUnRefImageDataAfterApply(false);
|
||||||
|
|
||||||
osg::Uniform* dynamicInstancesDataUniform = new osg::Uniform( "dynamicInstancesData", 8 );
|
osg::Uniform* dynamicInstancesDataUniform = new osg::Uniform( "dynamicInstancesData", 8 );
|
||||||
|
@ -50,6 +50,7 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute
|
|||||||
virtual unsigned getMember() const { return static_cast<unsigned int>(_index); }
|
virtual unsigned getMember() const { return static_cast<unsigned int>(_index); }
|
||||||
|
|
||||||
GLenum getTarget() const { return _target; }
|
GLenum getTarget() const { return _target; }
|
||||||
|
|
||||||
/** Get the index target.
|
/** Get the index target.
|
||||||
*/
|
*/
|
||||||
GLuint getIndex() const { return _index; }
|
GLuint getIndex() const { return _index; }
|
||||||
@ -58,7 +59,8 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute
|
|||||||
void setBufferObject(BufferObject *bo) { _bufferObject = bo; }
|
void setBufferObject(BufferObject *bo) { _bufferObject = bo; }
|
||||||
/** Get the buffer object to be bound.
|
/** Get the buffer object to be bound.
|
||||||
*/
|
*/
|
||||||
BufferObject* getBufferObject() const { return _bufferObject.get(); }
|
const BufferObject* getBufferObject() const { return _bufferObject.get(); }
|
||||||
|
BufferObject* getBufferObject(){ return _bufferObject.get(); }
|
||||||
/** Set the starting offset into the buffer object for data for
|
/** Set the starting offset into the buffer object for data for
|
||||||
the indexed target. Note: the required alignment on the offset
|
the indexed target. Note: the required alignment on the offset
|
||||||
may be quite large (e.g., 256 bytes on NVidia 8600M). This
|
may be quite large (e.g., 256 bytes on NVidia 8600M). This
|
||||||
@ -71,6 +73,7 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute
|
|||||||
void setSize(GLsizeiptr size) { _size = size; }
|
void setSize(GLsizeiptr size) { _size = size; }
|
||||||
GLsizeiptr getSize() const { return _size; }
|
GLsizeiptr getSize() const { return _size; }
|
||||||
virtual void apply(State& state) const;
|
virtual void apply(State& state) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~BufferIndexBinding();
|
virtual ~BufferIndexBinding();
|
||||||
const GLenum _target;
|
const GLenum _target;
|
||||||
@ -190,7 +193,27 @@ class OSG_EXPORT ShaderStorageBufferBinding : public BufferIndexBinding
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OSG_EXPORT DrawIndirectBufferBinding : public BufferIndexBinding
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DrawIndirectBufferBinding();
|
||||||
|
/** Create a binding for a uniform buffer index target.
|
||||||
|
* @param bo associated buffer object
|
||||||
|
*/
|
||||||
|
DrawIndirectBufferBinding( BufferObject* bo);
|
||||||
|
void apply(State& state) const;
|
||||||
|
DrawIndirectBufferBinding(const DrawIndirectBufferBinding& rhs, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||||
|
|
||||||
|
META_StateAttribute(osg, DrawIndirectBufferBinding, INDIRECTDRAWBUFFERBINDING);
|
||||||
|
|
||||||
|
virtual int compare(const StateAttribute& bb) const
|
||||||
|
{
|
||||||
|
COMPARE_StateAttribute_Types(DrawIndirectBufferBinding, bb)
|
||||||
|
COMPARE_StateAttribute_Parameter(_target)
|
||||||
|
COMPARE_StateAttribute_Parameter(_bufferObject)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace osg
|
} // namespace osg
|
||||||
|
@ -202,6 +202,8 @@ class OSG_EXPORT StateAttribute : public Object
|
|||||||
|
|
||||||
SHADERSTORAGEBUFFERBINDING,
|
SHADERSTORAGEBUFFERBINDING,
|
||||||
|
|
||||||
|
INDIRECTDRAWBUFFERBINDING,
|
||||||
|
|
||||||
CAPABILITY = 100
|
CAPABILITY = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
namespace osg {
|
namespace osg {
|
||||||
|
|
||||||
/** Encapsulates OpenGL texture buffer functionality.
|
/** Encapsulates OpenGL texture buffer functionality in a Texture delegating its content to attached BufferObject
|
||||||
*/
|
*/
|
||||||
class OSG_EXPORT TextureBuffer : public Texture
|
class OSG_EXPORT TextureBuffer : public Texture
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ class OSG_EXPORT TextureBuffer : public Texture
|
|||||||
|
|
||||||
TextureBuffer();
|
TextureBuffer();
|
||||||
|
|
||||||
TextureBuffer(Image* image);
|
TextureBuffer(BufferData* image);
|
||||||
|
|
||||||
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
|
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
|
||||||
TextureBuffer(const TextureBuffer& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
TextureBuffer(const TextureBuffer& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||||
@ -46,26 +46,25 @@ class OSG_EXPORT TextureBuffer : public Texture
|
|||||||
void setImage(Image* image);
|
void setImage(Image* image);
|
||||||
|
|
||||||
/** Gets the texture image. */
|
/** Gets the texture image. */
|
||||||
Image* getImage() { return _image.get(); }
|
Image* getImage() { return dynamic_cast<Image*>(_bufferData.get() ); }
|
||||||
|
|
||||||
/** Gets the const texture image. */
|
/** Gets the const texture image. */
|
||||||
inline const Image* getImage() const { return _image.get(); }
|
inline const Image* getImage() const { return dynamic_cast<Image*>(_bufferData.get() ); }
|
||||||
|
|
||||||
inline unsigned int& getModifiedCount(unsigned int contextID) const
|
inline unsigned int & getModifiedCount(unsigned int contextID) const
|
||||||
{
|
{
|
||||||
// get the modified count for the current contextID.
|
// get the modified count for the current contextID.
|
||||||
return _modifiedCount[contextID];
|
return _modifiedCount[contextID];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Sets the texture image, ignoring face. */
|
/** Sets the texture image, ignoring face. */
|
||||||
virtual void setImage(unsigned int, Image* image) { setImage(image); }
|
virtual void setImage(unsigned int, Image* image) { setImage(image); }
|
||||||
|
|
||||||
/** Gets the texture image, ignoring face. */
|
/** Gets the texture image, ignoring face. */
|
||||||
virtual Image* getImage(unsigned int) { return _image.get(); }
|
virtual Image* getImage(unsigned int) { return getImage(); }
|
||||||
|
|
||||||
/** Gets the const texture image, ignoring face. */
|
/** Gets the const texture image, ignoring face. */
|
||||||
virtual const Image* getImage(unsigned int) const { return _image.get(); }
|
virtual const Image* getImage(unsigned int) const { return getImage(); }
|
||||||
|
|
||||||
/** Gets the number of images that can be assigned to the Texture. */
|
/** Gets the number of images that can be assigned to the Texture. */
|
||||||
virtual unsigned int getNumImages() const { return 1; }
|
virtual unsigned int getNumImages() const { return 1; }
|
||||||
@ -80,58 +79,31 @@ class OSG_EXPORT TextureBuffer : public Texture
|
|||||||
virtual int getTextureHeight() const { return 1; }
|
virtual int getTextureHeight() const { return 1; }
|
||||||
virtual int getTextureDepth() const { return 1; }
|
virtual int getTextureDepth() const { return 1; }
|
||||||
|
|
||||||
inline void setUsageHint( GLenum usageHint ) { _usageHint=usageHint; }
|
|
||||||
inline GLenum getUsageHint() const { return _usageHint; }
|
|
||||||
|
|
||||||
virtual void allocateMipmap(State& /*state*/) const {};
|
virtual void allocateMipmap(State& /*state*/) const {};
|
||||||
|
|
||||||
/** Bind the texture buffer.*/
|
/** Bind the texture buffer.*/
|
||||||
virtual void apply(State& state) const;
|
virtual void apply(State& state) const;
|
||||||
|
|
||||||
/** Bind buffer to different target. */
|
/** Set setBufferData attached */
|
||||||
void bindBufferAs(unsigned int contextID, GLenum target);
|
void setBufferData(BufferData *bo);
|
||||||
void unbindBufferAs(unsigned int contextID, GLenum target);
|
|
||||||
|
|
||||||
|
/** Set setBufferData attached */
|
||||||
|
const BufferData * getBufferData()const {return _bufferData.get();}
|
||||||
protected :
|
protected :
|
||||||
|
|
||||||
virtual ~TextureBuffer();
|
virtual ~TextureBuffer();
|
||||||
|
|
||||||
virtual void computeInternalFormat() const;
|
virtual void computeInternalFormat() const;
|
||||||
|
|
||||||
ref_ptr<Image> _image;
|
ref_ptr< BufferData > _bufferData;
|
||||||
|
|
||||||
mutable GLsizei _textureWidth;
|
GLsizei _textureWidth;
|
||||||
GLenum _usageHint;
|
|
||||||
|
|
||||||
typedef buffered_value<unsigned int> ImageModifiedCount;
|
typedef buffered_value< unsigned int > BufferDataModifiedCount;
|
||||||
mutable ImageModifiedCount _modifiedCount;
|
mutable BufferDataModifiedCount _modifiedCount;
|
||||||
|
|
||||||
class TextureBufferObject : public osg::Referenced
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TextureBufferObject(unsigned int contextID, GLenum usageHint) :
|
|
||||||
_id(0),
|
|
||||||
_usageHint(usageHint)
|
|
||||||
{
|
|
||||||
_extensions = osg::GLExtensions::Get(contextID, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bindBuffer(GLenum target);
|
};
|
||||||
void unbindBuffer(GLenum target);
|
|
||||||
|
|
||||||
void texBuffer(GLenum internalFormat);
|
|
||||||
void bufferData( osg::Image* image );
|
|
||||||
void bufferSubData( osg::Image* image );
|
|
||||||
|
|
||||||
public:
|
|
||||||
GLuint _id;
|
|
||||||
GLenum _usageHint;
|
|
||||||
osg::GLExtensions* _extensions;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef osg::buffered_object<osg::ref_ptr<TextureBufferObject> > TextureBufferObjectList;
|
|
||||||
mutable TextureBufferObjectList _textureBufferObjects;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
#include <string.h> // for memcpy
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
|
#ifndef GL_DRAW_INDIRECT_BUFFER
|
||||||
|
#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace osg {
|
namespace osg {
|
||||||
|
|
||||||
@ -164,5 +167,33 @@ ShaderStorageBufferBinding::ShaderStorageBufferBinding(const ShaderStorageBuffer
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DrawIndirectBufferBinding::DrawIndirectBufferBinding( )
|
||||||
|
: BufferIndexBinding(GL_DRAW_INDIRECT_BUFFER, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void DrawIndirectBufferBinding::apply(State& state) const
|
||||||
|
{
|
||||||
|
if (_bufferObject.valid())
|
||||||
|
{
|
||||||
|
GLBufferObject* glObject
|
||||||
|
= _bufferObject->getOrCreateGLBufferObject(state.getContextID());
|
||||||
|
if (!glObject->_extensions->isUniformBufferObjectSupported)
|
||||||
|
return;
|
||||||
|
// if (glObject->isDirty()) glObject->compileBuffer();
|
||||||
|
glObject->_extensions->glBindBuffer (_target, glObject->getGLObjectID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawIndirectBufferBinding::DrawIndirectBufferBinding( BufferObject* bo)
|
||||||
|
: BufferIndexBinding(GL_DRAW_INDIRECT_BUFFER, 0, bo, 0, 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawIndirectBufferBinding::DrawIndirectBufferBinding(const DrawIndirectBufferBinding& rhs,
|
||||||
|
const CopyOp& copyop)
|
||||||
|
: BufferIndexBinding(rhs, copyop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace osg
|
} // namespace osg
|
||||||
|
@ -12,31 +12,65 @@
|
|||||||
*/
|
*/
|
||||||
#include <osg/TextureBuffer>
|
#include <osg/TextureBuffer>
|
||||||
#include <osg/State>
|
#include <osg/State>
|
||||||
|
#include <osg/PrimitiveSet>
|
||||||
|
|
||||||
|
#ifndef GL_TEXTURE_BUFFER
|
||||||
|
#define GL_TEXTURE_BUFFER 0x8C2A
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace osg;
|
using namespace osg;
|
||||||
|
|
||||||
TextureBuffer::TextureBuffer():
|
TextureBuffer::TextureBuffer():
|
||||||
_textureWidth(0), _usageHint(GL_STREAM_DRAW)
|
_textureWidth(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBuffer::TextureBuffer(osg::Image* image):
|
TextureBuffer::TextureBuffer(osg::BufferData* image):
|
||||||
_textureWidth(0), _usageHint(GL_STREAM_DRAW)
|
_textureWidth(0)
|
||||||
{
|
{
|
||||||
setImage(image);
|
setBufferData(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBuffer::TextureBuffer(const TextureBuffer& text,const CopyOp& copyop):
|
TextureBuffer::TextureBuffer(const TextureBuffer& text,const CopyOp& copyop):
|
||||||
Texture(text,copyop),
|
Texture(text,copyop),
|
||||||
_textureWidth(text._textureWidth),
|
_textureWidth(text._textureWidth)
|
||||||
_usageHint(text._usageHint)
|
|
||||||
{
|
{
|
||||||
setImage(copyop(text._image.get()));
|
setBufferData(osg::clone(text._bufferData.get(), copyop));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBuffer::~TextureBuffer()
|
TextureBuffer::~TextureBuffer()
|
||||||
{
|
{
|
||||||
setImage(NULL);
|
_bufferData=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureBuffer::setBufferData(BufferData *bufferdata)
|
||||||
|
{
|
||||||
|
if (_bufferData == bufferdata) return;
|
||||||
|
|
||||||
|
if (_bufferData.valid())
|
||||||
|
{
|
||||||
|
_bufferData->removeClient(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_bufferData=bufferdata;
|
||||||
|
_modifiedCount.setAllElementsTo(0);
|
||||||
|
|
||||||
|
|
||||||
|
if (_bufferData.valid())
|
||||||
|
{
|
||||||
|
_bufferData->addClient(this);
|
||||||
|
|
||||||
|
///set BufferObject if not setted by user
|
||||||
|
if(!_bufferData->getBufferObject())
|
||||||
|
{
|
||||||
|
VertexBufferObject* bo=new VertexBufferObject();
|
||||||
|
bo->setUsage(GL_STREAM_DRAW_ARB);
|
||||||
|
bufferdata->setBufferObject(bo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextureBuffer::compare(const StateAttribute& sa) const
|
int TextureBuffer::compare(const StateAttribute& sa) const
|
||||||
@ -45,13 +79,17 @@ int TextureBuffer::compare(const StateAttribute& sa) const
|
|||||||
// used by the COMPARE_StateAttribute_Parameter macros below.
|
// used by the COMPARE_StateAttribute_Parameter macros below.
|
||||||
COMPARE_StateAttribute_Types(TextureBuffer,sa)
|
COMPARE_StateAttribute_Types(TextureBuffer,sa)
|
||||||
|
|
||||||
if (_image!=rhs._image) // smart pointer comparison.
|
|
||||||
|
if (_bufferData!=rhs._bufferData) // smart pointer comparison.
|
||||||
{
|
{
|
||||||
if (_image.valid())
|
if (_bufferData.valid())
|
||||||
{
|
{
|
||||||
if (rhs._image.valid())
|
if (rhs._bufferData.valid())
|
||||||
{
|
{
|
||||||
int result = _image->compare(*rhs._image);
|
//int result = _bufferData->compare(*rhs._bufferData);
|
||||||
|
int result=0;
|
||||||
|
if(_bufferData.get()<rhs._bufferData.get())result=1;
|
||||||
|
if(_bufferData.get()>rhs._bufferData.get())result=-1;
|
||||||
if (result!=0) return result;
|
if (result!=0) return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -59,13 +97,13 @@ int TextureBuffer::compare(const StateAttribute& sa) const
|
|||||||
return 1; // valid lhs._image is greater than null.
|
return 1; // valid lhs._image is greater than null.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rhs._image.valid())
|
else if (rhs._bufferData.valid())
|
||||||
{
|
{
|
||||||
return -1; // valid rhs._image is greater than null.
|
return -1; // valid rhs._image is greater than null.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_image && !rhs._image)
|
if (!_bufferData && !rhs._bufferData)
|
||||||
{
|
{
|
||||||
int result = compareTextureObjects(rhs);
|
int result = compareTextureObjects(rhs);
|
||||||
if (result!=0) return result;
|
if (result!=0) return result;
|
||||||
@ -76,27 +114,19 @@ int TextureBuffer::compare(const StateAttribute& sa) const
|
|||||||
|
|
||||||
// compare each parameter in turn against the rhs.
|
// compare each parameter in turn against the rhs.
|
||||||
COMPARE_StateAttribute_Parameter(_textureWidth)
|
COMPARE_StateAttribute_Parameter(_textureWidth)
|
||||||
COMPARE_StateAttribute_Parameter(_usageHint)
|
//COMPARE_StateAttribute_Parameter(_usageHint)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuffer::setImage(Image* image)
|
void TextureBuffer::setImage(Image* image)
|
||||||
{
|
{
|
||||||
if (_image == image) return;
|
if (getImage() == image) return;
|
||||||
|
|
||||||
if (_image.valid())
|
setBufferData(image);
|
||||||
{
|
|
||||||
_image->removeClient(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_image = image;
|
|
||||||
_modifiedCount.setAllElementsTo(0);
|
|
||||||
|
|
||||||
if (_image.valid())
|
|
||||||
{
|
|
||||||
_image->addClient(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuffer::apply(State& state) const
|
void TextureBuffer::apply(State& state) const
|
||||||
@ -105,67 +135,93 @@ void TextureBuffer::apply(State& state) const
|
|||||||
const unsigned int contextID = state.getContextID();
|
const unsigned int contextID = state.getContextID();
|
||||||
|
|
||||||
TextureObject* textureObject = getTextureObject(contextID);
|
TextureObject* textureObject = getTextureObject(contextID);
|
||||||
TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get();
|
|
||||||
|
|
||||||
|
///This code could be usefull but would require to watch BufferData changes
|
||||||
|
///perhaps a mutable percontext dirtyflag (all reset to true onTextureObjectChanged) would do the trick
|
||||||
|
#if 0
|
||||||
|
if (textureObject)
|
||||||
|
{
|
||||||
|
bool textureObjectInvalidated = false;
|
||||||
|
if (textureObject->_profile._internalFormat != _internalFormat )
|
||||||
|
{
|
||||||
|
textureObjectInvalidated=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textureObjectInvalidated)
|
||||||
|
{
|
||||||
|
//OSG_NOTICE<<"Discarding TextureObject"<<std::endl;
|
||||||
|
_textureObjectBuffer[contextID]->release();
|
||||||
|
_textureObjectBuffer[contextID] = 0;
|
||||||
|
textureObject = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (textureObject)
|
if (textureObject)
|
||||||
{
|
{
|
||||||
if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
|
const GLExtensions* extensions = state.get<GLExtensions>();
|
||||||
|
if(_bufferData.valid() &&_modifiedCount[contextID]!=_bufferData->getModifiedCount() )
|
||||||
{
|
{
|
||||||
computeInternalFormat();
|
GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID);
|
||||||
textureBufferObject->bindBuffer(GL_TEXTURE_BUFFER);
|
if (glBufferObject)
|
||||||
textureBufferObject->bufferSubData(_image.get() );
|
{
|
||||||
textureBufferObject->unbindBuffer(GL_TEXTURE_BUFFER);
|
if( glBufferObject->isDirty() )
|
||||||
_modifiedCount[contextID] = _image->getModifiedCount();
|
{
|
||||||
|
//OSG_NOTICE<<"buffer upload"<<glBufferObject<<std::endl;
|
||||||
|
glBufferObject->compileBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_modifiedCount[contextID]=_bufferData->getModifiedCount() ;
|
||||||
}
|
}
|
||||||
textureObject->bind();
|
textureObject->bind();
|
||||||
|
|
||||||
if( getTextureParameterDirty(contextID) )
|
if( getTextureParameterDirty(contextID) )
|
||||||
{
|
{
|
||||||
const GLExtensions* extensions = state.get<GLExtensions>();
|
if( extensions->isBindImageTextureSupported() && _imageAttachment.access!=0 )
|
||||||
if (extensions->isBindImageTextureSupported() && _imageAttachment.access!=0)
|
|
||||||
{
|
{
|
||||||
extensions->glBindImageTexture(
|
|
||||||
_imageAttachment.unit, textureObject->id(), _imageAttachment.level,
|
|
||||||
_imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access,
|
|
||||||
_imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat);
|
|
||||||
}
|
|
||||||
getTextureParameterDirty(state.getContextID()) = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_image.valid() && _image->data())
|
|
||||||
{
|
|
||||||
textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER);
|
|
||||||
textureObject->bind();
|
|
||||||
|
|
||||||
textureBufferObject = new TextureBufferObject(contextID,_usageHint);
|
|
||||||
_textureBufferObjects[contextID] = textureBufferObject;
|
|
||||||
|
|
||||||
const GLExtensions* extensions = state.get<GLExtensions>();
|
|
||||||
if (extensions->isBindImageTextureSupported() && _imageAttachment.access!=0)
|
|
||||||
{
|
|
||||||
extensions->glBindImageTexture(
|
extensions->glBindImageTexture(
|
||||||
_imageAttachment.unit, textureObject->id(), _imageAttachment.level,
|
_imageAttachment.unit, textureObject->id(), _imageAttachment.level,
|
||||||
_imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access,
|
_imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access,
|
||||||
_imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat);
|
_imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat);
|
||||||
|
}
|
||||||
|
getTextureParameterDirty(state.getContextID()) = false;
|
||||||
}
|
}
|
||||||
getTextureParameterDirty(state.getContextID()) = false;
|
|
||||||
|
|
||||||
computeInternalFormat();
|
|
||||||
_textureWidth = _image->s();
|
|
||||||
textureBufferObject->bindBuffer(GL_TEXTURE_BUFFER);
|
|
||||||
textureBufferObject->bufferData( _image.get() );
|
|
||||||
textureObject->setAllocated(true);
|
|
||||||
textureBufferObject->unbindBuffer(GL_TEXTURE_BUFFER);
|
|
||||||
|
|
||||||
textureObject->bind();
|
|
||||||
textureBufferObject->texBuffer(_internalFormat);
|
|
||||||
|
|
||||||
_modifiedCount[contextID] = _image->getModifiedCount();
|
|
||||||
}
|
}
|
||||||
else
|
else if (_bufferData.valid() &&_bufferData->getBufferObject() )//&& _bufferObject->getNumBufferData()>0 )
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
/// now compile bufferobject if required
|
||||||
|
GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID);
|
||||||
|
if (glBufferObject )
|
||||||
|
{
|
||||||
|
const GLExtensions* extensions = state.get<GLExtensions>();
|
||||||
|
|
||||||
|
textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER);
|
||||||
|
textureObject->_profile._internalFormat=_internalFormat;
|
||||||
|
textureObject->bind();
|
||||||
|
|
||||||
|
if ( extensions->isBindImageTextureSupported() && _imageAttachment.access!=0 )
|
||||||
|
{
|
||||||
|
extensions->glBindImageTexture(
|
||||||
|
_imageAttachment.unit, textureObject->id(), _imageAttachment.level,
|
||||||
|
_imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access,
|
||||||
|
_imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat);
|
||||||
|
}
|
||||||
|
getTextureParameterDirty(state.getContextID()) = false;
|
||||||
|
|
||||||
|
computeInternalFormat();
|
||||||
|
|
||||||
|
if( glBufferObject->isDirty())
|
||||||
|
glBufferObject->compileBuffer();
|
||||||
|
|
||||||
|
textureObject->setAllocated(true);
|
||||||
|
extensions->glBindBuffer(_bufferData->getBufferObject()->getTarget(),0);
|
||||||
|
|
||||||
|
textureObject->bind();
|
||||||
|
extensions->glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, glBufferObject->getGLObjectID());
|
||||||
|
_modifiedCount[contextID] = _bufferData->getModifiedCount();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -173,49 +229,10 @@ void TextureBuffer::apply(State& state) const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuffer::bindBufferAs( unsigned int contextID, GLuint target )
|
|
||||||
{
|
|
||||||
TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get();
|
|
||||||
textureBufferObject->bindBuffer(target);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::unbindBufferAs( unsigned int contextID, GLuint target )
|
|
||||||
{
|
|
||||||
TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get();
|
|
||||||
textureBufferObject->unbindBuffer(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureBuffer::computeInternalFormat() const
|
void TextureBuffer::computeInternalFormat() const
|
||||||
{
|
{
|
||||||
if (_image.valid()) computeInternalFormatWithImage(*_image);
|
if (getImage() ) computeInternalFormatWithImage(*getImage());
|
||||||
else computeInternalFormatType();
|
else computeInternalFormatType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuffer::TextureBufferObject::bindBuffer(GLenum target)
|
|
||||||
{
|
|
||||||
if (_id == 0)
|
|
||||||
_extensions->glGenBuffers(1, &_id);
|
|
||||||
_extensions->glBindBuffer(target, _id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::TextureBufferObject::unbindBuffer(GLenum target)
|
|
||||||
{
|
|
||||||
_extensions->glBindBuffer(target, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::TextureBufferObject::texBuffer(GLenum internalFormat)
|
|
||||||
{
|
|
||||||
_extensions->glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, _id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::TextureBufferObject::bufferData( osg::Image* image )
|
|
||||||
{
|
|
||||||
_extensions->glBufferData(GL_TEXTURE_BUFFER, image->getTotalDataSize(), image->data(), _usageHint);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::TextureBufferObject::bufferSubData( osg::Image* image )
|
|
||||||
{
|
|
||||||
_extensions->glBufferSubData(GL_TEXTURE_BUFFER, 0, image->getTotalDataSize(), image->data());
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user