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:
Robert Osfield
2013-06-27 16:44:32 +00:00
parent 57947ea75c
commit 9f13e2fcb9
10 changed files with 180 additions and 58 deletions

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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);
}
}
}