first commit for Indirect Draw integration in osg

users will have to implement interfaces for their custom drawcommandarrays
add a lot of new primitive set + few defines
integration is made in osggpucull
This commit is contained in:
mp3butcher
2017-07-26 20:25:41 +02:00
parent c32d3eb926
commit 5be14bc2ba
9 changed files with 1332 additions and 144 deletions

View File

@@ -1,13 +1,11 @@
SET(TARGET_SRC
ShapeToGeometry.cpp
DrawIndirectPrimitiveSet.cpp
AggregateGeometryVisitor.cpp
osggpucull.cpp
)
SET(TARGET_H
ShapeToGeometry.h
DrawIndirectPrimitiveSet.h
AggregateGeometryVisitor.h
GpuCullShaders.h
)

View File

@@ -1,41 +0,0 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield
* Copyright (C) 2014 Pawel Ksiezopolski
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*
*/
#include "DrawIndirectPrimitiveSet.h"
#include <osg/State>
#include <osg/buffered_value>
#include <osg/ref_ptr>
#include <osg/GLExtensions>
#include <osg/Drawable>
void DrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
{
// 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 )
// osg::Drawable::Extensions *dext = osg::Drawable::getExtensions( state.getContextID(),true );
// int* tab = (int*)dext->glMapBuffer(GL_DRAW_INDIRECT_BUFFER,GL_READ_ONLY);
// int val = _indirect/sizeof(int);
// OSG_WARN<<"DrawArraysIndirect ("<<val<<"): "<< tab[val] << " " << tab[val+1] << " " << tab[val+2] << " " << tab[val+3] << std::endl;
// dext->glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
state.get<osg::GLExtensions>()->glDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect) );
}
void MultiDrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const
{
// DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true );
state.get<osg::GLExtensions>()->glMultiDrawArraysIndirect( _mode, reinterpret_cast<const void*>(_indirect), _drawcount, _stride );
}

View File

@@ -1,63 +0,0 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield
* Copyright (C) 2014 Pawel Ksiezopolski
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*
*/
#ifndef OSG_DRAWINDIRECTPRIMITIVESET
#define OSG_DRAWINDIRECTPRIMITIVESET 1
#include <osg/PrimitiveSet>
#include <osg/BufferObject>
#include <osg/TextureBuffer>
class DrawArraysIndirect : public osg::DrawArrays
{
public:
DrawArraysIndirect(GLenum mode=0, unsigned int indirect=0)
: osg::DrawArrays(mode), _indirect(indirect)
{
}
virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); }
virtual osg::Object* clone(const osg::CopyOp& /*copyop*/) const { return NULL; }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const DrawArraysIndirect*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
virtual const char* className() const { return "DrawArraysIndirect"; }
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
protected:
unsigned int _indirect;
};
class MultiDrawArraysIndirect : public osg::DrawArrays
{
public:
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(); }
virtual osg::Object* clone(const osg::CopyOp& /*copyop*/) const { return NULL; }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MultiDrawArraysIndirect*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
virtual const char* className() const { return "MultiDrawArraysIndirect"; }
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
protected:
unsigned int _indirect;
GLsizei _drawcount;
GLsizei _stride;
};
#endif

View File

@@ -38,12 +38,14 @@
#include <osg/BufferTemplate>
#include "ShapeToGeometry.h"
#include "AggregateGeometryVisitor.h"
#if 0
#include "DrawIndirectPrimitiveSet.h"
#else
#include <osg/PrimitiveSetIndirect>
#endif
#include "GpuCullShaders.h"
#ifndef GL_RASTERIZER_DISCARD
#define GL_RASTERIZER_DISCARD 0x8C89
#endif
// each instance type may have max 8 LODs ( if you change
// this value, don't forget to change it in vertex shaders accordingly )
@@ -178,23 +180,20 @@ struct IndirectTarget
IndirectTarget()
: maxTargetQuantity(0)
{
indirectCommands = new osg::BufferTemplate< std::vector<DrawArraysIndirectCommand> >;
indirectCommands = new osg::DefaultIndirectCommandDrawArrays;
}
IndirectTarget( AggregateGeometryVisitor* agv, osg::Program* program )
: geometryAggregator(agv), drawProgram(program), maxTargetQuantity(0)
{
indirectCommands = new osg::BufferTemplate< std::vector<DrawArraysIndirectCommand> >;
indirectCommands = new osg::DefaultIndirectCommandDrawArrays;
}
void endRegister(unsigned int index, unsigned int rowsPerInstance, GLenum pixelFormat, GLenum type, GLint internalFormat, bool useMultiDrawArraysIndirect )
{
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 * indirectCommandbuffer=new osg::VertexBufferObject();
indirectCommandbuffer->setUsage(GL_DYNAMIC_DRAW);
indirectCommands->setBufferObject(indirectCommandbuffer);
osg::VertexBufferObject * indirectCommandImagebuffer=new osg::VertexBufferObject();
indirectCommandImagebuffer->setUsage(GL_DYNAMIC_DRAW);
indirectCommandImage->setBufferObject(indirectCommandImagebuffer);
indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommandImage);
indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommands);
indirectCommandTextureBuffer->setInternalFormat( GL_R32I );
indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE);
indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false);
@@ -203,28 +202,29 @@ struct IndirectTarget
// add proper primitivesets to geometryAggregators
if( !useMultiDrawArraysIndirect ) // use glDrawArraysIndirect()
{
std::vector<DrawArraysIndirect*> newPrimitiveSets;
std::vector<osg::DrawArraysIndirect*> newPrimitiveSets;
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, j*sizeof( DrawArraysIndirectCommand ) ) );
for(unsigned int j=0;j<indirectCommands->size(); ++j){
osg::DrawArraysIndirect *ipr=new osg::DrawArraysIndirect( GL_TRIANGLES, j );
ipr->setIndirectCommandDrawArrays( indirectCommands);
newPrimitiveSets.push_back(ipr);
}
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
for(unsigned int j=0;j<indirectCommands->getData().size(); ++j)
for(unsigned int j=0;j<indirectCommands->size(); ++j)
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( newPrimitiveSets[j] );
}
else // use glMultiDrawArraysIndirect()
{
osg::MultiDrawArraysIndirect *ipr=new osg::MultiDrawArraysIndirect( GL_TRIANGLES );
ipr->setIndirectCommandDrawArrays( indirectCommands );
geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() );
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( new MultiDrawArraysIndirect( GL_TRIANGLES, 0, indirectCommands->getData().size(), 0 ) );
geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( ipr );
}
///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);
@@ -268,7 +268,7 @@ struct IndirectTarget
stateset->setAttributeAndModes( drawProgram.get(), osg::StateAttribute::ON );
}
osg::ref_ptr< osg::BufferTemplate< std::vector<DrawArraysIndirectCommand> > > indirectCommands;
osg::ref_ptr< osg::DefaultIndirectCommandDrawArrays > indirectCommands;
osg::ref_ptr<osg::TextureBuffer> indirectCommandTextureBuffer;
osg::ref_ptr< AggregateGeometryVisitor > geometryAggregator;
osg::ref_ptr<osg::Program> drawProgram;
@@ -318,7 +318,7 @@ struct GPUCullData
// AggregateGeometryVisitor creates single osg::Geometry from all objects used by specific indirect target
AggregateGeometryVisitor::AddObjectResult aoResult = target->second.geometryAggregator->addObject( node , typeID, lodNumber );
// Information about first vertex and a number of vertices is stored for later primitiveset creation
target->second.indirectCommands->getData().push_back( DrawArraysIndirectCommand( aoResult.first, aoResult.count ) );
target->second.indirectCommands->push_back( osg::DrawArraysIndirectCommand( aoResult.count,1, aoResult.first ) );
osg::ComputeBoundsVisitor cbv;
node->accept(cbv);
@@ -360,10 +360,10 @@ struct GPUCullData
std::map<unsigned int, IndirectTarget>::iterator it,eit;
for(it=targets.begin(), eit=targets.end(); it!=eit; ++it)
{
for(unsigned j=0; j<it->second.indirectCommands->getData().size(); ++j)
for(unsigned j=0; j<it->second.indirectCommands->size(); ++j)
{
DrawArraysIndirectCommand& iComm = it->second.indirectCommands->getData().at(j);
OSG_INFO<<"("<<iComm.first<<" "<<iComm.primCount<<" "<<iComm.count<<") ";
osg::DrawArraysIndirectCommand& iComm = it->second.indirectCommands->at(j);
OSG_INFO<<"("<<iComm.first<<" "<<iComm.instanceCount<<" "<<iComm.count<<") ";
}
unsigned int sizeInBytes = (unsigned int ) it->second.maxTargetQuantity * sizeof(osg::Vec4);
OSG_INFO<<" => Maximum elements in target : "<< it->second.maxTargetQuantity <<" ( "<< sizeInBytes <<" bytes, " << sizeInBytes/1024<< " kB )" << std::endl;
@@ -724,16 +724,16 @@ struct ResetTexturesCallback : public osg::StateSet::Callback
std::vector<unsigned int>::iterator it,eit;
for(it=texUnitsDirty.begin(), eit=texUnitsDirty.end(); it!=eit; ++it)
{
osg::Texture* tex = dynamic_cast<osg::Texture*>( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) );
osg::TextureBuffer* tex = dynamic_cast<osg::TextureBuffer*>( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) );
if(tex==NULL)
continue;
osg::Image* img = tex->getImage(0);
osg::BufferData* img =const_cast<osg::BufferData*>(tex->getBufferData());
if(img!=NULL)
img->dirty();
}
for(it=texUnitsDirtyParams.begin(), eit=texUnitsDirtyParams.end(); it!=eit; ++it)
{
osg::Texture* tex = dynamic_cast<osg::Texture*>( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) );
osg::TextureBuffer* tex = dynamic_cast<osg::TextureBuffer*>( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) );
if(tex!=NULL)
tex->dirtyTextureParameters();
}