Cleanup: USD: Delay creation of the import hook prim_map

Delay the creation of the `prim_map` data structure until the last
possible moment. This is more efficient in the majority of cases where
no Import hooks have been defined. Additionally, it removes the need for
locking in the `read_object_data` code path once we implement concurrent
loading.

Pull Request: https://projects.blender.org/blender/blender/pulls/132360
This commit is contained in:
Jesse Yurkovich
2024-12-27 03:36:22 +01:00
committed by Jesse Yurkovich
parent becaeac6da
commit 953fa94fb3
3 changed files with 42 additions and 39 deletions

View File

@@ -35,7 +35,6 @@
#include "DNA_collection_types.h"
#include "DNA_layer_types.h"
#include "DNA_listBase.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
@@ -100,7 +99,6 @@ struct ImportJobData {
USDImportParams params;
USDStageReader *archive;
ImportedPrimMap prim_map;
bool *stop;
bool *do_update;
@@ -275,22 +273,9 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
}
Object *ob = reader->object();
if (!ob) {
continue;
}
reader->read_object_data(data->bmain, 0.0);
/* TODO: Move this outside the loop once when we support reading object data in parallel. */
data->prim_map.lookup_or_add_default(reader->object_prim_path())
.append(RNA_id_pointer_create(&ob->id));
if (ob->data) {
data->prim_map.lookup_or_add_default(reader->data_prim_path())
.append(RNA_id_pointer_create(static_cast<ID *>(ob->data)));
}
USDPrimReader *parent = reader->parent();
if (parent == nullptr) {
ob->parent = nullptr;
}
@@ -307,14 +292,6 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
}
}
archive->settings().usd_path_to_mat_name.foreach_item(
[&](const std::string &path, const std::string &name) {
Material *mat = archive->settings().mat_name_to_mat.lookup_default(name, nullptr);
if (mat) {
data->prim_map.lookup_or_add_default(path).append(RNA_id_pointer_create(&mat->id));
}
});
if (data->params.import_skeletons) {
archive->process_armature_modifiers();
}
@@ -405,7 +382,7 @@ static void import_endjob(void *customdata)
data->archive->call_material_import_hooks(data->bmain);
call_import_hooks(data->archive->stage(), data->prim_map, data->params.worker_status->reports);
call_import_hooks(data->archive, data->params.worker_status->reports);
if (data->is_background_job) {
/* Blender already returned from the import operator, so we need to store our own extra undo

View File

@@ -6,13 +6,17 @@
#include "usd.hh"
#include "usd_asset_utils.hh"
#include "usd_reader_prim.hh"
#include "usd_reader_stage.hh"
#include "usd_writer_material.hh"
#include "BLI_map.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BKE_idtype.hh"
#include "BKE_report.hh"
#include "DNA_material_types.h"
#include "DNA_windowmanager_types.h"
#include "RNA_access.hh"
@@ -53,6 +57,7 @@ using namespace boost;
namespace blender::io::usd {
using USDHookList = std::list<std::unique_ptr<USDHook>>;
using ImportedPrimMap = Map<std::string, Vector<PointerRNA>>;
/* USD hook type declarations */
static USDHookList &hook_list()
@@ -195,7 +200,7 @@ struct USDMaterialExportContext {
* to the export directory if exporting textures is enabled in the export options. The
* function may return an empty string in case of an error.
*/
std::string export_texture(PYTHON_NS::object obj)
std::string export_texture(PYTHON_NS::object obj) const
{
ID *id;
if (!pyrna_id_FromPyObject(obj.ptr(), &id)) {
@@ -602,15 +607,43 @@ void call_material_export_hooks(pxr::UsdStageRefPtr stage,
on_material_export.call();
}
void call_import_hooks(pxr::UsdStageRefPtr stage,
const ImportedPrimMap &prim_map,
ReportList *reports)
void call_import_hooks(USDStageReader *archive, ReportList *reports)
{
if (hook_list().empty()) {
return;
}
OnImportInvoker on_import(stage, prim_map, reports);
const Vector<USDPrimReader *> &readers = archive->readers();
const ImportSettings &settings = archive->settings();
ImportedPrimMap prim_map;
/* Resize based on the typical scenario where there will be both Object and Data entries
* in the map in addition to each material. */
prim_map.reserve((readers.size() * 2) + settings.usd_path_to_mat_name.size());
for (const USDPrimReader *reader : readers) {
if (!reader) {
continue;
}
Object *ob = reader->object();
prim_map.lookup_or_add_default(reader->object_prim_path())
.append(RNA_id_pointer_create(&ob->id));
if (ob->data) {
prim_map.lookup_or_add_default(reader->data_prim_path())
.append(RNA_id_pointer_create(static_cast<ID *>(ob->data)));
}
}
settings.usd_path_to_mat_name.foreach_item(
[&](const std::string &path, const std::string &name) {
if (Material *mat = settings.mat_name_to_mat.lookup_default(name, nullptr)) {
prim_map.lookup_or_add_default(path).append(RNA_id_pointer_create(&mat->id));
}
});
OnImportInvoker on_import(archive->stage(), prim_map, reports);
on_import.call();
}

View File

@@ -3,11 +3,6 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_map.hh"
#include "BLI_vector.hh"
#include "RNA_types.hh"
#include <pxr/usd/usd/common.h>
#include <pxr/usd/usdShade/material.h>
@@ -19,7 +14,7 @@ namespace blender::io::usd {
struct USDExportParams;
struct USDImportParams;
using ImportedPrimMap = Map<std::string, Vector<PointerRNA>>;
class USDStageReader;
/** Ensure classes and type converters necessary for invoking import and export hooks
* are registered. */
@@ -36,9 +31,7 @@ void call_material_export_hooks(pxr::UsdStageRefPtr stage,
ReportList *reports);
/** Call the 'on_import' chaser function defined in the registered USDHook classes. */
void call_import_hooks(pxr::UsdStageRefPtr stage,
const ImportedPrimMap &imported_id_links,
ReportList *reports);
void call_import_hooks(USDStageReader *archive, ReportList *reports);
/** Returns true if there is a registered #USDHook class that can convert the given material. */
bool have_material_import_hook(pxr::UsdStageRefPtr stage,