From 7606159a781feb751f47adcc5a9573822142a04c Mon Sep 17 00:00:00 2001 From: mp3butcher Date: Thu, 27 Jul 2017 01:54:25 +0200 Subject: [PATCH 1/3] add DrawIndirectBufferObject as State variable in order to minimize call to glBindBuffer(GL_DRAW_INDIRECT_BUFFER,X) TODO: Promote PrimitiveSetIndirect's VBO to target explicited DIBO (in order to benefit from BOSet queue management) --- include/osg/State | 22 ++++++++++++++++++++++ src/osg/PrimitiveSetIndirect.cpp | 16 ++++++++-------- src/osg/State.cpp | 1 + 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/include/osg/State b/include/osg/State index b79420dfd..28a2880c4 100644 --- a/include/osg/State +++ b/include/osg/State @@ -591,6 +591,27 @@ class OSG_EXPORT State : public Referenced } + inline void bindDrawIndirectBufferObject(osg::GLBufferObject* ibo) + { + if (ibo->isDirty()) + { + ibo->compileBuffer(); + _currentDIBO = ibo; + } + else if (ibo != _currentDIBO) + { + _glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ibo->getGLObjectID()); + _currentDIBO = ibo; + } + } + + inline void unbindDrawIndirectBufferObject() + { + if (!_currentDIBO) return; + _glBindBuffer(GL_DRAW_INDIRECT_BUFFER,0); + _currentDIBO = 0; + } + void setCurrentVertexArrayObject(GLuint vao) { _currentVAO = vao; } GLuint getCurrentVertexArrayObject() const { return _currentVAO; } @@ -1259,6 +1280,7 @@ class OSG_EXPORT State : public Referenced unsigned int _currentActiveTextureUnit; unsigned int _currentClientActiveTextureUnit; GLBufferObject* _currentPBO; + GLBufferObject* _currentDIBO; GLuint _currentVAO; diff --git a/src/osg/PrimitiveSetIndirect.cpp b/src/osg/PrimitiveSetIndirect.cpp index add1c98a4..796769392 100644 --- a/src/osg/PrimitiveSetIndirect.cpp +++ b/src/osg/PrimitiveSetIndirect.cpp @@ -64,7 +64,7 @@ unsigned int DrawElementsIndirectUShort::getNumPrimitives() const{return getNumP void DrawElementsIndirectUInt::draw(State& state, bool useVertexBufferObjects) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) @@ -122,7 +122,7 @@ void DrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const } void DrawElementsIndirectUByte::draw(State& state, bool useVertexBufferObjects) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) @@ -176,7 +176,7 @@ void DrawElementsIndirectUByte::accept(PrimitiveIndexFunctor& functor) const } void DrawElementsIndirectUShort::draw(State& state, bool useVertexBufferObjects) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) @@ -282,7 +282,7 @@ void MultiDrawElementsIndirectUByte::draw(State& state, bool useVertexBufferObje { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; @@ -340,7 +340,7 @@ MultiDrawElementsIndirectUShort::~MultiDrawElementsIndirectUShort() void MultiDrawElementsIndirectUShort::draw(State& state, bool useVertexBufferObjects) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) @@ -397,7 +397,7 @@ MultiDrawElementsIndirectUInt::~MultiDrawElementsIndirectUInt() void MultiDrawElementsIndirectUInt::draw(State& state, bool useVertexBufferObjects) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLenum mode = _mode; #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN; @@ -450,7 +450,7 @@ void MultiDrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const void DrawArraysIndirect::draw(osg::State& state, bool) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLExtensions* ext = state.get(); @@ -517,7 +517,7 @@ unsigned int DrawArraysIndirect::getNumPrimitives() const void MultiDrawArraysIndirect::draw(osg::State& state, bool) const { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() ); - state.get()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, dibo->getGLObjectID()); + state.bindDrawIndirectBufferObject(dibo); GLExtensions* ext = state.get(); diff --git a/src/osg/State.cpp b/src/osg/State.cpp index e8c2446ca..c652d4cc6 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -89,6 +89,7 @@ State::State(): _currentClientActiveTextureUnit=0; _currentPBO = 0; + _currentDIBO = 0; _currentVAO = 0; _isSecondaryColorSupported = false; From 104b2dfc7217fe2d895d19af63cdddd339e5fb14 Mon Sep 17 00:00:00 2001 From: mp3butcher Date: Thu, 27 Jul 2017 12:00:41 +0200 Subject: [PATCH 2/3] Promote PrimitiveSetIndirect's VBO to a target explicited DIBO (in order to benefit from BOSet queue management) --- examples/osggpucull/osggpucull.cpp | 2 +- include/osg/BufferObject | 22 +++++++++++++++ include/osg/PrimitiveSetIndirect | 4 +-- include/osg/State | 2 +- src/osg/BufferObject.cpp | 44 ++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/examples/osggpucull/osggpucull.cpp b/examples/osggpucull/osggpucull.cpp index 194a9a946..0c00bbef3 100644 --- a/examples/osggpucull/osggpucull.cpp +++ b/examples/osggpucull/osggpucull.cpp @@ -189,7 +189,7 @@ struct IndirectTarget } void endRegister(unsigned int index, unsigned int rowsPerInstance, GLenum pixelFormat, GLenum type, GLint internalFormat, bool useMultiDrawArraysIndirect ) { - osg::VertexBufferObject * indirectCommandbuffer=new osg::VertexBufferObject(); + osg::DrawIndirectBufferObject * indirectCommandbuffer = new osg::DrawIndirectBufferObject(); indirectCommandbuffer->setUsage(GL_DYNAMIC_DRAW); indirectCommands->setBufferObject(indirectCommandbuffer); diff --git a/include/osg/BufferObject b/include/osg/BufferObject index c542e4121..37ae19a55 100644 --- a/include/osg/BufferObject +++ b/include/osg/BufferObject @@ -635,6 +635,28 @@ class OSG_EXPORT ElementBufferObject : public BufferObject virtual ~ElementBufferObject(); }; +class OSG_EXPORT DrawIndirectBufferObject : public BufferObject +{ + public: + + DrawIndirectBufferObject(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + DrawIndirectBufferObject(const DrawIndirectBufferObject& vbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); + + META_Object(osg,DrawIndirectBufferObject); + + unsigned int addArray(osg::Array* array); + void removeArray(osg::Array* array); + + void setArray(unsigned int i, Array* array); + Array* getArray(unsigned int i); + const Array* getArray(unsigned int i) const; + + protected: + virtual ~DrawIndirectBufferObject(); +}; + class Image; class OSG_EXPORT PixelBufferObject : public BufferObject { diff --git a/include/osg/PrimitiveSetIndirect b/include/osg/PrimitiveSetIndirect index d8771a781..6c8567c83 100644 --- a/include/osg/PrimitiveSetIndirect +++ b/include/osg/PrimitiveSetIndirect @@ -148,7 +148,7 @@ public: inline void setIndirectCommandArray(IndirectCommandDrawElements*idc) { _indirectCommandArray = idc; if(!_indirectCommandArray->getBufferObject()) - _indirectCommandArray->setBufferObject(new osg::VertexBufferObject()); + _indirectCommandArray->setBufferObject(new osg::DrawIndirectBufferObject()); } /// get command array of this indirect primitive set inline IndirectCommandDrawElements* getIndirectCommandArray() { return _indirectCommandArray; } @@ -656,7 +656,7 @@ public: inline void setIndirectCommandArray(IndirectCommandDrawArrays*idc) { _indirectCommandArray = idc; if(!_indirectCommandArray->getBufferObject()) - _indirectCommandArray->setBufferObject(new osg::VertexBufferObject()); + _indirectCommandArray->setBufferObject(new osg::DrawIndirectBufferObject()); } inline const IndirectCommandDrawArrays* getIndirectCommandArray() const { return _indirectCommandArray; diff --git a/include/osg/State b/include/osg/State index 28a2880c4..2d363105f 100644 --- a/include/osg/State +++ b/include/osg/State @@ -600,7 +600,7 @@ class OSG_EXPORT State : public Referenced } else if (ibo != _currentDIBO) { - _glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ibo->getGLObjectID()); + ibo->bindBuffer(); _currentDIBO = ibo; } } diff --git a/src/osg/BufferObject.cpp b/src/osg/BufferObject.cpp index 9e2199911..46fa4e869 100644 --- a/src/osg/BufferObject.cpp +++ b/src/osg/BufferObject.cpp @@ -1358,6 +1358,50 @@ const DrawElements* ElementBufferObject::getDrawElements(unsigned int i) const return dynamic_cast(getBufferData(i)); } +////////////////////////////////////////////////////////////////////////////////// +// +// DrawIndirectBufferObject +// +DrawIndirectBufferObject::DrawIndirectBufferObject() +{ + setTarget(GL_DRAW_INDIRECT_BUFFER); + setUsage(GL_STATIC_DRAW_ARB); +// setUsage(GL_STREAM_DRAW_ARB); +} + +DrawIndirectBufferObject::DrawIndirectBufferObject(const DrawIndirectBufferObject& vbo,const CopyOp& copyop): + BufferObject(vbo,copyop) +{ +} + +DrawIndirectBufferObject::~DrawIndirectBufferObject() +{ +} + +unsigned int DrawIndirectBufferObject::addArray(osg::Array* array) +{ + return addBufferData(array); +} + +void DrawIndirectBufferObject::removeArray(osg::Array* array) +{ + removeBufferData(array); +} + +void DrawIndirectBufferObject::setArray(unsigned int i, Array* array) +{ + setBufferData(i,array); +} + +Array* DrawIndirectBufferObject::getArray(unsigned int i) +{ + return dynamic_cast(getBufferData(i)); +} + +const Array* DrawIndirectBufferObject::getArray(unsigned int i) const +{ + return dynamic_cast(getBufferData(i)); +} ////////////////////////////////////////////////////////////////////////////////// // From a45c4c8f3986f0c7a2b0680f89d5f84bc548894b Mon Sep 17 00:00:00 2001 From: mp3butcher Date: Thu, 27 Jul 2017 12:27:55 +0200 Subject: [PATCH 3/3] set DIBO of the drawcommandarray directly in their interface constructor it makes osggpu use case lighter + drawcommandarray can't exist without a BO --- examples/osggpucull/osggpucull.cpp | 6 ++---- include/osg/PrimitiveSetIndirect | 14 ++++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/osggpucull/osggpucull.cpp b/examples/osggpucull/osggpucull.cpp index 0c00bbef3..de21f0280 100644 --- a/examples/osggpucull/osggpucull.cpp +++ b/examples/osggpucull/osggpucull.cpp @@ -181,18 +181,16 @@ struct IndirectTarget : maxTargetQuantity(0) { indirectCommands = new osg::DefaultIndirectCommandDrawArrays; + indirectCommands->getBufferObject()->setUsage(GL_DYNAMIC_DRAW); } IndirectTarget( AggregateGeometryVisitor* agv, osg::Program* program ) : geometryAggregator(agv), drawProgram(program), maxTargetQuantity(0) { indirectCommands = new osg::DefaultIndirectCommandDrawArrays; + indirectCommands->getBufferObject()->setUsage(GL_DYNAMIC_DRAW); } void endRegister(unsigned int index, unsigned int rowsPerInstance, GLenum pixelFormat, GLenum type, GLint internalFormat, bool useMultiDrawArraysIndirect ) { - osg::DrawIndirectBufferObject * indirectCommandbuffer = new osg::DrawIndirectBufferObject(); - indirectCommandbuffer->setUsage(GL_DYNAMIC_DRAW); - indirectCommands->setBufferObject(indirectCommandbuffer); - indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommands); indirectCommandTextureBuffer->setInternalFormat( GL_R32I ); indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE); diff --git a/include/osg/PrimitiveSetIndirect b/include/osg/PrimitiveSetIndirect index 6c8567c83..eae239076 100644 --- a/include/osg/PrimitiveSetIndirect +++ b/include/osg/PrimitiveSetIndirect @@ -25,7 +25,7 @@ namespace osg { class OSG_EXPORT IndirectCommandDrawArrays: public BufferData { public: - IndirectCommandDrawArrays():BufferData(){} + IndirectCommandDrawArrays():BufferData(){setBufferObject(new DrawIndirectBufferObject());} IndirectCommandDrawArrays(const IndirectCommandDrawArrays& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) :BufferData(copy, copyop){ } @@ -40,7 +40,7 @@ public: class OSG_EXPORT IndirectCommandDrawElements: public BufferData { public: - IndirectCommandDrawElements():BufferData(){} + IndirectCommandDrawElements():BufferData(){setBufferObject(new DrawIndirectBufferObject());} IndirectCommandDrawElements(const IndirectCommandDrawElements& copy,const CopyOp& copyop/*=CopyOp::SHALLOW_COPY*/) :BufferData(copy, copyop){} @@ -147,8 +147,9 @@ public: /// set command array of this indirect primitive set inline void setIndirectCommandArray(IndirectCommandDrawElements*idc) { _indirectCommandArray = idc; - if(!_indirectCommandArray->getBufferObject()) - _indirectCommandArray->setBufferObject(new osg::DrawIndirectBufferObject()); + //ensure bo of idc is of the correct type + if(!dynamic_cast(_indirectCommandArray->getBufferObject())) + _indirectCommandArray->setBufferObject(new DrawIndirectBufferObject()); } /// get command array of this indirect primitive set inline IndirectCommandDrawElements* getIndirectCommandArray() { return _indirectCommandArray; } @@ -655,8 +656,9 @@ public: inline void setIndirectCommandArray(IndirectCommandDrawArrays*idc) { _indirectCommandArray = idc; - if(!_indirectCommandArray->getBufferObject()) - _indirectCommandArray->setBufferObject(new osg::DrawIndirectBufferObject()); + //ensure bo of idc is of the correct type + if(!dynamic_cast(_indirectCommandArray->getBufferObject())) + _indirectCommandArray->setBufferObject(new DrawIndirectBufferObject()); } inline const IndirectCommandDrawArrays* getIndirectCommandArray() const { return _indirectCommandArray;