Added new osg::ShaderBinary class, and support for it in osg::Shader.

This commit is contained in:
Robert Osfield 2009-11-16 12:32:41 +00:00
parent 22e01d3cba
commit 52fbe9723f
2 changed files with 163 additions and 25 deletions

View File

@ -30,6 +30,41 @@ namespace osg {
class Program;
/** Simple class for wrapping up the data used in OpenGL ES 2's glShaderBinary calls.
* ShaderBinary is set up with the binary data then assigned to one or more osg::Shader. */
class OSG_EXPORT ShaderBinary : public osg::Object
{
public:
ShaderBinary();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
ShaderBinary(const ShaderBinary& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Object(osg, ShaderBinary);
/** Allocated a data buffer of specified size/*/
void allocate(unsigned int size);
/** Assign shader binary data, copying the specified data into locally stored data buffer, the original data can then be deleted.*/
void assign(unsigned int size, const unsigned char* data);
/** Get the size of the shader binary data.*/
unsigned int getSize() const { return _data.size(); }
/** Get a ptr to the shader binary data.*/
unsigned char* getData() { return _data.empty() ? 0 : &(_data.front()); }
/** Get a const ptr to the shader binary data.*/
const unsigned char* getData() const { return _data.empty() ? 0 : &(_data.front()); }
protected:
typedef std::vector<unsigned char> Data;
Data _data;
};
///////////////////////////////////////////////////////////////////////////
/** osg::Shader is an application-level abstraction of an OpenGL glShader.
* It is a container to load the shader source code text and manage its
@ -51,8 +86,9 @@ class OSG_EXPORT Shader : public osg::Object
UNDEFINED = -1
};
Shader( Type type = UNDEFINED);
Shader( Type type, const std::string& source );
Shader(Type type = UNDEFINED);
Shader(Type type, const std::string& source );
Shader(Type type, ShaderBinary* shaderBinary );
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
Shader(const Shader& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
@ -61,11 +97,39 @@ class OSG_EXPORT Shader : public osg::Object
int compare(const Shader& rhs) const;
bool setType( Type t );
/** Set the Shader type as an enum. */
bool setType(Type t);
/** Get the Shader type as an enum. */
inline Type getType() const { return _type; }
/** Get the Shader type as a descriptive string. */
const char* getTypename() const;
/** Load the Shader's source code text from a string. */
void setShaderSource( const std::string& sourceText );
/** Set file name for the shader source code. */
inline void setFileName(const std::string& fileName) { _shaderFileName = fileName; }
/** Get filename to which the shader source code belongs. */
inline const std::string& getFileName() const { return _shaderFileName; }
/** Set the Shader's source code text from a string. */
void setShaderSource(const std::string& sourceText);
/** Query the shader's source code text */
inline const std::string& getShaderSource() const { return _shaderSource; }
/** Set the Shader using a ShaderBinary. */
void setShaderBinary(ShaderBinary* shaderBinary) { _shaderBinary = shaderBinary; }
/** Get the Shader's ShaderBinary, return NULL if none is assigned. */
ShaderBinary* getShaderBinary() { return _shaderBinary.get(); }
/** Get the const Shader's ShaderBinary, return NULL if none is assigned. */
const ShaderBinary* getShaderBinary() const { return _shaderBinary.get(); }
/** Read shader source from file and then constructor shader of specified type.
* Return the resulting Shader or 0 if no valid shader source code be read.*/
@ -74,20 +138,7 @@ class OSG_EXPORT Shader : public osg::Object
/** Load the Shader's source code text from a file. */
bool loadShaderSourceFromFile( const std::string& fileName );
/** Query the shader's source code text */
inline const std::string& getShaderSource() const { return _shaderSource; }
/** Get the Shader type as an enum. */
inline Type getType() const { return _type; }
/** Get the Shader type as a descriptive string. */
const char* getTypename() const;
/** Set file name for the shader source code. */
inline void setFileName(const std::string& fileName) { _shaderFileName = fileName; }
/** Get filename to which the shader source code belongs. */
inline const std::string& getFileName() const { return _shaderFileName; }
/** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int maxSize);
@ -182,12 +233,14 @@ class OSG_EXPORT Shader : public osg::Object
bool removeProgramRef( osg::Program* program );
protected: /*data*/
Type _type;
std::string _shaderSource;
std::string _shaderFileName;
Type _type;
std::string _shaderFileName;
std::string _shaderSource;
osg::ref_ptr<ShaderBinary> _shaderBinary;
/** osg::Programs that this osg::Shader is attached to */
typedef std::set< osg::Program* > ProgramSet;
ProgramSet _programSet;
ProgramSet _programSet;
mutable osg::buffered_value< osg::ref_ptr<PerContextShader> > _pcsList;
private:

View File

@ -36,7 +36,34 @@
using namespace osg;
///////////////////////////////////////////////////////////////////////////
ShaderBinary::ShaderBinary()
{
}
ShaderBinary::ShaderBinary(const ShaderBinary& rhs, const osg::CopyOp&):
_data(rhs._data)
{
}
void ShaderBinary::allocate(unsigned int size)
{
_data.clear();
_data.resize(size);
}
void ShaderBinary::assign(unsigned int size, const unsigned char* data)
{
allocate(size);
if (data)
{
for(unsigned int i=0; i<size; ++i)
{
_data[i] = data[i];
}
}
}
///////////////////////////////////////////////////////////////////////////
// static cache of glShaders flagged for deletion, which will actually
// be deleted in the correct GL context.
@ -109,11 +136,18 @@ Shader::Shader(Type type, const std::string& source) :
setShaderSource( source);
}
Shader::Shader(Type type, ShaderBinary* shaderBinary) :
_type(type)
{
}
Shader::Shader(const Shader& rhs, const osg::CopyOp& copyop):
osg::Object( rhs, copyop ),
_type(rhs._type),
_shaderFileName(rhs._shaderFileName),
_shaderSource(rhs._shaderSource),
_shaderFileName(rhs._shaderFileName)
_shaderBinary(rhs._shaderBinary)
{
}
@ -121,7 +155,7 @@ Shader::~Shader()
{
}
bool Shader::setType( Type t )
bool Shader::setType(Type t)
{
if (_type==t) return true;
@ -379,6 +413,57 @@ void Shader::PerContextShader::compileShader(osg::State& state)
if( ! _needsCompile ) return;
_needsCompile = false;
#if defined(OSG_GLES2_AVAILABLE)
if (_shader->getShaderBinary())
{
GLint numFormats;
glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &numFormats);
if (numFormats>0)
{
GLint* formats = new GLint[numFormats];
glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats);
for(GLint i=0; i<numFormats; ++i)
{
osg::notify(osg::NOTICE)<<" format="<<formats[i]<<std::endl;
GLenum shaderBinaryFormat = formats[i];
glShaderBinary(1, &_glShaderHandle, shaderBinaryFormat, _shader->getShaderBinary()->getData(), _shader->getShaderBinary()->getSize());
if (glGetError() == GL_NO_ERROR)
{
_isCompiled = true;
return;
}
}
delete [] formats;
if (_shader->getShaderSource().empty())
{
osg::notify(osg::WARN)<<"Warning: No suitable shader of supported format by GLES driver found in shader binary, unable to compile shader."<<std::endl;
_isCompiled = false;
return;
}
else
{
osg::notify(osg::NOTICE)<<"osg::Shader::compileShader(): No suitable shader of supported format by GLES driver found in shader binary, falling back to shader source."<<std::endl;
}
}
else
{
if (_shader->getShaderSource().empty())
{
osg::notify(osg::WARN)<<"Warning: No shader binary formats supported by GLES driver, unable to compile shader."<<std::endl;
_isCompiled = false;
return;
}
else
{
osg::notify(osg::NOTICE)<<"osg::Shader::compileShader(): No shader binary formats supported by GLES driver, falling back to shader source."<<std::endl;
}
}
}
#endif
std::string source = _shader->getShaderSource();
if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
{