From Lionel Lagarde, "Support for paging and shared PBO"
"The attached file contains: - a per-context read counter in GLBufferObject::BufferEntry - a global client counter in BufferData - the glue between Texture* and Image client counter "
This commit is contained in:
@@ -194,9 +194,10 @@ class OSG_EXPORT GLBufferObject : public Referenced
|
||||
|
||||
struct BufferEntry
|
||||
{
|
||||
BufferEntry(): modifiedCount(0),dataSize(0),offset(0),dataSource(0) {}
|
||||
BufferEntry(): numRead(0), modifiedCount(0),dataSize(0),offset(0),dataSource(0) {}
|
||||
|
||||
BufferEntry(const BufferEntry& rhs):
|
||||
numRead(rhs.numRead),
|
||||
modifiedCount(rhs.modifiedCount),
|
||||
dataSize(rhs.dataSize),
|
||||
offset(rhs.offset),
|
||||
@@ -205,6 +206,7 @@ class OSG_EXPORT GLBufferObject : public Referenced
|
||||
BufferEntry& operator = (const BufferEntry& rhs)
|
||||
{
|
||||
if (&rhs==this) return *this;
|
||||
numRead = rhs.numRead;
|
||||
modifiedCount = rhs.modifiedCount;
|
||||
dataSize = rhs.dataSize;
|
||||
offset = rhs.offset;
|
||||
@@ -212,6 +214,9 @@ class OSG_EXPORT GLBufferObject : public Referenced
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int getNumClients() const;
|
||||
|
||||
unsigned int numRead;
|
||||
unsigned int modifiedCount;
|
||||
unsigned int dataSize;
|
||||
unsigned int offset;
|
||||
@@ -339,6 +344,10 @@ class OSG_EXPORT GLBufferObject : public Referenced
|
||||
* but need to ensure that they all use the same low common denominator extensions.*/
|
||||
static void setExtensions(unsigned int contextID,Extensions* extensions);
|
||||
|
||||
bool hasAllBufferDataBeenRead() const;
|
||||
|
||||
void setBufferDataHasBeenRead(const osg::BufferData* bd);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~GLBufferObject();
|
||||
@@ -610,14 +619,16 @@ class OSG_EXPORT BufferData : public Object
|
||||
BufferData():
|
||||
Object(true),
|
||||
_modifiedCount(0),
|
||||
_bufferIndex(0) {}
|
||||
_bufferIndex(0),
|
||||
_numClients(0) {}
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
BufferData(const BufferData& bd,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
|
||||
osg::Object(bd,copyop),
|
||||
_modifiedCount(0),
|
||||
_bufferIndex(0),
|
||||
_modifiedCallback(bd._modifiedCallback) {}
|
||||
_modifiedCallback(bd._modifiedCallback),
|
||||
_numClients(0) {}
|
||||
|
||||
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferData*>(obj)!=NULL; }
|
||||
virtual const char* libraryName() const { return "osg"; }
|
||||
@@ -683,6 +694,12 @@ class OSG_EXPORT BufferData : public Object
|
||||
* for all graphics contexts. */
|
||||
void releaseGLObjects(State* state=0) const;
|
||||
|
||||
unsigned int getNumClients() const { return _numClients; }
|
||||
|
||||
void addClient(osg::Object *client) { ++_numClients; }
|
||||
|
||||
void removeClient(osg::Object *client) { --_numClients; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~BufferData();
|
||||
@@ -692,6 +709,8 @@ protected:
|
||||
unsigned int _bufferIndex;
|
||||
osg::ref_ptr<BufferObject> _bufferObject;
|
||||
osg::ref_ptr<ModifiedCallback> _modifiedCallback;
|
||||
|
||||
unsigned int _numClients;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,15 @@
|
||||
|
||||
using namespace osg;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GLBufferObject::BufferEntry
|
||||
//
|
||||
unsigned int GLBufferObject::BufferEntry::getNumClients() const
|
||||
{
|
||||
return dataSource->getNumClients();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GLBufferObject
|
||||
@@ -129,9 +138,9 @@ void GLBufferObject::compileBuffer()
|
||||
|
||||
// OSG_NOTICE<<"GLBufferObject::compileBuffer(..) updating BufferEntry"<<std::endl;
|
||||
|
||||
|
||||
entry.offset = newTotalSize;
|
||||
entry.numRead = 0;
|
||||
entry.modifiedCount = 0xffffff;
|
||||
entry.offset = newTotalSize;
|
||||
entry.dataSize = bd->getTotalDataSize();
|
||||
entry.dataSource = bd;
|
||||
|
||||
@@ -203,6 +212,7 @@ void GLBufferObject::compileBuffer()
|
||||
if (entry.dataSource && (compileAll || entry.modifiedCount != entry.dataSource->getModifiedCount()))
|
||||
{
|
||||
// OSG_NOTICE<<"GLBufferObject::compileBuffer(..) downloading BufferEntry "<<&entry<<std::endl;
|
||||
entry.numRead = 0;
|
||||
entry.modifiedCount = entry.dataSource->getModifiedCount();
|
||||
|
||||
const osg::Image* image = entry.dataSource->asImage();
|
||||
@@ -220,7 +230,6 @@ void GLBufferObject::compileBuffer()
|
||||
{
|
||||
_extensions->glBufferSubData(_profile._target, (GLintptrARB)entry.offset, (GLsizeiptrARB)entry.dataSize, entry.dataSource->getDataPointer());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,6 +247,23 @@ void GLBufferObject::deleteGLObject()
|
||||
}
|
||||
}
|
||||
|
||||
bool GLBufferObject::hasAllBufferDataBeenRead() const
|
||||
{
|
||||
for (BufferEntries::const_iterator it=_bufferEntries.begin(); it!=_bufferEntries.end(); ++it)
|
||||
{
|
||||
if (it->numRead < it->getNumClients())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLBufferObject::setBufferDataHasBeenRead(const osg::BufferData* bd)
|
||||
{
|
||||
BufferEntry &entry = _bufferEntries[bd->getBufferIndex()];
|
||||
++entry.numRead;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Extension support
|
||||
|
||||
@@ -2089,8 +2089,12 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima
|
||||
const BufferObject* bo = image->getBufferObject();
|
||||
if (bo->getCopyDataAndReleaseGLBufferObject())
|
||||
{
|
||||
//OSG_NOTICE<<"Release PBO"<<std::endl;
|
||||
bo->releaseGLObjects(&state);
|
||||
pbo->setBufferDataHasBeenRead(image);
|
||||
if (pbo->hasAllBufferDataBeenRead())
|
||||
{
|
||||
//OSG_NOTICE<<"Release PBO"<<std::endl;
|
||||
bo->releaseGLObjects(&state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,15 +34,16 @@ Texture1D::Texture1D(osg::Image* image):
|
||||
|
||||
Texture1D::Texture1D(const Texture1D& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_image(copyop(text._image.get())),
|
||||
_textureWidth(text._textureWidth),
|
||||
_numMipmapLevels(text._numMipmapLevels),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
setImage(copyop(text._image.get()));
|
||||
}
|
||||
|
||||
Texture1D::~Texture1D()
|
||||
{
|
||||
setImage(NULL);
|
||||
}
|
||||
|
||||
int Texture1D::compare(const StateAttribute& sa) const
|
||||
@@ -96,10 +97,15 @@ void Texture1D::setImage(Image* image)
|
||||
{
|
||||
if (_image == image) return;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
_image->removeClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
// delete old texture objects.
|
||||
@@ -108,10 +114,15 @@ void Texture1D::setImage(Image* image)
|
||||
_image = image;
|
||||
_modifiedCount.setAllElementsTo(0);
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_image->addClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,16 +37,17 @@ Texture2D::Texture2D(Image* image):
|
||||
|
||||
Texture2D::Texture2D(const Texture2D& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_image(copyop(text._image.get())),
|
||||
_textureWidth(text._textureWidth),
|
||||
_textureHeight(text._textureHeight),
|
||||
_numMipmapLevels(text._numMipmapLevels),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
setImage(copyop(text._image.get()));
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
setImage(NULL);
|
||||
}
|
||||
|
||||
int Texture2D::compare(const StateAttribute& sa) const
|
||||
@@ -109,19 +110,29 @@ void Texture2D::setImage(Image* image)
|
||||
{
|
||||
if (_image == image) return;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
_image->removeClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
_image = image;
|
||||
_modifiedCount.setAllElementsTo(0);
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_image->addClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,17 @@ Texture2DArray::Texture2DArray(const Texture2DArray& text,const CopyOp& copyop):
|
||||
// copy all images by iterating through all of them
|
||||
for (int i=0; i < text._textureDepth; i++)
|
||||
{
|
||||
_images.push_back(copyop(text._images[i].get()));
|
||||
setImage(i, copyop(text._images[i].get()));
|
||||
_modifiedCount.push_back(ImageModifiedCount());
|
||||
}
|
||||
}
|
||||
|
||||
Texture2DArray::~Texture2DArray()
|
||||
{
|
||||
for (int i=0; i<_textureDepth; ++i)
|
||||
{
|
||||
setImage(i, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int Texture2DArray::compare(const StateAttribute& sa) const
|
||||
@@ -118,9 +122,19 @@ void Texture2DArray::setImage(unsigned int layer, Image* image)
|
||||
if (_images[i].valid() && _images[i]->requiresUpdateCall()) ++numImageRequireUpdateBefore;
|
||||
}
|
||||
|
||||
if (_images[layer].valid())
|
||||
{
|
||||
_images[layer]->removeClient(this);
|
||||
}
|
||||
|
||||
// set image
|
||||
_images[layer] = image;
|
||||
_modifiedCount[layer].setAllElementsTo(0);
|
||||
_modifiedCount[layer].setAllElementsTo(0);
|
||||
|
||||
if (_images[layer].valid())
|
||||
{
|
||||
_images[layer]->addClient(this);
|
||||
}
|
||||
|
||||
// find out if we need to reset the update callback to handle the animation of image
|
||||
unsigned numImageRequireUpdateAfter = 0;
|
||||
|
||||
@@ -42,17 +42,18 @@ Texture3D::Texture3D(Image* image):
|
||||
|
||||
Texture3D::Texture3D(const Texture3D& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_image(copyop(text._image.get())),
|
||||
_textureWidth(text._textureWidth),
|
||||
_textureHeight(text._textureHeight),
|
||||
_textureDepth(text._textureDepth),
|
||||
_numMipmapLevels(text._numMipmapLevels),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
setImage(copyop(text._image.get()));
|
||||
}
|
||||
|
||||
Texture3D::~Texture3D()
|
||||
{
|
||||
{
|
||||
setImage(NULL);
|
||||
}
|
||||
|
||||
int Texture3D::compare(const StateAttribute& sa) const
|
||||
@@ -108,10 +109,15 @@ void Texture3D::setImage(Image* image)
|
||||
{
|
||||
if (_image == image) return;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
_image->removeClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
// delete old texture objects.
|
||||
@@ -121,10 +127,15 @@ void Texture3D::setImage(Image* image)
|
||||
|
||||
_image = image;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_image->addClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,15 @@ TextureBuffer::TextureBuffer(osg::Image* image):
|
||||
|
||||
TextureBuffer::TextureBuffer(const TextureBuffer& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_image(copyop(text._image.get())),
|
||||
_textureWidth(text._textureWidth),
|
||||
_usageHint(text._usageHint)
|
||||
{
|
||||
setImage(copyop(text._image.get()));
|
||||
}
|
||||
|
||||
TextureBuffer::~TextureBuffer()
|
||||
{
|
||||
setImage(NULL);
|
||||
}
|
||||
|
||||
int TextureBuffer::compare(const StateAttribute& sa) const
|
||||
@@ -84,10 +85,19 @@ void TextureBuffer::setImage(Image* image)
|
||||
{
|
||||
if (_image == image) return;
|
||||
|
||||
if (_image.valid())
|
||||
{
|
||||
_image->removeClient(this);
|
||||
}
|
||||
|
||||
_image = image;
|
||||
_modifiedCount.setAllElementsTo(0);
|
||||
}
|
||||
|
||||
if (_image.valid())
|
||||
{
|
||||
_image->addClient(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureBuffer::apply(State& state) const
|
||||
{
|
||||
|
||||
@@ -48,28 +48,24 @@ TextureCubeMap::TextureCubeMap(const TextureCubeMap& text,const CopyOp& copyop):
|
||||
_numMipmapLevels(text._numMipmapLevels),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
_images[0] = copyop(text._images[0].get());
|
||||
_images[1] = copyop(text._images[1].get());
|
||||
_images[2] = copyop(text._images[2].get());
|
||||
_images[3] = copyop(text._images[3].get());
|
||||
_images[4] = copyop(text._images[4].get());
|
||||
_images[5] = copyop(text._images[5].get());
|
||||
|
||||
_modifiedCount[0].setAllElementsTo(0);
|
||||
_modifiedCount[1].setAllElementsTo(0);
|
||||
_modifiedCount[2].setAllElementsTo(0);
|
||||
_modifiedCount[3].setAllElementsTo(0);
|
||||
_modifiedCount[4].setAllElementsTo(0);
|
||||
_modifiedCount[5].setAllElementsTo(0);
|
||||
|
||||
setImage(0, copyop(text._images[0].get()));
|
||||
setImage(1, copyop(text._images[1].get()));
|
||||
setImage(2, copyop(text._images[2].get()));
|
||||
setImage(3, copyop(text._images[3].get()));
|
||||
setImage(4, copyop(text._images[4].get()));
|
||||
setImage(5, copyop(text._images[5].get()));
|
||||
}
|
||||
|
||||
|
||||
TextureCubeMap::~TextureCubeMap()
|
||||
{
|
||||
setImage(0, NULL);
|
||||
setImage(1, NULL);
|
||||
setImage(2, NULL);
|
||||
setImage(3, NULL);
|
||||
setImage(4, NULL);
|
||||
setImage(5, NULL);
|
||||
}
|
||||
|
||||
|
||||
int TextureCubeMap::compare(const StateAttribute& sa) const
|
||||
{
|
||||
// check the types are equal and then create the rhs variable
|
||||
@@ -126,7 +122,7 @@ int TextureCubeMap::compare(const StateAttribute& sa) const
|
||||
}
|
||||
|
||||
|
||||
void TextureCubeMap::setImage( unsigned int face, Image* image)
|
||||
void TextureCubeMap::setImage(unsigned int face, Image* image)
|
||||
{
|
||||
if (_images[face] == image) return;
|
||||
|
||||
@@ -136,9 +132,18 @@ void TextureCubeMap::setImage( unsigned int face, Image* image)
|
||||
if (_images[i].valid() && _images[i]->requiresUpdateCall()) ++numImageRequireUpdateBefore;
|
||||
}
|
||||
|
||||
if (_images[face].valid())
|
||||
{
|
||||
_images[face]->removeClient(this);
|
||||
}
|
||||
|
||||
_images[face] = image;
|
||||
_modifiedCount[face].setAllElementsTo(0);
|
||||
|
||||
if (_images[face].valid())
|
||||
{
|
||||
_images[face]->addClient(this);
|
||||
}
|
||||
|
||||
// find out if we need to reset the update callback to handle the animation of image
|
||||
unsigned numImageRequireUpdateAfter = 0;
|
||||
|
||||
@@ -62,15 +62,16 @@ TextureRectangle::TextureRectangle(Image* image):
|
||||
|
||||
TextureRectangle::TextureRectangle(const TextureRectangle& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_image(copyop(text._image.get())),
|
||||
_textureWidth(text._textureWidth),
|
||||
_textureHeight(text._textureHeight),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
setImage(copyop(text._image.get()));
|
||||
}
|
||||
|
||||
TextureRectangle::~TextureRectangle()
|
||||
{
|
||||
setImage(NULL);
|
||||
}
|
||||
|
||||
int TextureRectangle::compare(const StateAttribute& sa) const
|
||||
@@ -125,10 +126,15 @@ void TextureRectangle::setImage(Image* image)
|
||||
{
|
||||
if (_image == image) return;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
_image->removeClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(0);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
// delete old texture objects.
|
||||
@@ -136,10 +142,15 @@ void TextureRectangle::setImage(Image* image)
|
||||
|
||||
_image = image;
|
||||
|
||||
if (_image.valid() && _image->requiresUpdateCall())
|
||||
if (_image.valid())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_image->addClient(this);
|
||||
|
||||
if (_image->requiresUpdateCall())
|
||||
{
|
||||
setUpdateCallback(new Image::UpdateCallback());
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user