manage texture memory for tinydisplay

This commit is contained in:
David Rose 2008-05-06 03:17:29 +00:00
parent acedeeceff
commit 07ee48ae07
9 changed files with 92 additions and 17 deletions

View File

@ -17,6 +17,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "simpleLru.h" #include "simpleLru.h"
#include "clockObject.h"
// We define this as a reference to an allocated object, instead of as // 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 // 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); MutexHolder holder(SimpleLru::_global_lock);
if (_lru == lru) { if (_lru == lru) {
if (_lru != (SimpleLru *)NULL) {
remove_from_list();
insert_before(_lru);
}
return; return;
} }
@ -116,7 +121,8 @@ count_active_size() const {
// Function: SimpleLru::do_evict // Function: SimpleLru::do_evict
// Access: Private // Access: Private
// Description: Evicts pages until the LRU is within tolerance. // 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:: void SimpleLru::
do_evict() { do_evict() {
@ -144,6 +150,11 @@ do_evict() {
// If we reach the original tail of the list, stop. // If we reach the original tail of the list, stop.
return; return;
} }
if (node == _active_marker) {
// Also stop if we reach the active marker. Nodes beyond this
// were added within this epoch.
return;
}
node = next; node = next;
} }
} }

View File

@ -155,6 +155,7 @@ static TimeCollectorProperties time_properties[] = {
{ 1, "Draw:Clear", { 0.0, 0.8, 0.6 } }, { 1, "Draw:Clear", { 0.0, 0.8, 0.6 } },
{ 1, "Draw:Flush", { 0.9, 0.2, 0.7 } }, { 1, "Draw:Flush", { 0.9, 0.2, 0.7 } },
{ 1, "Draw:Sync", { 0.5, 0.7, 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:Primitive", { 0.0, 0.0, 0.5 } },
{ 0, "Draw:Set State", { 0.2, 0.6, 0.8 } }, { 0, "Draw:Set State", { 0.2, 0.6, 0.8 } },
{ 1, "Draw:Wait occlusion", { 1.0, 0.5, 0.0 } }, { 1, "Draw:Wait occlusion", { 1.0, 0.5, 0.0 } },

View File

@ -58,6 +58,16 @@ ConfigVariableInt x_wheel_down_button
"mouse button number does the system report when the mouse wheel " "mouse button number does the system report when the mouse wheel "
"is rolled one notch down?")); "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 // Function: init_libtinydisplay
// Description: Initializes the library. This must be called at // Description: Initializes the library. This must be called at

View File

@ -34,4 +34,6 @@ extern ConfigVariableBool x_error_abort;
extern ConfigVariableInt x_wheel_up_button; extern ConfigVariableInt x_wheel_up_button;
extern ConfigVariableInt x_wheel_down_button; extern ConfigVariableInt x_wheel_down_button;
extern ConfigVariableInt td_texture_ram;
#endif #endif

View File

@ -504,7 +504,8 @@ static const ZB_fillTriangleFunc fill_tri_funcs
TinyGraphicsStateGuardian:: TinyGraphicsStateGuardian::
TinyGraphicsStateGuardian(GraphicsPipe *pipe, TinyGraphicsStateGuardian(GraphicsPipe *pipe,
TinyGraphicsStateGuardian *share_with) : TinyGraphicsStateGuardian *share_with) :
GraphicsStateGuardian(CS_yup_right, pipe) GraphicsStateGuardian(CS_yup_right, pipe),
_textures_lru("textures_lru", td_texture_ram)
{ {
_c = NULL; _c = NULL;
_vertices = NULL; _vertices = NULL;
@ -825,6 +826,9 @@ end_frame(Thread *current_thread) {
// Flush any PCollectors specific to this kind of GSG. // Flush any PCollectors specific to this kind of GSG.
_vertices_immediate_pcollector.flush_level(); _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; fo += _c->zb->linesize / PSZB;
} }
#ifdef DO_PSTATS
gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4); gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
#endif
gtc->mark_loaded(); gtc->mark_loaded();
gtc->enqueue_lru(&_textures_lru);
} }
@ -1614,6 +1617,7 @@ release_texture(TextureContext *tc) {
} }
gl_free(gltex); gl_free(gltex);
gtc->dequeue_lru();
delete gtc; delete gtc;
} }
@ -1998,20 +2002,17 @@ apply_texture(TextureContext *tc) {
_c->current_texture = gtc->_gltex; _c->current_texture = gtc->_gltex;
_c->texture_2d_enabled = true; _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 the texture image was modified, reload the texture.
if (!upload_texture(gtc)) { if (!upload_texture(gtc)) {
_c->texture_2d_enabled = false; _c->texture_2d_enabled = false;
} }
gtc->mark_loaded(); 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.pixmap = gltex->pixmap;
_c->zb->current_texture.s_mask = gltex->s_mask; _c->zb->current_texture.s_mask = gltex->s_mask;
_c->zb->current_texture.t_mask = gltex->t_mask; _c->zb->current_texture.t_mask = gltex->t_mask;
@ -2092,9 +2093,8 @@ upload_texture(TinyTextureContext *gtc) {
break; break;
} }
#ifdef DO_PSTATS int bytecount = gltex->xsize * gltex->ysize * 4;
gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4); gtc->update_data_size_bytes(bytecount);
#endif
tex->texture_uploaded(); tex->texture_uploaded();

View File

@ -23,6 +23,7 @@
#include "graphicsStateGuardian.h" #include "graphicsStateGuardian.h"
#include "tinySDLGraphicsPipe.h" #include "tinySDLGraphicsPipe.h"
#include "simpleLru.h"
extern "C" { extern "C" {
#include "zmath.h" #include "zmath.h"
@ -134,6 +135,8 @@ private:
}; };
int _color_material_flags; int _color_material_flags;
SimpleLru _textures_lru;
// Used during being_draw_primitives() .. end_draw_primitives(). // Used during being_draw_primitives() .. end_draw_primitives().
int _min_vertex; int _min_vertex;
int _max_vertex; int _max_vertex;

View File

@ -24,7 +24,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE TinyTextureContext:: INLINE TinyTextureContext::
TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) :
TextureContext(pgo, tex) TextureContext(pgo, tex), SimpleLruPage(0)
{ {
_gltex = NULL; _gltex = NULL;
} }
@ -38,3 +38,16 @@ INLINE TinyTextureContext::
~TinyTextureContext() { ~TinyTextureContext() {
nassertv(_gltex == NULL); 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);
}

View File

@ -18,4 +18,35 @@
#include "tinyTextureContext.h" #include "tinyTextureContext.h"
extern "C" {
#include "zgl.h"
}
TypeHandle TinyTextureContext::_type_handle; 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);
}

View File

@ -22,6 +22,7 @@
#include "pandabase.h" #include "pandabase.h"
#include "textureContext.h" #include "textureContext.h"
#include "deletedChain.h" #include "deletedChain.h"
#include "simpleLru.h"
struct GLTexture; struct GLTexture;
@ -29,13 +30,16 @@ struct GLTexture;
// Class : TinyTextureContext // Class : TinyTextureContext
// Description : // Description :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
class TinyTextureContext : public TextureContext { class TinyTextureContext : public TextureContext, public SimpleLruPage {
public: public:
INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex); INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex);
ALLOC_DELETED_CHAIN(TinyTextureContext); ALLOC_DELETED_CHAIN(TinyTextureContext);
INLINE ~TinyTextureContext(); INLINE ~TinyTextureContext();
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
virtual void evict_lru();
GLTexture *_gltex; GLTexture *_gltex;
public: public: