mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -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();
|
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
|
// Function: GraphicsStateGuardian::set_active
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -1511,6 +1511,8 @@ close_gsg() {
|
|||||||
if (_prepared_objects->get_ref_count() == 1) {
|
if (_prepared_objects->get_ref_count() == 1) {
|
||||||
release_all_textures();
|
release_all_textures();
|
||||||
release_all_geoms();
|
release_all_geoms();
|
||||||
|
release_all_vertex_buffers();
|
||||||
|
release_all_index_buffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,8 @@ public:
|
|||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE int release_all_textures();
|
INLINE int release_all_textures();
|
||||||
INLINE int release_all_geoms();
|
INLINE int release_all_geoms();
|
||||||
|
INLINE int release_all_vertex_buffers();
|
||||||
|
INLINE int release_all_index_buffers();
|
||||||
|
|
||||||
INLINE void set_active(bool active);
|
INLINE void set_active(bool active);
|
||||||
INLINE bool is_active() const;
|
INLINE bool is_active() const;
|
||||||
|
@ -59,7 +59,7 @@ GraphicsThreadingModel(const string &model) {
|
|||||||
|
|
||||||
size_t slash = model.find('/', start);
|
size_t slash = model.find('/', start);
|
||||||
if (slash == string::npos) {
|
if (slash == string::npos) {
|
||||||
_cull_name = model;
|
_cull_name = model.substr(start);
|
||||||
} else {
|
} else {
|
||||||
_cull_name = model.substr(start, slash - start);
|
_cull_name = model.substr(start, slash - start);
|
||||||
_draw_name = model.substr(slash + 1);
|
_draw_name = model.substr(slash + 1);
|
||||||
|
@ -3197,45 +3197,52 @@ release_texture(TextureContext *tc) {
|
|||||||
VertexBufferContext *DXGraphicsStateGuardian8::
|
VertexBufferContext *DXGraphicsStateGuardian8::
|
||||||
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
|
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
|
||||||
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(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;
|
return dvbc;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DXGraphicsStateGuardian8::apply_vertex_buffer
|
// Function: DXGraphicsStateGuardian8::apply_vertex_buffer
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Makes the data the currently available data for
|
// Description: Updates the vertex buffer with the current data, and
|
||||||
// rendering.
|
// makes it the current vertex buffer for rendering.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DXGraphicsStateGuardian8::
|
void DXGraphicsStateGuardian8::
|
||||||
apply_vertex_buffer(VertexBufferContext *vbc) {
|
apply_vertex_buffer(VertexBufferContext *vbc) {
|
||||||
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, 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);
|
add_to_vertex_buffer_record(dvbc);
|
||||||
|
|
||||||
if (dvbc->was_modified()) {
|
if (dvbc->was_modified()) {
|
||||||
if (dvbc->changed_size()) {
|
if (dvbc->changed_size()) {
|
||||||
// Here we have to destroy the old vertex buffer and create a
|
// We have to destroy the old vertex buffer and create a new
|
||||||
// new one.
|
// one.
|
||||||
dvbc->create_vbuffer(*_pScrn);
|
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);
|
add_to_total_buffer_record(dvbc);
|
||||||
dvbc->mark_loaded();
|
dvbc->mark_loaded();
|
||||||
}
|
}
|
||||||
@ -3243,9 +3250,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
|
|||||||
_pD3DDevice->SetStreamSource
|
_pD3DDevice->SetStreamSource
|
||||||
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
|
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
|
||||||
_vbuffer_active = true;
|
_vbuffer_active = true;
|
||||||
|
|
||||||
} else {
|
|
||||||
_vbuffer_active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_vertex_format(dvbc->_fvf);
|
set_vertex_format(dvbc->_fvf);
|
||||||
@ -3281,54 +3285,55 @@ release_vertex_buffer(VertexBufferContext *vbc) {
|
|||||||
IndexBufferContext *DXGraphicsStateGuardian8::
|
IndexBufferContext *DXGraphicsStateGuardian8::
|
||||||
prepare_index_buffer(qpGeomPrimitive *data) {
|
prepare_index_buffer(qpGeomPrimitive *data) {
|
||||||
DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(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;
|
return dibc;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DXGraphicsStateGuardian8::apply_index_buffer
|
// Function: DXGraphicsStateGuardian8::apply_index_buffer
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Makes the data the currently available data for
|
// Description: Updates the index buffer with the current data, and
|
||||||
// rendering.
|
// makes it the current index buffer for rendering.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DXGraphicsStateGuardian8::
|
void DXGraphicsStateGuardian8::
|
||||||
apply_index_buffer(IndexBufferContext *ibc) {
|
apply_index_buffer(IndexBufferContext *ibc) {
|
||||||
DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, 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);
|
add_to_index_buffer_record(dibc);
|
||||||
|
|
||||||
if (dibc->was_modified()) {
|
if (dibc->was_modified()) {
|
||||||
if (dibc->changed_size()) {
|
if (dibc->changed_size()) {
|
||||||
// Here we have to destroy the old index buffer and create a
|
// We have to destroy the old index buffer and create a new
|
||||||
// new one.
|
// one.
|
||||||
dibc->create_ibuffer(*_pScrn);
|
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);
|
add_to_total_buffer_record(dibc);
|
||||||
dibc->mark_loaded();
|
dibc->mark_loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
_pD3DDevice->SetIndices(dibc->_ibuffer, 0);
|
_pD3DDevice->SetIndices(dibc->_ibuffer, 0);
|
||||||
_ibuffer_active = true;
|
_ibuffer_active = true;
|
||||||
|
|
||||||
} else {
|
|
||||||
_pD3DDevice->SetIndices(NULL, 0);
|
|
||||||
_ibuffer_active = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ DXIndexBufferContext8::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DXIndexBufferContext8::create_ibuffer
|
// Function: DXIndexBufferContext8::create_ibuffer
|
||||||
// Access: Public
|
// 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::
|
void DXIndexBufferContext8::
|
||||||
create_ibuffer(DXScreenData &scrn) {
|
create_ibuffer(DXScreenData &scrn) {
|
||||||
@ -77,9 +78,14 @@ create_ibuffer(DXScreenData &scrn) {
|
|||||||
dxgsg8_cat.warning()
|
dxgsg8_cat.warning()
|
||||||
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
|
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
|
||||||
_ibuffer = NULL;
|
_ibuffer = NULL;
|
||||||
|
|
||||||
} else {
|
} 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
|
// Function: DXVertexBufferContext8::create_vbuffer
|
||||||
// Access: Public
|
// 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::
|
void DXVertexBufferContext8::
|
||||||
create_vbuffer(DXScreenData &scrn) {
|
create_vbuffer(DXScreenData &scrn) {
|
||||||
@ -169,9 +170,13 @@ create_vbuffer(DXScreenData &scrn) {
|
|||||||
dxgsg8_cat.warning()
|
dxgsg8_cat.warning()
|
||||||
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
||||||
_vbuffer = NULL;
|
_vbuffer = NULL;
|
||||||
|
|
||||||
} else {
|
} 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
|
// instance of a class that derives from ReferenceCount. Or maybe
|
||||||
// your headers are out of sync, and you need to make clean in
|
// your headers are out of sync, and you need to make clean in
|
||||||
// direct or some higher tree.
|
// 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
|
// automatic (local variable) instance of a class that derives from
|
||||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||||
// need to make clean in direct or some higher tree.
|
// 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
|
// If this assertion fails, the reference counts are all screwed
|
||||||
// up altogether. Maybe some errant code stomped all over memory
|
// up altogether. Maybe some errant code stomped all over memory
|
||||||
@ -129,7 +135,7 @@ INLINE ReferenceCount::
|
|||||||
// constructor for a ReferenceCount object, and then bitwise
|
// constructor for a ReferenceCount object, and then bitwise
|
||||||
// copied a dynamically allocated value--reference count and
|
// copied a dynamically allocated value--reference count and
|
||||||
// all--onto a locally allocated one.
|
// 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.
|
// Tell our weak reference holders that we're going away now.
|
||||||
if (_weak_list != (WeakReferenceList *)NULL) {
|
if (_weak_list != (WeakReferenceList *)NULL) {
|
||||||
@ -138,10 +144,10 @@ INLINE ReferenceCount::
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Ok, all clear to delete. Now set the reference count to -100,
|
// Ok, all clear to delete. Now set the reference count to
|
||||||
// so we'll have a better chance of noticing if we happen to have
|
// deleted_ref_count, so we'll have a better chance of noticing if
|
||||||
// a stray pointer to it still out there.
|
// we happen to have a stray pointer to it still out there.
|
||||||
_ref_count = -100;
|
_ref_count = deleted_ref_count;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DO_MEMORY_USAGE
|
#ifdef DO_MEMORY_USAGE
|
||||||
@ -151,7 +157,7 @@ INLINE ReferenceCount::
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ReferenceCount::get_ref_count
|
// Function: ReferenceCount::get_ref_count
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Returns the current reference count.
|
// Description: Returns the current reference count.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int ReferenceCount::
|
INLINE int ReferenceCount::
|
||||||
@ -164,7 +170,7 @@ get_ref_count() const {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ReferenceCount::ref
|
// Function: ReferenceCount::ref
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Explicitly increments the reference count. User code
|
// Description: Explicitly increments the reference count. User code
|
||||||
// should avoid using ref() and unref() directly, which
|
// should avoid using ref() and unref() directly, which
|
||||||
// can result in missed reference counts. Instead, let
|
// can result in missed reference counts. Instead, let
|
||||||
@ -191,7 +197,7 @@ ref() const {
|
|||||||
// automatic (local variable) instance of a class that derives from
|
// automatic (local variable) instance of a class that derives from
|
||||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||||
// need to make clean in direct or some higher tree.
|
// 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
|
// If this assertion fails, the reference counts are all screwed
|
||||||
// up altogether. Maybe some errant code stomped all over memory
|
// up altogether. Maybe some errant code stomped all over memory
|
||||||
@ -203,7 +209,7 @@ ref() const {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ReferenceCount::unref
|
// Function: ReferenceCount::unref
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Explicitly decrements the reference count. Note that
|
// Description: Explicitly decrements the reference count. Note that
|
||||||
// the object will not be implicitly deleted by unref()
|
// the object will not be implicitly deleted by unref()
|
||||||
// simply because the reference count drops to zero.
|
// simply because the reference count drops to zero.
|
||||||
@ -237,7 +243,7 @@ unref() const {
|
|||||||
// automatic (local variable) instance of a class that derives from
|
// automatic (local variable) instance of a class that derives from
|
||||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||||
// need to make clean in direct or some higher tree.
|
// 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
|
// If this assertion fails, the reference counts are all screwed
|
||||||
// up altogether. Maybe some errant code stomped all over memory
|
// up altogether. Maybe some errant code stomped all over memory
|
||||||
@ -254,7 +260,7 @@ unref() const {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ReferenceCount::test_ref_count_integrity
|
// Function: ReferenceCount::test_ref_count_integrity
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Does some easy checks to make sure that the reference
|
// Description: Does some easy checks to make sure that the reference
|
||||||
// count isn't completely bogus.
|
// count isn't completely bogus.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -270,7 +276,7 @@ test_ref_count_integrity() const {
|
|||||||
// automatic (local variable) instance of a class that derives from
|
// automatic (local variable) instance of a class that derives from
|
||||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||||
// need to make clean in direct or some higher tree.
|
// 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
|
// If this assertion fails, the reference counts are all screwed
|
||||||
// up altogether. Maybe some errant code stomped all over memory
|
// up altogether. Maybe some errant code stomped all over memory
|
||||||
@ -279,6 +285,30 @@ test_ref_count_integrity() const {
|
|||||||
#endif
|
#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
|
// Function: ReferenceCount::has_weak_list
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -54,6 +54,7 @@ PUBLISHED:
|
|||||||
INLINE void test_ref_count_integrity() const;
|
INLINE void test_ref_count_integrity() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
INLINE void local_object();
|
||||||
INLINE bool has_weak_list() const;
|
INLINE bool has_weak_list() const;
|
||||||
INLINE WeakReferenceList *get_weak_list() const;
|
INLINE WeakReferenceList *get_weak_list() const;
|
||||||
|
|
||||||
@ -61,6 +62,22 @@ public:
|
|||||||
INLINE void weak_unref(WeakPointerToVoid *ptv);
|
INLINE void weak_unref(WeakPointerToVoid *ptv);
|
||||||
|
|
||||||
private:
|
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;
|
int _ref_count;
|
||||||
WeakReferenceList *_weak_list;
|
WeakReferenceList *_weak_list;
|
||||||
|
|
||||||
@ -137,8 +154,6 @@ private:
|
|||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "referenceCount.I"
|
#include "referenceCount.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -206,14 +206,19 @@ ConfigVariableString fake_texture_image
|
|||||||
"the same texture file, which will presumably only be loaded "
|
"the same texture file, which will presumably only be loaded "
|
||||||
"once."));
|
"once."));
|
||||||
|
|
||||||
ConfigVariableInt vertex_convert_cache
|
ConfigVariableInt geom_cache_size
|
||||||
("vertex-convert-cache", 4194304, // 4 MB
|
("geom-cache-size", 5000,
|
||||||
PRC_DESC("This is the amount of memory, in bytes, that should be set "
|
PRC_DESC("Specifies the maximum number of entries in the cache "
|
||||||
"aside for storing pre-processed data for rendering vertices. "
|
"for storing pre-processed data for rendering "
|
||||||
"This is not a limit on the actual vertex data, which is "
|
"vertices. This limit is flexible, and may be "
|
||||||
"determined by the model; it is also not a limit on the "
|
"temporarily exceeded if many different Geoms are "
|
||||||
"amount of memory used by the video driver or the system "
|
"pre-processed during the space of a single frame."));
|
||||||
"graphics interface, which Panda has no control over."));
|
|
||||||
|
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
|
ConfigVariableDouble default_near
|
||||||
("default-near", 1.0,
|
("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 ConfigVariableEnum<AutoTextureScale> textures_square;
|
||||||
extern EXPCL_PANDA ConfigVariableString fake_texture_image;
|
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_near;
|
||||||
extern ConfigVariableDouble default_far;
|
extern ConfigVariableDouble default_far;
|
||||||
|
@ -187,11 +187,34 @@ get_modified() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE qpGeom::CacheEntry::
|
INLINE qpGeom::CacheEntry::
|
||||||
CacheEntry(const qpGeomVertexData *source_data, const qpGeomMunger *modifier) :
|
CacheEntry(const qpGeomVertexData *source_data, const qpGeomMunger *modifier) :
|
||||||
|
_source(NULL),
|
||||||
_source_data(source_data),
|
_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 <
|
// Function: qpGeom::CacheEntry::operator <
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -469,7 +469,7 @@ munge_geom(const qpGeomMunger *munger,
|
|||||||
{
|
{
|
||||||
CDReader cdata(_cycler);
|
CDReader cdata(_cycler);
|
||||||
CacheEntry temp_entry(source_data, munger);
|
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);
|
Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
|
||||||
if (ci != cdata->_cache.end()) {
|
if (ci != cdata->_cache.end()) {
|
||||||
CacheEntry *entry = (*ci);
|
CacheEntry *entry = (*ci);
|
||||||
@ -483,7 +483,6 @@ munge_geom(const qpGeomMunger *munger,
|
|||||||
entry->refresh();
|
entry->refresh();
|
||||||
result = entry->_geom_result;
|
result = entry->_geom_result;
|
||||||
data = entry->_data_result;
|
data = entry->_data_result;
|
||||||
temp_entry.unref();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +495,6 @@ munge_geom(const qpGeomMunger *munger,
|
|||||||
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
|
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
|
||||||
cdataw->_cache.erase(entry);
|
cdataw->_cache.erase(entry);
|
||||||
}
|
}
|
||||||
temp_entry.unref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, invoke the munger.
|
// Ok, invoke the munger.
|
||||||
@ -513,10 +511,8 @@ munge_geom(const qpGeomMunger *munger,
|
|||||||
CacheEntry *entry;
|
CacheEntry *entry;
|
||||||
{
|
{
|
||||||
CDWriter cdata(((qpGeom *)this)->_cycler);
|
CDWriter cdata(((qpGeom *)this)->_cycler);
|
||||||
entry = new CacheEntry(source_data, munger);
|
entry = new CacheEntry((qpGeom *)this, source_data, munger,
|
||||||
entry->_source = (qpGeom *)this;
|
result, data);
|
||||||
entry->_geom_result = result;
|
|
||||||
entry->_data_result = data;
|
|
||||||
bool inserted = cdata->_cache.insert(entry).second;
|
bool inserted = cdata->_cache.insert(entry).second;
|
||||||
nassertv(inserted);
|
nassertv(inserted);
|
||||||
}
|
}
|
||||||
@ -880,6 +876,18 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
manager->read_cdata(scan, _cycler);
|
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
|
// Function: qpGeom::CacheEntry::evict_callback
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -900,17 +908,6 @@ evict_callback() {
|
|||||||
_source->_cycler.release_write_stage(0, cdata);
|
_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
|
// Function: qpGeom::CacheEntry::output
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -134,22 +134,27 @@ private:
|
|||||||
// We have to use reference-counting pointers here instead of having
|
// We have to use reference-counting pointers here instead of having
|
||||||
// explicit cleanup in the GeomVertexFormat destructor, because the
|
// explicit cleanup in the GeomVertexFormat destructor, because the
|
||||||
// cache needs to be stored in the CycleData, which makes accurate
|
// cache needs to be stored in the CycleData, which makes accurate
|
||||||
// cleanup more difficult. We use the GeomVertexCacheManager class
|
// cleanup more difficult. We use the GeomCacheManager class to
|
||||||
// to avoid cache bloat.
|
// avoid cache bloat.
|
||||||
class CacheEntry : public qpGeomCacheEntry {
|
class CacheEntry : public qpGeomCacheEntry {
|
||||||
public:
|
public:
|
||||||
INLINE CacheEntry(const qpGeomVertexData *source_data,
|
INLINE CacheEntry(const qpGeomVertexData *source_data,
|
||||||
const qpGeomMunger *modifier);
|
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;
|
INLINE bool operator < (const CacheEntry &other) const;
|
||||||
|
|
||||||
virtual void evict_callback();
|
virtual void evict_callback();
|
||||||
virtual int get_result_size() const;
|
|
||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
qpGeom *_source;
|
qpGeom *_source;
|
||||||
CPT(qpGeomVertexData) _source_data;
|
CPT(qpGeomVertexData) _source_data;
|
||||||
CPT(qpGeomMunger) _modifier;
|
CPT(qpGeomMunger) _modifier;
|
||||||
CPT(qpGeom) _geom_result;
|
const qpGeom *_geom_result; // ref-counted if not same as _source
|
||||||
CPT(qpGeomVertexData) _data_result;
|
CPT(qpGeomVertexData) _data_result;
|
||||||
};
|
};
|
||||||
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
||||||
|
@ -30,27 +30,6 @@ qpGeomCacheEntry() {
|
|||||||
#endif
|
#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
|
// Function: qpGeomCacheEntry::remove_from_list
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "qpgeomCacheManager.h"
|
#include "qpgeomCacheManager.h"
|
||||||
#include "mutexHolder.h"
|
#include "mutexHolder.h"
|
||||||
#include "config_gobj.h"
|
#include "config_gobj.h"
|
||||||
|
#include "clockObject.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: qpGeomCacheEntry::Destructor
|
// Function: qpGeomCacheEntry::Destructor
|
||||||
@ -41,21 +42,20 @@ record() {
|
|||||||
nassertr(_next == (qpGeomCacheEntry *)NULL && _prev == (qpGeomCacheEntry *)NULL, NULL);
|
nassertr(_next == (qpGeomCacheEntry *)NULL && _prev == (qpGeomCacheEntry *)NULL, NULL);
|
||||||
PT(qpGeomCacheEntry) keepme = this;
|
PT(qpGeomCacheEntry) keepme = this;
|
||||||
|
|
||||||
_result_size = get_result_size();
|
|
||||||
|
|
||||||
qpGeomCacheManager *cache_mgr = qpGeomCacheManager::get_global_ptr();
|
qpGeomCacheManager *cache_mgr = qpGeomCacheManager::get_global_ptr();
|
||||||
MutexHolder holder(cache_mgr->_lock);
|
MutexHolder holder(cache_mgr->_lock);
|
||||||
|
|
||||||
if (gobj_cat.is_debug()) {
|
if (gobj_cat.is_debug()) {
|
||||||
gobj_cat.debug()
|
gobj_cat.debug()
|
||||||
<< "recording cache entry: " << *this << ", total_size = "
|
<< "recording cache entry: " << *this << ", total_size = "
|
||||||
<< cache_mgr->_total_size + _result_size << "\n";
|
<< cache_mgr->_total_size + 1 << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_before(cache_mgr->_list);
|
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_size_pcollector.set_level(cache_mgr->_total_size);
|
||||||
cache_mgr->_geom_cache_record_pcollector.add_level(1);
|
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
|
// 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
|
// so we don't have to play games with it later--this is inner-loop
|
||||||
@ -70,6 +70,25 @@ record() {
|
|||||||
return this;
|
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
|
// Function: qpGeomCacheEntry::erase
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -92,7 +111,7 @@ erase() {
|
|||||||
MutexHolder holder(cache_mgr->_lock);
|
MutexHolder holder(cache_mgr->_lock);
|
||||||
|
|
||||||
remove_from_list();
|
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_size_pcollector.set_level(cache_mgr->_total_size);
|
||||||
cache_mgr->_geom_cache_erase_pcollector.add_level(1);
|
cache_mgr->_geom_cache_erase_pcollector.add_level(1);
|
||||||
|
|
||||||
@ -109,17 +128,6 @@ void qpGeomCacheEntry::
|
|||||||
evict_callback() {
|
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
|
// Function: qpGeomCacheEntry::output
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -43,15 +43,14 @@ public:
|
|||||||
virtual ~qpGeomCacheEntry();
|
virtual ~qpGeomCacheEntry();
|
||||||
|
|
||||||
PT(qpGeomCacheEntry) record();
|
PT(qpGeomCacheEntry) record();
|
||||||
INLINE void refresh();
|
void refresh();
|
||||||
PT(qpGeomCacheEntry) erase();
|
PT(qpGeomCacheEntry) erase();
|
||||||
|
|
||||||
virtual void evict_callback();
|
virtual void evict_callback();
|
||||||
virtual int get_result_size() const;
|
|
||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _result_size;
|
int _last_frame_used;
|
||||||
|
|
||||||
INLINE void remove_from_list();
|
INLINE void remove_from_list();
|
||||||
INLINE void insert_before(qpGeomCacheEntry *node);
|
INLINE void insert_before(qpGeomCacheEntry *node);
|
||||||
|
@ -20,37 +20,39 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: qpGeomCacheManager::set_max_size
|
// Function: qpGeomCacheManager::set_max_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Specifies the amount of memory, in bytes, that should
|
// Description: Specifies the maximum number of entries in the cache
|
||||||
// be set aside for storing pre-processed data for
|
// for storing pre-processed data for rendering
|
||||||
// rendering vertices. This is not a limit on the
|
// vertices. This limit is flexible, and may be
|
||||||
// actual vertex data, which is what it is; it is also
|
// temporarily exceeded if many different Geoms are
|
||||||
// not a limit on the amount of memory used by the video
|
// pre-processed during the space of a single frame.
|
||||||
// driver or the system graphics interface, which Panda
|
//
|
||||||
// has no control over.
|
// 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::
|
INLINE void qpGeomCacheManager::
|
||||||
set_max_size(int max_size) const {
|
set_max_size(int max_size) const {
|
||||||
// We directly change the config variable.
|
// We directly change the config variable.
|
||||||
vertex_convert_cache = max_size;
|
geom_cache_size = max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: qpGeomCacheManager::get_max_size
|
// Function: qpGeomCacheManager::get_max_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Returns the amount of memory, in bytes, that should
|
// Description: Returns the maximum number of entries in the cache
|
||||||
// be set aside for storing pre-processed data for
|
// for storing pre-processed data for rendering
|
||||||
// rendering vertices. See set_max_size().
|
// vertices. See set_max_size().
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int qpGeomCacheManager::
|
INLINE int qpGeomCacheManager::
|
||||||
get_max_size() const {
|
get_max_size() const {
|
||||||
return vertex_convert_cache;
|
return geom_cache_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: qpGeomCacheManager::get_total_size
|
// Function: qpGeomCacheManager::get_total_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Returns the amount of memory, in bytes, currently
|
// Description: Returns the number of entries currently in the cache.
|
||||||
// consumed by the cache of pre-processed vertex data.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int qpGeomCacheManager::
|
INLINE int qpGeomCacheManager::
|
||||||
get_total_size() const {
|
get_total_size() const {
|
||||||
|
@ -77,21 +77,36 @@ void qpGeomCacheManager::
|
|||||||
evict_old_entries() {
|
evict_old_entries() {
|
||||||
MutexHolder holder(_lock);
|
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();
|
int max_size = get_max_size();
|
||||||
while (_total_size > max_size) {
|
while (_total_size > max_size) {
|
||||||
PT(qpGeomCacheEntry) entry = _list->_next;
|
PT(qpGeomCacheEntry) entry = _list->_next;
|
||||||
nassertv(entry != _list);
|
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();
|
entry->unref();
|
||||||
|
|
||||||
if (gobj_cat.is_debug()) {
|
if (gobj_cat.is_debug()) {
|
||||||
gobj_cat.debug()
|
gobj_cat.debug()
|
||||||
<< "cache total_size = " << _total_size << ", max_size = "
|
<< "cache total_size = " << _total_size << " entries, max_size = "
|
||||||
<< max_size << ", removing " << *entry << "\n";
|
<< max_size << ", removing " << *entry << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->evict_callback();
|
entry->evict_callback();
|
||||||
|
|
||||||
_total_size -= entry->_result_size;
|
--_total_size;
|
||||||
entry->remove_from_list();
|
entry->remove_from_list();
|
||||||
_geom_cache_evict_pcollector.add_level(1);
|
_geom_cache_evict_pcollector.add_level(1);
|
||||||
}
|
}
|
||||||
|
@ -252,17 +252,6 @@ do_unregister() {
|
|||||||
_formats_by_animation.clear();
|
_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
|
// Function: qpGeomMunger::CacheEntry::output
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -118,7 +118,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
class CacheEntry : public qpGeomCacheEntry {
|
class CacheEntry : public qpGeomCacheEntry {
|
||||||
public:
|
public:
|
||||||
virtual int get_result_size() const;
|
|
||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
PT(qpGeomMunger) _munger;
|
PT(qpGeomMunger) _munger;
|
||||||
|
@ -300,12 +300,7 @@ clear_vertices() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void qpGeomPrimitive::
|
void qpGeomPrimitive::
|
||||||
offset_vertices(int offset) {
|
offset_vertices(int offset) {
|
||||||
CDWriter cdata(_cycler);
|
qpGeomVertexRewriter index(modify_vertices(), 0);
|
||||||
|
|
||||||
cdata->_got_minmax = false;
|
|
||||||
|
|
||||||
qpGeomVertexRewriter index(cdata->_vertices, 0);
|
|
||||||
|
|
||||||
while (!index.is_at_end()) {
|
while (!index.is_at_end()) {
|
||||||
index.set_data1i(index.get_data1i() + offset);
|
index.set_data1i(index.get_data1i() + offset);
|
||||||
}
|
}
|
||||||
|
@ -136,3 +136,9 @@ CData(const qpGeomVertexArrayData::CData ©) :
|
|||||||
_modified(copy._modified)
|
_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();
|
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
|
// Function: qpGeomVertexArrayData::modify_data
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -81,6 +81,9 @@ PUBLISHED:
|
|||||||
INLINE int get_data_size_bytes() const;
|
INLINE int get_data_size_bytes() const;
|
||||||
INLINE UpdateSeq get_modified() const;
|
INLINE UpdateSeq get_modified() const;
|
||||||
|
|
||||||
|
void output(ostream &out) const;
|
||||||
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INLINE CPTA_uchar get_data() const;
|
INLINE CPTA_uchar get_data() const;
|
||||||
PTA_uchar modify_data();
|
PTA_uchar modify_data();
|
||||||
@ -158,6 +161,8 @@ private:
|
|||||||
friend class PreparedGraphicsObjects;
|
friend class PreparedGraphicsObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INLINE ostream &operator << (ostream &out, const qpGeomVertexArrayData &obj);
|
||||||
|
|
||||||
#include "qpgeomVertexArrayData.I"
|
#include "qpgeomVertexArrayData.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -435,13 +435,13 @@ write(ostream &out, int indent_level) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void qpGeomVertexArrayFormat::
|
void qpGeomVertexArrayFormat::
|
||||||
write_with_data(ostream &out, int indent_level,
|
write_with_data(ostream &out, int indent_level,
|
||||||
const qpGeomVertexData *data, int array_index) const {
|
const qpGeomVertexArrayData *array_data) const {
|
||||||
consider_sort_columns();
|
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)
|
indent(out, indent_level)
|
||||||
<< "row " << i << ":\n";
|
<< "row " << i << ":\n";
|
||||||
reader.set_row(i);
|
reader.set_row(i);
|
||||||
@ -449,7 +449,7 @@ write_with_data(ostream &out, int indent_level,
|
|||||||
for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
|
for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
|
||||||
const qpGeomVertexColumn *column = (*ci);
|
const qpGeomVertexColumn *column = (*ci);
|
||||||
int num_values = min(column->get_num_values(), 4);
|
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();
|
const LVecBase4f &d = reader.get_data4f();
|
||||||
|
|
||||||
indent(out, indent_level + 2)
|
indent(out, indent_level + 2)
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
class qpGeomVertexFormat;
|
class qpGeomVertexFormat;
|
||||||
class qpGeomVertexData;
|
class qpGeomVertexData;
|
||||||
|
class qpGeomVertexArrayData;
|
||||||
class InternalName;
|
class InternalName;
|
||||||
class FactoryParams;
|
class FactoryParams;
|
||||||
class BamWriter;
|
class BamWriter;
|
||||||
@ -109,7 +110,7 @@ PUBLISHED:
|
|||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
void write_with_data(ostream &out, int indent_level,
|
void write_with_data(ostream &out, int indent_level,
|
||||||
const qpGeomVertexData *data, int array_index) const;
|
const qpGeomVertexArrayData *array_data) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int compare_to(const qpGeomVertexArrayFormat &other) const;
|
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.
|
// Okay, convert the data to the new format.
|
||||||
if (gobj_cat.is_debug()) {
|
if (gobj_cat.is_debug()) {
|
||||||
gobj_cat.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);
|
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();
|
CPTA_uchar array_data = data->get_array(i)->get_data();
|
||||||
indent(out, indent_level)
|
indent(out, indent_level)
|
||||||
<< "Array " << i << " (" << (void *)array_data.p() << "):\n";
|
<< "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", { 0.0, 0.6, 0.8 }, "", 500 },
|
||||||
{ 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } },
|
{ 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } },
|
||||||
{ 1, "Vertex buffer switch:Index", { 0.8, 0.6, 0.3 } },
|
{ 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 size", { 0.6, 0.8, 0.6 }, "", 500 },
|
||||||
{ 1, "Geom cache operations", { 1.0, 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:record", { 0.2, 0.4, 0.8 } },
|
||||||
{ 1, "Geom cache operations:erase", { 0.4, 0.8, 0.2 } },
|
{ 1, "Geom cache operations:erase", { 0.4, 0.8, 0.2 } },
|
||||||
{ 1, "Geom cache operations:evict", { 0.8, 0.2, 0.4 } },
|
{ 1, "Geom cache operations:evict", { 0.8, 0.2, 0.4 } },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user