From 18369bed2d888f26b104e834381ddee7530f5fb8 Mon Sep 17 00:00:00 2001 From: d-a-heitbrink Date: Fri, 13 Jan 2017 09:33:49 -0600 Subject: [PATCH 1/5] added code to deal with #extension for shader, added int64 and uint64 support --- src/osg/GLExtensions.cpp | 27 +++++++ src/osg/State.cpp | 7 ++ src/osg/Uniform.cpp | 169 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 200 insertions(+), 3 deletions(-) diff --git a/src/osg/GLExtensions.cpp b/src/osg/GLExtensions.cpp index 7a4b038a3..58068cf22 100644 --- a/src/osg/GLExtensions.cpp +++ b/src/osg/GLExtensions.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -637,6 +638,25 @@ GLExtensions::GLExtensions(unsigned int in_contextID): setGLExtensionFuncPtr(glUniform2uiv, "glUniform2uiv", "glUniform2uivEXT", validContext); setGLExtensionFuncPtr(glUniform3uiv, "glUniform3uiv", "glUniform3uivEXT", validContext); setGLExtensionFuncPtr(glUniform4uiv, "glUniform4uiv", "glUniform4uivEXT", validContext); + + // ARB_gpu_shader_int64 + setGLExtensionFuncPtr(glUniform1i64, "glUniform1i64", "glUniform1i64ARB", validContext); + setGLExtensionFuncPtr(glUniform1ui64, "glUniform1ui64", "glUniform1ui64ARB", validContext); + setGLExtensionFuncPtr(glUniform2i64, "glUniform2i64", "glUniform2i64ARB", validContext); + setGLExtensionFuncPtr(glUniform2ui64, "glUniform2ui64", "glUniform2ui64ARB", validContext); + setGLExtensionFuncPtr(glUniform3i64, "glUniform3i64", "glUniform3i64ARB", validContext); + setGLExtensionFuncPtr(glUniform3ui64, "glUniform3ui64", "glUniform3ui64ARB", validContext); + setGLExtensionFuncPtr(glUniform4i64, "glUniform4i64", "glUniform4i64ARB", validContext); + setGLExtensionFuncPtr(glUniform4ui64, "glUniform4ui64", "glUniform4ui64ARB", validContext); + setGLExtensionFuncPtr(glUniform1i64v, "glUniform1i64v", "glUniform1i64vARB", validContext); + setGLExtensionFuncPtr(glUniform1ui64v,"glUniform1ui64v","glUniform1ui64vARB",validContext); + setGLExtensionFuncPtr(glUniform2i64v, "glUniform2i64v", "glUniform2i64vARB", validContext); + setGLExtensionFuncPtr(glUniform2ui64v,"glUniform2ui64v","glUniform2ui64vARB",validContext); + setGLExtensionFuncPtr(glUniform3i64v, "glUniform3i64v", "glUniform3i64vARB", validContext); + setGLExtensionFuncPtr(glUniform3ui64v,"glUniform3ui64v","glUniform3ui64vARB",validContext); + setGLExtensionFuncPtr(glUniform4i64v, "glUniform4i64v", "glUniform4i64vARB", validContext); + setGLExtensionFuncPtr(glUniform4ui64v,"glUniform4ui64v","glUniform4ui64vARB",validContext); + // ARB_uniform_buffer_object setGLExtensionFuncPtr(glGetUniformIndices, "glGetUniformIndices", validContext); setGLExtensionFuncPtr(glGetActiveUniformsiv, "glGetActiveUniformsiv", validContext); @@ -937,6 +957,13 @@ GLExtensions::GLExtensions(unsigned int in_contextID): maxLayerCount = 0; if (validContext) glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &maxLayerCount); + // Bindless textures + setGLExtensionFuncPtr(glGetTextureHandle, "glGetTextureHandle", "glGetTextureHandleARB","glGetTextureHandleNV", validContext); + setGLExtensionFuncPtr(glMakeTextureHandleResident, "glMakeTextureHandleResident", "glMakeTextureHandleResidentARB","glMakeTextureHandleResidentNV", validContext); + setGLExtensionFuncPtr(glMakeTextureHandleNonResident, "glMakeTextureHandleNonResident", "glMakeTextureHandleNonResidentARB", "glMakeTextureHandleNonResidentNV",validContext); + setGLExtensionFuncPtr(glUniformHandleui64, "glUniformHandleui64", "glUniformHandleui64ARB","glUniformHandleui64NV", validContext); + setGLExtensionFuncPtr(glIsTextureHandleResident, "glIsTextureHandleResident","glIsTextureHandleResidentARB", "glIsTextureHandleResidentNV", validContext); + // Blending isBlendColorSupported = OSG_GLES2_FEATURES || OSG_GL3_FEATURES || isGLExtensionSupported(contextID,"GL_EXT_blend_color") || diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 030a57e5c..e0ddf6a0b 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -1226,6 +1226,13 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const declPos = 0; } + std::string::size_type extPos = source.rfind( "#extension " ); + if ( extPos != std::string::npos ) + { + // found the string, now find the next linefeed and set the insertion point after it. + declPos = source.find( '\n', extPos ); + declPos = declPos != std::string::npos ? declPos+1 : source.length(); + } if (_useModelViewAndProjectionUniforms) { // replace ftransform as it only works with built-ins diff --git a/src/osg/Uniform.cpp b/src/osg/Uniform.cpp index 2c0b103d7..50ab08552 100644 --- a/src/osg/Uniform.cpp +++ b/src/osg/Uniform.cpp @@ -168,6 +168,8 @@ bool Uniform::setArray( FloatArray* array ) _doubleArray = 0; _intArray = 0; _uintArray = 0; + _int64Array = 0; + _uint64Array = 0; dirty(); return true; } @@ -187,6 +189,8 @@ bool Uniform::setArray( DoubleArray* array ) _floatArray = 0; _intArray = 0; _uintArray = 0; + _int64Array = 0; + _uint64Array = 0; dirty(); return true; } @@ -206,6 +210,8 @@ bool Uniform::setArray( IntArray* array ) _floatArray = 0; _doubleArray = 0; _uintArray = 0; + _int64Array = 0; + _uint64Array = 0; dirty(); return true; } @@ -225,6 +231,49 @@ bool Uniform::setArray( UIntArray* array ) _floatArray = 0; _doubleArray = 0; _intArray = 0; + _int64Array = 0; + _uint64Array = 0; + dirty(); + return true; +} +bool Uniform::setArray( UInt64Array* array ) +{ + if( !array ) return false; + + // incoming array must match configuration of the Uniform + if( getInternalArrayType(getType())!=GL_UNSIGNED_INT || getInternalArrayNumElements()!=array->getNumElements() ) + { + OSG_WARN << "Uniform::setArray : incompatible array" << std::endl; + return false; + } + + _uint64Array = array; + _floatArray = 0; + _doubleArray = 0; + _intArray = 0; + _uintArray = 0; + _int64Array =0; + dirty(); + return true; +} + +bool Uniform::setArray( Int64Array* array ) +{ + if( !array ) return false; + + // incoming array must match configuration of the Uniform + if( getInternalArrayType(getType())!=GL_UNSIGNED_INT || getInternalArrayNumElements()!=array->getNumElements() ) + { + OSG_WARN << "Uniform::setArray : incompatible array" << std::endl; + return false; + } + + _int64Array = array; + _floatArray = 0; + _doubleArray = 0; + _intArray = 0; + _uintArray = 0; + _uint64Array =0; dirty(); return true; } @@ -282,6 +331,22 @@ int Uniform::compareData(const Uniform& rhs) const return memcmp( _uintArray->getDataPointer(), rhs._uintArray->getDataPointer(), _uintArray->getTotalDataSize() ); } + + else if( _uint64Array.valid() ) + { + if( ! rhs._uint64Array ) return 1; + if( _uint64Array == rhs._uint64Array ) return 0; + return memcmp( _uint64Array->getDataPointer(), rhs._uint64Array->getDataPointer(), + _uint64Array->getTotalDataSize() ); + } + + else if( _int64Array.valid() ) + { + if( ! rhs._int64Array ) return 1; + if( _int64Array == rhs._int64Array ) return 0; + return memcmp( _int64Array->getDataPointer(), rhs._int64Array->getDataPointer(), + _int64Array->getTotalDataSize() ); + } return -1; // how got here? } @@ -296,6 +361,8 @@ void Uniform::copyData(const Uniform& rhs) if( _doubleArray.valid() && rhs._doubleArray.valid() ) *_doubleArray = *rhs._doubleArray; if( _intArray.valid() && rhs._intArray.valid() ) *_intArray = *rhs._intArray; if( _uintArray.valid() && rhs._uintArray.valid() ) *_uintArray = *rhs._uintArray; + if( _int64Array.valid() && rhs._int64Array.valid() ) *_int64Array = *rhs._int64Array; + if( _uint64Array.valid() && rhs._uint64Array.valid() ) *_uint64Array = *rhs._uint64Array; dirty(); } @@ -361,6 +428,9 @@ const char* Uniform::getTypename( Type t ) case BOOL_VEC3: return "bvec3"; case BOOL_VEC4: return "bvec4"; + case INT64: return "int64_t"; + case UNSIGNED_INT64: return "uint64_t"; + case FLOAT_MAT2: return "mat2"; case FLOAT_MAT3: return "mat3"; case FLOAT_MAT4: return "mat4"; @@ -473,6 +543,8 @@ int Uniform::getTypeNumComponents( Type t ) case INT: case UNSIGNED_INT: case BOOL: + case UNSIGNED_INT64: + case INT64: case SAMPLER_1D: case SAMPLER_2D: @@ -635,6 +707,9 @@ Uniform::Type Uniform::getTypeId( const std::string& tname ) if( tname == "bvec3" ) return BOOL_VEC3; if( tname == "bvec4" ) return BOOL_VEC4; + if( tname == "uint64_t" ) return UNSIGNED_INT64; + if( tname == "int64_t" ) return INT64; + if( tname == "mat2" || tname == "mat2x2" ) return FLOAT_MAT2; if( tname == "mat3" || tname == "mat3x3" ) return FLOAT_MAT3; if( tname == "mat4" || tname == "mat4x4" ) return FLOAT_MAT4; @@ -832,6 +907,12 @@ Uniform::Type Uniform::getGlApiType( Type t ) case BOOL_VEC4: return INT_VEC4; + case UNSIGNED_INT64: + return UNSIGNED_INT64; + + case INT64: + return INT64; + default: return t; } @@ -965,6 +1046,12 @@ GLenum Uniform::getInternalArrayType( Type t ) case UNSIGNED_INT_VEC4: return GL_UNSIGNED_INT; + case UNSIGNED_INT64: + return GL_UNSIGNED_INT64_ARB; + + case INT64: + return GL_INT64_ARB; + default: return 0; } @@ -1298,8 +1385,21 @@ Uniform::Uniform( const char* name, bool b0, bool b1, bool b2, bool b3 ) : allocateDataArray(); set( b0, b1, b2, b3 ); } - -/////////////////////////////////////////////////////////////////////////// +Uniform::Uniform( const char* name, unsigned long long ull) : + _type(UNSIGNED_INT64), _numElements(1), _modifiedCount(0) +{ + setName(name); + allocateDataArray(); + set( ull ); +} +Uniform::Uniform( const char* name, long long ll) : + _type(INT64), _numElements(1), _modifiedCount(0) +{ + setName(name); + allocateDataArray(); + set( ll ); +} +//////////////////////////////////////////////////////////////////////// // Value assignment for single-element (ie: non-array) uniforms. // (For backwards compatibility, if not already configured, set the // Uniform's _numElements=1) @@ -1532,6 +1632,17 @@ bool Uniform::set( bool b0, bool b1, bool b2, bool b3 ) return isScalar() ? setElement(0,b0,b1,b2,b3) : false; } + +bool Uniform::set( unsigned long long ull ) +{ + if( getNumElements() == 0 ) setNumElements(1); + return isScalar() ? setElement(0,ull) : false; +} +bool Uniform::set( long long ll ) +{ + if( getNumElements() == 0 ) setNumElements(1); + return isScalar() ? setElement(0,ll) : false; +} /////////////////////////////////////////////////////////////////////////// // Value query for single-element (ie: non-array) uniforms. @@ -1725,6 +1836,14 @@ bool Uniform::get( bool& b0, bool& b1, bool& b2, bool& b3 ) const return isScalar() ? getElement(0,b0,b1,b2,b3) : false; } +bool Uniform::get( unsigned long long& ull ) const +{ + return isScalar() ? getElement(0,ull) : false; +} +bool Uniform::get( long long& ll ) const +{ + return isScalar() ? getElement(0,ll) : false; +} /////////////////////////////////////////////////////////////////////////// // Value assignment for array uniforms. @@ -2110,7 +2229,22 @@ bool Uniform::setElement( unsigned int index, bool b0, bool b1, bool b2, bool b3 dirty(); return true; } - +bool Uniform::setElement( unsigned int index, unsigned long long ull ) +{ + if( index>=getNumElements() || !isCompatibleType(UNSIGNED_INT64) ) return false; + unsigned int j = index * getTypeNumComponents(getType()); + (*_uint64Array)[j] = ull; + dirty(); + return true; +} +bool Uniform::setElement( unsigned int index, long long ll ) +{ + if( index>=getNumElements() || !isCompatibleType(INT64) ) return false; + unsigned int j = index * getTypeNumComponents(getType()); + (*_int64Array)[j] = ll; + dirty(); + return true; +} /////////////////////////////////////////////////////////////////////////// // Value query for array uniforms. @@ -2422,6 +2556,22 @@ bool Uniform::getElement( unsigned int index, bool& b ) const return true; } +bool Uniform::getElement( unsigned int index, unsigned long long& ull ) const +{ + if( index>=getNumElements() || !isCompatibleType(UNSIGNED_INT64) ) return false; + unsigned int j = index * getTypeNumComponents(getType()); + ull = ((*_uint64Array)[j] != 0); + return true; +} + +bool Uniform::getElement( unsigned int index, long long& ll ) const +{ + if( index>=getNumElements() || !isCompatibleType(INT64) ) return false; + unsigned int j = index * getTypeNumComponents(getType()); + ll = ((*_int64Array)[j] != 0); + return true; +} + bool Uniform::getElement( unsigned int index, bool& b0, bool& b1 ) const { if( index>=getNumElements() || !isCompatibleType(BOOL_VEC2) ) return false; @@ -2604,6 +2754,19 @@ void Uniform::apply(const GLExtensions* ext, GLint location) const if( _uintArray.valid() ) ext->glUniform4uiv( location, num, &_uintArray->front() ); break; + case UNSIGNED_INT64: + if( _uint64Array.valid() ){ + if (ext->glUniform1ui64v) + ext->glUniform1ui64v( location, num, &_uint64Array->front() ); + else + OSG_WARN << "how got here? " __FILE__ ":" << __LINE__ << std::endl; + } + break; + + case INT64: + if( _int64Array.valid() ) ext->glUniform1i64v( location, num, &_int64Array->front() ); + break; + default: OSG_FATAL << "how got here? " __FILE__ ":" << __LINE__ << std::endl; break; From 3d2f4ea4040bc14f94f40b7ef430e69d050cfb0c Mon Sep 17 00:00:00 2001 From: d-a-heitbrink Date: Fri, 13 Jan 2017 09:56:42 -0600 Subject: [PATCH 2/5] Added support for Bindless texture extension, 64 bit uniforms, 64 bit buffers Added new bindless texture example --- examples/CMakeLists.txt | 3 +- include/osg/Array | 20 +++++++++-- include/osg/GLDefines | 13 ++++++- include/osg/GLExtensions | 22 +++++++++++- include/osg/Uniform | 26 +++++++++++++- include/osgDB/DataTypes | 4 +++ include/osgDB/OutputStream | 2 ++ include/osgDB/StreamOperator | 2 ++ src/osgDB/ClassInterface.cpp | 2 ++ src/osgPlugins/ive/DataOutputStream.cpp | 34 ++++++++++++++++++- src/osgPlugins/ive/DataOutputStream.h | 6 +++- src/osgPlugins/ive/DataTypeSize.h | 2 +- src/osgPlugins/osg/AsciiStreamOperator.h | 6 ++++ src/osgPlugins/osg/BinaryStreamOperator.h | 12 +++++++ src/osgPlugins/osg/XmlStreamOperator.h | 12 +++++++ .../deprecated-dotosg/osg/Geometry.cpp | 15 ++++++++ 16 files changed, 171 insertions(+), 10 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 79d8ca3e6..d695fe86f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -166,10 +166,9 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgwidgettable) ADD_SUBDIRECTORY(osgwidgetwindow) ADD_SUBDIRECTORY(osguserdata) - # GL3/GL4 example ADD_SUBDIRECTORY(osgsimplegl3) - + ADD_SUBDIRECTORY(osgbindlesstext) IF(OSG_CPP_EXCEPTIONS_AVAILABLE) ADD_SUBDIRECTORY(osgunittests) ADD_SUBDIRECTORY(osgmemorytest) diff --git a/include/osg/Array b/include/osg/Array index 3a602c000..d7ae6609c 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -112,7 +112,10 @@ class OSG_EXPORT Array : public BufferData MatrixArrayType = 33, MatrixdArrayType = 34, - QuatArrayType = 35 + QuatArrayType = 35, + + UInt64ArrayType = 36, + Int64ArrayType = 37 }; enum Binding @@ -442,7 +445,8 @@ typedef TemplateArray typedef TemplateArray QuatArray; - +typedef TemplateIndexArray UInt64Array; +typedef TemplateIndexArray Int64Array; class ArrayVisitor { public: @@ -497,6 +501,9 @@ class ArrayVisitor virtual void apply(MatrixfArray&) {} virtual void apply(MatrixdArray&) {} + + virtual void apply(UInt64Array&) {} + virtual void apply(Int64Array&) {} }; class ConstArrayVisitor @@ -553,6 +560,9 @@ class ConstArrayVisitor virtual void apply(const MatrixfArray&) {} virtual void apply(const MatrixdArray&) {} + + virtual void apply(const UInt64Array&) {} + virtual void apply(const Int64Array&) {} }; @@ -610,6 +620,9 @@ class ValueVisitor virtual void apply(Matrixd&) {} virtual void apply(Quat&) {} + + virtual void apply(GLuint64&){} + virtual void apply(GLint64&){} }; class ConstValueVisitor @@ -666,6 +679,9 @@ class ConstValueVisitor virtual void apply(const Matrixd&) {} virtual void apply(const Quat&) {} + + virtual void apply(const GLuint64&){} + virtual void apply(const GLint64&){} }; template diff --git a/include/osg/GLDefines b/include/osg/GLDefines index 51b9e6134..b5442820d 100644 --- a/include/osg/GLDefines +++ b/include/osg/GLDefines @@ -556,6 +556,14 @@ typedef char GLchar; #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 #endif +#define GL_INT64_ARB 0x140E +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 /* ------------------------------ GL_KHR_debug ----------------------------- */ #ifndef GL_KHR_debug #define GL_KHR_debug 1 @@ -602,7 +610,6 @@ typedef char GLchar; #define GL_DEBUG_OUTPUT 0x92E0 #endif /* GL_KHR_debug */ - #ifndef GL_ARB_sync #define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 #define GL_OBJECT_TYPE 0x9112 @@ -653,6 +660,10 @@ typedef char GLchar; #define GL_ALPHA_TEST 0x0BC0 #endif +#ifndef GLuint64EXT + typedef uint64_t GLuint64EXT; +#endif + namespace osg { #ifndef GL_VERSION_3_2 diff --git a/include/osg/GLExtensions b/include/osg/GLExtensions index d4c46c093..3309660df 100644 --- a/include/osg/GLExtensions +++ b/include/osg/GLExtensions @@ -319,6 +319,22 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glUniform2uiv)( GLint location, GLsizei count, const GLuint *value ); void (GL_APIENTRY * glUniform3uiv)( GLint location, GLsizei count, const GLuint *value ); void (GL_APIENTRY * glUniform4uiv)( GLint location, GLsizei count, const GLuint *value ); + void (GL_APIENTRY * glUniform1i64 )(GLint location, GLint64 x) ; + void (GL_APIENTRY * glUniform1i64v )(GLint location, GLsizei count, const GLint64* value) ; + void (GL_APIENTRY * glUniform1ui64 )(GLint location, GLuint64 x) ; + void (GL_APIENTRY * glUniform1ui64v)(GLint location, GLsizei count, const GLuint64* value) ; + void (GL_APIENTRY * glUniform2i64 )(GLint location, GLint64 x, GLint64 y) ; + void (GL_APIENTRY * glUniform2i64v )(GLint location, GLsizei count, const GLint64* value) ; + void (GL_APIENTRY * glUniform2ui64 )(GLint location, GLuint64 x, GLuint64 y) ; + void (GL_APIENTRY * glUniform2ui64v)(GLint location, GLsizei count, const GLuint64* value) ; + void (GL_APIENTRY * glUniform3i64 )(GLint location, GLint64 x, GLint64 y, GLint64 z) ; + void (GL_APIENTRY * glUniform3i64v )(GLint location, GLsizei count, const GLint64* value) ; + void (GL_APIENTRY * glUniform3ui64 )(GLint location, GLuint64 x, GLuint64 y, GLuint64 z) ; + void (GL_APIENTRY * glUniform3ui64v)(GLint location, GLsizei count, const GLuint64* value) ; + void (GL_APIENTRY * glUniform4i64 )(GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w) ; + void (GL_APIENTRY * glUniform4i64v )(GLint location, GLsizei count, const GLint64* value) ; + void (GL_APIENTRY * glUniform4ui64 )(GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w) ; + void (GL_APIENTRY * glUniform4ui64v)(GLint location, GLsizei count, const GLuint64* value) ; GLuint (GL_APIENTRY * glGetHandleARB) (GLenum pname); void (GL_APIENTRY * glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices); void (GL_APIENTRY * glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); @@ -348,7 +364,11 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glUniformMatrix4x3dv)( GLint location, GLsizei count, GLboolean transpose, const GLdouble* value ); void (GL_APIENTRY * glGetActiveAtomicCounterBufferiv)( GLuint program, GLuint bufferIndex, GLenum pname, GLint* params ); void (GL_APIENTRY * glDispatchCompute)( GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ ); - + GLuint64EXT (GL_APIENTRY* glGetTextureHandle)(GLint texture); + void (GL_APIENTRY* glMakeTextureHandleResident)(GLuint64EXT handle); + void (GL_APIENTRY* glMakeTextureHandleNonResident)(GLuint64EXT handle); + void (GL_APIENTRY* glUniformHandleui64)(GLint location, GLuint64EXT handle); + GLboolean (GL_APIENTRY* glIsTextureHandleResident)(GLuint64EXT handle); // Buffer Object extensions bool isBufferObjectSupported; diff --git a/include/osg/Uniform b/include/osg/Uniform index 134897a6e..22fbc3993 100644 --- a/include/osg/Uniform +++ b/include/osg/Uniform @@ -439,6 +439,9 @@ class OSG_EXPORT Uniform : public Object BOOL_VEC3 = GL_BOOL_VEC3, BOOL_VEC4 = GL_BOOL_VEC4, + INT64 = GL_INT64_ARB, + UNSIGNED_INT64 = GL_UNSIGNED_INT64_ARB, + FLOAT_MAT2 = GL_FLOAT_MAT2, FLOAT_MAT3 = GL_FLOAT_MAT3, FLOAT_MAT4 = GL_FLOAT_MAT4, @@ -603,6 +606,8 @@ class OSG_EXPORT Uniform : public Object explicit Uniform( const char* name, int i ); explicit Uniform( const char* name, unsigned int ui ); explicit Uniform( const char* name, bool b ); + explicit Uniform( const char* name, unsigned long long ull); + explicit Uniform( const char* name, long long ll ); Uniform( const char* name, const osg::Vec2& v2 ); Uniform( const char* name, const osg::Vec3& v3 ); Uniform( const char* name, const osg::Vec4& v4 ); @@ -679,6 +684,8 @@ class OSG_EXPORT Uniform : public Object bool set( int i ); bool set( unsigned int ui ); bool set( bool b ); + bool set( unsigned long long ull ); + bool set( long long ll ); bool set( const osg::Vec2& v2 ); bool set( const osg::Vec3& v3 ); bool set( const osg::Vec4& v4 ); @@ -719,6 +726,8 @@ class OSG_EXPORT Uniform : public Object bool get( int& i ) const; bool get( unsigned int& ui ) const; bool get( bool& b ) const; + bool get( unsigned long long & ull ) const; + bool get( long long& ll ) const; bool get( osg::Vec2& v2 ) const; bool get( osg::Vec3& v3 ) const; bool get( osg::Vec4& v4 ) const; @@ -759,6 +768,8 @@ class OSG_EXPORT Uniform : public Object bool setElement( unsigned int index, int i ); bool setElement( unsigned int index, unsigned int ui ); bool setElement( unsigned int index, bool b ); + bool setElement( unsigned int index, unsigned long long ull ); + bool setElement( unsigned int index, long long ll ); bool setElement( unsigned int index, const osg::Vec2& v2 ); bool setElement( unsigned int index, const osg::Vec3& v3 ); bool setElement( unsigned int index, const osg::Vec4& v4 ); @@ -799,6 +810,8 @@ class OSG_EXPORT Uniform : public Object bool getElement( unsigned int index, int& i ) const; bool getElement( unsigned int index, unsigned int& ui ) const; bool getElement( unsigned int index, bool& b ) const; + bool getElement( unsigned int index, unsigned long long & ull ) const; + bool getElement( unsigned int index, long long& ll ) const; bool getElement( unsigned int index, osg::Vec2& v2 ) const; bool getElement( unsigned int index, osg::Vec3& v3 ) const; bool getElement( unsigned int index, osg::Vec4& v4 ) const; @@ -866,7 +879,8 @@ class OSG_EXPORT Uniform : public Object bool setArray( DoubleArray* array ); bool setArray( IntArray* array ); bool setArray( UIntArray* array ); - + bool setArray( UInt64Array* array ); + bool setArray( Int64Array* array ); /** Get the internal data array for a float osg::Uniform. */ FloatArray* getFloatArray() { return _floatArray.get(); } const FloatArray* getFloatArray() const { return _floatArray.get(); } @@ -883,6 +897,14 @@ class OSG_EXPORT Uniform : public Object UIntArray* getUIntArray() { return _uintArray.get(); } const UIntArray* getUIntArray() const { return _uintArray.get(); } + /** Get the internal data array for an unsigned int osg::Uniform. */ + UInt64Array* getUInt64Array() { return _uint64Array.get(); } + const UInt64Array* getUInt64Array() const { return _uint64Array.get(); } + + /** Get the internal data array for an unsigned int osg::Uniform. */ + Int64Array* getInt64Array() { return _int64Array.get(); } + const Int64Array* getInt64Array() const { return _int64Array.get(); } + inline void setModifiedCount(unsigned int mc) { _modifiedCount = mc; } inline unsigned int getModifiedCount() const { return _modifiedCount; } @@ -922,6 +944,8 @@ class OSG_EXPORT Uniform : public Object ref_ptr _doubleArray; ref_ptr _intArray; ref_ptr _uintArray; + ref_ptr _int64Array; + ref_ptr _uint64Array; ref_ptr _updateCallback; ref_ptr _eventCallback; diff --git a/include/osgDB/DataTypes b/include/osgDB/DataTypes index db8a70cd2..8d319e806 100644 --- a/include/osgDB/DataTypes +++ b/include/osgDB/DataTypes @@ -33,6 +33,7 @@ const int CHAR_SIZE = 1; const int SHORT_SIZE = 2; const int INT_SIZE = 4; const int LONG_SIZE = 4; +const int INT64_SIZE = 8; const int FLOAT_SIZE = 4; const int DOUBLE_SIZE = 8; const int GLENUM_SIZE = 4; @@ -71,6 +72,9 @@ const int ID_VEC2UI_ARRAY = 29; const int ID_VEC3UI_ARRAY = 30; const int ID_VEC4UI_ARRAY = 31; +const int ID_UINT64_ARRAY = 32; +const int ID_INT64_ARRAY = 33; + const int ID_DRAWARRAYS = 50; const int ID_DRAWARRAY_LENGTH = 51; const int ID_DRAWELEMENTS_UBYTE = 52; diff --git a/include/osgDB/OutputStream b/include/osgDB/OutputStream index 538ff9755..d312680bb 100644 --- a/include/osgDB/OutputStream +++ b/include/osgDB/OutputStream @@ -102,6 +102,8 @@ public: OutputStream& operator<<( unsigned long l ) { _out->writeULong(l); return *this; } OutputStream& operator<<( float f ) { _out->writeFloat(f); return *this; } OutputStream& operator<<( double d ) { _out->writeDouble(d); return *this; } + OutputStream& operator<<( long long ll ) { _out->writeInt64(ll); return *this; } + OutputStream& operator<<( unsigned long long ull ) { _out->writeUInt64(ull); return *this; } OutputStream& operator<<( const std::string& s ) { _out->writeString(s); return *this; } OutputStream& operator<<( const char* s ) { _out->writeString(s); return *this; } OutputStream& operator<<( std::ostream& (*fn)(std::ostream&) ) { _out->writeStream(fn); return *this; } diff --git a/include/osgDB/StreamOperator b/include/osgDB/StreamOperator index c4abc1331..6b29e29dd 100644 --- a/include/osgDB/StreamOperator +++ b/include/osgDB/StreamOperator @@ -37,6 +37,8 @@ public: virtual void writeUInt( unsigned int i ) = 0; virtual void writeLong( long l ) = 0; virtual void writeULong( unsigned long l ) = 0; + virtual void writeInt64( int64_t ll ) = 0; + virtual void writeUInt64( uint64_t ull ) = 0; virtual void writeFloat( float f ) = 0; virtual void writeDouble( double d ) = 0; virtual void writeString( const std::string& s ) = 0; diff --git a/src/osgDB/ClassInterface.cpp b/src/osgDB/ClassInterface.cpp index 15253262b..f2c7c0b8b 100644 --- a/src/osgDB/ClassInterface.cpp +++ b/src/osgDB/ClassInterface.cpp @@ -58,6 +58,8 @@ public: virtual void writeULong( unsigned long l ) { write(l); } virtual void writeFloat( float f ) { write(f); } virtual void writeDouble( double d ) { write(d); } + virtual void writeInt64( long long ll ) { write(ll); } + virtual void writeUInt64( unsigned long long ull ) { write(ull); } virtual void writeString( const std::string& s ) { _str.insert(_str.end(), s.begin(), s.end()); } virtual void writeStream( std::ostream& (*)(std::ostream&) ) {} virtual void writeBase( std::ios_base& (*)(std::ios_base&) ) {} diff --git a/src/osgPlugins/ive/DataOutputStream.cpp b/src/osgPlugins/ive/DataOutputStream.cpp index dde9203c4..afeada60e 100644 --- a/src/osgPlugins/ive/DataOutputStream.cpp +++ b/src/osgPlugins/ive/DataOutputStream.cpp @@ -497,6 +497,34 @@ void DataOutputStream::writeVec4b(const osg::Vec4b& v){ if (_verboseOutput) std::cout<<"read/writeVec4b() ["<write((char*)&ull, INT64SIZE); + + if (_verboseOutput) std::cout<<"read/writeUInt64() ["<write((char*)&ll, INT64SIZE); + + if (_verboseOutput) std::cout<<"read/writeInt64() ["<getNumElements(); + writeUInt64(size); + for(int i =0; igetNumElements(); + writeInt64(size); + for(int i =0; i(a)); break; - case osg::Array::Vec4dArrayType: + case osg::Array::Vec4dArrayType: writeChar((char)17); writeVec4dArray(static_cast(a)); break; + case osg::Array::UInt64ArrayType: + writeChar((char)18); + writeUInt64Array(static_cast(a)); + break; default: throwException("Unknown array type in DataOutputStream::writeArray()"); } } diff --git a/src/osgPlugins/ive/DataOutputStream.h b/src/osgPlugins/ive/DataOutputStream.h index 9969079bc..262c5cb9a 100644 --- a/src/osgPlugins/ive/DataOutputStream.h +++ b/src/osgPlugins/ive/DataOutputStream.h @@ -72,7 +72,11 @@ public: void writeVec2b(const osg::Vec2b& v); void writeVec3b(const osg::Vec3b& v); void writeVec4b(const osg::Vec4b& v); - + + void writeUInt64(unsigned long long ull); + void writeInt64(long long ll); + void writeUInt64Array(const osg::UInt64Array* a); + void writeInt64Array(const osg::Int64Array* a); void writePackedFloatArray(const osg::FloatArray* a, float maxError); void writeFloatArray(const osg::FloatArray* a); diff --git a/src/osgPlugins/ive/DataTypeSize.h b/src/osgPlugins/ive/DataTypeSize.h index 7b9c0db8c..a82cf5fbc 100644 --- a/src/osgPlugins/ive/DataTypeSize.h +++ b/src/osgPlugins/ive/DataTypeSize.h @@ -9,7 +9,7 @@ #define FLOATSIZE 4 #define LONGSIZE 4 #define DOUBLESIZE 8 - +#define INT64SIZE 8 //Don't know where else to put this namespace ive{ diff --git a/src/osgPlugins/osg/AsciiStreamOperator.h b/src/osgPlugins/osg/AsciiStreamOperator.h index c0925e989..0097d575c 100644 --- a/src/osgPlugins/osg/AsciiStreamOperator.h +++ b/src/osgPlugins/osg/AsciiStreamOperator.h @@ -49,6 +49,12 @@ public: virtual void writeULong( unsigned long l ) { indentIfRequired(); *_out << l << ' '; } + virtual void writeInt64( long long ll ) + { indentIfRequired(); *_out << ll << ' '; } + + virtual void writeUInt64( unsigned long long ull ) + { indentIfRequired(); *_out << ull << ' '; } + virtual void writeFloat( float f ) { indentIfRequired(); *_out << f << ' '; } diff --git a/src/osgPlugins/osg/BinaryStreamOperator.h b/src/osgPlugins/osg/BinaryStreamOperator.h index 479a844e1..552bb10ff 100644 --- a/src/osgPlugins/osg/BinaryStreamOperator.h +++ b/src/osgPlugins/osg/BinaryStreamOperator.h @@ -49,6 +49,18 @@ public: _out->write( (char*)&value, osgDB::LONG_SIZE ); } + virtual void writeInt64( int64_t ll ) + {_out->write( (char*)&ll, osgDB::INT64_SIZE );} + + virtual void writeUInt64( uint64_t ull ) + {_out->write( (char*)&ull, osgDB::INT64_SIZE );} + + virtual void writeInt( long long ll ) + { _out->write( (char*)&ll, osgDB::INT64_SIZE ); } + + virtual void writeUInt( unsigned long long ull ) + { _out->write( (char*)&ull, osgDB::INT64_SIZE ); } + virtual void writeFloat( float f ) { _out->write( (char*)&f, osgDB::FLOAT_SIZE ); } diff --git a/src/osgPlugins/osg/XmlStreamOperator.h b/src/osgPlugins/osg/XmlStreamOperator.h index 33bb50f7a..07c740737 100644 --- a/src/osgPlugins/osg/XmlStreamOperator.h +++ b/src/osgPlugins/osg/XmlStreamOperator.h @@ -59,6 +59,18 @@ public: virtual void writeULong( unsigned long l ) { _sstream << l; addToCurrentNode( _sstream.str() ); _sstream.str(""); } + virtual void writeUInt64(uint64_t ull) + {_sstream << ull; addToCurrentNode( _sstream.str() ); _sstream.str("");} + + virtual void writeInt64(int64_t ll) + {_sstream << ll; addToCurrentNode( _sstream.str() ); _sstream.str("");} + + virtual void writeInt( unsigned long long ull ) + { _sstream << ull; addToCurrentNode( _sstream.str() ); _sstream.str(""); } + + virtual void writeUInt( long long ll ) + { _sstream << ll; addToCurrentNode( _sstream.str() ); _sstream.str(""); } + virtual void writeFloat( float f ) { _sstream << f; addToCurrentNode( _sstream.str() ); _sstream.str(""); } diff --git a/src/osgWrappers/deprecated-dotosg/osg/Geometry.cpp b/src/osgWrappers/deprecated-dotosg/osg/Geometry.cpp index 8b0489b3c..3d42e35e1 100644 --- a/src/osgWrappers/deprecated-dotosg/osg/Geometry.cpp +++ b/src/osgWrappers/deprecated-dotosg/osg/Geometry.cpp @@ -995,6 +995,21 @@ bool Array_writeLocalData(const Array& array,Output& fw) return true; } break; + case(Array::UInt64ArrayType): + { + fw<(array.getDataPointer()); + writeArray(fw,&base[0], &base[array.getNumElements()]); + return true; + } + case(Array::Int64ArrayType): + { + fw<(array.getDataPointer()); + writeArray(fw,&base[0], &base[array.getNumElements()]); + return true; + } + break; case(Array::ArrayType): default: return false; From 98e0b7e41cf3a48e0509e5a7925ca840c64481d6 Mon Sep 17 00:00:00 2001 From: d-a-heitbrink Date: Fri, 13 Jan 2017 09:57:32 -0600 Subject: [PATCH 3/5] missing CMakeLists --- examples/osgbindlesstext/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 examples/osgbindlesstext/CMakeLists.txt diff --git a/examples/osgbindlesstext/CMakeLists.txt b/examples/osgbindlesstext/CMakeLists.txt new file mode 100644 index 000000000..8dfd28a92 --- /dev/null +++ b/examples/osgbindlesstext/CMakeLists.txt @@ -0,0 +1,2 @@ +SET(TARGET_SRC osgbindlesstext.cpp ) +SETUP_EXAMPLE(osgbindlesstext) \ No newline at end of file From 69b8d01de6bfa4a4256d6720f8244d03377de354 Mon Sep 17 00:00:00 2001 From: D-A-Heitbrink Date: Wed, 1 Mar 2017 15:33:19 -0600 Subject: [PATCH 4/5] Add files via upload --- examples/osgbindlesstext/osgbindlesstext.cpp | 599 +++++++++++++++++++ 1 file changed, 599 insertions(+) create mode 100644 examples/osgbindlesstext/osgbindlesstext.cpp diff --git a/examples/osgbindlesstext/osgbindlesstext.cpp b/examples/osgbindlesstext/osgbindlesstext.cpp new file mode 100644 index 000000000..a5555ed66 --- /dev/null +++ b/examples/osgbindlesstext/osgbindlesstext.cpp @@ -0,0 +1,599 @@ +/* OpenSceneGraph example, osgbindlesstex. +* +* 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. +*/ + +///\author David A Heitbrink +/// This is an example implementation of the use of bindless textures. +/// "bindless" textures are relatively simple concept, basically +/// you get a texture handle, then ask the driver to keep said +/// handle resident. +/// +/// Once the texture has been made resident, we need to upload +/// the handle (a 64 bit unsigned int) to the shader. This can +/// be done in a number of ways, through attributes, uniform +/// buffer objects, shader buffer objects or just plain uniforms. +/// +/// The basic point of the bindless texture is to remove the need +/// to bind a new texture every time we want to render something +/// with a different texture. Generally speaking in broad terms +/// driver overhead tends to be a huge bottle neck on modern +/// hardware (as of late 2016). By using bindless textures +/// we can remove alot of calls to the driver to switch active +/// textures while rendering. What this also allows us to do +/// is to consolidate more objects + draw states as we do +/// not need to change textures, this save us alot of calls to +/// the driver. +/// +/// This example combines instancing with bindless textures +/// to draw 1000 cubes, each with a unique texture. This is +/// a pretty simplified example, where each instance ID is +/// used as a index into the array of textures. +/// +/// One of the powerfull things about bindless textures is it allows +/// many more objects to be combined into a single drawable. +/// However to do this you may need to add an attribute to +/// use an index into the array of texture handles, and not +/// just use the instance ID like in this example. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +#include + +#include +#include + +#include + +#include +#include +//Hard coded constant for number unique textures +const int TextureCount = 1000; +// To use bindless textures, we need to tell the GPU to +// enable the use of 64 bit integers and bindless textures +// +// +// At this time (late 2016) NVidia drivers seem to dislike +// the ARB, GL_ARB_bindless_texture, if you do not have a +// NVidia driver, you will most likely have to change: +// GL_NV_gpu_shader5 +// to: +// GL_ARB_gpu_shader5 + +//the XXX is so we can replace it with a string from TextureCount +std::string vertShader= +"#version 450 compatibility \n" +"#extension GL_ARB_bindless_texture : require \n" +"#extension GL_NV_gpu_shader5 : require // uint64_t \n" +"//#extension GL_ARB_gpu_shader5 : require // uint64_t \n" +"//#extension GL_ARB_gpu_shader_int64: require // uint64_t \n" +"in float osg_FrameTime; \n" +"out vec2 TexCoord; \n" +"flat out int textureIndex; \n" +"void main() { \n" +" mat4 scale =mat4(0.01, 0.00, 0.00, 0.00, \n" +" 0.00, 0.01, 0.00, 0.00, \n" +" 0.00, 0.00, 0.01, 0.00, \n" +" 0.00, 0.00, 0.00, 1.00); \n" +" vec4 pos = gl_Vertex*scale; \n" +" pos.x += ((gl_InstanceID%100)/10)*0.015-0.075; \n" +" pos.y += (gl_InstanceID/100)*0.015 - 0.075; \n" +" pos.z += (gl_InstanceID%10)*0.015 - 0.075; \n" +" pos.w = 1; \n" +" gl_Position = gl_ModelViewProjectionMatrix*pos; \n" +" TexCoord = gl_MultiTexCoord0.xy; \n" +" textureIndex = gl_InstanceID%XXX; \n" +"} \n" +; +//we could setup tex to be of type sampler2D, and not have to do +//the type conversion, but I wanted to added code to test if tex +//had a value set. +//If we get a red cube, we are not getting our handle from our UBO, +//if we get a black cube, then we are having an issue with the +//texture handle itself +std::string fragShader = +"#version 450 compatibility \n" +"#extension GL_ARB_bindless_texture : require \n" +"#extension GL_NV_gpu_shader5 : require // uint64_t \n" +"//#extension GL_ARB_gpu_shader5 : require // uint64_t \n" +"//#extension GL_ARB_gpu_shader_int64: require // uint64_t \n" +"uniform sampler2D TextureId; \n" +"in vec2 TexCoord; \n" +"flat in int textureIndex; \n" +"layout (binding = 0, std140) uniform TEXTURE_BLOCK \n" +"{ \n" +" uint64_t tex[XXX]; \n" +"}; \n" +"void main() { \n" +" int tIndex = (int)(textureIndex); \n" +" sampler2D myText = sampler2D(tex[tIndex]); \n" +" gl_FragColor = texture2D(myText,TexCoord); \n" +" if (tex[tIndex] == 0) gl_FragColor.r = 1.0; \n" +"} \n" +; + +///This class provides a basic wraper for a Uniform Buffer Object +///or UBO, and provides the storage for the texture handles +class BindlessBuffer: public osg::Referenced{ +public: + typedef osg::ref_ptr UniBufferObjRef; + typedef osg::ref_ptr UniBufferBindingRef; + typedef osg::ref_ptr HandleArrayRef; + typedef osg::ref_ptr BindlessBufferRef; + static BindlessBufferRef Make(size_t count){ + BindlessBufferRef val = new BindlessBuffer(); + val->_count = count; + val->_sbbo = new osg::UniformBufferObject; + val->_handles = new osg::UInt64Array(); + val->_handles->resize(count*2,0); + val->_handles->setBufferObject(val->_sbbo); + val->_ssbb = new osg::UniformBufferBinding(0, val->_sbbo.get(), 0, sizeof(GLuint64)*count); + return val; + } + BindlessBuffer& operator = (const BindlessBuffer& rhs){ + if (this != &rhs){ + _count=rhs._count; + _sbbo =rhs._sbbo ; + _ssbb =rhs._ssbb ; + _handles = rhs._handles; + } + return *this; + } + BindlessBuffer(const BindlessBuffer& rhs):osg::Referenced(rhs){ + if (this != &rhs){ + _count=rhs._count; + _sbbo =rhs._sbbo ; + _ssbb =rhs._ssbb ; + _handles = rhs._handles; + } + } + UniBufferObjRef& Object(){return _sbbo;} + UniBufferBindingRef& Binding(){return _ssbb;} + HandleArrayRef& Handles(){return _handles;} + int count(){return _count;} +private: + int _count; + UniBufferObjRef _sbbo; + UniBufferBindingRef _ssbb; + HandleArrayRef _handles; + + BindlessBuffer():osg::Referenced(),_count(0){ + } +}; + +///This class extends a Texture, when this is texture is applied +///the first time, it will setup all our texture handles, after that +///it will not make any more GL calls until it gets released +class BindlessTexture: public osg::Texture2D +{ +public: + typedef osg::ref_ptr BufferRef; + typedef std::vector > TextureList; + typedef std::vector HandleList; + typedef osg::ref_ptr< osg::Texture::TextureObject> TextureObjectRef; + typedef std::vector TextureObjectList; + typedef osg::buffered_object TextureObjectBuffer; + + BindlessTexture(); + BindlessTexture(BufferRef, TextureList); + BindlessTexture(const BindlessTexture& rhs, const osg::CopyOp& copy =osg::CopyOp::SHALLOW_COPY); + void releaseGLObjects(osg::State* state) const; + void resizeGLObjectBuffers(unsigned maxSize); + void setBidlessIndex(unsigned int index); + META_StateAttribute(osg, BindlessTexture, TEXTURE); + + void apply(osg::State& state) const; +protected: + void applyOnce(osg::State &state) const; + mutable osg::buffered_object _handles; + mutable TextureList _textureList; + mutable osg::ref_ptr _buffer; + mutable std::vector _isBound; + mutable TextureObjectBuffer _textureBufferList; + // array index = texture image unit. + unsigned int _bindlessIndex; +}; + + +BindlessTexture::BindlessTexture():osg::Texture2D(),_bindlessIndex(0) +{ + _isBound.resize(5,false); +} + +BindlessTexture::BindlessTexture(const BindlessTexture& rhs, const osg::CopyOp& copy) + :osg::Texture2D( rhs, copy ) +{ + _isBound.resize(5,false); + _buffer = rhs._buffer; + _bindlessIndex = rhs._bindlessIndex; + for(unsigned i=0; i image = _image; + if (_handles[contextID].size() < _textureList.size()) + _handles[contextID].resize( _textureList.size(),0); + if (_textureBufferList[contextID].size() < _textureList.size()) + _textureBufferList[contextID].resize( _textureList.size()); + int txtcount = _textureList.size(); + if (_buffer->count() < txtcount) + txtcount = _buffer->count(); + //for each actual texture we have, bind it, get the texture hande, assign the value to our UBO + for (int i = 0; i bind(); + applyTexParameters(GL_TEXTURE_2D,state); + + applyTexImage2D_load(state,GL_TEXTURE_2D,image.get(), + _textureWidth, _textureHeight, _numMipmapLevels); + textureObject->setAllocated(true); + _textureBufferList[contextID][i] = textureObject; + + //Here is where the "magic" happens, we get the texture handle for our texture, copy it to our UBO, + //and then tell OpenGL to keep the handle resident + _handles[contextID][i] = extensions->glGetTextureHandle( textureObject->id() ); + std::vector &vec = _buffer->Handles()->asVector(); + vec[i*2] = _handles[contextID][i]; + _buffer->Object()->dirty(); + _buffer->Handles()->dirty(); + + if ( _handles[contextID][i] != 0L || extensions->glIsTextureHandleResident( _handles[contextID][i]) == GL_FALSE) + { + extensions->glMakeTextureHandleResident( _handles[contextID][i] ); + } + } + + // update the modified tag to show that it is up to date. + getModifiedCount(contextID) = image->getModifiedCount(); +} + +void BindlessTexture::apply(osg::State& state) const +{ + unsigned contextID = state.getContextID(); + if ( _isBound[contextID] == false ) + { + applyOnce(state); + _isBound[contextID] = true; + }else{ + //we should mostly hit this durring the lifetime of this object, + //note we basically do nothing...... + } +} +/// cleanup, we just need to tell OpenGL to release our texture handle +void BindlessTexture::releaseGLObjects(osg::State* state) const +{ + if ( state ) + { + unsigned contextID = state->getContextID(); + osg::Texture2D::releaseGLObjects( state ); + osg::GLExtensions* ext = osg::GLExtensions::Get( contextID, true ); + + for(unsigned i=0; i<_handles[contextID].size(); ++i) + { + ext->glMakeTextureHandleNonResident( _handles[contextID][i] ); + _handles[contextID][i] = 0; + } + + } +} + +void +BindlessTexture::resizeGLObjectBuffers(unsigned maxSize) +{ + osg::Texture2D::resizeGLObjectBuffers( maxSize ); + + size_t handleSize = _handles.size(); + size_t txtSize = _textureList.size(); + size_t boundSize = _isBound.size(); + if ( handleSize < maxSize ) { + _isBound.resize(maxSize,false); + } + if ( handleSize < maxSize ) { + _handles.resize( maxSize ); + for(unsigned i=handleSize; i<_handles.size(); ++i){ + for(unsigned j=0; j ImageRef; +/////////////////////////////////////////////////////// +///Create an array of images, with checkerboard +///pattern with random color and size +/// +void createImageArray(osg::StateSet* attachPnt){ + BindlessTexture::TextureList images; + images.resize(TextureCount); + BindlessBuffer::BindlessBufferRef buffer = BindlessBuffer::Make(TextureCount); + srand (time(NULL)); + for (int i =0; i < TextureCount; i++){ + ImageRef tImage = new osg::Image(); + int powerOf2 = rand()%6+4; + const unsigned int imageSize = 1<allocateImage(imageSize,imageSize,1,GL_RGBA,GL_UNSIGNED_BYTE); + unsigned char* buff = tImage->data(); + const int stride = 4; + unsigned char primaryColor[4]; + + int boxWidth = rand()%15+2; + int boxLength = rand()%15+2; + + //light squares + primaryColor[0] = rand()%128 + 128; + primaryColor[1] = rand()%128 + 128; + primaryColor[2] = rand()%128 + 128; + //dark squares + unsigned char secondaryColor[4]; + secondaryColor[0] = rand()%128; + secondaryColor[1] = rand()%128; + secondaryColor[2] = rand()%128; + for (int x = 0; x < imageSize; x++){ + for (int y =0; y0; + if (isPrimaryColor){ + pixel[0] = primaryColor[0]; + pixel[1] = primaryColor[1]; + pixel[2] = primaryColor[2]; + }else{ + pixel[0] = secondaryColor[0]; + pixel[1] = secondaryColor[1]; + pixel[2] = secondaryColor[2]; + } + pixel[3] = 255; + } + } + images[i] = tImage; + + std::stringstream sstr; + sstr<<"Image"<setName(sstr.str()); + } + BindlessTexture* tex = new BindlessTexture(buffer,images); + attachPnt->setTextureAttribute(0,tex,osg::StateAttribute::ON); + attachPnt->setAttributeAndModes(buffer->Binding(), osg::StateAttribute::ON); +} +///Create a cube centered at the origin, with given by size +/// +osg::Geometry* createCube(float scale, osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f) ) +{ + osg::Geometry* geometry = new osg::Geometry; + geometry->setName("TexturedCubeArray"); + + osg::Vec3Array* vertices = new osg::Vec3Array; + geometry->setVertexArray(vertices); + + osg::Vec2Array* tcoords = new osg::Vec2Array(); + geometry->setTexCoordArray(0,tcoords); + + origin -= osg::Vec3(scale/2.0f,scale/2.0f,scale/2.0f); + osg::Vec3 dx(scale,0.0f,0.0f); + osg::Vec3 dy(0.0f,scale,0.0f); + osg::Vec3 dz(0.0f,0.0f,scale); + + { + // front face + vertices->push_back(origin); + vertices->push_back(origin+dx); + vertices->push_back(origin+dx+dz); + vertices->push_back(origin+dz); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + + { + // back face + vertices->push_back(origin+dy); + vertices->push_back(origin+dy+dz); + vertices->push_back(origin+dy+dx+dz); + vertices->push_back(origin+dy+dx); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + + { + // left face + vertices->push_back(origin+dy); + vertices->push_back(origin); + vertices->push_back(origin+dz); + vertices->push_back(origin+dy+dz); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + + { + // right face + vertices->push_back(origin+dx+dy); + vertices->push_back(origin+dx+dy+dz); + vertices->push_back(origin+dx+dz); + vertices->push_back(origin+dx); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + + { + // top face + vertices->push_back(origin+dz); + vertices->push_back(origin+dz+dx); + vertices->push_back(origin+dz+dx+dy); + vertices->push_back(origin+dz+dy); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + + { + // bottom face + vertices->push_back(origin); + vertices->push_back(origin+dy); + vertices->push_back(origin+dx+dy); + vertices->push_back(origin+dx); + + tcoords->push_back(osg::Vec2(0.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,0.0f)); + tcoords->push_back(osg::Vec2(1.0f,1.0f)); + tcoords->push_back(osg::Vec2(0.0f,1.0f)); + } + osg::DrawArrays* primSet = new osg::DrawArrays(GL_QUADS, 0, vertices->size()); + geometry->addPrimitiveSet(primSet); + + return geometry; +} +/// +///Here we are going to create our scene, basically we need to make sure our +///Bindless texture gets applied before our shader programs. +/// +/// +osg::Group* CreateScene(){ + osg::Group* sceneRoot= new osg::Group(); + sceneRoot->setName("Root"); + osg::Geode *geo = new osg::Geode(); + geo->setName("Geo"); + sceneRoot->addChild(geo); + float size = 1.0f; + osg::StateSet* scene_ss = sceneRoot->getOrCreateStateSet(); + createImageArray(scene_ss); + scene_ss->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON); + + osg::ref_ptr geom = createCube(0.9f); + osg::PrimitiveSet *prim = geom->getPrimitiveSet(0); + //instanced elements must use VBOs + geom->setUseDisplayList(false); + geom->setUseVertexBufferObjects(true); + geom->setCullingActive(false); + prim->setNumInstances(1000); + prim->dirty(); + sceneRoot->addChild(geo); + geo->addDrawable(geom.get()); + + osg::StateSet* ss = geo->getOrCreateStateSet(); + + std::string strTextureCount; + std::stringstream ssconv; + ssconv<>strTextureCount; + std::string::size_type pos = vertShader.find("XXX"); + vertShader.replace(pos,size_t(3),strTextureCount); + + pos = fragShader.find("XXX"); + fragShader.replace(pos,size_t(3),strTextureCount); + + osg::Program* program = new osg::Program; + osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertShader); + program->addShader(vertex_shader); + + osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragShader); + program->addShader(fragment_shader); + + ss->setAttributeAndModes(program, osg::StateAttribute::ON); + + + return sceneRoot; + } +int main(int argc, char** argv) +{ + // construct the viewer + osg::ArgumentParser arguments(&argc,argv); + + // construct the viewer. + osgViewer::Viewer viewer(arguments); + + // add the stats handler + viewer.addEventHandler(new osgViewer::StatsHandler); + + // add model to viewer. + viewer.setSceneData( CreateScene() ); + viewer.setUpViewOnSingleScreen(2); + viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true); + + double fovy;double aspectRatio; + double zNear;double zFar; + + return viewer.run(); +} + From cfaf72bc56e750cc832389e0653ca393811a209b Mon Sep 17 00:00:00 2001 From: d-a-heitbrink Date: Wed, 1 Mar 2017 18:12:46 -0600 Subject: [PATCH 5/5] removed some of the hard coded options in the main funct. --- examples/osgbindlesstext/osgbindlesstext.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/osgbindlesstext/osgbindlesstext.cpp b/examples/osgbindlesstext/osgbindlesstext.cpp index a5555ed66..aae24f6db 100644 --- a/examples/osgbindlesstext/osgbindlesstext.cpp +++ b/examples/osgbindlesstext/osgbindlesstext.cpp @@ -577,7 +577,7 @@ osg::Group* CreateScene(){ } int main(int argc, char** argv) { - // construct the viewer + // set command line options osg::ArgumentParser arguments(&argc,argv); // construct the viewer. @@ -588,12 +588,9 @@ int main(int argc, char** argv) // add model to viewer. viewer.setSceneData( CreateScene() ); - viewer.setUpViewOnSingleScreen(2); + viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true); - double fovy;double aspectRatio; - double zNear;double zFar; - return viewer.run(); }