mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 07:48:37 -04:00
gobj: Move TextureReloadRequest to new Texture::async_ensure_ram_image()
The task is implemented with just a simple lambda, much more compact than a whole TextureReloadRequest task. The latter is now deprecated. Since Loader can't be used within Texture, there's now a new task chain, configurable with texture-reload-num-threads and texture-reload-thread-priority. This does mean that it no longer happens on the same thread as model loads, but I think that's fine, and perhaps texture reloads should be higher priority than model loads anyway since a long texture reload delay with allow-incomplete-render directly and negatively affects user experience during gameplay. The new name also better communicates that it just calls get_ram_image(), it doesn't force a reload, but we could add an async_reload() for that if we want.
This commit is contained in:
parent
9e7ca63662
commit
fa0ea312ea
@ -3581,31 +3581,8 @@ async_reload_texture(TextureContext *tc) {
|
||||
priority = _current_display_region->get_texture_reload_priority();
|
||||
}
|
||||
|
||||
string task_name = string("reload:") + tc->get_texture()->get_name();
|
||||
PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
|
||||
|
||||
// See if we are already loading this task.
|
||||
AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
|
||||
size_t num_tasks = orig_tasks.get_num_tasks();
|
||||
for (size_t ti = 0; ti < num_tasks; ++ti) {
|
||||
AsyncTask *task = orig_tasks.get_task(ti);
|
||||
if (task->is_exact_type(TextureReloadRequest::get_class_type()) &&
|
||||
((TextureReloadRequest *)task)->get_texture() == tc->get_texture()) {
|
||||
// This texture is already queued to be reloaded. Don't queue it again,
|
||||
// just make sure the priority is updated, and return.
|
||||
task->set_priority(std::max(task->get_priority(), priority));
|
||||
return (AsyncFuture *)task;
|
||||
}
|
||||
}
|
||||
|
||||
// This texture has not yet been queued to be reloaded. Queue it up now.
|
||||
PT(AsyncTask) request =
|
||||
new TextureReloadRequest(task_name,
|
||||
_prepared_objects, tc->get_texture(),
|
||||
_supports_compressed_texture);
|
||||
request->set_priority(priority);
|
||||
_loader->load_async(request);
|
||||
return (AsyncFuture *)request.p();
|
||||
Texture *tex = tc->get_texture();
|
||||
return tex->async_ensure_ram_image(_supports_compressed_texture, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -366,6 +366,23 @@ ConfigVariableDouble simple_image_threshold
|
||||
"simple images. Generally the value should be considerably "
|
||||
"less than 1."));
|
||||
|
||||
ConfigVariableInt texture_reload_num_threads
|
||||
("texture-reload-num-threads", 1,
|
||||
PRC_DESC("The number of threads that will be started by the Texture class "
|
||||
"to reload textures asynchronously. These threads will only be "
|
||||
"started if the asynchronous interface is used, and if threading "
|
||||
"support is compiled into Panda. The default is one thread, "
|
||||
"which allows textures to be loaded one at a time in a single "
|
||||
"asychronous thread. You can set this higher, particularly if "
|
||||
"you have many CPU's available, to allow loading multiple models "
|
||||
"simultaneously."));
|
||||
|
||||
ConfigVariableEnum<ThreadPriority> texture_reload_thread_priority
|
||||
("texture-reload-thread-priority", TP_normal,
|
||||
PRC_DESC("The default thread priority to assign to the threads created for "
|
||||
"asynchronous texture loading. The default is 'normal'; you may "
|
||||
"also specify 'low', 'high', or 'urgent'."));
|
||||
|
||||
ConfigVariableInt geom_cache_size
|
||||
("geom-cache-size", 5000,
|
||||
PRC_DESC("Specifies the maximum number of entries in the cache "
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "configVariableString.h"
|
||||
#include "configVariableList.h"
|
||||
#include "autoTextureScale.h"
|
||||
#include "threadPriority.h"
|
||||
|
||||
NotifyCategoryDecl(gobj, EXPCL_PANDA_GOBJ, EXPTP_PANDA_GOBJ);
|
||||
NotifyCategoryDecl(shader, EXPCL_PANDA_GOBJ, EXPTP_PANDA_GOBJ);
|
||||
@ -62,6 +63,8 @@ extern EXPCL_PANDA_GOBJ ConfigVariableBool textures_auto_power_2;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool textures_header_only;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt simple_image_size;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableDouble simple_image_threshold;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt texture_reload_num_threads;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableEnum<ThreadPriority> texture_reload_thread_priority;
|
||||
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt geom_cache_size;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt geom_cache_min_frames;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "streamReader.h"
|
||||
#include "texturePeeker.h"
|
||||
#include "convert_srgb.h"
|
||||
#include "asyncTaskManager.h"
|
||||
|
||||
#ifdef HAVE_SQUISH
|
||||
#include <squish.h>
|
||||
@ -1019,6 +1020,69 @@ load_related(const InternalName *suffix) const {
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a background task that reloads the the Texture from its disk file
|
||||
* if there is not currently a RAM image (or uncompressed RAM image, if
|
||||
* allow_compression is false).
|
||||
*
|
||||
* A higher priority value indicates that this texture should be reloaded sooner
|
||||
* than textures with a lower priority value. If the reload hasn't taken place
|
||||
* yet, you can call this again to update the priority value.
|
||||
*
|
||||
* If someone else reloads the texture using an explicit call to reload() while
|
||||
* an async reload request is pending, the async reload request is cancelled.
|
||||
*/
|
||||
PT(AsyncFuture) Texture::
|
||||
async_ensure_ram_image(bool allow_compression, int priority) {
|
||||
CDLockedReader cdata(_cycler);
|
||||
if (allow_compression ? do_has_ram_image(cdata) : do_has_uncompressed_ram_image(cdata)) {
|
||||
// We already have a RAM image.
|
||||
PT(AsyncFuture) fut = new AsyncFuture;
|
||||
fut->set_result(nullptr);
|
||||
return fut;
|
||||
}
|
||||
if (!do_can_reload(cdata)) {
|
||||
// We don't have a filename to load from. This is an error.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AsyncTask *task = cdata->_reload_task;
|
||||
if (task != nullptr) {
|
||||
// This texture is already queued to be reloaded. Don't queue it again,
|
||||
// just make sure the priority is updated, and return.
|
||||
task->set_priority(std::max(task->get_priority(), priority));
|
||||
return (AsyncFuture *)task;
|
||||
}
|
||||
|
||||
CDWriter cdataw(_cycler, cdata, true);
|
||||
|
||||
string task_name = string("reload:") + get_name();
|
||||
AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
|
||||
static PT(AsyncTaskChain) chain = task_mgr->make_task_chain("texture_reload");
|
||||
chain->set_num_threads(texture_reload_num_threads);
|
||||
chain->set_thread_priority(texture_reload_thread_priority);
|
||||
|
||||
double delay = async_load_delay;
|
||||
|
||||
// This texture has not yet been queued to be reloaded. Queue it up now.
|
||||
task = new FunctionAsyncTask(task_name, [=](AsyncTask *task) {
|
||||
if (delay != 0.0) {
|
||||
Thread::sleep(delay);
|
||||
}
|
||||
if (allow_compression) {
|
||||
get_ram_image();
|
||||
} else {
|
||||
get_uncompressed_ram_image();
|
||||
}
|
||||
return AsyncTask::DS_done;
|
||||
});
|
||||
task->set_task_chain("texture_reload");
|
||||
task->set_priority(priority);
|
||||
task_mgr->add(task);
|
||||
cdataw->_reload_task = task;
|
||||
return (AsyncFuture *)task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current system-RAM image with the new data, converting it
|
||||
* first if necessary from the indicated component-order format. See
|
||||
@ -5611,6 +5675,12 @@ do_reload_ram_image(CData *cdata, bool allow_compression) {
|
||||
cache->store(record);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any pending asynchronous reload operation.
|
||||
if (cdata->_reload_task != nullptr) {
|
||||
cdata->_reload_task->remove();
|
||||
cdata->_reload_task = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "bamCacheRecord.h"
|
||||
#include "pnmImage.h"
|
||||
#include "pfmFile.h"
|
||||
#include "asyncFuture.h"
|
||||
#include "asyncTask.h"
|
||||
|
||||
class TextureContext;
|
||||
class FactoryParams;
|
||||
@ -448,6 +448,7 @@ PUBLISHED:
|
||||
MAKE_PROPERTY(expected_ram_image_size, get_expected_ram_image_size);
|
||||
MAKE_PROPERTY(expected_ram_page_size, get_expected_ram_page_size);
|
||||
|
||||
PT(AsyncFuture) async_ensure_ram_image(bool allow_compression = true, int priority = 0);
|
||||
INLINE CPTA_uchar get_ram_image();
|
||||
INLINE CompressionMode get_ram_image_compression() const;
|
||||
INLINE CPTA_uchar get_uncompressed_ram_image();
|
||||
@ -784,6 +785,7 @@ protected:
|
||||
void do_set_pad_size(CData *cdata, int x, int y, int z);
|
||||
virtual bool do_can_reload(const CData *cdata) const;
|
||||
bool do_reload(CData *cdata);
|
||||
AsyncFuture *do_async_ensure_ram_image(const CData *cdata, bool allow_compression, int priority);
|
||||
|
||||
INLINE AutoTextureScale do_get_auto_texture_scale(const CData *cdata) const;
|
||||
|
||||
@ -1032,6 +1034,8 @@ protected:
|
||||
|
||||
ModifiedPageRanges _modified_pages;
|
||||
|
||||
PT(AsyncTask) _reload_task;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -27,6 +27,8 @@
|
||||
* force the texture's image to be re-read from disk. It is used by
|
||||
* GraphicsStateGuardian::async_reload_texture(), when get_incomplete_render()
|
||||
* is true.
|
||||
*
|
||||
* @deprecated Use Texture::async_ensure_ram_image() instead.
|
||||
*/
|
||||
class EXPCL_PANDA_GOBJ TextureReloadRequest : public AsyncTask {
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user