Fix ShaderBuffer cleanup assertion with state cache disabled

This commit is contained in:
rdb 2018-12-26 22:44:26 +01:00
parent a9d6d3be46
commit 669a655366
16 changed files with 106 additions and 61 deletions

View File

@ -16,8 +16,9 @@
*/
INLINE CLP(BufferContext)::
CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo) :
BufferContext(&pgo->_sbuffer_residency),
PreparedGraphicsObjects *pgo,
TypedWritableReferenceCount *object) :
BufferContext(&pgo->_sbuffer_residency, object),
AdaptiveLruPage(0),
_glgsg(glgsg)
{

View File

@ -21,7 +21,8 @@
class EXPCL_GL CLP(BufferContext) : public BufferContext, public AdaptiveLruPage {
public:
INLINE CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo);
PreparedGraphicsObjects *pgo,
TypedWritableReferenceCount *object);
ALLOC_DELETED_CHAIN(CLP(BufferContext));
virtual void evict_lru();

View File

@ -1413,7 +1413,7 @@ open_buffer() {
}
if (_rb_context == nullptr) {
_rb_context = new BufferContext(&(glgsg->_renderbuffer_residency));
_rb_context = new BufferContext(&(glgsg->_renderbuffer_residency), nullptr);
}
/*

View File

@ -6519,7 +6519,7 @@ prepare_shader_buffer(ShaderBuffer *data) {
if (_supports_shader_buffers) {
PStatGPUTimer timer(this, _prepare_shader_buffer_pcollector);
CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects);
CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects, data);
_glGenBuffers(1, &gbc->_index);
if (GLCAT.is_debug() && gl_debug_buffers) {

View File

@ -11,6 +11,14 @@
* @date 2006-03-16
*/
/**
* Returns the associated object.
*/
INLINE TypedWritableReferenceCount *BufferContext::
get_object() const {
return _object;
}
/**
* Returns the number of bytes previously reported for the data object. This
* is used to track changes in the data object's allocated size; if it changes

View File

@ -19,7 +19,8 @@ TypeHandle BufferContext::_type_handle;
*
*/
BufferContext::
BufferContext(BufferResidencyTracker *residency) :
BufferContext(BufferResidencyTracker *residency, TypedWritableReferenceCount *object) :
_object(object),
_residency(residency),
_residency_state(0),
_data_size_bytes(0),

View File

@ -23,6 +23,7 @@
#include "bufferResidencyTracker.h"
class PreparedGraphicsObjects;
class TypedWritableReferenceCount;
/**
* This is a base class for those kinds of SavedContexts that occupy an
@ -36,15 +37,19 @@ class PreparedGraphicsObjects;
*/
class EXPCL_PANDA_GOBJ BufferContext : public SavedContext, private LinkedListNode {
public:
BufferContext(BufferResidencyTracker *residency);
BufferContext(BufferResidencyTracker *residency, TypedWritableReferenceCount *object);
virtual ~BufferContext();
INLINE TypedWritableReferenceCount *get_object() const;
PUBLISHED:
INLINE size_t get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
INLINE bool get_active() const;
INLINE bool get_resident() const;
MAKE_PROPERTY(object, get_object);
MAKE_PROPERTY(data_size_bytes, get_data_size_bytes);
MAKE_PROPERTY(modified, get_modified);
MAKE_PROPERTY(active, get_active);
@ -62,6 +67,11 @@ public:
private:
void set_owning_chain(BufferContextChain *chain);
protected:
// This cannot be a PT(), because the object and the GSG both own their
// BufferContexts! That would create a circular reference count.
TypedWritableReferenceCount *_object;
private:
BufferResidencyTracker *_residency;
int _residency_state;

View File

@ -16,9 +16,8 @@
*/
INLINE IndexBufferContext::
IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
BufferContext(&pgo->_ibuffer_residency),
AdaptiveLruPage(0),
_data(data)
BufferContext(&pgo->_ibuffer_residency, data),
AdaptiveLruPage(0)
{
}
@ -27,7 +26,7 @@ IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
*/
INLINE GeomPrimitive *IndexBufferContext::
get_data() const {
return _data;
return (GeomPrimitive *)_object;
}
/**
@ -36,7 +35,7 @@ get_data() const {
*/
INLINE bool IndexBufferContext::
changed_size(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_data_size_bytes() != (size_t)reader->get_data_size_bytes();
}
@ -46,7 +45,7 @@ changed_size(const GeomPrimitivePipelineReader *reader) const {
*/
INLINE bool IndexBufferContext::
changed_usage_hint(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return _usage_hint != reader->get_usage_hint();
}
@ -56,7 +55,7 @@ changed_usage_hint(const GeomPrimitivePipelineReader *reader) const {
*/
INLINE bool IndexBufferContext::
was_modified(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_modified() != reader->get_modified();
}
@ -76,7 +75,7 @@ update_data_size_bytes(size_t new_data_size_bytes) {
*/
INLINE void IndexBufferContext::
mark_loaded(const GeomPrimitivePipelineReader *reader) {
nassertv(reader->get_object() == _data);
nassertv(reader->get_object() == get_data());
update_data_size_bytes(reader->get_data_size_bytes());
update_modified(reader->get_modified());
_usage_hint = reader->get_usage_hint();

View File

@ -50,9 +50,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(GeomPrimitive), because the data and the GSG both own
// their IndexBufferContexts! That would create a circular reference count.
GeomPrimitive *_data;
GeomEnums::UsageHint _usage_hint;
public:

View File

@ -270,11 +270,11 @@ void PreparedGraphicsObjects::
release_texture(TextureContext *tc) {
ReMutexHolder holder(_lock);
tc->_texture->clear_prepared(tc->get_view(), this);
tc->get_texture()->clear_prepared(tc->get_view(), this);
// We have to set the Texture pointer to NULL at this point, since the
// Texture itself might destruct at any time after it has been released.
tc->_texture = nullptr;
tc->_object = nullptr;
bool removed = (_prepared_textures.erase(tc) != 0);
nassertv(removed);
@ -307,8 +307,8 @@ release_all_textures() {
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
tc->_texture->clear_prepared(tc->get_view(), this);
tc->_texture = nullptr;
tc->get_texture()->clear_prepared(tc->get_view(), this);
tc->_object = nullptr;
_released_textures.insert(tc);
}
@ -946,14 +946,14 @@ void PreparedGraphicsObjects::
release_vertex_buffer(VertexBufferContext *vbc) {
ReMutexHolder holder(_lock);
vbc->_data->clear_prepared(this);
vbc->get_data()->clear_prepared(this);
size_t data_size_bytes = vbc->_data->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = vbc->_data->get_usage_hint();
size_t data_size_bytes = vbc->get_data()->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = vbc->get_data()->get_usage_hint();
// We have to set the Data pointer to NULL at this point, since the Data
// itself might destruct at any time after it has been released.
vbc->_data = nullptr;
vbc->_object = nullptr;
bool removed = (_prepared_vertex_buffers.erase(vbc) != 0);
nassertv(removed);
@ -985,8 +985,8 @@ release_all_vertex_buffers() {
vbci != _prepared_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
vbc->_data->clear_prepared(this);
vbc->_data = nullptr;
vbc->get_data()->clear_prepared(this);
vbc->_object = nullptr;
_released_vertex_buffers.insert(vbc);
}
@ -1061,7 +1061,7 @@ prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *
_vertex_buffer_cache, _vertex_buffer_cache_lru,
_vertex_buffer_cache_size);
if (vbc != nullptr) {
vbc->_data = data;
vbc->_object = data;
} else {
// Ask the GSG to create a brand new VertexBufferContext. There might be
@ -1144,14 +1144,14 @@ void PreparedGraphicsObjects::
release_index_buffer(IndexBufferContext *ibc) {
ReMutexHolder holder(_lock);
ibc->_data->clear_prepared(this);
ibc->get_data()->clear_prepared(this);
size_t data_size_bytes = ibc->_data->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = ibc->_data->get_usage_hint();
size_t data_size_bytes = ibc->get_data()->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = ibc->get_data()->get_usage_hint();
// We have to set the Data pointer to NULL at this point, since the Data
// itself might destruct at any time after it has been released.
ibc->_data = nullptr;
ibc->_object = nullptr;
bool removed = (_prepared_index_buffers.erase(ibc) != 0);
nassertv(removed);
@ -1183,8 +1183,8 @@ release_all_index_buffers() {
ibci != _prepared_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
ibc->_data->clear_prepared(this);
ibc->_data = nullptr;
ibc->get_data()->clear_prepared(this);
ibc->_object = nullptr;
_released_index_buffers.insert(ibc);
}
@ -1258,7 +1258,7 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
_index_buffer_cache, _index_buffer_cache_lru,
_index_buffer_cache_size);
if (ibc != nullptr) {
ibc->_data = data;
ibc->_object = data;
} else {
// Ask the GSG to create a brand new IndexBufferContext. There might be
@ -1341,6 +1341,13 @@ void PreparedGraphicsObjects::
release_shader_buffer(BufferContext *bc) {
ReMutexHolder holder(_lock);
ShaderBuffer *buffer = (ShaderBuffer *)bc->_object;
buffer->clear_prepared(this);
// We have to set the ShaderBuffer pointer to NULL at this point, since the
// buffer itself might destruct at any time after it has been released.
bc->_object = nullptr;
bool removed = (_prepared_shader_buffers.erase(bc) != 0);
nassertv(removed);

View File

@ -143,6 +143,31 @@ release_all() {
return num_freed;
}
/**
* Removes the indicated PreparedGraphicsObjects table from the buffer's
* table, without actually releasing the texture. This is intended to be
* called only from PreparedGraphicsObjects::release_shader_buffer(); it
* should never be called by user code.
*/
void ShaderBuffer::
clear_prepared(PreparedGraphicsObjects *prepared_objects) {
nassertv(_contexts != nullptr);
Contexts::iterator ci;
ci = _contexts->find(prepared_objects);
if (ci != _contexts->end()) {
_contexts->erase(ci);
if (_contexts->empty()) {
delete _contexts;
_contexts = nullptr;
}
} else {
// If this assertion fails, clear_prepared() was given a prepared_objects
// which the data array didn't know about.
nassert_raise("unknown PreparedGraphicsObjects");
}
}
/**
* Tells the BamReader how to create objects of type ParamValue.
*/

View File

@ -57,6 +57,9 @@ PUBLISHED:
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
private:
uint64_t _data_size_bytes;
UsageHint _usage_hint;
@ -91,6 +94,8 @@ public:
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
INLINE std::ostream &operator << (std::ostream &out, const ShaderBuffer &m) {

View File

@ -16,9 +16,8 @@
*/
INLINE TextureContext::
TextureContext(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
BufferContext(&pgo->_texture_residency),
BufferContext(&pgo->_texture_residency, tex),
AdaptiveLruPage(0),
_texture(tex),
_view(view)
{
}
@ -28,7 +27,7 @@ TextureContext(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
*/
INLINE Texture *TextureContext::
get_texture() const {
return _texture;
return (Texture *)_object;
}
/**
@ -56,7 +55,7 @@ was_modified() const {
*/
INLINE bool TextureContext::
was_properties_modified() const {
return _properties_modified != _texture->get_properties_modified();
return _properties_modified != get_texture()->get_properties_modified();
}
/**
@ -65,7 +64,7 @@ was_properties_modified() const {
*/
INLINE bool TextureContext::
was_image_modified() const {
return _image_modified != _texture->get_image_modified();
return _image_modified != get_texture()->get_image_modified();
}
/**
@ -74,7 +73,7 @@ was_image_modified() const {
*/
INLINE bool TextureContext::
was_simple_image_modified() const {
return _simple_image_modified != _texture->get_simple_image_modified();
return _simple_image_modified != get_texture()->get_simple_image_modified();
}
/**
@ -121,8 +120,8 @@ update_data_size_bytes(size_t new_data_size_bytes) {
INLINE void TextureContext::
mark_loaded() {
// _data_size_bytes = _data->get_texture_size_bytes();
_properties_modified = _texture->get_properties_modified();
_image_modified = _texture->get_image_modified();
_properties_modified = get_texture()->get_properties_modified();
_image_modified = get_texture()->get_image_modified();
update_modified(std::max(_properties_modified, _image_modified));
// Assume the texture is now resident.
@ -135,8 +134,8 @@ mark_loaded() {
*/
INLINE void TextureContext::
mark_simple_loaded() {
_properties_modified = _texture->get_properties_modified();
_simple_image_modified = _texture->get_simple_image_modified();
_properties_modified = get_texture()->get_properties_modified();
_simple_image_modified = get_texture()->get_simple_image_modified();
update_modified(std::max(_properties_modified, _simple_image_modified));
// The texture's not exactly resident now, but some part of it is.

View File

@ -60,9 +60,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(Texture), because the texture and the GSG both own
// their TextureContexts! That would create a circular reference count.
Texture *_texture;
int _view;
UpdateSeq _properties_modified;
UpdateSeq _image_modified;

View File

@ -16,9 +16,8 @@
*/
INLINE VertexBufferContext::
VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
BufferContext(&pgo->_vbuffer_residency),
AdaptiveLruPage(0),
_data(data)
BufferContext(&pgo->_vbuffer_residency, data),
AdaptiveLruPage(0)
{
}
@ -27,7 +26,7 @@ VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
*/
INLINE GeomVertexArrayData *VertexBufferContext::
get_data() const {
return _data;
return (GeomVertexArrayData *)_object;
}
/**
@ -36,7 +35,7 @@ get_data() const {
*/
INLINE bool VertexBufferContext::
changed_size(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_data_size_bytes() != (size_t)reader->get_data_size_bytes();
}
@ -46,7 +45,7 @@ changed_size(const GeomVertexArrayDataHandle *reader) const {
*/
INLINE bool VertexBufferContext::
changed_usage_hint(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return _usage_hint != reader->get_usage_hint();
}
@ -56,7 +55,7 @@ changed_usage_hint(const GeomVertexArrayDataHandle *reader) const {
*/
INLINE bool VertexBufferContext::
was_modified(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_modified() != reader->get_modified();
}
@ -77,7 +76,7 @@ update_data_size_bytes(size_t new_data_size_bytes) {
*/
INLINE void VertexBufferContext::
mark_loaded(const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == _data);
nassertv(reader->get_object() == get_data());
update_data_size_bytes(reader->get_data_size_bytes());
update_modified(reader->get_modified());
_usage_hint = reader->get_usage_hint();

View File

@ -51,10 +51,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(GeomVertexArrayData), because the data and the GSG
// both own their VertexBufferContexts! That would create a circular
// reference count.
GeomVertexArrayData *_data;
GeomEnums::UsageHint _usage_hint;
public: