diff --git a/examples/osgSSBO/osgSSBO.cpp b/examples/osgSSBO/osgSSBO.cpp index 637f466bc..5ce2ec07c 100644 --- a/examples/osgSSBO/osgSSBO.cpp +++ b/examples/osgSSBO/osgSSBO.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -167,6 +167,7 @@ class ComputeNode : public osg::PositionAttitudeTransform public: + osg::ref_ptr _computeDispatch; osg::ref_ptr _computeProgram; osg::ref_ptr _computeShader; //compute and write position data in SSBO @@ -204,6 +205,8 @@ public: _vertexShaderSourcePath = "shaders/osgssboVertexShader.vs"; _geometryShaderSourcePath = "shaders/osgssboGeometryShader.gs"; _fragmentShaderSourcePath = "shaders/osgssboFragmentShader.fs"; + _computeDispatch=new osg::ComputeDispatch(); + addChild(_computeDispatch); } }; @@ -622,7 +625,7 @@ void ComputeNode::initComputingSetup() { _computeProgram = new osg::Program; - _computeProgram->setComputeGroups((NUM_ELEMENTS_X / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_X / WORK_GROUP_SIZE), (NUM_ELEMENTS_Y / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_Y / WORK_GROUP_SIZE), 1); + _computeDispatch->setComputeGroups((NUM_ELEMENTS_X / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_X / WORK_GROUP_SIZE), (NUM_ELEMENTS_Y / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_Y / WORK_GROUP_SIZE), 1); _computeShader = osgDB::readRefShaderFile(osg::Shader::COMPUTE, _computeShaderSourcePath); _computeProgram->addShader(_computeShader.get()); diff --git a/examples/osgcomputeshaders/osgcomputeshaders.cpp b/examples/osgcomputeshaders/osgcomputeshaders.cpp index 87073cfe5..7d87a7472 100644 --- a/examples/osgcomputeshaders/osgcomputeshaders.cpp +++ b/examples/osgcomputeshaders/osgcomputeshaders.cpp @@ -20,7 +20,7 @@ // This example can work only if GL version is 4.3 or greater #include -#include +#include #include #include #include @@ -57,14 +57,12 @@ int main( int argc, char** argv ) // The compute shader can't work with other kinds of shaders // It also requires the work group numbers. Setting them to 0 will disable the compute shader osg::ref_ptr computeProg = new osg::Program; - computeProg->setComputeGroups( 512/16, 512/16, 1 ); computeProg->addShader( new osg::Shader(osg::Shader::COMPUTE, computeSrc) ); // Create a node for outputting to the texture. // It is OK to have just an empty node here, but seems inbuilt uniforms like osg_FrameTime won't work then. // TODO: maybe we can have a custom drawable which also will implement glMemoryBarrier? - osg::ref_ptr sourceNode = osgDB::readRefNodeFile("axes.osgt"); - if ( !sourceNode ) sourceNode = new osg::Node; + osg::ref_ptr sourceNode = new osg::ComputeDispatch(512/16, 512/16, 1 ); sourceNode->setDataVariance( osg::Object::DYNAMIC ); sourceNode->getOrCreateStateSet()->setAttributeAndModes( computeProg.get() ); sourceNode->getOrCreateStateSet()->addUniform( new osg::Uniform("targetTex", (int)0) ); diff --git a/include/osg/ComputeDispatch b/include/osg/ComputeDispatch new file mode 100644 index 000000000..411d8de32 --- /dev/null +++ b/include/osg/ComputeDispatch @@ -0,0 +1,55 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield + * Copyright (C) 2017 Julien Valentin + * + * 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_COMPUTEDISPATCH +#define OSG_COMPUTEDISPATCH 1 + +#include + +#include + +namespace osg{ + class OSG_EXPORT ComputeDispatch : public osg::Drawable + { + public: + ComputeDispatch(GLint numGroupsX=0, GLint numGroupsY=0, GLint numGroupsZ=0): + Drawable(), + _numGroupsX(numGroupsX), + _numGroupsY(numGroupsY), + _numGroupsZ(numGroupsZ) + {} + + ComputeDispatch(const ComputeDispatch&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osg, ComputeDispatch); + + virtual void compileGLObjects(RenderInfo& renderInfo) const {} + + virtual VertexArrayState* createVertexArrayState(RenderInfo& renderInfo) const { return 0; } + + virtual void drawImplementation(RenderInfo& renderInfo) const; + + /** Set compute shader work groups */ + void setComputeGroups( GLint numGroupsX, GLint numGroupsY, GLint numGroupsZ ) { _numGroupsX=numGroupsX; _numGroupsY=numGroupsY; _numGroupsZ=numGroupsZ; } + + /** Get compute shader work groups */ + void getComputeGroups( GLint& numGroupsX, GLint& numGroupsY, GLint& numGroupsZ ) const{ numGroupsX=_numGroupsX; numGroupsY=_numGroupsY; numGroupsZ=_numGroupsZ; } + + protected: + GLint _numGroupsX, _numGroupsY, _numGroupsZ; + + }; +} +#endif + diff --git a/include/osg/Program b/include/osg/Program index 36aa7ed2f..e9e26829f 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -103,10 +103,6 @@ class OSG_EXPORT Program : public osg::StateAttribute void setParameter( GLenum pname, GLint value ); GLint getParameter( GLenum pname ) const; - /** Set/get compute shader work groups */ - void setComputeGroups( GLint numGroupsX, GLint numGroupsY, GLint numGroupsZ ); - void getComputeGroups( GLint& numGroupsX, GLint& numGroupsY, GLint& numGroupsZ ) const; - /** Add an attribute location binding. */ void addBindAttribLocation( const std::string& name, GLuint index ); @@ -439,12 +435,6 @@ class OSG_EXPORT Program : public osg::StateAttribute GLint _geometryInputType; GLint _geometryOutputType; - - /** Parameter maintained with glDispatchCompute */ - GLint _numGroupsX; - GLint _numGroupsY; - GLint _numGroupsZ; - /**TransformFeedBack**/ GLenum _feedbackmode; std::vector _feedbackout; diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 845306551..5fc119403 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -55,6 +55,7 @@ SET(TARGET_H ${HEADER_PATH}/ColorMaski ${HEADER_PATH}/ColorMatrix ${HEADER_PATH}/ComputeBoundsVisitor + ${HEADER_PATH}/ComputeDispatch ${HEADER_PATH}/ContextData ${HEADER_PATH}/ConvexPlanarOccluder ${HEADER_PATH}/ConvexPlanarPolygon @@ -267,6 +268,7 @@ SET(TARGET_SRC ColorMaski.cpp ColorMatrix.cpp ComputeBoundsVisitor.cpp + ComputeDispatch.cpp ContextData.cpp ConvexPlanarOccluder.cpp ConvexPlanarPolygon.cpp diff --git a/src/osg/ComputeDispatch.cpp b/src/osg/ComputeDispatch.cpp new file mode 100644 index 000000000..c689bd95b --- /dev/null +++ b/src/osg/ComputeDispatch.cpp @@ -0,0 +1,16 @@ +#include + +using namespace osg; + +ComputeDispatch::ComputeDispatch(const ComputeDispatch&o,const osg::CopyOp& copyop): + Drawable(o,copyop), + _numGroupsX(o._numGroupsX), + _numGroupsY(o._numGroupsY), + _numGroupsZ(o._numGroupsZ) +{ +} + +void ComputeDispatch::drawImplementation(RenderInfo& renderInfo) const +{ + renderInfo.getState()->get()->glDispatchCompute(_numGroupsX, _numGroupsY, _numGroupsZ); +} diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 68fadaf0c..b41d27b81 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -92,8 +92,7 @@ void Program::ProgramBinary::assign(unsigned int size, const unsigned char* data Program::Program() : _geometryVerticesOut(1), _geometryInputType(GL_TRIANGLES), - _geometryOutputType(GL_TRIANGLE_STRIP), - _numGroupsX(0), _numGroupsY(0), _numGroupsZ(0), _feedbackmode(GL_SEPARATE_ATTRIBS) + _geometryOutputType(GL_TRIANGLE_STRIP), _feedbackmode(GL_SEPARATE_ATTRIBS) { } @@ -133,10 +132,6 @@ Program::Program(const Program& rhs, const osg::CopyOp& copyop): _geometryInputType = rhs._geometryInputType; _geometryOutputType = rhs._geometryOutputType; - _numGroupsX = rhs._numGroupsX; - _numGroupsY = rhs._numGroupsY; - _numGroupsZ = rhs._numGroupsZ; - _feedbackmode=rhs._feedbackmode; _feedbackout=rhs._feedbackout; } @@ -173,15 +168,6 @@ int Program::compare(const osg::StateAttribute& sa) const if( _geometryOutputType < rhs._geometryOutputType ) return -1; if( rhs._geometryOutputType < _geometryOutputType ) return 1; - if( _numGroupsX < rhs._numGroupsX ) return -1; - if( rhs._numGroupsX < _numGroupsX ) return 1; - - if( _numGroupsY < rhs._numGroupsY ) return -1; - if( rhs._numGroupsY < _numGroupsY ) return 1; - - if( _numGroupsZ < rhs._numGroupsZ ) return -1; - if( rhs._numGroupsZ < _numGroupsZ ) return 1; - if(_feedbackoutglUseProgram( _glProgramHandle ); - if ( _program->_numGroupsX>0 && _program->_numGroupsY>0 && _program->_numGroupsZ>0 ) - { - _extensions->glDispatchCompute( _program->_numGroupsX, _program->_numGroupsY, _program->_numGroupsZ ); - } } diff --git a/src/osgWrappers/serializers/osg/ComputeDispatch.cpp b/src/osgWrappers/serializers/osg/ComputeDispatch.cpp new file mode 100644 index 000000000..d77533a5d --- /dev/null +++ b/src/osgWrappers/serializers/osg/ComputeDispatch.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +// _numGroupsX/Y/Z +static bool checkComputeGroups( const osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + attr.getComputeGroups( numX, numY, numZ ); + return numX>0 && numY>0 && numZ>0; +} + +static bool readComputeGroups( osgDB::InputStream& is, osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + is >> numX >> numY >> numZ; + attr.setComputeGroups( numX, numY, numZ ); + return true; +} + +static bool writeComputeGroups( osgDB::OutputStream& os, const osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + attr.getComputeGroups( numX, numY, numZ ); + os << numX << numY << numZ << std::endl; + return true; +} + +REGISTER_OBJECT_WRAPPER( ComputeDispatch, + new osg::ComputeDispatch, + osg::ComputeDispatch, + "osg::Object osg::Node osg::Drawable osg::ComputeDispatch" ) +{ + ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z +} diff --git a/src/osgWrappers/serializers/osg/Program.cpp b/src/osgWrappers/serializers/osg/Program.cpp index 1513aa484..13195c87d 100644 --- a/src/osgWrappers/serializers/osg/Program.cpp +++ b/src/osgWrappers/serializers/osg/Program.cpp @@ -121,29 +121,6 @@ static bool writeFeedBackMode( osgDB::OutputStream& os, const osg::Program& attr os << attr.getTransformFeedBackMode()<< std::endl; return true; } -// _numGroupsX/Y/Z -static bool checkComputeGroups( const osg::Program& attr ) -{ - GLint numX = 0, numY = 0, numZ = 0; - attr.getComputeGroups( numX, numY, numZ ); - return numX>0 && numY>0 && numZ>0; -} - -static bool readComputeGroups( osgDB::InputStream& is, osg::Program& attr ) -{ - GLint numX = 0, numY = 0, numZ = 0; - is >> numX >> numY >> numZ; - attr.setComputeGroups( numX, numY, numZ ); - return true; -} - -static bool writeComputeGroups( osgDB::OutputStream& os, const osg::Program& attr ) -{ - GLint numX = 0, numY = 0, numZ = 0; - attr.getComputeGroups( numX, numY, numZ ); - os << numX << numY << numZ << std::endl; - return true; -} static bool checkBindUniformBlock( const osg::Program& node ) { @@ -190,11 +167,6 @@ REGISTER_OBJECT_WRAPPER( Program, ADD_USER_SERIALIZER( GeometryInputType ); // _geometryInputType ADD_USER_SERIALIZER( GeometryOutputType ); // _geometryOutputType - { - UPDATE_TO_VERSION_SCOPED( 95 ) - ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z - } - { UPDATE_TO_VERSION_SCOPED( 116 ) ADD_USER_SERIALIZER( FeedBackVaryingsName );