mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
Fix ShaderBuffer cleanup assertion with state cache disabled
This commit is contained in:
parent
a9d6d3be46
commit
669a655366
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user