From Wang Rui, "In the attached files I've added the Compute Shader support for OSG, as well as serializer updates and a new osgcomputeshaders example. My submission also include a setComputeGroups() function in Program for setting compute-shader work groups, and a bindToImageUnit() function in Texture for binding textures as image variables in shaders.

All code are tested on Windows 7 + NVIDIA GFX 570 with the latest GeForce 310.70 Driver (BETA), which could support OpenGL 4.3.

Compute shader information can be found at "http://www.opengl.org/registry/specs/ARB/compute_shader.txt"
"
This commit is contained in:
Robert Osfield
2013-01-25 11:54:03 +00:00
parent f6450a1123
commit 26a8f63212
16 changed files with 397 additions and 4 deletions

View File

@@ -180,6 +180,7 @@ IF(DYNAMIC_OPENSCENEGRAPH)
ADD_SUBDIRECTORY(osgphotoalbum)
ADD_SUBDIRECTORY(osgtessellate)
ADD_SUBDIRECTORY(osgtessellationshaders)
ADD_SUBDIRECTORY(osgcomputeshaders)
ADD_SUBDIRECTORY(osgpdf)

View File

@@ -0,0 +1,2 @@
SET(TARGET_SRC osgcomputeshaders.cpp)
SETUP_EXAMPLE(osgcomputeshaders)

View File

@@ -0,0 +1,92 @@
/* -*-c++-*- OpenSceneGraph example, osgcomputeshaders.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Written by Wang Rui
// This example can work only if GL version is 4.3 or greater
#include <osg/Texture2D>
#include <osg/Geometry>
#include <osg/Geode>
#include <osgDB/ReadFile>
#include <osgGA/StateSetManipulator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
static char* computeSrc = {
"#version 430\n"
"uniform float osg_FrameTime;\n"
"uniform image2D targetTex;\n"
"layout (local_size_x = 16, local_size_y = 16) in;\n"
"void main() {\n"
" ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\n"
" float coeffcient = 0.5*sin(float(gl_WorkGroupID.x + gl_WorkGroupID.y)*0.1 + osg_FrameTime);\n"
" coeffcient *= length(vec2(ivec2(gl_LocalInvocationID.xy) - ivec2(8)) / vec2(8.0));\n"
" imageStore(targetTex, storePos, vec4(1.0-coeffcient, 0.0, 0.0, 0.0));\n"
"}\n"
};
int main( int argc, char** argv )
{
osg::ArgumentParser arguments( &argc, argv );
// Create the texture as both the output of compute shader and the input of a normal quad
osg::ref_ptr<osg::Texture2D> tex2D = new osg::Texture2D;
tex2D->setTextureSize( 512, 512 );
tex2D->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
tex2D->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
tex2D->setInternalFormat( GL_R32F );
tex2D->setSourceFormat( GL_RED );
tex2D->setSourceType( GL_FLOAT );
tex2D->bindToImageUnit( 0, osg::Texture::WRITE_ONLY ); // So we can use 'image2D' in the compute shader
// 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<osg::Program> 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::Node* sourceNode = osgDB::readNodeFile("axes.osgt");
if ( !sourceNode ) sourceNode = new osg::Node;
sourceNode->setDataVariance( osg::Object::DYNAMIC );
sourceNode->getOrCreateStateSet()->setAttributeAndModes( computeProg.get() );
sourceNode->getOrCreateStateSet()->addUniform( new osg::Uniform("targetTex", (int)0) );
sourceNode->getOrCreateStateSet()->setTextureAttributeAndModes( 0, tex2D.get() );
// Display the texture on a quad. We will also be able to operate on the data if reading back to CPU side
osg::Geometry* geom = osg::createTexturedQuadGeometry(
osg::Vec3(), osg::Vec3(1.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,1.0f) );
osg::ref_ptr<osg::Geode> quad = new osg::Geode;
quad->addDrawable( geom );
quad->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
quad->getOrCreateStateSet()->setTextureAttributeAndModes( 0, tex2D.get() );
// Create the scene graph and start the viewer
osg::ref_ptr<osg::Group> scene = new osg::Group;
scene->addChild( sourceNode );
scene->addChild( quad.get() );
osgViewer::Viewer viewer;
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
viewer.addEventHandler( new osgViewer::StatsHandler );
viewer.addEventHandler( new osgViewer::WindowSizeHandler );
viewer.setSceneData( scene.get() );
return viewer.run();
}

View File

@@ -442,6 +442,28 @@ typedef char GLchar;
#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
#endif
// ARB_compute_shader
#ifndef GL_ARB_compute_shader
#define GL_COMPUTE_SHADER 0x91B9
#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
#define GL_MAX_COMPUTE_LOCAL_INVOCATIONS 0x90EB
#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
#define GL_COMPUTE_LOCAL_WORK_SIZE 0x8267
#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
#define GL_COMPUTE_SHADER_BIT 0x00000020
#endif
#ifndef GL_ARB_depth_clamp
#define GL_DEPTH_CLAMP 0x864F
#endif
@@ -689,6 +711,8 @@ class OSG_EXPORT GL2Extensions : public osg::Referenced
// ARB_shader_atomic_counters
void glGetActiveAtomicCounterBufferiv( GLuint program, GLuint bufferIndex, GLenum pname, GLint* params ) const;
// ARB_compute_shader
void glDispatchCompute( GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ ) const;
protected:
~GL2Extensions() {}
@@ -855,6 +879,7 @@ class OSG_EXPORT GL2Extensions : public osg::Referenced
typedef void (GL_APIENTRY * UniformMatrix3x4dvProc)( GLint location, GLsizei count, GLboolean transpose, const GLdouble* value );
typedef void (GL_APIENTRY * UniformMatrix4x3dvProc)( GLint location, GLsizei count, GLboolean transpose, const GLdouble* value );
typedef void (GL_APIENTRY * GetActiveAtomicCounterBufferivProc)( GLuint program, GLuint bufferIndex, GLenum pname, GLint* params );
typedef void (GL_APIENTRY * DispatchComputeProc)( GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ );
BlendEquationSeparateProc _glBlendEquationSeparate;
DrawBuffersProc _glDrawBuffers;
@@ -1020,6 +1045,9 @@ class OSG_EXPORT GL2Extensions : public osg::Referenced
// ARB_shader_atomic_counters
GetActiveAtomicCounterBufferivProc _glGetActiveAtomicCounterBufferiv;
// ARB_compute_shader
DispatchComputeProc _glDispatchCompute;
};
}

View File

@@ -101,6 +101,10 @@ class OSG_EXPORT Program : public osg::StateAttribute
void setParameterfv( GLenum pname, const GLfloat* value );
const GLfloat* getParameterfv( 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 );
@@ -388,6 +392,11 @@ class OSG_EXPORT Program : public osg::StateAttribute
// todo add tessellation default level
//GLfloat _patchDefaultInnerLevel[2];
//GLfloat _patchDefaultOuterLevel[4];
/** Parameter maintained with glDispatchCompute */
GLint _numGroupsX;
GLint _numGroupsY;
GLint _numGroupsZ;
private:
Program& operator=(const Program&); // disallowed

View File

@@ -92,6 +92,7 @@ class OSG_EXPORT Shader : public osg::Object
TESSEVALUATION = GL_TESS_EVALUATION_SHADER,
GEOMETRY = GL_GEOMETRY_SHADER_EXT,
FRAGMENT = GL_FRAGMENT_SHADER,
COMPUTE = GL_COMPUTE_SHADER,
UNDEFINED = -1
};

View File

@@ -302,7 +302,6 @@
#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
#endif
#ifndef GL_ARB_texture_rg
#define GL_RG 0x8227
#define GL_RG_INTEGER 0x8228
@@ -328,12 +327,77 @@
#define GL_RG32UI 0x823C
#endif
#ifndef GL_ARB_shader_image_load_store
#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
#define GL_UNIFORM_BARRIER_BIT 0x00000004
#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
#define GL_COMMAND_BARRIER_BIT 0x00000040
#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
#define GL_MAX_IMAGE_UNITS 0x8F38
#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
#define GL_IMAGE_BINDING_NAME 0x8F3A
#define GL_IMAGE_BINDING_LEVEL 0x8F3B
#define GL_IMAGE_BINDING_LAYERED 0x8F3C
#define GL_IMAGE_BINDING_LAYER 0x8F3D
#define GL_IMAGE_BINDING_ACCESS 0x8F3E
#define GL_IMAGE_1D 0x904C
#define GL_IMAGE_2D 0x904D
#define GL_IMAGE_3D 0x904E
#define GL_IMAGE_2D_RECT 0x904F
#define GL_IMAGE_CUBE 0x9050
#define GL_IMAGE_BUFFER 0x9051
#define GL_IMAGE_1D_ARRAY 0x9052
#define GL_IMAGE_2D_ARRAY 0x9053
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
#define GL_IMAGE_2D_MULTISAMPLE 0x9055
#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
#define GL_INT_IMAGE_1D 0x9057
#define GL_INT_IMAGE_2D 0x9058
#define GL_INT_IMAGE_3D 0x9059
#define GL_INT_IMAGE_2D_RECT 0x905A
#define GL_INT_IMAGE_CUBE 0x905B
#define GL_INT_IMAGE_BUFFER 0x905C
#define GL_INT_IMAGE_1D_ARRAY 0x905D
#define GL_INT_IMAGE_2D_ARRAY 0x905E
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
#define GL_MAX_IMAGE_SAMPLES 0x906D
#define GL_IMAGE_BINDING_FORMAT 0x906E
#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
#endif
#ifndef GL_ARB_half_float_pixel
#define GL_HALF_FLOAT 0x140B
#endif
namespace osg {
@@ -590,6 +654,37 @@ class OSG_EXPORT Texture : public osg::StateAttribute
* min filter is used. */
void allocateMipmapLevels();
/** Encapsulates texture image load/store attributes */
struct ImageAttachment
{
GLuint unit;
GLint level;
GLboolean layered;
GLint layer;
GLenum access;
GLenum format;
ImageAttachment()
: unit(0), level(0), layered(GL_FALSE), layer(0), access(0), format(0) {}
};
/** Type of access that will be performed on the texture image. */
enum ImageAccess
{
NOT_USED = 0,
READ_ONLY = GL_READ_ONLY_ARB,
WRITE_ONLY = GL_WRITE_ONLY_ARB,
READ_WRITE = GL_READ_WRITE_ARB
};
/** Bind texture to an image unit (available only if GL version is 4.2 or greater)
* The format parameter for the image unit need not exactly match the texture internal format,
* but if it is set to 0, the texture internal format will be used.
* See http://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt */
void bindToImageUnit(unsigned int unit, GLenum access, GLenum format=0, int level=0, bool layered=false, int layer=0);
ImageAttachment& getImageAttachment() { return _imageAttachment; }
const ImageAttachment& getImageAttachment() const { return _imageAttachment; }
/** Sets GL_TEXTURE_COMPARE_MODE_ARB to GL_COMPARE_R_TO_TEXTURE_ARB
* See http://oss.sgi.com/projects/ogl-sample/registry/ARB/shadow.txt. */
@@ -746,6 +841,8 @@ class OSG_EXPORT Texture : public osg::StateAttribute
void setTextureIntegerSupported(bool flag) { _isTextureIntegerEXTSupported=flag; }
bool isTextureIntegerSupported() const { return _isTextureIntegerEXTSupported; }
bool isBindImageTextureSupported() const { return _glBindImageTexture!=0; }
void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const
{
_glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
@@ -776,6 +873,12 @@ class OSG_EXPORT Texture : public osg::StateAttribute
_glTexParameterIuiv(target, pname, data);
}
// ARB_shader_image_load_store
void glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) const
{
_glBindImageTexture(unit, texture, level, layered, layer, access, format);
}
protected:
~Extensions() {}
@@ -786,6 +889,7 @@ class OSG_EXPORT Texture : public osg::StateAttribute
typedef void (GL_APIENTRY * TexImage2DMultisample)(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
typedef void (GL_APIENTRY * TexParameterIivProc)(GLenum target, GLenum pname, const GLint* data);
typedef void (GL_APIENTRY * TexParameterIuivProc)(GLenum target, GLenum pname, const GLuint* data);
typedef void (GL_APIENTRY * BindImageTextureProc)( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format );
CompressedTexImage2DArbProc _glCompressedTexImage2D;
CompressedTexSubImage2DArbProc _glCompressedTexSubImage2D;
@@ -794,6 +898,8 @@ class OSG_EXPORT Texture : public osg::StateAttribute
TexParameterIivProc _glTexParameterIiv;
TexParameterIuivProc _glTexParameterIuiv;
// ARB_shader_image_load_store
BindImageTextureProc _glBindImageTexture;
bool _isMultiTexturingSupported;
bool _isTextureFilterAnisotropicSupported;
@@ -938,6 +1044,8 @@ class OSG_EXPORT Texture : public osg::StateAttribute
ShadowTextureMode _shadow_texture_mode;
float _shadow_ambient;
ImageAttachment _imageAttachment;
public:
struct OSG_EXPORT TextureProfile

View File

@@ -214,6 +214,9 @@ GL2Extensions::GL2Extensions(const GL2Extensions& rhs) : osg::Referenced()
// ARB_shader_atomic_counters
_glGetActiveAtomicCounterBufferiv = rhs._glGetActiveAtomicCounterBufferiv;
// ARB_compute_shader
_glDispatchCompute = rhs._glDispatchCompute;
}
@@ -399,6 +402,9 @@ void GL2Extensions::lowestCommonDenominator(const GL2Extensions& rhs)
// ARB_shader_atomic_counters
if(!rhs._glGetActiveAtomicCounterBufferiv) _glGetActiveAtomicCounterBufferiv = 0;
// ARB_compute_shder
if(!rhs._glDispatchCompute) _glDispatchCompute = 0;
}
@@ -589,6 +595,9 @@ void GL2Extensions::setupGL2Extensions(unsigned int contextID)
// ARB_shader_atomic_counters
_glGetActiveAtomicCounterBufferiv= 0;
// ARB_compute_shader
_glDispatchCompute= 0;
return;
}
@@ -794,6 +803,9 @@ void GL2Extensions::setupGL2Extensions(unsigned int contextID)
// ARB_shader_atomic_counters
setGLExtensionFuncPtr(_glGetActiveAtomicCounterBufferiv, "glGetActiveAtomicCounterBufferiv" );
// ARB_compute_shader
setGLExtensionFuncPtr(_glDispatchCompute, "glDispatchCompute" );
}
@@ -2826,6 +2838,18 @@ void GL2Extensions::glGetActiveAtomicCounterBufferiv( GLuint program, GLuint buf
}
}
void GL2Extensions::glDispatchCompute( GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ ) const
{
if (_glDispatchCompute)
{
_glDispatchCompute( numGroupsX, numGroupsY, numGroupsZ );
}
else
{
NotSupported( "glDispatchCompute" );
}
}
///////////////////////////////////////////////////////////////////////////
// C++-friendly convenience methods

View File

@@ -137,7 +137,8 @@ void Program::ProgramBinary::assign(unsigned int size, const unsigned char* data
Program::Program() :
_geometryVerticesOut(1), _geometryInputType(GL_TRIANGLES),
_geometryOutputType(GL_TRIANGLE_STRIP),
_patchVertices(3)
_patchVertices(3),
_numGroupsX(0), _numGroupsY(0), _numGroupsZ(0)
{
}
@@ -167,6 +168,10 @@ Program::Program(const Program& rhs, const osg::CopyOp& copyop):
_geometryOutputType = rhs._geometryOutputType;
_patchVertices = rhs._patchVertices;
_numGroupsX = rhs._numGroupsX;
_numGroupsY = rhs._numGroupsY;
_numGroupsZ = rhs._numGroupsZ;
}
@@ -203,6 +208,15 @@ int Program::compare(const osg::StateAttribute& sa) const
if( _patchVertices < rhs._patchVertices ) return -1;
if( rhs._patchVertices < _patchVertices ) 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;
ShaderList::const_iterator litr=_shaderList.begin();
ShaderList::const_iterator ritr=rhs._shaderList.begin();
@@ -397,6 +411,19 @@ GLint Program::getParameter( GLenum pname ) const
return 0;
}
void Program::setComputeGroups( GLint numGroupsX, GLint numGroupsY, GLint numGroupsZ )
{
_numGroupsX = numGroupsX;
_numGroupsY = numGroupsY;
_numGroupsZ = numGroupsZ;
}
void Program::getComputeGroups( GLint& numGroupsX, GLint& numGroupsY, GLint& numGroupsZ ) const
{
numGroupsX = _numGroupsX;
numGroupsY = _numGroupsY;
numGroupsZ = _numGroupsZ;
}
void Program::addBindAttribLocation( const std::string& name, GLuint index )
{
@@ -930,4 +957,8 @@ Program::ProgramBinary* Program::PerContextProgram::compileProgramBinary(osg::St
void Program::PerContextProgram::useProgram() const
{
_extensions->glUseProgram( _glProgramHandle );
if ( _program->_numGroupsX>0 && _program->_numGroupsY>0 && _program->_numGroupsZ>0 )
{
_extensions->glDispatchCompute( _program->_numGroupsX, _program->_numGroupsY, _program->_numGroupsZ );
}
}

View File

@@ -330,6 +330,7 @@ const char* Shader::getTypename() const
case TESSEVALUATION: return "TESSEVALUATION";
case GEOMETRY: return "GEOMETRY";
case FRAGMENT: return "FRAGMENT";
case COMPUTE: return "COMPUTE";
default: return "UNDEFINED";
}
}
@@ -342,6 +343,7 @@ Shader::Type Shader::getTypeId( const std::string& tname )
if( tname == "TESSEVALUATION") return TESSEVALUATION;
if( tname == "GEOMETRY" ) return GEOMETRY;
if( tname == "FRAGMENT" ) return FRAGMENT;
if( tname == "COMPUTE" ) return COMPUTE;
return UNDEFINED;
}

View File

@@ -52,6 +52,7 @@ osg::Program* ShaderComposer::getOrCreateProgram(const ShaderComponents& shaderC
Shaders tessEvaluationShaders;
Shaders geometryShaders;
Shaders fragmentShaders;
Shaders computeShaders;
OSG_NOTICE<<"ShaderComposer::getOrCreateProgram(shaderComponents.size()=="<<shaderComponents.size()<<std::endl;
@@ -81,6 +82,9 @@ osg::Program* ShaderComposer::getOrCreateProgram(const ShaderComponents& shaderC
case(Shader::FRAGMENT):
fragmentShaders.push_back(shader);
break;
case(Shader::COMPUTE):
computeShaders.push_back(shader);
break;
case(Shader::UNDEFINED):
OSG_WARN<<"Warning: ShaderCompose::getOrCreateProgam(ShaderComponts) encounterd invalid Shader::Type."<<std::endl;
break;
@@ -105,6 +109,11 @@ osg::Program* ShaderComposer::getOrCreateProgram(const ShaderComponents& shaderC
addShaderToProgram(program.get(), fragmentShaders);
}
if (!computeShaders.empty())
{
addShaderToProgram(program.get(), computeShaders);
}
// assign newly created program to map.
_programMap[shaderComponents] = program;

View File

@@ -1226,6 +1226,16 @@ void Texture::setMaxAnisotropy(float anis)
}
}
void Texture::bindToImageUnit(unsigned int unit, GLenum access, GLenum format, int level, bool layered, int layer)
{
_imageAttachment.unit = unit;
_imageAttachment.level = level;
_imageAttachment.layered = layered ? GL_TRUE : GL_FALSE;
_imageAttachment.layer = layer;
_imageAttachment.access = access;
_imageAttachment.format = format;
dirtyTextureParameters();
}
/** Force a recompile on next apply() of associated OpenGL texture objects.*/
void Texture::dirtyTextureObject()
@@ -1741,6 +1751,19 @@ void Texture::applyTexParameters(GLenum target, State& state) const
}
}
// Apply image load/store attributes
if (extensions->isBindImageTextureSupported() && _imageAttachment.access!=0)
{
TextureObject* tobj = getTextureObject(contextID);
if (tobj)
{
extensions->glBindImageTexture(
_imageAttachment.unit, tobj->id(), _imageAttachment.level,
_imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access,
_imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat);
}
}
getTextureParameterDirty(state.getContextID()) = false;
}
@@ -2590,6 +2613,8 @@ Texture::Extensions::Extensions(unsigned int contextID)
if (_glTexParameterIiv == NULL) setGLExtensionFuncPtr(_glTexParameterIiv, "glTexParameterIivEXT");
if (_glTexParameterIuiv == NULL) setGLExtensionFuncPtr(_glTexParameterIuiv, "glTexParameterIuivEXT");
setGLExtensionFuncPtr(_glBindImageTexture, "glBindImageTexture", "glBindImageTextureARB");
_isTextureMaxLevelSupported = ( getGLVersionNumber() >= 1.2f );
}

View File

@@ -23,6 +23,7 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
supportsExtension("glsl","OpenGL Shader Language format");
supportsExtension("tctrl","OpenGL Shader Language format");
supportsExtension("teval","OpenGL Shader Language format");
supportsExtension("compute","OpenGL Shader Language format");
}
virtual const char* className() const { return "GLSL Shader Reader"; }
@@ -100,6 +101,7 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
if (options->getOptionString().find("geometry")!=std::string::npos) shader->setType(osg::Shader::GEOMETRY);
if (options->getOptionString().find("tesscontrol")!=std::string::npos) shader->setType(osg::Shader::TESSCONTROL);
if (options->getOptionString().find("tessevaluation")!=std::string::npos) shader->setType(osg::Shader::TESSEVALUATION);
if (options->getOptionString().find("compute")!=std::string::npos) shader->setType(osg::Shader::COMPUTE);
}
// return valid shader
@@ -129,6 +131,7 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter
if (ext == "geom") shader->setType(osg::Shader::GEOMETRY);
if (ext == "tctrl") shader->setType(osg::Shader::TESSCONTROL);
if (ext == "teval") shader->setType(osg::Shader::TESSEVALUATION);
if (ext == "compute") shader->setType(osg::Shader::COMPUTE);
}
}
return rr;

View File

@@ -77,6 +77,30 @@ static bool writeShaders( osgDB::OutputStream& os, const osg::Program& attr )
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;
}
REGISTER_OBJECT_WRAPPER( Program,
new osg::Program,
osg::Program,
@@ -88,4 +112,8 @@ REGISTER_OBJECT_WRAPPER( Program,
ADD_USER_SERIALIZER( GeometryVerticesOut ); // _geometryVerticesOut
ADD_USER_SERIALIZER( GeometryInputType ); // _geometryInputType
ADD_USER_SERIALIZER( GeometryOutputType ); // _geometryOutputType
{
UPDATE_TO_VERSION_SCOPED( 95 )
ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z
}
}

View File

@@ -55,6 +55,7 @@ REGISTER_OBJECT_WRAPPER( Shader,
ADD_ENUM_VALUE( TESSEVALUATION );
ADD_ENUM_VALUE( FRAGMENT );
ADD_ENUM_VALUE( GEOMETRY );
ADD_ENUM_VALUE( COMPUTE );
ADD_ENUM_VALUE( UNDEFINED );
END_ENUM_SERIALIZER(); // _type

View File

@@ -70,6 +70,30 @@ static bool writeInternalFormat( osgDB::OutputStream& os, const osg::Texture& te
return true;
}
// _imageAttachment
static bool checkImageAttachment( const osg::Texture& attr )
{
return attr.getImageAttachment().access!=0;
}
static bool readImageAttachment( osgDB::InputStream& is, osg::Texture& attr )
{
osg::Texture::ImageAttachment attachment;
is >> attachment.unit >> attachment.level >> attachment.layered
>> attachment.layer >> attachment.access >> attachment.format;
attr.bindToImageUnit( attachment.unit, attachment.access, attachment.format,
attachment.level, attachment.layered!=GL_FALSE, attachment.layer );
return true;
}
static bool writeImageAttachment( osgDB::OutputStream& os, const osg::Texture& attr )
{
const osg::Texture::ImageAttachment& attachment = attr.getImageAttachment();
os << attachment.unit << attachment.level << attachment.layered
<< attachment.layer << attachment.access << attachment.format << std::endl;
return true;
}
REGISTER_OBJECT_WRAPPER( Texture,
/*new osg::Texture*/NULL,
osg::Texture,
@@ -127,4 +151,9 @@ REGISTER_OBJECT_WRAPPER( Texture,
END_ENUM_SERIALIZER(); // _shadow_texture_mode
ADD_FLOAT_SERIALIZER( ShadowAmbient, 0.0f ); // _shadow_ambient
{
UPDATE_TO_VERSION_SCOPED( 95 )
ADD_USER_SERIALIZER( ImageAttachment ); // _imageAttachment
}
}