Added support for primitive instancing

This commit is contained in:
Robert Osfield
2009-01-06 14:55:49 +00:00
parent 9bd7fa7e6e
commit 4f3b1baee4
7 changed files with 158 additions and 43 deletions

View File

@@ -175,8 +175,9 @@ class OSG_EXPORT PrimitiveSet : public Object
POLYGON = GL_POLYGON
};
PrimitiveSet(Type primType=PrimitiveType,GLenum mode=0):
PrimitiveSet(Type primType=PrimitiveType,GLenum mode=0, int numInstances=0):
_primitiveType(primType),
_numInstances(numInstances),
_mode(mode),
_modifiedCount(0),
_rangeModifiedCount(0) {}
@@ -184,6 +185,7 @@ class OSG_EXPORT PrimitiveSet : public Object
PrimitiveSet(const PrimitiveSet& prim,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Object(prim,copyop),
_primitiveType(prim._primitiveType),
_numInstances(prim._numInstances),
_mode(prim._mode),
_modifiedCount(0),
_rangeModifiedCount(0) {}
@@ -200,6 +202,9 @@ class OSG_EXPORT PrimitiveSet : public Object
virtual DrawElements* getDrawElements() { return 0; }
virtual const DrawElements* getDrawElements() const { return 0; }
void setNumInstances(int n) { _numInstances = n; }
int getNumInstances() const { return _numInstances; }
void setMode(GLenum mode) { _mode = mode; }
GLenum getMode() const { return _mode; }
@@ -238,6 +243,7 @@ class OSG_EXPORT PrimitiveSet : public Object
virtual ~PrimitiveSet() {}
Type _primitiveType;
int _numInstances;
GLenum _mode;
unsigned int _modifiedCount;
mutable unsigned int _rangeModifiedCount;
@@ -275,8 +281,8 @@ class OSG_EXPORT DrawArrays : public PrimitiveSet
_first(0),
_count(0) {}
DrawArrays(GLenum mode, GLint first, GLsizei count):
PrimitiveSet(DrawArraysPrimitiveType,mode),
DrawArrays(GLenum mode, GLint first, GLsizei count, int numInstances=0):
PrimitiveSet(DrawArraysPrimitiveType, mode, numInstances),
_first(first),
_count(count) {}
@@ -385,8 +391,8 @@ class DrawElements : public PrimitiveSet
{
public:
DrawElements(Type primType=PrimitiveType, GLenum mode=0):
PrimitiveSet(primType,mode),
DrawElements(Type primType=PrimitiveType, GLenum mode=0, int numInstances=0):
PrimitiveSet(primType,mode, numInstances),
_eboOffset(0) {}
DrawElements(const DrawElements& copy,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
@@ -472,8 +478,8 @@ class OSG_EXPORT DrawElementsUByte : public DrawElements, public VectorGLubyte
DrawElements(array,copyop),
vector_type(array) {}
DrawElementsUByte(GLenum mode, unsigned int no, const GLubyte* ptr) :
DrawElements(DrawElementsUBytePrimitiveType,mode),
DrawElementsUByte(GLenum mode, unsigned int no, const GLubyte* ptr, int numInstances=0) :
DrawElements(DrawElementsUBytePrimitiveType,mode,numInstances),
vector_type(ptr,ptr+no) {}
DrawElementsUByte(GLenum mode, unsigned int no) :
@@ -542,8 +548,8 @@ class OSG_EXPORT DrawElementsUShort : public DrawElements, public VectorGLushort
DrawElements(array,copyop),
vector_type(array) {}
DrawElementsUShort(GLenum mode, unsigned int no, const GLushort* ptr) :
DrawElements(DrawElementsUShortPrimitiveType,mode),
DrawElementsUShort(GLenum mode, unsigned int no, const GLushort* ptr, int numInstances=0) :
DrawElements(DrawElementsUShortPrimitiveType,mode,numInstances),
vector_type(ptr,ptr+no) {}
DrawElementsUShort(GLenum mode, unsigned int no) :
@@ -616,8 +622,8 @@ class OSG_EXPORT DrawElementsUInt : public DrawElements, public VectorGLuint
DrawElements(array,copyop),
vector_type(array) {}
DrawElementsUInt(GLenum mode, unsigned int no, const GLuint* ptr) :
DrawElements(DrawElementsUIntPrimitiveType,mode),
DrawElementsUInt(GLenum mode, unsigned int no, const GLuint* ptr, int numInstances=0) :
DrawElements(DrawElementsUIntPrimitiveType,mode,numInstances),
vector_type(ptr,ptr+no) {}
DrawElementsUInt(GLenum mode, unsigned int no) :

View File

@@ -459,6 +459,20 @@ class OSG_EXPORT State : public Referenced
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
_currentPBO = 0;
}
inline void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
if (primcount>=1 && _glDrawArraysInstanced!=0) _glDrawArraysInstanced(mode, first, count, primcount);
else glDrawArrays(mode, first, count);
}
inline void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount )
{
if (primcount>=1 && _glDrawElementsInstanced!=0) _glDrawElementsInstanced(mode, count, type, indices, primcount);
else glDrawElements(mode, count, type, indices);
}
/** Wrapper around glInterleavedArrays(..).
* also resets the internal array points and modes within osg::State to keep the other
@@ -1293,7 +1307,9 @@ class OSG_EXPORT State : public Referenced
typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int);
typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int);
typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
typedef void (APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
typedef void (APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
bool _extensionProcsInitialized;
GLint _glMaxTextureCoords;
@@ -1306,7 +1322,8 @@ class OSG_EXPORT State : public Referenced
EnableVertexAttribProc _glEnableVertexAttribArray;
DisableVertexAttribProc _glDisableVertexAttribArray;
BindBufferProc _glBindBuffer;
DrawArraysInstancedProc _glDrawArraysInstanced;
DrawElementsInstancedProc _glDrawElementsInstanced;
unsigned int _dynamicObjectCount;
osg::ref_ptr<DynamicObjectRenderingCompletedCallback> _completeDynamicObjectRenderingCallback;

View File

@@ -35,9 +35,10 @@ unsigned int PrimitiveSet::getNumPrimitives() const
return 0;
}
void DrawArrays::draw(State&, bool) const
void DrawArrays::draw(State& state, bool) const
{
glDrawArrays(_mode,_first,_count);
if (_numInstances>=1) state.glDrawArraysInstanced(_mode,_first,_count, _numInstances);
else glDrawArrays(_mode,_first,_count);
}
void DrawArrays::accept(PrimitiveFunctor& functor) const
@@ -129,16 +130,19 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
state.bindElementBufferObject(ebo);
if (ebo)
{
glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, getElementBufferObjectOffset());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, getElementBufferObjectOffset(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, getElementBufferObjectOffset());
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, &front());
}
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, &front());
}
}
@@ -176,16 +180,19 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
state.bindElementBufferObject(ebo);
if (ebo)
{
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, getElementBufferObjectOffset());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, getElementBufferObjectOffset(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, getElementBufferObjectOffset());
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, &front());
}
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, &front());
}
}
@@ -223,16 +230,19 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
state.bindElementBufferObject(ebo);
if (ebo)
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, getElementBufferObjectOffset());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, getElementBufferObjectOffset(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_INT, getElementBufferObjectOffset());
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
}
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
if (_numInstances>=1) state.glDrawElementsInstanced(_mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
else glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
}
}

View File

@@ -79,6 +79,8 @@ State::State():
_glVertexAttribPointer = 0;
_glEnableVertexAttribArray = 0;
_glDisableVertexAttribArray = 0;
_glDrawArraysInstanced = 0;
_glDrawElementsInstanced = 0;
_dynamicObjectCount = 0;
@@ -754,6 +756,9 @@ void State::initializeExtensionProcs()
setGLExtensionFuncPtr(_glDisableVertexAttribArray, "glDisableVertexAttribArray","glDisableVertexAttribArrayARB");
setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
setGLExtensionFuncPtr(_glDrawArraysInstanced, "glDrawArraysInstanced","glDrawArraysInstancedEXT");
setGLExtensionFuncPtr(_glDrawElementsInstanced, "glDrawElementsInstanced","glDrawElementsInstancedEXT");
if ( osg::getGLVersionNumber() >= 2.0 || osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_shader") )
{
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&_glMaxTextureUnits);

View File

@@ -46,8 +46,9 @@
#define VERSION_0035 35
#define VERSION_0036 36
#define VERSION_0037 37
#define VERSION_0038 38
#define VERSION VERSION_0037
#define VERSION VERSION_0038
/* The BYTE_SEX tag is used to check the endian
of the IVE file being read in. The IVE format

View File

@@ -30,6 +30,11 @@ void PrimitiveSet::write(DataOutputStream* out){
throw Exception("PrimitiveSet::write(): Could not cast this osg::PrimitiveSet to an osg::Object.");
if ( out->getVersion() >= VERSION_0038 )
{
out->writeInt(getNumInstances());
}
// Write PrimitiveSet's properties.
out->writeInt(getMode());
}
@@ -49,6 +54,11 @@ void PrimitiveSet::read(DataInputStream* in){
throw Exception("PrimitiveSet::read(): Could not cast this osg::PrimitiveSet to an osg::Object.");
if ( in->getVersion() >= VERSION_0038 )
{
setNumInstances(in->readInt());
}
// Read in primitiveset properties.
setMode(in->readInt());
}

View File

@@ -1003,7 +1003,9 @@ bool Array_writeLocalData(const Array& array,Output& fw)
bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
{
bool iteratorAdvanced = false;
if (fr.matchSequence("DrawArrays %w %i %i"))
bool firstMatched = false;
if ((firstMatched = fr.matchSequence("DrawArrays %w %i %i %i")) ||
fr.matchSequence("DrawArrays %w %i %i") )
{
GLenum mode;
@@ -1015,14 +1017,25 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
int count;
fr[3].getInt(count);
geom.addPrimitiveSet(new DrawArrays(mode,first,count));
int numInstances = 0;
if (firstMatched)
{
fr[4].getInt(numInstances);
fr += 5;
}
else
{
fr += 4;
}
geom.addPrimitiveSet(new DrawArrays(mode, first, count, numInstances));
fr += 4;
iteratorAdvanced = true;
}
else if (fr.matchSequence("DrawArrayLengths %w %i %i {"))
else if ((firstMatched = fr.matchSequence("DrawArrayLengths %w %i %i %i {")) ||
fr.matchSequence("DrawArrayLengths %w %i %i {") )
{
int entry = fr[1].getNoNestedBrackets();
@@ -1035,10 +1048,20 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
int capacity;
fr[3].getInt(capacity);
fr += 5;
int numInstances = 0;
if (firstMatched)
{
fr[4].getInt(numInstances);
fr += 6;
}
else
{
fr += 5;
}
DrawArrayLengths* prim = new DrawArrayLengths;
prim->setMode(mode);
prim->setNumInstances(numInstances);
prim->setFirst(first);
prim->reserve(capacity);
@@ -1057,7 +1080,8 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
iteratorAdvanced = true;
}
else if (fr.matchSequence("DrawElementsUByte %w %i {"))
else if ((firstMatched = fr.matchSequence("DrawElementsUByte %w %i %i {")) ||
fr.matchSequence("DrawElementsUByte %w %i {"))
{
int entry = fr[1].getNoNestedBrackets();
@@ -1067,10 +1091,20 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
int capacity;
fr[2].getInt(capacity);
fr += 4;
int numInstances = 0;
if (firstMatched)
{
fr[3].getInt(numInstances);
fr += 5;
}
else
{
fr += 4;
}
DrawElementsUByte* prim = new DrawElementsUByte;
prim->setMode(mode);
prim->setNumInstances(numInstances);
prim->reserve(capacity);
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
@@ -1088,7 +1122,8 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
iteratorAdvanced = true;
}
else if (fr.matchSequence("DrawElementsUShort %w %i {"))
else if ((firstMatched = fr.matchSequence("DrawElementsUShort %w %i %i {")) ||
fr.matchSequence("DrawElementsUShort %w %i {"))
{
int entry = fr[1].getNoNestedBrackets();
@@ -1098,10 +1133,20 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
int capacity;
fr[2].getInt(capacity);
fr += 4;
int numInstances = 0;
if (firstMatched)
{
fr[3].getInt(numInstances);
fr += 5;
}
else
{
fr += 4;
}
DrawElementsUShort* prim = new DrawElementsUShort;
prim->setMode(mode);
prim->setNumInstances(numInstances);
prim->reserve(capacity);
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
@@ -1119,7 +1164,8 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
iteratorAdvanced = true;
}
else if (fr.matchSequence("DrawElementsUInt %w %i {"))
else if ((firstMatched = fr.matchSequence("DrawElementsUInt %w %i %i {")) ||
fr.matchSequence("DrawElementsUInt %w %i {"))
{
int entry = fr[1].getNoNestedBrackets();
@@ -1129,10 +1175,20 @@ bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
int capacity;
fr[2].getInt(capacity);
fr += 4;
int numInstances = 0;
if (firstMatched)
{
fr[3].getInt(numInstances);
fr += 5;
}
else
{
fr += 4;
}
DrawElementsUInt* prim = new DrawElementsUInt;
prim->setMode(mode);
prim->setNumInstances(numInstances);
prim->reserve(capacity);
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
@@ -1162,14 +1218,18 @@ bool Primitive_writeLocalData(const PrimitiveSet& prim,Output& fw)
case(PrimitiveSet::DrawArraysPrimitiveType):
{
const DrawArrays& cprim = static_cast<const DrawArrays&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.getFirst()<<" "<<cprim.getCount()<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.getFirst()<<" "<<cprim.getCount();
if (prim.getNumInstances()>0) fw<<" "<<prim.getNumInstances();
fw<<std::endl;
return true;
}
break;
case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
{
const DrawArrayLengths& cprim = static_cast<const DrawArrayLengths&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.getFirst()<<" "<<cprim.size()<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.getFirst()<<" "<<cprim.size();
if (prim.getNumInstances()>0) fw<<" "<<prim.getNumInstances();
fw<<std::endl;
writeArray(fw,cprim.begin(),cprim.end());
return true;
}
@@ -1177,7 +1237,9 @@ bool Primitive_writeLocalData(const PrimitiveSet& prim,Output& fw)
case(PrimitiveSet::DrawElementsUBytePrimitiveType):
{
const DrawElementsUByte& cprim = static_cast<const DrawElementsUByte&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size();
if (prim.getNumInstances()>0) fw<<" "<<prim.getNumInstances();
fw<<std::endl;
writeArrayAsInts(fw,cprim.begin(),cprim.end());
return true;
}
@@ -1185,7 +1247,9 @@ bool Primitive_writeLocalData(const PrimitiveSet& prim,Output& fw)
case(PrimitiveSet::DrawElementsUShortPrimitiveType):
{
const DrawElementsUShort& cprim = static_cast<const DrawElementsUShort&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size();
if (prim.getNumInstances()>0) fw<<" "<<prim.getNumInstances();
fw<<std::endl;
writeArray(fw,cprim.begin(),cprim.end());
return true;
}
@@ -1193,7 +1257,9 @@ bool Primitive_writeLocalData(const PrimitiveSet& prim,Output& fw)
case(PrimitiveSet::DrawElementsUIntPrimitiveType):
{
const DrawElementsUInt& cprim = static_cast<const DrawElementsUInt&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size();
if (prim.getNumInstances()>0) fw<<" "<<prim.getNumInstances();
fw<<std::endl;
writeArray(fw,cprim.begin(),cprim.end());
return true;
}