Fix: USD import: lazily create cache file

This fixes an issue where a CacheFile was always created for the USD
file, causing USD_create_handle() to be called unnecessarily even if the
USD does not have animating meshes or transforms.

This bug would sometimes result in the stage remaining open in a
CacheArchiveHandle after import (because the CacheFile is never
freed), preventing the USD from being reloaded from disk.

The cache file is now accessible to readers through an
ImportSettings::get_cache_file function wrapper which creates a
CacheFile as needed, the first time the function is called.

The allocated CacheFile pointer is now stored in a new
ImportJobData::cache_file member.

Pull Request: https://projects.blender.org/blender/blender/pulls/116242
This commit is contained in:
Michael Kowalski
2024-01-11 20:54:03 +01:00
committed by Michael Kowalski
parent 935ed0791f
commit 3fc97a3ed4
4 changed files with 29 additions and 15 deletions

View File

@@ -183,6 +183,8 @@ struct ImportJobData {
bool was_canceled;
bool import_ok;
timeit::TimePoint start_time;
CacheFile *cache_file;
};
static void report_job_duration(const ImportJobData *data)
@@ -203,6 +205,7 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
data->was_canceled = false;
data->archive = nullptr;
data->start_time = timeit::Clock::now();
data->cache_file = nullptr;
data->params.worker_status = worker_status;
@@ -227,19 +230,26 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
BLI_path_abs(data->filepath, BKE_main_blendfile_path_from_global());
CacheFile *cache_file = static_cast<CacheFile *>(
BKE_cachefile_add(data->bmain, BLI_path_basename(data->filepath)));
/* Callback function to lazily create a cache file when converting
* time varying data. */
auto get_cache_file = [data]() {
if (!data->cache_file) {
data->cache_file = static_cast<CacheFile *>(
BKE_cachefile_add(data->bmain, BLI_path_basename(data->filepath)));
/* Decrement the ID ref-count because it is going to be incremented for each
* modifier and constraint that it will be attached to, so since currently
* it is not used by anyone, its use count will off by one. */
id_us_min(&cache_file->id);
/* Decrement the ID ref-count because it is going to be incremented for each
* modifier and constraint that it will be attached to, so since currently
* it is not used by anyone, its use count will off by one. */
id_us_min(&data->cache_file->id);
cache_file->is_sequence = data->params.is_sequence;
cache_file->scale = data->params.scale;
STRNCPY(cache_file->filepath, data->filepath);
data->cache_file->is_sequence = data->params.is_sequence;
data->cache_file->scale = data->params.scale;
STRNCPY(data->cache_file->filepath, data->filepath);
}
return data->cache_file;
};
data->settings.cache_file = cache_file;
data->settings.get_cache_file = get_cache_file;
*data->do_update = true;
*data->progress = 0.05f;

View File

@@ -22,12 +22,16 @@ namespace blender::io::usd {
void USDGeomReader::add_cache_modifier()
{
if (!settings_->get_cache_file) {
return;
}
ModifierData *md = BKE_modifier_new(eModifierType_MeshSequenceCache);
BLI_addtail(&object_->modifiers, md);
MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
mcmd->cache_file = settings_->cache_file;
mcmd->cache_file = settings_->get_cache_file();
id_us_plus(&mcmd->cache_file->id);
mcmd->read_flag = import_params_.mesh_read_flag;

View File

@@ -44,7 +44,7 @@ struct ImportSettings {
bool validate_meshes;
CacheFile *cache_file;
std::function<CacheFile *()> get_cache_file;
/* Map a USD material prim path to a Blender material name.
* This map is updated by readers during stage traversal.
@@ -74,7 +74,7 @@ struct ImportSettings {
sequence_offset(0),
read_flag(0),
validate_meshes(false),
cache_file(NULL),
get_cache_file(nullptr),
stage_meters_per_unit(1.0),
skip_prefix(pxr::SdfPath{})
{

View File

@@ -45,7 +45,7 @@ void USDXformReader::read_object_data(Main * /*bmain*/, const double motionSampl
read_matrix(transform_from_usd, motionSampleTime, import_params_.scale, &is_constant);
if (!is_constant) {
if (!is_constant && settings_->get_cache_file) {
bConstraint *con = BKE_constraint_add_for_object(
object_, nullptr, CONSTRAINT_TYPE_TRANSFORM_CACHE);
bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
@@ -55,7 +55,7 @@ void USDXformReader::read_object_data(Main * /*bmain*/, const double motionSampl
STRNCPY(data->object_path, prim_path.c_str());
data->cache_file = settings_->cache_file;
data->cache_file = settings_->get_cache_file();
id_us_plus(&data->cache_file->id);
}