From 07ee48ae07c1a4b8a8358b1692c39704fb55c96a Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 6 May 2008 03:17:29 +0000 Subject: [PATCH] manage texture memory for tinydisplay --- panda/src/gobj/simpleLru.cxx | 13 +++++++- panda/src/pstatclient/pStatProperties.cxx | 1 + panda/src/tinydisplay/config_tinydisplay.cxx | 10 ++++++ panda/src/tinydisplay/config_tinydisplay.h | 2 ++ .../tinydisplay/tinyGraphicsStateGuardian.cxx | 28 ++++++++--------- .../tinydisplay/tinyGraphicsStateGuardian.h | 3 ++ panda/src/tinydisplay/tinyTextureContext.I | 15 ++++++++- panda/src/tinydisplay/tinyTextureContext.cxx | 31 +++++++++++++++++++ panda/src/tinydisplay/tinyTextureContext.h | 6 +++- 9 files changed, 92 insertions(+), 17 deletions(-) diff --git a/panda/src/gobj/simpleLru.cxx b/panda/src/gobj/simpleLru.cxx index 4a201673bd..539fa85c72 100644 --- a/panda/src/gobj/simpleLru.cxx +++ b/panda/src/gobj/simpleLru.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "simpleLru.h" +#include "clockObject.h" // We define this as a reference to an allocated object, instead of as // a concrete object, so that it won't get destructed when the program @@ -71,6 +72,10 @@ enqueue_lru(SimpleLru *lru) { MutexHolder holder(SimpleLru::_global_lock); if (_lru == lru) { + if (_lru != (SimpleLru *)NULL) { + remove_from_list(); + insert_before(_lru); + } return; } @@ -116,7 +121,8 @@ count_active_size() const { // Function: SimpleLru::do_evict // Access: Private // Description: Evicts pages until the LRU is within tolerance. -// Assumes the lock is already held. +// Assumes the lock is already held. Does not evict +// "active" pages that were added within this epoch. //////////////////////////////////////////////////////////////////// void SimpleLru:: do_evict() { @@ -144,6 +150,11 @@ do_evict() { // If we reach the original tail of the list, stop. return; } + if (node == _active_marker) { + // Also stop if we reach the active marker. Nodes beyond this + // were added within this epoch. + return; + } node = next; } } diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index d44390d649..6b283f52d6 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -155,6 +155,7 @@ static TimeCollectorProperties time_properties[] = { { 1, "Draw:Clear", { 0.0, 0.8, 0.6 } }, { 1, "Draw:Flush", { 0.9, 0.2, 0.7 } }, { 1, "Draw:Sync", { 0.5, 0.7, 0.7 } }, + { 0, "Draw:Transform", { 0.0, 0.5, 0.0 } }, { 0, "Draw:Primitive", { 0.0, 0.0, 0.5 } }, { 0, "Draw:Set State", { 0.2, 0.6, 0.8 } }, { 1, "Draw:Wait occlusion", { 1.0, 0.5, 0.0 } }, diff --git a/panda/src/tinydisplay/config_tinydisplay.cxx b/panda/src/tinydisplay/config_tinydisplay.cxx index 103fd50fbe..7e3fae5d1d 100644 --- a/panda/src/tinydisplay/config_tinydisplay.cxx +++ b/panda/src/tinydisplay/config_tinydisplay.cxx @@ -58,6 +58,16 @@ ConfigVariableInt x_wheel_down_button "mouse button number does the system report when the mouse wheel " "is rolled one notch down?")); +ConfigVariableInt td_texture_ram +("td-texture-ram", -1, + PRC_DESC("This specifies the maximum amount of RAM to devote to keeping " + "textures resident with the tinydisplay software renderer. When " + "this limit is exceeded, textures over the limit that have not " + "been rendered within the current frame will be evicted. " + "(Textures will not be evicted while they are still in the " + "frame, even if this means this limit remains exceeded.) " + "Set it to -1 for no limit.")); + //////////////////////////////////////////////////////////////////// // Function: init_libtinydisplay // Description: Initializes the library. This must be called at diff --git a/panda/src/tinydisplay/config_tinydisplay.h b/panda/src/tinydisplay/config_tinydisplay.h index f32800bb8c..1cc39ce0d1 100644 --- a/panda/src/tinydisplay/config_tinydisplay.h +++ b/panda/src/tinydisplay/config_tinydisplay.h @@ -34,4 +34,6 @@ extern ConfigVariableBool x_error_abort; extern ConfigVariableInt x_wheel_up_button; extern ConfigVariableInt x_wheel_down_button; +extern ConfigVariableInt td_texture_ram; + #endif diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index af87d87959..b23fd71982 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -504,7 +504,8 @@ static const ZB_fillTriangleFunc fill_tri_funcs TinyGraphicsStateGuardian:: TinyGraphicsStateGuardian(GraphicsPipe *pipe, TinyGraphicsStateGuardian *share_with) : - GraphicsStateGuardian(CS_yup_right, pipe) + GraphicsStateGuardian(CS_yup_right, pipe), + _textures_lru("textures_lru", td_texture_ram) { _c = NULL; _vertices = NULL; @@ -825,6 +826,9 @@ end_frame(Thread *current_thread) { // Flush any PCollectors specific to this kind of GSG. _vertices_immediate_pcollector.flush_level(); + + // Evict any textures that exceed our texture memory. + _textures_lru.begin_epoch(); } @@ -1399,10 +1403,9 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, fo += _c->zb->linesize / PSZB; } -#ifdef DO_PSTATS gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4); -#endif gtc->mark_loaded(); + gtc->enqueue_lru(&_textures_lru); } @@ -1614,6 +1617,7 @@ release_texture(TextureContext *tc) { } gl_free(gltex); + gtc->dequeue_lru(); delete gtc; } @@ -1998,20 +2002,17 @@ apply_texture(TextureContext *tc) { _c->current_texture = gtc->_gltex; _c->texture_2d_enabled = true; - if (gtc->was_image_modified()) { + GLTexture *gltex = gtc->_gltex; + + if (gtc->was_image_modified() || gltex->pixmap == NULL) { // If the texture image was modified, reload the texture. if (!upload_texture(gtc)) { _c->texture_2d_enabled = false; } gtc->mark_loaded(); - - } else if (gtc->was_properties_modified()) { - // If only the properties have been modified, we don't need to - // reload the texture. - gtc->mark_loaded(); } + gtc->enqueue_lru(&_textures_lru); - GLTexture *gltex = gtc->_gltex; _c->zb->current_texture.pixmap = gltex->pixmap; _c->zb->current_texture.s_mask = gltex->s_mask; _c->zb->current_texture.t_mask = gltex->t_mask; @@ -2091,10 +2092,9 @@ upload_texture(TinyTextureContext *gtc) { copy_la_image(gltex, tex); break; } - -#ifdef DO_PSTATS - gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4); -#endif + + int bytecount = gltex->xsize * gltex->ysize * 4; + gtc->update_data_size_bytes(bytecount); tex->texture_uploaded(); diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h index 460990e097..07827d97b7 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h @@ -23,6 +23,7 @@ #include "graphicsStateGuardian.h" #include "tinySDLGraphicsPipe.h" +#include "simpleLru.h" extern "C" { #include "zmath.h" @@ -134,6 +135,8 @@ private: }; int _color_material_flags; + SimpleLru _textures_lru; + // Used during being_draw_primitives() .. end_draw_primitives(). int _min_vertex; int _max_vertex; diff --git a/panda/src/tinydisplay/tinyTextureContext.I b/panda/src/tinydisplay/tinyTextureContext.I index d8b05d1560..3844bf014b 100644 --- a/panda/src/tinydisplay/tinyTextureContext.I +++ b/panda/src/tinydisplay/tinyTextureContext.I @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////// INLINE TinyTextureContext:: TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : - TextureContext(pgo, tex) + TextureContext(pgo, tex), SimpleLruPage(0) { _gltex = NULL; } @@ -38,3 +38,16 @@ INLINE TinyTextureContext:: ~TinyTextureContext() { nassertv(_gltex == NULL); } + +//////////////////////////////////////////////////////////////////// +// Function: TinyTextureContext::update_data_size_bytes +// Access: Public +// Description: This is overloaded (non-virtually) to update both the +// BufferContext and the LRU page with the same +// information. +//////////////////////////////////////////////////////////////////// +INLINE void TinyTextureContext:: +update_data_size_bytes(size_t new_data_size_bytes) { + TextureContext::update_data_size_bytes(new_data_size_bytes); + SimpleLruPage::set_lru_size(new_data_size_bytes); +} diff --git a/panda/src/tinydisplay/tinyTextureContext.cxx b/panda/src/tinydisplay/tinyTextureContext.cxx index 44d0b1a2da..0598d1e81e 100644 --- a/panda/src/tinydisplay/tinyTextureContext.cxx +++ b/panda/src/tinydisplay/tinyTextureContext.cxx @@ -18,4 +18,35 @@ #include "tinyTextureContext.h" +extern "C" { +#include "zgl.h" +} + TypeHandle TinyTextureContext::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: TinyTextureContext::evict_lru +// Access: Public, Virtual +// Description: Evicts the page from the LRU. Called internally when +// the LRU determines that it is full. May also be +// called externally when necessary to explicitly evict +// the page. +// +// It is legal for this method to either evict the page +// as requested, do nothing (in which case the eviction +// will be requested again at the next epoch), or +// requeue itself on the tail of the queue (in which +// case the eviction will be requested again much +// later). +//////////////////////////////////////////////////////////////////// +void TinyTextureContext:: +evict_lru() { + dequeue_lru(); + + if (_gltex->pixmap != NULL) { + gl_free(_gltex->pixmap); + _gltex->pixmap = NULL; + } + + set_resident(false); +} diff --git a/panda/src/tinydisplay/tinyTextureContext.h b/panda/src/tinydisplay/tinyTextureContext.h index 37bb48a2f7..cfd1bce6e6 100644 --- a/panda/src/tinydisplay/tinyTextureContext.h +++ b/panda/src/tinydisplay/tinyTextureContext.h @@ -22,6 +22,7 @@ #include "pandabase.h" #include "textureContext.h" #include "deletedChain.h" +#include "simpleLru.h" struct GLTexture; @@ -29,13 +30,16 @@ struct GLTexture; // Class : TinyTextureContext // Description : //////////////////////////////////////////////////////////////////// -class TinyTextureContext : public TextureContext { +class TinyTextureContext : public TextureContext, public SimpleLruPage { public: INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex); ALLOC_DELETED_CHAIN(TinyTextureContext); INLINE ~TinyTextureContext(); + INLINE void update_data_size_bytes(size_t new_data_size_bytes); + virtual void evict_lru(); + GLTexture *_gltex; public: