diff --git a/examples/osggpucull/CMakeLists.txt b/examples/osggpucull/CMakeLists.txt index 11d3b0463..6cfe7a646 100644 --- a/examples/osggpucull/CMakeLists.txt +++ b/examples/osggpucull/CMakeLists.txt @@ -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 ) diff --git a/examples/osggpucull/DrawIndirectPrimitiveSet.cpp b/examples/osggpucull/DrawIndirectPrimitiveSet.cpp deleted file mode 100644 index bbb5ff45b..000000000 --- a/examples/osggpucull/DrawIndirectPrimitiveSet.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include - -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 ("<glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); - - state.get()->glDrawArraysIndirect( _mode, reinterpret_cast(_indirect) ); - -} - -void MultiDrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const -{ - // DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true ); - state.get()->glMultiDrawArraysIndirect( _mode, reinterpret_cast(_indirect), _drawcount, _stride ); -} diff --git a/examples/osggpucull/DrawIndirectPrimitiveSet.h b/examples/osggpucull/DrawIndirectPrimitiveSet.h deleted file mode 100644 index 8a6c7b777..000000000 --- a/examples/osggpucull/DrawIndirectPrimitiveSet.h +++ /dev/null @@ -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 -#include -#include - - -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(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(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 diff --git a/examples/osggpucull/osggpucull.cpp b/examples/osggpucull/osggpucull.cpp index b091a4921..52d272db5 100644 --- a/examples/osggpucull/osggpucull.cpp +++ b/examples/osggpucull/osggpucull.cpp @@ -38,12 +38,14 @@ #include #include "ShapeToGeometry.h" #include "AggregateGeometryVisitor.h" +#if 0 #include "DrawIndirectPrimitiveSet.h" +#else +#include +#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 >; + indirectCommands = new osg::DefaultIndirectCommandDrawArrays; } IndirectTarget( AggregateGeometryVisitor* agv, osg::Program* program ) : geometryAggregator(agv), drawProgram(program), maxTargetQuantity(0) { - indirectCommands = new osg::BufferTemplate< std::vector >; + 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 newPrimitiveSets; + std::vector newPrimitiveSets; - for(unsigned int j=0;jgetData().size(); ++j) - newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, j*sizeof( DrawArraysIndirectCommand ) ) ); + for(unsigned int j=0;jsize(); ++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;jgetData().size(); ++j) + for(unsigned int j=0;jsize(); ++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 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 > > indirectCommands; + osg::ref_ptr< osg::DefaultIndirectCommandDrawArrays > indirectCommands; osg::ref_ptr indirectCommandTextureBuffer; osg::ref_ptr< AggregateGeometryVisitor > geometryAggregator; osg::ref_ptr 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::iterator it,eit; for(it=targets.begin(), eit=targets.end(); it!=eit; ++it) { - for(unsigned j=0; jsecond.indirectCommands->getData().size(); ++j) + for(unsigned j=0; jsecond.indirectCommands->size(); ++j) { - DrawArraysIndirectCommand& iComm = it->second.indirectCommands->getData().at(j); - OSG_INFO<<"("<second.indirectCommands->at(j); + OSG_INFO<<"("<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::iterator it,eit; for(it=texUnitsDirty.begin(), eit=texUnitsDirty.end(); it!=eit; ++it) { - osg::Texture* tex = dynamic_cast( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) ); + osg::TextureBuffer* tex = dynamic_cast( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) ); if(tex==NULL) continue; - osg::Image* img = tex->getImage(0); + osg::BufferData* img =const_cast(tex->getBufferData()); if(img!=NULL) img->dirty(); } for(it=texUnitsDirtyParams.begin(), eit=texUnitsDirtyParams.end(); it!=eit; ++it) { - osg::Texture* tex = dynamic_cast( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) ); + osg::TextureBuffer* tex = dynamic_cast( stateset->getTextureAttribute(*it,osg::StateAttribute::TEXTURE) ); if(tex!=NULL) tex->dirtyTextureParameters(); } diff --git a/include/osg/GLDefines b/include/osg/GLDefines index bebce6656..7efd433e4 100644 --- a/include/osg/GLDefines +++ b/include/osg/GLDefines @@ -435,6 +435,8 @@ typedef char GLchar; #define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D #define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E #define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 #endif // ARB_shader_atomic_counters @@ -556,14 +558,14 @@ typedef char GLchar; #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 #endif -#define GL_INT64_ARB 0x140E -#define GL_UNSIGNED_INT64_ARB 0x140F -#define GL_INT64_VEC2_ARB 0x8FE9 -#define GL_INT64_VEC3_ARB 0x8FEA -#define GL_INT64_VEC4_ARB 0x8FEB -#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 -#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 -#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 +#define GL_INT64_ARB 0x140E +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 /* ------------------------------ GL_KHR_debug ----------------------------- */ #ifndef GL_KHR_debug #define GL_KHR_debug 1 diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index aee28712b..0524de177 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -133,7 +133,15 @@ class OSG_EXPORT PrimitiveSet : public BufferData DrawElementsUBytePrimitiveType, DrawElementsUShortPrimitiveType, DrawElementsUIntPrimitiveType, - MultiDrawArraysPrimitiveType + MultiDrawArraysPrimitiveType, + DrawArraysIndirectPrimitiveType, + DrawElementsUByteIndirectPrimitiveType, + DrawElementsUShortIndirectPrimitiveType, + DrawElementsUIntIndirectPrimitiveType, + MultiDrawArraysIndirectPrimitiveType, + MultiDrawElementsUByteIndirectPrimitiveType, + MultiDrawElementsUShortIndirectPrimitiveType, + MultiDrawElementsUIntIndirectPrimitiveType }; enum Mode diff --git a/include/osg/PrimitiveSetIndirect b/include/osg/PrimitiveSetIndirect new file mode 100644 index 000000000..dcb608af7 --- /dev/null +++ b/include/osg/PrimitiveSetIndirect @@ -0,0 +1,697 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * 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. + * + * osg/PrimitiveSetIndirect + * Author: Julien Valentin 2016-2017 +*/ + +#ifndef OSG_INDIRECTPRIMITIVESET +#define OSG_INDIRECTPRIMITIVESET 1 + +#include + + +namespace osg { +///common interface for IndirectCommandDrawArrayss +class OSG_EXPORT IndirectCommandDrawArrays: public BufferData +{ +public: + IndirectCommandDrawArrays():BufferData(){} + IndirectCommandDrawArrays(const IndirectCommandDrawArrays& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) + :BufferData(copy, copyop){ } + + virtual unsigned int & count(const unsigned int&index)=0; + virtual unsigned int & instanceCount(const unsigned int&index)=0; + virtual unsigned int & first(const unsigned int&index)=0; + virtual unsigned int & baseInstance(const unsigned int&index)=0; + + virtual unsigned int getElementSize() const = 0; + virtual unsigned int getNumElements() const = 0; +}; +class OSG_EXPORT IndirectCommandDrawElements: public BufferData +{ +public: + IndirectCommandDrawElements():BufferData(){} + IndirectCommandDrawElements(const IndirectCommandDrawElements& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) + :BufferData(copy, copyop){} + + virtual unsigned int & count(const unsigned int&index)=0; + virtual unsigned int & instanceCount(const unsigned int&index)=0; + virtual unsigned int & firstIndex(const unsigned int&index)=0; + virtual unsigned int & baseVertex(const unsigned int&index)=0; + virtual unsigned int & baseInstance(const unsigned int&index)=0; + + virtual unsigned int getElementSize()const = 0; + virtual unsigned int getNumElements() const = 0; + +}; + + + +/// DrawArraysCommand +struct DrawArraysIndirectCommand { + DrawArraysIndirectCommand(unsigned int pcount = 0, unsigned int pinstanceCount = 0, unsigned int pfirst = 0, unsigned int pbaseInstance = 0) + :count(pcount), instanceCount(pinstanceCount), first(pfirst), baseInstance(pbaseInstance){}; + unsigned int count; + unsigned int instanceCount; + unsigned int first; + unsigned int baseInstance; +}; + +/// default implementation of IndirectCommandDrawArrays +/// DefaultIndirectCommandDrawArrays to be hosted on GPU +class OSG_EXPORT DefaultIndirectCommandDrawArrays: public IndirectCommandDrawArrays, public MixinVector +{ +public: + META_Object(osg,DefaultIndirectCommandDrawArrays) + + DefaultIndirectCommandDrawArrays():IndirectCommandDrawArrays(), MixinVector() {} + DefaultIndirectCommandDrawArrays(const DefaultIndirectCommandDrawArrays& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) + :IndirectCommandDrawArrays(copy, copyop),MixinVector() {} + + virtual const GLvoid* getDataPointer() const { + return empty()?0:&front(); + } + virtual unsigned int getTotalDataSize() const { + return 16u*static_cast(size()); + } + virtual unsigned int getElementSize()const {return 16u;}; + virtual unsigned int & count(const unsigned int&index){return at(index).count;} + virtual unsigned int & instanceCount(const unsigned int&index){return at(index).instanceCount;} + virtual unsigned int & first(const unsigned int&index){return at(index).first;} + virtual unsigned int & baseInstance(const unsigned int&index){return at(index).baseInstance;} + virtual unsigned int getNumElements() const {return static_cast(size());} +}; + + +/// default implementation of IndirectCommandDrawElements +/// DrawElementsCommand +struct DrawElementsIndirectCommand{ + DrawElementsIndirectCommand(unsigned int pcount = 0, unsigned int pinstanceCount = 0, unsigned int pfirstIndex = 0, unsigned int pbaseVertex = 0, unsigned int pbaseInstance = 0) + :count(pcount), instanceCount(pinstanceCount), firstIndex(pfirstIndex), baseVertex(pbaseVertex), baseInstance(pbaseInstance){}; + unsigned int count; + unsigned int instanceCount; + unsigned int firstIndex; + unsigned int baseVertex; + unsigned int baseInstance; +}; + +/// vector of DrawElementsCommand to be hosted on GPU +class OSG_EXPORT DefaultIndirectCommandDrawElements: public IndirectCommandDrawElements, public MixinVector +{ +public: + META_Object(osg,DefaultIndirectCommandDrawElements) + DefaultIndirectCommandDrawElements():IndirectCommandDrawElements(), MixinVector() {} + DefaultIndirectCommandDrawElements(const DefaultIndirectCommandDrawElements& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) + :IndirectCommandDrawElements(copy, copyop), MixinVector(){} + virtual const GLvoid* getDataPointer() const { + return empty()?0:&front(); + } + virtual unsigned int getTotalDataSize() const { + return 20u*static_cast(size()); + } + + virtual unsigned int getElementSize()const {return 20u;}; + virtual unsigned int & count(const unsigned int&index){return at(index).count;} + virtual unsigned int & instanceCount(const unsigned int&index){return at(index).instanceCount;} + virtual unsigned int & firstIndex(const unsigned int&index){return at(index).firstIndex;} + virtual unsigned int & baseVertex(const unsigned int&index){return at(index).baseVertex;} + virtual unsigned int & baseInstance(const unsigned int&index){return at(index).baseInstance;} + virtual unsigned int getNumElements() const {return static_cast(size());} +}; + +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The DrawElementsIndirect base PrimitiveSet +/// +class OSG_EXPORT DrawElementsIndirect : public DrawElements +{ +public: + + DrawElementsIndirect(Type primType=PrimitiveType, GLenum mode = 0,unsigned int firstCommand = 0, GLsizei stride = 0): + DrawElements(primType,mode, 0),_firstCommand(firstCommand),_stride(stride){setIndirectCommandDrawArrays(new DefaultIndirectCommandDrawElements());} + + DrawElementsIndirect(const DrawElementsIndirect& rhs,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElements(rhs,copyop),_firstCommand(rhs._firstCommand), _stride(rhs._stride) { + _IndirectCommandDrawArrays=(DefaultIndirectCommandDrawElements*)copyop(rhs._IndirectCommandDrawArrays.get()); + } + /// set command array of this indirect primitive set + inline void setIndirectCommandDrawArrays(IndirectCommandDrawElements*idc) { + _IndirectCommandDrawArrays = idc; + if(!_IndirectCommandDrawArrays->getBufferObject()) + _IndirectCommandDrawArrays->setBufferObject(new osg::VertexBufferObject()); + } + /// get command array of this indirect primitive set + inline IndirectCommandDrawElements* getIndirectCommandDrawArrays()const { + return _IndirectCommandDrawArrays; + } + ///Further methods are for advanced DI when you plan to use your own IndirectCommandElement (stride) + ///or if you want to draw a particular command index of the IndirectCommandElement(FirstCommandToDraw) + + /// set offset of the first command to draw in the IndirectCommandDrawArrays + inline void setFirstCommandToDraw( unsigned int i) { + _firstCommand=i; + } + /// get offset of the first command in the IndirectCommandDrawArrays + inline unsigned int getFirstCommandToDraw()const { + return _firstCommand; + } + /// stride (to set if you use custom CommandArray) + inline void setStride( GLsizei i) { + _stride=i; + } + /// stride (to set if you use custom CommandArray) + inline GLsizei getStride()const { + return _stride; + } + virtual unsigned int getNumPrimitives() const=0; + +protected: + virtual ~DrawElementsIndirect() {} + + unsigned int _firstCommand; + GLsizei _stride; + ref_ptr _IndirectCommandDrawArrays; + +}; +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The DrawElementsIndirectUByte PrimitiveSet +/// +class OSG_EXPORT DrawElementsIndirectUByte : public DrawElementsIndirect, public VectorGLubyte +{ +public: + + typedef VectorGLubyte vector_type; + + DrawElementsIndirectUByte(GLenum mode = 0,unsigned int firstCommand = 0, GLsizei stride = 0): + DrawElementsIndirect(DrawElementsUByteIndirectPrimitiveType,mode,firstCommand,stride) {} + + DrawElementsIndirectUByte(const DrawElementsIndirectUByte& array, const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirect(array,copyop), + vector_type(array) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + * \param ptr Pointer to a GLubyte to copy index data from. + */ + DrawElementsIndirectUByte(GLenum mode, unsigned int no, const GLubyte* ptr) : + DrawElementsIndirect(MultiDrawElementsUByteIndirectPrimitiveType,mode), + vector_type(ptr,ptr+no) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + */ + DrawElementsIndirectUByte(GLenum mode, unsigned int no) : + DrawElementsIndirect(MultiDrawElementsUByteIndirectPrimitiveType,mode), + vector_type(no) {} + + virtual Object* cloneType() const { + return new DrawElementsIndirectUByte(); + } + virtual Object* clone(const CopyOp& copyop) const { + return new DrawElementsIndirectUByte(*this,copyop); + } + virtual bool isSameKindAs(const Object* obj) const { + return dynamic_cast(obj)!=NULL; + } + virtual const char* libraryName() const { + return "osg"; + } + virtual const char* className() const { + return "DrawElementsIndirectUByte"; + } + + virtual const GLvoid* getDataPointer() const { + return empty()?0:&front(); + } + virtual unsigned int getTotalDataSize() const { + return static_cast(size()); + } + virtual bool supportsBufferObject() const { + return false; + } + + virtual void draw(State& state, bool useVertexBufferObjects) const; + + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + + virtual unsigned int getNumIndices() const { + return static_cast(size()); + } + virtual unsigned int index(unsigned int pos) const { + return (*this)[pos]; + } + virtual void offsetIndices(int offset); + + virtual GLenum getDataType() { + return GL_UNSIGNED_BYTE; + } + virtual void resizeElements(unsigned int numIndices) { + resize(numIndices); + } + virtual void reserveElements(unsigned int numIndices) { + reserve(numIndices); + } + virtual void setElement(unsigned int i, unsigned int v) { + (*this)[i] = v; + } + virtual unsigned int getElement(unsigned int i) { + return (*this)[i]; + } + virtual void addElement(unsigned int v) { + push_back(GLubyte(v)); + } + virtual unsigned int getNumPrimitives() const; +protected: + + virtual ~DrawElementsIndirectUByte(); +}; + + +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The DrawElementsIndirectUShort PrimitiveSet +/// +class OSG_EXPORT DrawElementsIndirectUShort : public DrawElementsIndirect, public VectorGLushort +{ +public: + + typedef VectorGLushort vector_type; + + DrawElementsIndirectUShort(GLenum mode = 0,unsigned int firstCommand = 0, GLsizei stride = 0): + DrawElementsIndirect(DrawElementsUShortIndirectPrimitiveType,mode,firstCommand,stride) {} + + DrawElementsIndirectUShort(const DrawElementsIndirectUShort& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirect(array,copyop), + vector_type(array) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + * \param ptr Pointer to a GLushort to copy index data from. + */ + DrawElementsIndirectUShort(GLenum mode, unsigned int no, const GLushort* ptr) : + DrawElementsIndirect(MultiDrawElementsUShortIndirectPrimitiveType,mode), + vector_type(ptr,ptr+no) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + */ + DrawElementsIndirectUShort(GLenum mode, unsigned int no) : + DrawElementsIndirect(MultiDrawElementsUShortIndirectPrimitiveType,mode), + vector_type(no) {} + + template + DrawElementsIndirectUShort(GLenum mode, InputIterator first,InputIterator last) : + DrawElementsIndirect(MultiDrawElementsUShortIndirectPrimitiveType,mode), + vector_type(first,last) {} + + virtual Object* cloneType() const { + return new DrawElementsIndirectUShort(); + } + virtual Object* clone(const CopyOp& copyop) const { + return new DrawElementsIndirectUShort(*this,copyop); + } + virtual bool isSameKindAs(const Object* obj) const { + return dynamic_cast(obj)!=NULL; + } + virtual const char* libraryName() const { + return "osg"; + } + virtual const char* className() const { + return "DrawElementsIndirectUShort"; + } + + virtual const GLvoid* getDataPointer() const { + return empty()?0:&front(); + } + virtual unsigned int getTotalDataSize() const { + return 2u*static_cast(size()); + } + virtual bool supportsBufferObject() const { + return false; + } + + virtual void draw(State& state, bool useVertexBufferObjects) const; + + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + + virtual unsigned int getNumIndices() const { + return static_cast(size()); + } + virtual unsigned int index(unsigned int pos) const { + return (*this)[pos]; + } + virtual void offsetIndices(int offset); + + virtual GLenum getDataType() { + return GL_UNSIGNED_SHORT; + } + virtual void resizeElements(unsigned int numIndices) { + resize(numIndices); + } + virtual void reserveElements(unsigned int numIndices) { + reserve(numIndices); + } + virtual void setElement(unsigned int i, unsigned int v) { + (*this)[i] = v; + } + virtual unsigned int getElement(unsigned int i) { + return (*this)[i]; + } + virtual void addElement(unsigned int v) { + push_back(GLushort(v)); + } + virtual unsigned int getNumPrimitives() const; +protected: + + virtual ~DrawElementsIndirectUShort(); +}; + +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The DrawElementsIndirectUInt PrimitiveSet +/// +class OSG_EXPORT DrawElementsIndirectUInt : public DrawElementsIndirect, public VectorGLuint +{ +public: + + typedef VectorGLuint vector_type; + + DrawElementsIndirectUInt(GLenum mode = 0,unsigned int firstCommand = 0, GLsizei stride = 0): + DrawElementsIndirect(DrawElementsUIntIndirectPrimitiveType,mode,firstCommand,stride) {} + + DrawElementsIndirectUInt(const DrawElementsIndirectUInt& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirect(array,copyop), + vector_type(array) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + * \param ptr Pointer to a GLunsigned int to copy index data from. + */ + DrawElementsIndirectUInt(GLenum mode, unsigned int no, const GLuint* ptr) : + DrawElementsIndirect(DrawElementsUIntIndirectPrimitiveType,mode), + vector_type(ptr,ptr+no) {} + + /** + * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. + * \param no Number of intended elements. This will be the size of the underlying vector. + */ + DrawElementsIndirectUInt(GLenum mode, unsigned int no) : + DrawElementsIndirect(MultiDrawElementsUIntIndirectPrimitiveType,mode), + vector_type(no) {} + + template + DrawElementsIndirectUInt(GLenum mode, InputIterator first,InputIterator last) : + DrawElementsIndirect(MultiDrawElementsUIntIndirectPrimitiveType,mode), + vector_type(first,last) {} + + virtual Object* cloneType() const { + return new DrawElementsIndirectUInt(); + } + virtual Object* clone(const CopyOp& copyop) const { + return new DrawElementsIndirectUInt(*this,copyop); + } + virtual bool isSameKindAs(const Object* obj) const { + return dynamic_cast(obj)!=NULL; + } + virtual const char* libraryName() const { + return "osg"; + } + virtual const char* className() const { + return "DrawElementsIndirectUInt"; + } + + virtual const GLvoid* getDataPointer() const { + return empty()?0:&front(); + } + virtual unsigned int getTotalDataSize() const { + return 4u*static_cast(size()); + } + virtual bool supportsBufferObject() const { + return false; + } + + virtual void draw(State& state, bool useVertexBufferObjects) const; + + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + + virtual unsigned int getNumIndices() const { + return static_cast(size()); + } + virtual unsigned int index(unsigned int pos) const { + return (*this)[pos]; + } + virtual void offsetIndices(int offset); + + virtual GLenum getDataType() { + return GL_UNSIGNED_INT; + } + virtual void resizeElements(unsigned int numIndices) { + resize(numIndices); + } + virtual void reserveElements(unsigned int numIndices) { + reserve(numIndices); + } + virtual void setElement(unsigned int i, unsigned int v) { + (*this)[i] = v; + } + virtual unsigned int getElement(unsigned int i) { + return (*this)[i]; + } + virtual void addElement(unsigned int v) { + push_back(GLuint(v)); + } + + virtual unsigned int getNumPrimitives() const; +protected: + + virtual ~DrawElementsIndirectUInt(); +}; +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The MultiDrawElementsIndirect PrimitiveSets +/// +class OSG_EXPORT MultiDrawElementsIndirectUShort : public DrawElementsIndirectUShort +{ +public: + MultiDrawElementsIndirectUShort(GLenum mode = 0,unsigned int firstCommand = 0,unsigned int commandcount = 0, GLsizei stride = 0): + DrawElementsIndirectUShort(mode,firstCommand,stride),_count(commandcount){_primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType));} + MultiDrawElementsIndirectUShort(const MultiDrawElementsIndirectUShort& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirectUShort(mdi,copyop),_count(mdi._count) {} + + virtual void draw(State& state, bool useVertexBufferObjects) const; + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + virtual unsigned int getNumPrimitives() const; + + ///if you want to draw a subset of the IndirectCommandElement(FirstCommandToDraw,NumCommandsToDraw) + + /// count of Indirect Command to execute + inline void setNumCommandsToDraw( unsigned int i) { + _count=i; + } + /// count of Indirect Command to execute + inline unsigned int getNumCommandsToDraw()const { + return _count; + } +protected: + unsigned int _count; + virtual ~MultiDrawElementsIndirectUShort(); +}; + +class OSG_EXPORT MultiDrawElementsIndirectUByte : public DrawElementsIndirectUByte +{ +public: + MultiDrawElementsIndirectUByte(GLenum mode = 0,unsigned int firstCommand = 0,unsigned int commandcount = 0, GLsizei stride = 0): + DrawElementsIndirectUByte(mode,firstCommand,stride),_count(commandcount){_primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType));} + MultiDrawElementsIndirectUByte(const MultiDrawElementsIndirectUByte& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirectUByte(mdi,copyop),_count(mdi._count) {} + virtual void draw(State& state, bool useVertexBufferObjects) const; + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + virtual unsigned int getNumPrimitives() const; + /// count of Indirect Command to execute + inline void setNumCommandsToDraw( unsigned int i) { + _count=i; + } + /// count of Indirect Command to execute + inline unsigned int getNumCommandsToDraw()const { + return _count; + } +protected: + unsigned int _count; + virtual ~MultiDrawElementsIndirectUByte(); +}; +class OSG_EXPORT MultiDrawElementsIndirectUInt : public DrawElementsIndirectUInt +{ +public: + MultiDrawElementsIndirectUInt(GLenum mode = 0,unsigned int firstCommand = 0,unsigned int commandcount = 0, GLsizei stride = 0): + DrawElementsIndirectUInt(mode,firstCommand,stride),_count(commandcount){_primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType));} + MultiDrawElementsIndirectUInt(const MultiDrawElementsIndirectUInt& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawElementsIndirectUInt(mdi,copyop),_count(mdi._count) {} + + virtual void draw(State& state, bool useVertexBufferObjects) const; + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + virtual unsigned int getNumPrimitives() const; + /// count of Indirect Command to execute + inline void setNumCommandsToDraw( unsigned int i) { + _count=i; + } + /// count of Indirect Command to execute + inline unsigned int getNumCommandsToDraw()const { + return _count; + } +protected: + unsigned int _count; + virtual ~MultiDrawElementsIndirectUInt(); +}; +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The MultiDrawArraysIndirect PrimitiveSet +/// +class OSG_EXPORT DrawArraysIndirect : public osg::PrimitiveSet +{ +public: + + DrawArraysIndirect(GLenum mode=0, unsigned int firstcommand = 0, GLsizei stride = 0): + osg::PrimitiveSet(Type(DrawArraysIndirectPrimitiveType), mode), + _firstCommand(firstcommand), _stride(stride) {setIndirectCommandDrawArrays(new DefaultIndirectCommandDrawArrays);} + + DrawArraysIndirect(const DrawArraysIndirect& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + osg::PrimitiveSet(dal,copyop), + _firstCommand(dal._firstCommand), + _stride(dal._stride), + _IndirectCommandDrawArrays((DefaultIndirectCommandDrawArrays*)copyop( dal._IndirectCommandDrawArrays.get())) + {} + + virtual osg::Object* cloneType() const { + return new DrawArraysIndirect(); + } + virtual osg::Object* clone(const osg::CopyOp& copyop) const { + return new DrawArraysIndirect(*this,copyop); + } + virtual bool isSameKindAs(const osg::Object* obj) const { + return dynamic_cast(obj)!=NULL; + } + virtual const char* libraryName() const { + return "osg"; + } + virtual const char* className() const { + return "DrawArraysIndirect"; + } + + virtual void draw(State& state, bool useVertexBufferObjects) const; + + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + + virtual unsigned int getNumIndices() const; + virtual unsigned int index(unsigned int pos) const; + virtual void offsetIndices(int offset); + + virtual unsigned int getNumPrimitives() const; + + /// stride (to set if you use custom CommandArray) + inline void setStride( GLsizei i) { + _stride=i; + } + /// stride (to set if you use custom CommandArray) + inline GLsizei getStride()const { + return _stride; + } + /// set offset of the first command in the IndirectCommandDrawArrays + inline void setFirstCommand( unsigned int i) { + _firstCommand=i; + } + /// get offset of the first command in the IndirectCommandDrawArrays + inline unsigned int getFirstCommand()const { + return _firstCommand; + } + + inline void setIndirectCommandDrawArrays(IndirectCommandDrawArrays*idc) { + _IndirectCommandDrawArrays = idc; + if(!_IndirectCommandDrawArrays->getBufferObject()) + _IndirectCommandDrawArrays->setBufferObject(new osg::VertexBufferObject()); + } + inline IndirectCommandDrawArrays* getIndirectCommandDrawArrays()const { + return _IndirectCommandDrawArrays; + } + +protected: + + unsigned int _firstCommand; + GLsizei _stride; + ref_ptr _IndirectCommandDrawArrays; + +}; + +/////////////////////////////////////////////////////////////////////////////////////// +/// \brief The MultiDrawArraysIndirect PrimitiveSet +/// +class OSG_EXPORT MultiDrawArraysIndirect : public DrawArraysIndirect +{ +public: + + MultiDrawArraysIndirect(GLenum mode=0, unsigned int firstcommand = 0, unsigned int count = 0, GLsizei stride = 0): + osg::DrawArraysIndirect(mode, firstcommand, stride), _count(count) + {_primitiveType=Type(MultiDrawArraysIndirectPrimitiveType);} + + MultiDrawArraysIndirect(const MultiDrawArraysIndirect& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + osg::DrawArraysIndirect(dal,copyop), _count(dal._count) + {} + + virtual osg::Object* cloneType() const { + return new MultiDrawArraysIndirect(); + } + virtual osg::Object* clone(const osg::CopyOp& copyop) const { + return new MultiDrawArraysIndirect(*this,copyop); + } + virtual bool isSameKindAs(const osg::Object* obj) const { + return dynamic_cast(obj)!=NULL; + } + + virtual const char* className() const { + return "MultiDrawArraysIndirect"; + } + + virtual void draw(State& state, bool useVertexBufferObjects) const; + + virtual void accept(PrimitiveFunctor& functor) const; + virtual void accept(PrimitiveIndexFunctor& functor) const; + + virtual unsigned int getNumIndices() const; + virtual unsigned int index(unsigned int pos) const; + virtual void offsetIndices(int offset); + + virtual unsigned int getNumPrimitives() const; + + /// count of Indirect Command to execute + inline void setNumCommandsToDraw( unsigned int i) { + _count=i; + } + /// count of Indirect Command to execute + inline unsigned int getNumCommandsToDraw()const { + return _count; + } +protected: + unsigned int _count; + +}; + +} + +#endif + diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index aa1561869..845306551 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -136,6 +136,7 @@ SET(TARGET_H ${HEADER_PATH}/Polytope ${HEADER_PATH}/PositionAttitudeTransform ${HEADER_PATH}/PrimitiveSet + ${HEADER_PATH}/PrimitiveSetIndirect ${HEADER_PATH}/PrimitiveRestartIndex ${HEADER_PATH}/Program ${HEADER_PATH}/Projection @@ -342,6 +343,7 @@ SET(TARGET_SRC Polytope.cpp PositionAttitudeTransform.cpp PrimitiveSet.cpp + PrimitiveSetIndirect.cpp PrimitiveRestartIndex.cpp Program.cpp Projection.cpp diff --git a/src/osg/PrimitiveSetIndirect.cpp b/src/osg/PrimitiveSetIndirect.cpp new file mode 100644 index 000000000..d3b10e585 --- /dev/null +++ b/src/osg/PrimitiveSetIndirect.cpp @@ -0,0 +1,585 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * 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. + * + * osg/PrimitiveSetIndirect.cpp + * Author: Julien Valentin 2016-2017 +*/ + +#include +#include +#include +#include +#include + +using namespace osg; +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// DrawElementsIndirect +// +template inline +unsigned int getNumPrimitivesDI( const T&_this) +{ + unsigned int offset= _this.getFirstCommandToDraw(); + IndirectCommandDrawElements *cmd=_this.getIndirectCommandDrawArrays(); + unsigned int total=0; + switch(_this.getMode()) + { + case(PrimitiveSet::POINTS): + return cmd->count(offset); + case(PrimitiveSet::LINES): + return cmd->count(offset)/2; + case(PrimitiveSet::TRIANGLES): + return cmd->count(offset)/3; + case(PrimitiveSet::QUADS): + return cmd->count(offset)/4; + case(PrimitiveSet::LINE_STRIP): + case(PrimitiveSet::LINE_LOOP): + case(PrimitiveSet::TRIANGLE_STRIP): + case(PrimitiveSet::TRIANGLE_FAN): + case(PrimitiveSet::QUAD_STRIP): + case(PrimitiveSet::PATCHES): + case(PrimitiveSet::POLYGON): + { + return 1; + } + } + return total; +} + +unsigned int DrawElementsIndirectUInt::getNumPrimitives() const{return getNumPrimitivesDI(*this);} +unsigned int DrawElementsIndirectUByte::getNumPrimitives() const{return getNumPrimitivesDI(*this);} +unsigned int DrawElementsIndirectUShort::getNumPrimitives() const{return getNumPrimitivesDI(*this);} + +void DrawElementsIndirectUInt::draw(State& state, bool useVertexBufferObjects) const +{ GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glDrawElementsIndirect(mode, GL_UNSIGNED_INT, + (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex()) //command array adress + +_firstCommand* _IndirectCommandDrawArrays->getElementSize())// runtime offset computaion can be sizeof(*_IndirectCommandDrawArrays->begin()) + ); + +} + +DrawElementsIndirectUInt::~DrawElementsIndirectUInt() +{ + releaseGLObjects(); +} +void DrawElementsIndirectUInt::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} +void DrawElementsIndirectUInt::accept(PrimitiveFunctor& functor) const +{ + /* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ +} + +void DrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const +{ +/* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ + +} +void DrawElementsIndirectUByte::draw(State& state, bool useVertexBufferObjects) const +{ GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glDrawElementsIndirect(mode, GL_UNSIGNED_BYTE, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex()) + +_firstCommand* _IndirectCommandDrawArrays->getElementSize())); + +} +DrawElementsIndirectUByte::~DrawElementsIndirectUByte() +{ + releaseGLObjects(); +} +void DrawElementsIndirectUByte::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} +void DrawElementsIndirectUByte::accept(PrimitiveFunctor& functor) const +{ +/* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ +} + +void DrawElementsIndirectUByte::accept(PrimitiveIndexFunctor& functor) const +{ +/* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ + +} +void DrawElementsIndirectUShort::draw(State& state, bool useVertexBufferObjects) const +{ GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glDrawElementsIndirect(mode, GL_UNSIGNED_SHORT, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex()) + +_firstCommand* _IndirectCommandDrawArrays->getElementSize())); + +} +DrawElementsIndirectUShort::~DrawElementsIndirectUShort() +{ + releaseGLObjects(); +} +void DrawElementsIndirectUShort::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} +void DrawElementsIndirectUShort::accept(PrimitiveFunctor& functor) const +{ +/* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ +} + +void DrawElementsIndirectUShort::accept(PrimitiveIndexFunctor& functor) const +{ +/* if (!empty() && cmd) + functor.drawElements(_mode,_IndirectCommandDrawArrays->count(_firstCommand), + &(*this)[_IndirectCommandDrawArrays->firstIndex(_firstCommand)] + _IndirectCommandDrawArrays->baseVertex(_firstCommand)); + */ + +} +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawElementsIndirect +// +template inline +unsigned int getNumPrimitivesMDI( const T&_this) +{ IndirectCommandDrawElements *_IndirectCommandDrawArrays=_this.getIndirectCommandDrawArrays(); + unsigned int total=0; + switch(_this.getMode()) + { + case(PrimitiveSet::POINTS): + for(unsigned int i=0;i<_IndirectCommandDrawArrays->getNumElements();i++) + total+=_IndirectCommandDrawArrays->count(i); + case(PrimitiveSet::LINES): + for(unsigned int i=0;i<_IndirectCommandDrawArrays->getNumElements();i++) + total+=_IndirectCommandDrawArrays->count(i)/2; + case(PrimitiveSet::TRIANGLES): + for(unsigned int i=0;i<_IndirectCommandDrawArrays->getNumElements();i++) + total+=_IndirectCommandDrawArrays->count(i)/3; + case(PrimitiveSet::QUADS): + for(unsigned int i=0;i<_IndirectCommandDrawArrays->getNumElements();i++) + total+=_IndirectCommandDrawArrays->count(i)/4; + case(PrimitiveSet::LINE_STRIP): + case(PrimitiveSet::LINE_LOOP): + case(PrimitiveSet::TRIANGLE_STRIP): + case(PrimitiveSet::TRIANGLE_FAN): + case(PrimitiveSet::QUAD_STRIP): + case(PrimitiveSet::PATCHES): + case(PrimitiveSet::POLYGON): + { + unsigned int primcount = _IndirectCommandDrawArrays->getNumElements(); + return primcount; + } + } + return total; +} + +unsigned int MultiDrawElementsIndirectUInt::getNumPrimitives() const{return getNumPrimitivesMDI(*this);} +unsigned int MultiDrawElementsIndirectUByte::getNumPrimitives() const{return getNumPrimitivesMDI(*this);} +unsigned int MultiDrawElementsIndirectUShort::getNumPrimitives() const{return getNumPrimitivesMDI(*this);} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawElementsIndirectUByte +// +MultiDrawElementsIndirectUByte::~MultiDrawElementsIndirectUByte() +{ + releaseGLObjects(); +} +void MultiDrawElementsIndirectUByte::draw(State& state, bool useVertexBufferObjects) const +{ + GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_BYTE, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex())),_IndirectCommandDrawArrays->getNumElements(), _stride); + +} + +void MultiDrawElementsIndirectUByte::accept(PrimitiveFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ +} + +void MultiDrawElementsIndirectUByte::accept(PrimitiveIndexFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ +} + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawElementsIndirectUShort +// +MultiDrawElementsIndirectUShort::~MultiDrawElementsIndirectUShort() +{ + releaseGLObjects(); +} + +void MultiDrawElementsIndirectUShort::draw(State& state, bool useVertexBufferObjects) const +{ GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_SHORT, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex())), + _count>0?_count:_IndirectCommandDrawArrays->getNumElements(),_stride); + +} + +void MultiDrawElementsIndirectUShort::accept(PrimitiveFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ +} + +void MultiDrawElementsIndirectUShort::accept(PrimitiveIndexFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawElementsIndirectUInt +// +MultiDrawElementsIndirectUInt::~MultiDrawElementsIndirectUInt() +{ + releaseGLObjects(); +} + +void MultiDrawElementsIndirectUInt::draw(State& state, bool useVertexBufferObjects) const +{ + GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + GLenum mode = _mode; +#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) + if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; + if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP; +#endif + + + GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); + + assert (useVertexBufferObjects && ebo); + + state.bindElementBufferObject(ebo); + + state.get()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_INT, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex())), + _count>0?_count:_IndirectCommandDrawArrays->getNumElements(), _stride); + +} + +void MultiDrawElementsIndirectUInt::accept(PrimitiveFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ +} + +void MultiDrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const +{ + /* if (!empty() ) + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i), + &(*this)[_IndirectCommandDrawArrays->firstIndex(i)], + _IndirectCommandDrawArrays->baseVertex(i)); + */ + +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawArrays +// +void DrawArraysIndirect::draw(osg::State& state, bool) const +{ + GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLExtensions* ext = state.get(); + + ext->glDrawArraysIndirect(_mode, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex()) + +_firstCommand* _IndirectCommandDrawArrays->getElementSize())); + +} + +void DrawArraysIndirect::accept(PrimitiveFunctor& functor) const +{ + functor.drawArrays(_mode, _IndirectCommandDrawArrays->first(_firstCommand), _IndirectCommandDrawArrays->count(_firstCommand)); +} + +void DrawArraysIndirect::accept(PrimitiveIndexFunctor& functor) const +{ + functor.drawArrays(_mode, _IndirectCommandDrawArrays->first(_firstCommand), _IndirectCommandDrawArrays->count(_firstCommand)); +} + +unsigned int DrawArraysIndirect::getNumIndices() const +{ + return _IndirectCommandDrawArrays->count(_firstCommand); +} + +unsigned int DrawArraysIndirect::index(unsigned int pos) const +{ + return _IndirectCommandDrawArrays->first(_firstCommand)+ pos; +} + +void DrawArraysIndirect::offsetIndices(int offset) +{ + _IndirectCommandDrawArrays->first(_firstCommand)+= offset; +} + +unsigned int DrawArraysIndirect::getNumPrimitives() const +{ + switch(_mode) + { + case(POINTS): + return _IndirectCommandDrawArrays->count(_firstCommand); + case(LINES): + return _IndirectCommandDrawArrays->count(_firstCommand)/2; + case(TRIANGLES): + return _IndirectCommandDrawArrays->count(_firstCommand)/3; + case(QUADS): + return _IndirectCommandDrawArrays->count(_firstCommand)/4; + case(LINE_STRIP): + case(LINE_LOOP): + case(TRIANGLE_STRIP): + case(TRIANGLE_FAN): + case(QUAD_STRIP): + case(PATCHES): + case(POLYGON): + { + return 1; + } + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MultiDrawArrays +// +void MultiDrawArraysIndirect::draw(osg::State& state, bool) const +{ + GLBufferObject* dibo = _IndirectCommandDrawArrays->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); + state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + + GLExtensions* ext = state.get(); + + ext->glMultiDrawArraysIndirect(_mode, (const GLvoid *)(dibo->getOffset(_IndirectCommandDrawArrays->getBufferIndex())+_firstCommand*_IndirectCommandDrawArrays->getElementSize()), + _count>0?_count:_IndirectCommandDrawArrays->getNumElements(), _stride); + +} + +void MultiDrawArraysIndirect::accept(PrimitiveFunctor& functor) const +{ + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; ifirst(i), _IndirectCommandDrawArrays->count(i)); + } +} + +void MultiDrawArraysIndirect::accept(PrimitiveIndexFunctor& functor) const +{ + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; ifirst(i), _IndirectCommandDrawArrays->count(i)); + } +} + +unsigned int MultiDrawArraysIndirect::getNumIndices() const +{ + unsigned int total=0; + + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i); + return total; +} + +unsigned int MultiDrawArraysIndirect::index(unsigned int pos) const +{ + /* unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; icount(i); + if (posfirst(maxindex-1) + pos;*/ + return pos;//??? + +} + +void MultiDrawArraysIndirect::offsetIndices(int offset) +{ + unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + for(unsigned int i=_firstCommand; ifirst(i) += offset; +} + +unsigned int MultiDrawArraysIndirect::getNumPrimitives() const +{ + unsigned int total=0;unsigned int maxindex=_count>0?_firstCommand + _count : _IndirectCommandDrawArrays->getNumElements() - _firstCommand; + + switch(_mode) + { + case(POINTS): + for(unsigned int i=_firstCommand; icount(i); + case(LINES): + for(unsigned int i=_firstCommand; icount(i)/2; + case(TRIANGLES): + for(unsigned int i=_firstCommand; icount(i)/3; + case(QUADS): + for(unsigned int i=_firstCommand; icount(i)/4; + case(LINE_STRIP): + case(LINE_LOOP): + case(TRIANGLE_STRIP): + case(TRIANGLE_FAN): + case(QUAD_STRIP): + case(PATCHES): + case(POLYGON): + { + unsigned int primcount = _IndirectCommandDrawArrays->getNumElements(); + return primcount; + } + } + return total; +} +