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:
@@ -180,6 +180,7 @@ IF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ADD_SUBDIRECTORY(osgphotoalbum)
|
||||
ADD_SUBDIRECTORY(osgtessellate)
|
||||
ADD_SUBDIRECTORY(osgtessellationshaders)
|
||||
ADD_SUBDIRECTORY(osgcomputeshaders)
|
||||
|
||||
ADD_SUBDIRECTORY(osgpdf)
|
||||
|
||||
|
||||
2
examples/osgcomputeshaders/CMakeLists.txt
Normal file
2
examples/osgcomputeshaders/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
SET(TARGET_SRC osgcomputeshaders.cpp)
|
||||
SETUP_EXAMPLE(osgcomputeshaders)
|
||||
92
examples/osgcomputeshaders/osgcomputeshaders.cpp
Normal file
92
examples/osgcomputeshaders/osgcomputeshaders.cpp
Normal 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();
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user