mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
add ReferenceCount::local_object(), clarify GeomVertexCache
This commit is contained in:
parent
c83feafc70
commit
05ba41b4d6
@ -62,6 +62,28 @@ release_all_geoms() {
|
||||
return _prepared_objects->release_all_geoms();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::release_all_vertex_buffers
|
||||
// Access: Public
|
||||
// Description: Frees the resources for all vertex buffers associated
|
||||
// with this GSG.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsStateGuardian::
|
||||
release_all_vertex_buffers() {
|
||||
return _prepared_objects->release_all_vertex_buffers();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::release_all_index_buffers
|
||||
// Access: Public
|
||||
// Description: Frees the resources for all index buffers associated
|
||||
// with this GSG.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsStateGuardian::
|
||||
release_all_index_buffers() {
|
||||
return _prepared_objects->release_all_index_buffers();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_active
|
||||
// Access: Published
|
||||
|
@ -1511,6 +1511,8 @@ close_gsg() {
|
||||
if (_prepared_objects->get_ref_count() == 1) {
|
||||
release_all_textures();
|
||||
release_all_geoms();
|
||||
release_all_vertex_buffers();
|
||||
release_all_index_buffers();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,8 @@ public:
|
||||
PUBLISHED:
|
||||
INLINE int release_all_textures();
|
||||
INLINE int release_all_geoms();
|
||||
INLINE int release_all_vertex_buffers();
|
||||
INLINE int release_all_index_buffers();
|
||||
|
||||
INLINE void set_active(bool active);
|
||||
INLINE bool is_active() const;
|
||||
|
@ -59,7 +59,7 @@ GraphicsThreadingModel(const string &model) {
|
||||
|
||||
size_t slash = model.find('/', start);
|
||||
if (slash == string::npos) {
|
||||
_cull_name = model;
|
||||
_cull_name = model.substr(start);
|
||||
} else {
|
||||
_cull_name = model.substr(start, slash - start);
|
||||
_draw_name = model.substr(slash + 1);
|
||||
|
@ -3197,44 +3197,51 @@ release_texture(TextureContext *tc) {
|
||||
VertexBufferContext *DXGraphicsStateGuardian8::
|
||||
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
|
||||
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
|
||||
|
||||
if (vertex_buffers && data->get_usage_hint() != qpGeom::UH_client) {
|
||||
dvbc->create_vbuffer(*_pScrn);
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "creating vertex buffer " << dvbc->_vbuffer << ": "
|
||||
<< data->get_num_rows() << " vertices "
|
||||
<< *data->get_array_format() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return dvbc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXGraphicsStateGuardian8::apply_vertex_buffer
|
||||
// Access: Public
|
||||
// Description: Makes the data the currently available data for
|
||||
// rendering.
|
||||
// Description: Updates the vertex buffer with the current data, and
|
||||
// makes it the current vertex buffer for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
apply_vertex_buffer(VertexBufferContext *vbc) {
|
||||
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
|
||||
|
||||
if (dvbc->_vbuffer != NULL) {
|
||||
if (dvbc->_vbuffer == NULL) {
|
||||
// Attempt to create a new vertex buffer.
|
||||
if (vertex_buffers &&
|
||||
dvbc->get_data()->get_usage_hint() != qpGeom::UH_client) {
|
||||
dvbc->create_vbuffer(*_pScrn);
|
||||
}
|
||||
|
||||
if (dvbc->_vbuffer != NULL) {
|
||||
dvbc->upload_data();
|
||||
|
||||
add_to_vertex_buffer_record(dvbc);
|
||||
add_to_total_buffer_record(dvbc);
|
||||
dvbc->mark_loaded();
|
||||
|
||||
_pD3DDevice->SetStreamSource
|
||||
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
|
||||
_vbuffer_active = true;
|
||||
} else {
|
||||
_vbuffer_active = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
add_to_vertex_buffer_record(dvbc);
|
||||
|
||||
if (dvbc->was_modified()) {
|
||||
if (dvbc->changed_size()) {
|
||||
// Here we have to destroy the old vertex buffer and create a
|
||||
// new one.
|
||||
// We have to destroy the old vertex buffer and create a new
|
||||
// one.
|
||||
dvbc->create_vbuffer(*_pScrn);
|
||||
|
||||
} else {
|
||||
// Here we just copy the new data to the vertex buffer.
|
||||
dvbc->upload_data();
|
||||
}
|
||||
|
||||
dvbc->upload_data();
|
||||
|
||||
add_to_total_buffer_record(dvbc);
|
||||
dvbc->mark_loaded();
|
||||
@ -3243,9 +3250,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
|
||||
_pD3DDevice->SetStreamSource
|
||||
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
|
||||
_vbuffer_active = true;
|
||||
|
||||
} else {
|
||||
_vbuffer_active = false;
|
||||
}
|
||||
|
||||
set_vertex_format(dvbc->_fvf);
|
||||
@ -3281,43 +3285,48 @@ release_vertex_buffer(VertexBufferContext *vbc) {
|
||||
IndexBufferContext *DXGraphicsStateGuardian8::
|
||||
prepare_index_buffer(qpGeomPrimitive *data) {
|
||||
DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data);
|
||||
|
||||
dibc->create_ibuffer(*_pScrn);
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "creating index buffer " << dibc->_ibuffer << ": "
|
||||
<< data->get_num_vertices() << " indices ("
|
||||
<< data->get_vertices()->get_array_format()->get_column(0)->get_numeric_type()
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
return dibc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXGraphicsStateGuardian8::apply_index_buffer
|
||||
// Access: Public
|
||||
// Description: Makes the data the currently available data for
|
||||
// rendering.
|
||||
// Description: Updates the index buffer with the current data, and
|
||||
// makes it the current index buffer for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
apply_index_buffer(IndexBufferContext *ibc) {
|
||||
DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc);
|
||||
|
||||
if (dibc->_ibuffer != NULL) {
|
||||
if (dibc->_ibuffer == NULL) {
|
||||
// Attempt to create a new index buffer.
|
||||
dibc->create_ibuffer(*_pScrn);
|
||||
|
||||
if (dibc->_ibuffer != NULL) {
|
||||
dibc->upload_data();
|
||||
add_to_index_buffer_record(dibc);
|
||||
add_to_total_buffer_record(dibc);
|
||||
dibc->mark_loaded();
|
||||
|
||||
_pD3DDevice->SetIndices(dibc->_ibuffer, 0);
|
||||
_ibuffer_active = true;
|
||||
} else {
|
||||
|
||||
_pD3DDevice->SetIndices(NULL, 0);
|
||||
_ibuffer_active = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
add_to_index_buffer_record(dibc);
|
||||
|
||||
if (dibc->was_modified()) {
|
||||
if (dibc->changed_size()) {
|
||||
// Here we have to destroy the old index buffer and create a
|
||||
// new one.
|
||||
// We have to destroy the old index buffer and create a new
|
||||
// one.
|
||||
dibc->create_ibuffer(*_pScrn);
|
||||
|
||||
} else {
|
||||
// Here we just copy the new data to the index buffer.
|
||||
dibc->upload_data();
|
||||
}
|
||||
|
||||
dibc->upload_data();
|
||||
|
||||
add_to_total_buffer_record(dibc);
|
||||
dibc->mark_loaded();
|
||||
@ -3325,10 +3334,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
|
||||
|
||||
_pD3DDevice->SetIndices(dibc->_ibuffer, 0);
|
||||
_ibuffer_active = true;
|
||||
|
||||
} else {
|
||||
_pD3DDevice->SetIndices(NULL, 0);
|
||||
_ibuffer_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,8 @@ DXIndexBufferContext8::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext8::create_ibuffer
|
||||
// Access: Public
|
||||
// Description: Creates a new index buffer and uploads data to it.
|
||||
// Description: Creates a new index buffer (but does not upload data
|
||||
// to it).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext8::
|
||||
create_ibuffer(DXScreenData &scrn) {
|
||||
@ -77,9 +78,14 @@ create_ibuffer(DXScreenData &scrn) {
|
||||
dxgsg8_cat.warning()
|
||||
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_ibuffer = NULL;
|
||||
|
||||
} else {
|
||||
upload_data();
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "creating index buffer " << _ibuffer << ": "
|
||||
<< get_data()->get_num_vertices() << " indices ("
|
||||
<< get_data()->get_vertices()->get_array_format()->get_column(0)->get_numeric_type()
|
||||
<< ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,8 @@ DXVertexBufferContext8::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext8::create_vbuffer
|
||||
// Access: Public
|
||||
// Description: Creates a new vertex buffer and uploads data to it.
|
||||
// Description: Creates a new vertex buffer (but does not upload data
|
||||
// to it).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext8::
|
||||
create_vbuffer(DXScreenData &scrn) {
|
||||
@ -169,9 +170,13 @@ create_vbuffer(DXScreenData &scrn) {
|
||||
dxgsg8_cat.warning()
|
||||
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_vbuffer = NULL;
|
||||
|
||||
} else {
|
||||
upload_data();
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "created vertex buffer " << _vbuffer << ": "
|
||||
<< get_data()->get_num_rows() << " vertices "
|
||||
<< *get_data()->get_array_format() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ operator = (const ReferenceCount &) {
|
||||
// instance of a class that derives from ReferenceCount. Or maybe
|
||||
// your headers are out of sync, and you need to make clean in
|
||||
// direct or some higher tree.
|
||||
nassertv(_ref_count != -100);
|
||||
nassertv(_ref_count != deleted_ref_count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -112,7 +112,13 @@ INLINE ReferenceCount::
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertv(_ref_count != -100);
|
||||
nassertv(_ref_count != deleted_ref_count);
|
||||
|
||||
// If this assertion fails, we're trying to delete a static object
|
||||
// that still has an outstanding reference count. You should make
|
||||
// sure that all references to your static objects are gone by the
|
||||
// time the object itself destructs.
|
||||
nassertv(_ref_count <= local_ref_count);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
@ -129,7 +135,7 @@ INLINE ReferenceCount::
|
||||
// constructor for a ReferenceCount object, and then bitwise
|
||||
// copied a dynamically allocated value--reference count and
|
||||
// all--onto a locally allocated one.
|
||||
nassertv(_ref_count == 0);
|
||||
nassertv(_ref_count == 0 || _ref_count == local_ref_count);
|
||||
|
||||
// Tell our weak reference holders that we're going away now.
|
||||
if (_weak_list != (WeakReferenceList *)NULL) {
|
||||
@ -138,10 +144,10 @@ INLINE ReferenceCount::
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Ok, all clear to delete. Now set the reference count to -100,
|
||||
// so we'll have a better chance of noticing if we happen to have
|
||||
// a stray pointer to it still out there.
|
||||
_ref_count = -100;
|
||||
// Ok, all clear to delete. Now set the reference count to
|
||||
// deleted_ref_count, so we'll have a better chance of noticing if
|
||||
// we happen to have a stray pointer to it still out there.
|
||||
_ref_count = deleted_ref_count;
|
||||
#endif
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
@ -151,7 +157,7 @@ INLINE ReferenceCount::
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::get_ref_count
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the current reference count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ReferenceCount::
|
||||
@ -164,7 +170,7 @@ get_ref_count() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::ref
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Explicitly increments the reference count. User code
|
||||
// should avoid using ref() and unref() directly, which
|
||||
// can result in missed reference counts. Instead, let
|
||||
@ -191,7 +197,7 @@ ref() const {
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertr(_ref_count != -100, 0);
|
||||
nassertr(_ref_count != deleted_ref_count, 0);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
@ -203,7 +209,7 @@ ref() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::unref
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Explicitly decrements the reference count. Note that
|
||||
// the object will not be implicitly deleted by unref()
|
||||
// simply because the reference count drops to zero.
|
||||
@ -237,7 +243,7 @@ unref() const {
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertr(_ref_count != -100, false);
|
||||
nassertr(_ref_count != deleted_ref_count, false);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
@ -254,7 +260,7 @@ unref() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::test_ref_count_integrity
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Does some easy checks to make sure that the reference
|
||||
// count isn't completely bogus.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -270,7 +276,7 @@ test_ref_count_integrity() const {
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertv(_ref_count != -100);
|
||||
nassertv(_ref_count != deleted_ref_count);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
@ -279,6 +285,30 @@ test_ref_count_integrity() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::local_object
|
||||
// Access: Public
|
||||
// Description: This function should be called, once, immediately
|
||||
// after creating a new instance of some
|
||||
// ReferenceCount-derived object on the stack.
|
||||
//
|
||||
// This allows the object to be passed to functions that
|
||||
// will increment and decrement the object's reference
|
||||
// count temporarily, and it will prevent the object
|
||||
// from being deleted (inappropriately), when the
|
||||
// reference count returns to zero. It actually
|
||||
// achieves this by setting a large positive value in
|
||||
// the reference count field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ReferenceCount::
|
||||
local_object() {
|
||||
// If this assertion fails, you didn't call this immediately after
|
||||
// creating a local object.
|
||||
nassertv(_ref_count == 0);
|
||||
|
||||
_ref_count = local_ref_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReferenceCount::has_weak_list
|
||||
// Access: Public
|
||||
|
@ -54,6 +54,7 @@ PUBLISHED:
|
||||
INLINE void test_ref_count_integrity() const;
|
||||
|
||||
public:
|
||||
INLINE void local_object();
|
||||
INLINE bool has_weak_list() const;
|
||||
INLINE WeakReferenceList *get_weak_list() const;
|
||||
|
||||
@ -61,6 +62,22 @@ public:
|
||||
INLINE void weak_unref(WeakPointerToVoid *ptv);
|
||||
|
||||
private:
|
||||
enum {
|
||||
// We use this value as a flag to indicate an object has been
|
||||
// indicated as a local object, and should not be deleted except
|
||||
// by its own destructor. Really, any nonzero value would do, but
|
||||
// having a large specific number makes the sanity checks easier.
|
||||
local_ref_count = 10000000,
|
||||
|
||||
// This value is used as a flag to indicate that an object has
|
||||
// just been deleted, and you're looking at deallocated memory.
|
||||
// It's not guaranteed to stick around, of course (since the
|
||||
// deleted memory might be repurposed for anything else, including
|
||||
// a new object), but if you ever do encounter this value in a
|
||||
// reference count field, you screwed up.
|
||||
deleted_ref_count = -100,
|
||||
};
|
||||
|
||||
int _ref_count;
|
||||
WeakReferenceList *_weak_list;
|
||||
|
||||
@ -137,8 +154,6 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "referenceCount.I"
|
||||
|
||||
#endif
|
||||
|
@ -206,14 +206,19 @@ ConfigVariableString fake_texture_image
|
||||
"the same texture file, which will presumably only be loaded "
|
||||
"once."));
|
||||
|
||||
ConfigVariableInt vertex_convert_cache
|
||||
("vertex-convert-cache", 4194304, // 4 MB
|
||||
PRC_DESC("This is the amount of memory, in bytes, that should be set "
|
||||
"aside for storing pre-processed data for rendering vertices. "
|
||||
"This is not a limit on the actual vertex data, which is "
|
||||
"determined by the model; it is also not a limit on the "
|
||||
"amount of memory used by the video driver or the system "
|
||||
"graphics interface, which Panda has no control over."));
|
||||
ConfigVariableInt geom_cache_size
|
||||
("geom-cache-size", 5000,
|
||||
PRC_DESC("Specifies the maximum number of entries in the cache "
|
||||
"for storing pre-processed data for rendering "
|
||||
"vertices. This limit is flexible, and may be "
|
||||
"temporarily exceeded if many different Geoms are "
|
||||
"pre-processed during the space of a single frame."));
|
||||
|
||||
ConfigVariableInt geom_cache_min_frames
|
||||
("geom-cache-min-frames", 1,
|
||||
PRC_DESC("Specifies the minimum number of frames any one particular "
|
||||
"object will remain in the geom cache, even if geom-cache-size "
|
||||
"is exceeded."));
|
||||
|
||||
ConfigVariableDouble default_near
|
||||
("default-near", 1.0,
|
||||
|
@ -66,7 +66,8 @@ extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_power_2;
|
||||
extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_square;
|
||||
extern EXPCL_PANDA ConfigVariableString fake_texture_image;
|
||||
|
||||
extern EXPCL_PANDA ConfigVariableInt vertex_convert_cache;
|
||||
extern EXPCL_PANDA ConfigVariableInt geom_cache_size;
|
||||
extern EXPCL_PANDA ConfigVariableInt geom_cache_min_frames;
|
||||
|
||||
extern ConfigVariableDouble default_near;
|
||||
extern ConfigVariableDouble default_far;
|
||||
|
@ -187,11 +187,34 @@ get_modified() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeom::CacheEntry::
|
||||
CacheEntry(const qpGeomVertexData *source_data, const qpGeomMunger *modifier) :
|
||||
_source(NULL),
|
||||
_source_data(source_data),
|
||||
_modifier(modifier)
|
||||
_modifier(modifier),
|
||||
_geom_result(NULL),
|
||||
_data_result(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeom::CacheEntry::
|
||||
CacheEntry(qpGeom *source, const qpGeomVertexData *source_data,
|
||||
const qpGeomMunger *modifier, const qpGeom *geom_result,
|
||||
const qpGeomVertexData *data_result) :
|
||||
_source(source),
|
||||
_source_data(source_data),
|
||||
_modifier(modifier),
|
||||
_geom_result(geom_result),
|
||||
_data_result(data_result)
|
||||
{
|
||||
if (_geom_result != _source) {
|
||||
_geom_result->ref();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::operator <
|
||||
// Access: Public
|
||||
|
@ -469,7 +469,7 @@ munge_geom(const qpGeomMunger *munger,
|
||||
{
|
||||
CDReader cdata(_cycler);
|
||||
CacheEntry temp_entry(source_data, munger);
|
||||
temp_entry.ref(); // big ugly hack to allow a stack-allocated ReferenceCount object.
|
||||
temp_entry.local_object();
|
||||
Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
|
||||
if (ci != cdata->_cache.end()) {
|
||||
CacheEntry *entry = (*ci);
|
||||
@ -483,7 +483,6 @@ munge_geom(const qpGeomMunger *munger,
|
||||
entry->refresh();
|
||||
result = entry->_geom_result;
|
||||
data = entry->_data_result;
|
||||
temp_entry.unref();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -496,7 +495,6 @@ munge_geom(const qpGeomMunger *munger,
|
||||
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
|
||||
cdataw->_cache.erase(entry);
|
||||
}
|
||||
temp_entry.unref();
|
||||
}
|
||||
|
||||
// Ok, invoke the munger.
|
||||
@ -513,10 +511,8 @@ munge_geom(const qpGeomMunger *munger,
|
||||
CacheEntry *entry;
|
||||
{
|
||||
CDWriter cdata(((qpGeom *)this)->_cycler);
|
||||
entry = new CacheEntry(source_data, munger);
|
||||
entry->_source = (qpGeom *)this;
|
||||
entry->_geom_result = result;
|
||||
entry->_data_result = data;
|
||||
entry = new CacheEntry((qpGeom *)this, source_data, munger,
|
||||
result, data);
|
||||
bool inserted = cdata->_cache.insert(entry).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
@ -880,6 +876,18 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
manager->read_cdata(scan, _cycler);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpGeom::CacheEntry::
|
||||
~CacheEntry() {
|
||||
if (_geom_result != _source) {
|
||||
unref_delete(_geom_result);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::evict_callback
|
||||
// Access: Public, Virtual
|
||||
@ -900,17 +908,6 @@ evict_callback() {
|
||||
_source->_cycler.release_write_stage(0, cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::get_result_size
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the approximate number of bytes represented
|
||||
// by the computed result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int qpGeom::CacheEntry::
|
||||
get_result_size() const {
|
||||
return _geom_result->get_num_bytes() + _data_result->get_num_bytes();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::CacheEntry::output
|
||||
// Access: Public, Virtual
|
||||
|
@ -134,22 +134,27 @@ private:
|
||||
// We have to use reference-counting pointers here instead of having
|
||||
// explicit cleanup in the GeomVertexFormat destructor, because the
|
||||
// cache needs to be stored in the CycleData, which makes accurate
|
||||
// cleanup more difficult. We use the GeomVertexCacheManager class
|
||||
// to avoid cache bloat.
|
||||
// cleanup more difficult. We use the GeomCacheManager class to
|
||||
// avoid cache bloat.
|
||||
class CacheEntry : public qpGeomCacheEntry {
|
||||
public:
|
||||
INLINE CacheEntry(const qpGeomVertexData *source_data,
|
||||
const qpGeomMunger *modifier);
|
||||
INLINE CacheEntry(qpGeom *source,
|
||||
const qpGeomVertexData *source_data,
|
||||
const qpGeomMunger *modifier,
|
||||
const qpGeom *geom_result,
|
||||
const qpGeomVertexData *data_result);
|
||||
virtual ~CacheEntry();
|
||||
INLINE bool operator < (const CacheEntry &other) const;
|
||||
|
||||
virtual void evict_callback();
|
||||
virtual int get_result_size() const;
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
qpGeom *_source;
|
||||
CPT(qpGeomVertexData) _source_data;
|
||||
CPT(qpGeomMunger) _modifier;
|
||||
CPT(qpGeom) _geom_result;
|
||||
const qpGeom *_geom_result; // ref-counted if not same as _source
|
||||
CPT(qpGeomVertexData) _data_result;
|
||||
};
|
||||
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
||||
|
@ -30,27 +30,6 @@ qpGeomCacheEntry() {
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::refresh
|
||||
// Access: Public
|
||||
// Description: Marks the cache entry recently used, so it will not
|
||||
// be evicted for a while.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomCacheEntry::
|
||||
refresh() {
|
||||
nassertv(_next != (qpGeomCacheEntry *)NULL && _prev != (qpGeomCacheEntry *)NULL);
|
||||
|
||||
qpGeomCacheManager *cache_mgr = qpGeomCacheManager::get_global_ptr();
|
||||
MutexHolder holder(cache_mgr->_lock);
|
||||
|
||||
remove_from_list();
|
||||
insert_before(cache_mgr->_list);
|
||||
|
||||
int new_size = get_result_size();
|
||||
cache_mgr->_total_size += (new_size - _result_size);
|
||||
_result_size = new_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::remove_from_list
|
||||
// Access: Private
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qpgeomCacheManager.h"
|
||||
#include "mutexHolder.h"
|
||||
#include "config_gobj.h"
|
||||
#include "clockObject.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::Destructor
|
||||
@ -41,21 +42,20 @@ record() {
|
||||
nassertr(_next == (qpGeomCacheEntry *)NULL && _prev == (qpGeomCacheEntry *)NULL, NULL);
|
||||
PT(qpGeomCacheEntry) keepme = this;
|
||||
|
||||
_result_size = get_result_size();
|
||||
|
||||
qpGeomCacheManager *cache_mgr = qpGeomCacheManager::get_global_ptr();
|
||||
MutexHolder holder(cache_mgr->_lock);
|
||||
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
<< "recording cache entry: " << *this << ", total_size = "
|
||||
<< cache_mgr->_total_size + _result_size << "\n";
|
||||
<< cache_mgr->_total_size + 1 << "\n";
|
||||
}
|
||||
|
||||
insert_before(cache_mgr->_list);
|
||||
cache_mgr->_total_size += _result_size;
|
||||
++cache_mgr->_total_size;
|
||||
cache_mgr->_geom_cache_size_pcollector.set_level(cache_mgr->_total_size);
|
||||
cache_mgr->_geom_cache_record_pcollector.add_level(1);
|
||||
_last_frame_used = ClockObject::get_global_clock()->get_frame_count();
|
||||
|
||||
// Increment our own reference count while we're in the queue, just
|
||||
// so we don't have to play games with it later--this is inner-loop
|
||||
@ -70,6 +70,25 @@ record() {
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::refresh
|
||||
// Access: Public
|
||||
// Description: Marks the cache entry recently used, so it will not
|
||||
// be evicted for a while.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomCacheEntry::
|
||||
refresh() {
|
||||
nassertv(_next != (qpGeomCacheEntry *)NULL && _prev != (qpGeomCacheEntry *)NULL);
|
||||
|
||||
qpGeomCacheManager *cache_mgr = qpGeomCacheManager::get_global_ptr();
|
||||
MutexHolder holder(cache_mgr->_lock);
|
||||
|
||||
remove_from_list();
|
||||
insert_before(cache_mgr->_list);
|
||||
|
||||
_last_frame_used = ClockObject::get_global_clock()->get_frame_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::erase
|
||||
// Access: Public
|
||||
@ -92,7 +111,7 @@ erase() {
|
||||
MutexHolder holder(cache_mgr->_lock);
|
||||
|
||||
remove_from_list();
|
||||
cache_mgr->_total_size -= _result_size;
|
||||
--cache_mgr->_total_size;
|
||||
cache_mgr->_geom_cache_size_pcollector.set_level(cache_mgr->_total_size);
|
||||
cache_mgr->_geom_cache_erase_pcollector.add_level(1);
|
||||
|
||||
@ -109,17 +128,6 @@ void qpGeomCacheEntry::
|
||||
evict_callback() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::get_result_size
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the approximate number of bytes represented
|
||||
// by the computed result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int qpGeomCacheEntry::
|
||||
get_result_size() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheEntry::output
|
||||
// Access: Public, Virtual
|
||||
|
@ -43,15 +43,14 @@ public:
|
||||
virtual ~qpGeomCacheEntry();
|
||||
|
||||
PT(qpGeomCacheEntry) record();
|
||||
INLINE void refresh();
|
||||
void refresh();
|
||||
PT(qpGeomCacheEntry) erase();
|
||||
|
||||
virtual void evict_callback();
|
||||
virtual int get_result_size() const;
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
int _result_size;
|
||||
int _last_frame_used;
|
||||
|
||||
INLINE void remove_from_list();
|
||||
INLINE void insert_before(qpGeomCacheEntry *node);
|
||||
|
@ -20,37 +20,39 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheManager::set_max_size
|
||||
// Access: Published
|
||||
// Description: Specifies the amount of memory, in bytes, that should
|
||||
// be set aside for storing pre-processed data for
|
||||
// rendering vertices. This is not a limit on the
|
||||
// actual vertex data, which is what it is; it is also
|
||||
// not a limit on the amount of memory used by the video
|
||||
// driver or the system graphics interface, which Panda
|
||||
// has no control over.
|
||||
// Description: Specifies the maximum number of entries in the cache
|
||||
// for storing pre-processed data for rendering
|
||||
// vertices. This limit is flexible, and may be
|
||||
// temporarily exceeded if many different Geoms are
|
||||
// pre-processed during the space of a single frame.
|
||||
//
|
||||
// This is not a limit on the actual vertex data, which
|
||||
// is what it is; it is also not a limit on the amount
|
||||
// of memory used by the video driver or the system
|
||||
// graphics interface, which Panda has no control over.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomCacheManager::
|
||||
set_max_size(int max_size) const {
|
||||
// We directly change the config variable.
|
||||
vertex_convert_cache = max_size;
|
||||
geom_cache_size = max_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheManager::get_max_size
|
||||
// Access: Published
|
||||
// Description: Returns the amount of memory, in bytes, that should
|
||||
// be set aside for storing pre-processed data for
|
||||
// rendering vertices. See set_max_size().
|
||||
// Description: Returns the maximum number of entries in the cache
|
||||
// for storing pre-processed data for rendering
|
||||
// vertices. See set_max_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpGeomCacheManager::
|
||||
get_max_size() const {
|
||||
return vertex_convert_cache;
|
||||
return geom_cache_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomCacheManager::get_total_size
|
||||
// Access: Published
|
||||
// Description: Returns the amount of memory, in bytes, currently
|
||||
// consumed by the cache of pre-processed vertex data.
|
||||
// Description: Returns the number of entries currently in the cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpGeomCacheManager::
|
||||
get_total_size() const {
|
||||
|
@ -77,21 +77,36 @@ void qpGeomCacheManager::
|
||||
evict_old_entries() {
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
int current_frame = ClockObject::get_global_clock()->get_frame_count();
|
||||
int min_frames = geom_cache_min_frames;
|
||||
|
||||
int max_size = get_max_size();
|
||||
while (_total_size > max_size) {
|
||||
PT(qpGeomCacheEntry) entry = _list->_next;
|
||||
nassertv(entry != _list);
|
||||
|
||||
if (current_frame - entry->_last_frame_used < min_frames) {
|
||||
// Never mind, this one is too new.
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
<< "Oldest element in cache is "
|
||||
<< current_frame - entry->_last_frame_used
|
||||
<< " frames; keeping cache at " << _total_size << " entries.\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
entry->unref();
|
||||
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
<< "cache total_size = " << _total_size << ", max_size = "
|
||||
<< "cache total_size = " << _total_size << " entries, max_size = "
|
||||
<< max_size << ", removing " << *entry << "\n";
|
||||
}
|
||||
|
||||
entry->evict_callback();
|
||||
|
||||
_total_size -= entry->_result_size;
|
||||
--_total_size;
|
||||
entry->remove_from_list();
|
||||
_geom_cache_evict_pcollector.add_level(1);
|
||||
}
|
||||
|
@ -252,17 +252,6 @@ do_unregister() {
|
||||
_formats_by_animation.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::CacheEntry::get_result_size
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the approximate number of bytes represented
|
||||
// by the computed result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int qpGeomMunger::CacheEntry::
|
||||
get_result_size() const {
|
||||
return sizeof(qpGeomMunger);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::CacheEntry::output
|
||||
// Access: Public, Virtual
|
||||
|
@ -118,7 +118,6 @@ private:
|
||||
private:
|
||||
class CacheEntry : public qpGeomCacheEntry {
|
||||
public:
|
||||
virtual int get_result_size() const;
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
PT(qpGeomMunger) _munger;
|
||||
|
@ -300,12 +300,7 @@ clear_vertices() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomPrimitive::
|
||||
offset_vertices(int offset) {
|
||||
CDWriter cdata(_cycler);
|
||||
|
||||
cdata->_got_minmax = false;
|
||||
|
||||
qpGeomVertexRewriter index(cdata->_vertices, 0);
|
||||
|
||||
qpGeomVertexRewriter index(modify_vertices(), 0);
|
||||
while (!index.is_at_end()) {
|
||||
index.set_data1i(index.get_data1i() + offset);
|
||||
}
|
||||
|
@ -136,3 +136,9 @@ CData(const qpGeomVertexArrayData::CData ©) :
|
||||
_modified(copy._modified)
|
||||
{
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpGeomVertexArrayData &obj) {
|
||||
obj.output(out);
|
||||
return out;
|
||||
}
|
||||
|
@ -159,6 +159,26 @@ set_usage_hint(qpGeomVertexArrayData::UsageHint usage_hint) {
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexArrayData::
|
||||
output(ostream &out) const {
|
||||
out << get_num_rows() << " rows: " << *get_array_format();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::write
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexArrayData::
|
||||
write(ostream &out, int indent_level) const {
|
||||
_array_format->write_with_data(out, indent_level, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::modify_data
|
||||
// Access: Public
|
||||
|
@ -81,6 +81,9 @@ PUBLISHED:
|
||||
INLINE int get_data_size_bytes() const;
|
||||
INLINE UpdateSeq get_modified() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
public:
|
||||
INLINE CPTA_uchar get_data() const;
|
||||
PTA_uchar modify_data();
|
||||
@ -158,6 +161,8 @@ private:
|
||||
friend class PreparedGraphicsObjects;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const qpGeomVertexArrayData &obj);
|
||||
|
||||
#include "qpgeomVertexArrayData.I"
|
||||
|
||||
#endif
|
||||
|
@ -435,13 +435,13 @@ write(ostream &out, int indent_level) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexArrayFormat::
|
||||
write_with_data(ostream &out, int indent_level,
|
||||
const qpGeomVertexData *data, int array_index) const {
|
||||
const qpGeomVertexArrayData *array_data) const {
|
||||
consider_sort_columns();
|
||||
int num_vertices = data->get_num_rows();
|
||||
int num_rows = array_data->get_num_rows();
|
||||
|
||||
qpGeomVertexReader reader(data);
|
||||
qpGeomVertexReader reader(array_data);
|
||||
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
for (int i = 0; i < num_rows; i++) {
|
||||
indent(out, indent_level)
|
||||
<< "row " << i << ":\n";
|
||||
reader.set_row(i);
|
||||
@ -449,7 +449,7 @@ write_with_data(ostream &out, int indent_level,
|
||||
for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
|
||||
const qpGeomVertexColumn *column = (*ci);
|
||||
int num_values = min(column->get_num_values(), 4);
|
||||
reader.set_column(array_index, column);
|
||||
reader.set_column(0, column);
|
||||
const LVecBase4f &d = reader.get_data4f();
|
||||
|
||||
indent(out, indent_level + 2)
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
class qpGeomVertexFormat;
|
||||
class qpGeomVertexData;
|
||||
class qpGeomVertexArrayData;
|
||||
class InternalName;
|
||||
class FactoryParams;
|
||||
class BamWriter;
|
||||
@ -109,7 +110,7 @@ PUBLISHED:
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
void write_with_data(ostream &out, int indent_level,
|
||||
const qpGeomVertexData *data, int array_index) const;
|
||||
const qpGeomVertexArrayData *array_data) const;
|
||||
|
||||
public:
|
||||
int compare_to(const qpGeomVertexArrayFormat &other) const;
|
||||
|
@ -553,7 +553,8 @@ convert_to(const qpGeomVertexFormat *new_format) const {
|
||||
// Okay, convert the data to the new format.
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
<< "Converting " << get_num_rows() << " rows.\n";
|
||||
<< "Converting " << get_num_rows() << " rows from " << *_format
|
||||
<< " to " << *new_format << "\n";
|
||||
}
|
||||
PStatTimer timer(_convert_pcollector);
|
||||
|
||||
|
@ -418,7 +418,7 @@ write_with_data(ostream &out, int indent_level,
|
||||
CPTA_uchar array_data = data->get_array(i)->get_data();
|
||||
indent(out, indent_level)
|
||||
<< "Array " << i << " (" << (void *)array_data.p() << "):\n";
|
||||
_arrays[i]->write_with_data(out, indent_level + 2, data, i);
|
||||
_arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,8 +169,8 @@ static LevelCollectorProperties level_properties[] = {
|
||||
{ 1, "Vertex buffer switch", { 0.0, 0.6, 0.8 }, "", 500 },
|
||||
{ 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } },
|
||||
{ 1, "Vertex buffer switch:Index", { 0.8, 0.6, 0.3 } },
|
||||
{ 1, "Geom cache size", { 1.0, 0.8, 0.6 }, "MB", 12, 1048576 },
|
||||
{ 1, "Geom cache operations", { 1.0, 0.8, 0.6 }, "", 500 },
|
||||
{ 1, "Geom cache size", { 0.6, 0.8, 0.6 }, "", 500 },
|
||||
{ 1, "Geom cache operations", { 1.0, 0.6, 0.6 }, "", 500 },
|
||||
{ 1, "Geom cache operations:record", { 0.2, 0.4, 0.8 } },
|
||||
{ 1, "Geom cache operations:erase", { 0.4, 0.8, 0.2 } },
|
||||
{ 1, "Geom cache operations:evict", { 0.8, 0.2, 0.4 } },
|
||||
|
Loading…
x
Reference in New Issue
Block a user