From 953fa94fb3cc87dfa6b87726dbc6d0b2ecb5e475 Mon Sep 17 00:00:00 2001 From: Jesse Yurkovich Date: Fri, 27 Dec 2024 03:36:22 +0100 Subject: [PATCH] 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 --- .../blender/io/usd/intern/usd_capi_import.cc | 25 +---------- source/blender/io/usd/intern/usd_hook.cc | 45 ++++++++++++++++--- source/blender/io/usd/intern/usd_hook.hh | 11 +---- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index 54bf91fb18e..28ded4a1359 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -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(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 diff --git a/source/blender/io/usd/intern/usd_hook.cc b/source/blender/io/usd/intern/usd_hook.cc index c06e343629b..bced8d62bb1 100644 --- a/source/blender/io/usd/intern/usd_hook.cc +++ b/source/blender/io/usd/intern/usd_hook.cc @@ -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>; +using ImportedPrimMap = Map>; /* 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 &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(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(); } diff --git a/source/blender/io/usd/intern/usd_hook.hh b/source/blender/io/usd/intern/usd_hook.hh index b3b85fce81f..a6c59874492 100644 --- a/source/blender/io/usd/intern/usd_hook.hh +++ b/source/blender/io/usd/intern/usd_hook.hh @@ -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 #include @@ -19,7 +14,7 @@ namespace blender::io::usd { struct USDExportParams; struct USDImportParams; -using ImportedPrimMap = Map>; +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,