dump texture ram between frames, not during a frame

This commit is contained in:
David Rose 2009-02-04 16:30:28 +00:00
parent 86409f66e4
commit 1a4a978b3a
9 changed files with 59 additions and 15 deletions

View File

@ -696,6 +696,14 @@ render_frame() {
} }
_windows.swap(new_windows); _windows.swap(new_windows);
// Go ahead and release any textures' ram images for textures that
// were drawn in the previous frame.
LoadedTextures::iterator lti;
for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
(*lti)->texture_uploaded();
}
_loaded_textures.clear();
// Now it's time to do any drawing from the main frame--after all of // Now it's time to do any drawing from the main frame--after all of
// the App code has executed, but before we begin the next frame. // the App code has executed, but before we begin the next frame.
_app.do_frame(this, current_thread); _app.do_frame(this, current_thread);
@ -1054,6 +1062,29 @@ remove_callback(const string &thread_name,
return wr->remove_callback(callback_time, Callback(func, data)); return wr->remove_callback(callback_time, Callback(func, data));
} }
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::texture_uploaded
// Access: Public
// Description: This method is called by the GraphicsStateGuardian
// after a texture has been successfully uploaded to
// graphics memory. It is intended as a callback so the
// texture can release its RAM image, if _keep_ram_image
// is false.
//
// Normally, this is not called directly except by the
// GraphicsStateGuardian. It will be called in the draw
// thread.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
texture_uploaded(Texture *tex) {
LightReMutexHolder holder(_lock);
// We defer this until the end of the frame; multiple GSG's might be
// rendering the texture within the same frame, and we don't want to
// dump the texture image until they've all had a chance at it.
_loaded_textures.push_back(tex);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::scene_root_func // Function: GraphicsEngine::scene_root_func
// Access: Private, Static // Access: Private, Static

View File

@ -128,6 +128,8 @@ public:
bool remove_callback(const string &thread_name, CallbackTime callback_time, bool remove_callback(const string &thread_name, CallbackTime callback_time,
CallbackFunction *func, void *data); CallbackFunction *func, void *data);
void texture_uploaded(Texture *tex);
private: private:
class Callback { class Callback {
public: public:
@ -344,6 +346,9 @@ private:
bool _singular_warning_last_frame; bool _singular_warning_last_frame;
bool _singular_warning_this_frame; bool _singular_warning_this_frame;
typedef pvector< PT(Texture) > LoadedTextures;
LoadedTextures _loaded_textures;
LightReMutex _lock; LightReMutex _lock;
static PT(GraphicsEngine) _global_ptr; static PT(GraphicsEngine) _global_ptr;

View File

@ -386,6 +386,7 @@ restore_gamma() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PyObject *GraphicsStateGuardian:: PyObject *GraphicsStateGuardian::
get_prepared_textures() const { get_prepared_textures() const {
ReMutexHolder holder(_prepared_objects->_lock);
size_t num_textures = _prepared_objects->_prepared_textures.size(); size_t num_textures = _prepared_objects->_prepared_textures.size();
PyObject *list = PyList_New(num_textures); PyObject *list = PyList_New(num_textures);
@ -394,15 +395,18 @@ get_prepared_textures() const {
for (ti = _prepared_objects->_prepared_textures.begin(); for (ti = _prepared_objects->_prepared_textures.begin();
ti != _prepared_objects->_prepared_textures.end(); ti != _prepared_objects->_prepared_textures.end();
++ti) { ++ti) {
Texture *tex = (*ti)->get_texture(); PT(Texture) tex = (*ti)->get_texture();
PyObject *element = PyObject *element =
DTool_CreatePyInstanceTyped(tex, Dtool_Texture, DTool_CreatePyInstanceTyped(tex, Dtool_Texture,
true, false, tex->get_type_index()); true, false, tex->get_type_index());
tex->ref();
nassertr(i < num_textures, NULL);
PyList_SetItem(list, i, element); PyList_SetItem(list, i, element);
++i; ++i;
} }
nassertr(i == num_textures, NULL);
return list; return list;
} }
@ -418,6 +422,7 @@ get_prepared_textures() const {
void GraphicsStateGuardian:: void GraphicsStateGuardian::
traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
void *callback_arg) { void *callback_arg) {
ReMutexHolder holder(_prepared_objects->_lock);
PreparedGraphicsObjects::Textures::const_iterator ti; PreparedGraphicsObjects::Textures::const_iterator ti;
for (ti = _prepared_objects->_prepared_textures.begin(); for (ti = _prepared_objects->_prepared_textures.begin();
ti != _prepared_objects->_prepared_textures.end(); ti != _prepared_objects->_prepared_textures.end();

View File

@ -18,6 +18,7 @@
#include "pStatTimer.h" #include "pStatTimer.h"
#include "dxgsg8base.h" #include "dxgsg8base.h"
#include "bamCache.h" #include "bamCache.h"
#include "graphicsEngine.h"
#include <assert.h> #include <assert.h>
#include <time.h> #include <time.h>
@ -794,7 +795,7 @@ create_texture(DXScreenData &scrn) {
} }
} }
tex->texture_uploaded(scrn._dxgsg8); scrn._dxgsg8->get_engine()->texture_uploaded(tex);
mark_loaded(); mark_loaded();
return true; return true;

View File

@ -17,6 +17,7 @@
#include "pStatTimer.h" #include "pStatTimer.h"
#include "dxTextureContext9.h" #include "dxTextureContext9.h"
#include "bamCache.h" #include "bamCache.h"
#include "graphicsEngine.h"
#include <d3dx9tex.h> #include <d3dx9tex.h>
#include <assert.h> #include <assert.h>
#include <time.h> #include <time.h>
@ -946,7 +947,7 @@ create_texture(DXScreenData &scrn) {
// must not put render to texture into LRU // must not put render to texture into LRU
if (!_managed && !tex->get_render_to_texture()) { if (!_managed && !tex->get_render_to_texture()) {
tex->texture_uploaded(scrn._dxgsg9); scrn._dxgsg9->get_engine()->texture_uploaded(tex);
} }
mark_loaded(); mark_loaded();

View File

@ -59,6 +59,7 @@
#include "stencilAttrib.h" #include "stencilAttrib.h"
#include "lightAttrib.h" #include "lightAttrib.h"
#include "scissorAttrib.h" #include "scissorAttrib.h"
#include "graphicsEngine.h"
#ifdef HAVE_CG #ifdef HAVE_CG
#include "Cg/cgGL.h" #include "Cg/cgGL.h"
@ -7462,7 +7463,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) {
} }
} }
tex->texture_uploaded(this); get_engine()->texture_uploaded(tex);
gtc->mark_loaded(); gtc->mark_loaded();
report_my_gl_errors(); report_my_gl_errors();

View File

@ -1564,18 +1564,17 @@ down_to_power_2(int value) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Texture::texture_uploaded // Function: Texture::texture_uploaded
// Access: Public // Access: Public
// Description: This method is called by the GraphicsStateGuardian // Description: This method is called by the GraphicsEngine at the
// after a texture has been successfully uploaded to // beginning of the frame *after* a texture has been
// graphics memory. It is intended as a callback so the // successfully uploaded to graphics memory. It is
// texture can release its RAM image, if _keep_ram_image // intended as a callback so the texture can release its
// is false. // RAM image, if _keep_ram_image is false.
// //
// Normally, this is not called directly except by the // This is called indirectly when the GSG calls
// GraphicsStateGuardian. It will be called in the draw // GraphicsEngine::texture_uploaded().
// thread.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void Texture:: void Texture::
texture_uploaded(GraphicsStateGuardianBase *gsg) { texture_uploaded() {
MutexHolder holder(_lock); MutexHolder holder(_lock);
if (!keep_texture_ram && !_keep_ram_image) { if (!keep_texture_ram && !_keep_ram_image) {

View File

@ -428,7 +428,7 @@ PUBLISHED:
static int down_to_power_2(int value); static int down_to_power_2(int value);
public: public:
void texture_uploaded(GraphicsStateGuardianBase *gsg); void texture_uploaded();
virtual bool has_cull_callback() const; virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;

View File

@ -38,6 +38,7 @@
#include "zmath.h" #include "zmath.h"
#include "ztriangle_table.h" #include "ztriangle_table.h"
#include "store_pixel_table.h" #include "store_pixel_table.h"
#include "graphicsEngine.h"
TypeHandle TinyGraphicsStateGuardian::_type_handle; TypeHandle TinyGraphicsStateGuardian::_type_handle;
@ -2536,7 +2537,7 @@ upload_texture(TinyTextureContext *gtc, bool force) {
gtc->update_data_size_bytes(bytecount); gtc->update_data_size_bytes(bytecount);
tex->texture_uploaded(this); get_engine()->texture_uploaded(tex);
gtc->mark_loaded(); gtc->mark_loaded();
return true; return true;