Commit: 871fda82e662d889046e37061b582758f705a2af Author: Michael A. Kowalski Date: Thu Dec 3 21:01:59 2020 -0500 Branches: usd-importer-T81257 https://developer.blender.org/rB871fda82e662d889046e37061b582758f705a2af
USD importer: instancing improvements. Added new USDDataCache class for caching prototype mesh data. No longer using a global static cache for prototype meshes. Now precomputing the prototype meshes in a USDDataCache instance which is passed as an argument to USDXformableReade::create_objects(). These changes simplify the code, provide better support for thread safety and circumvent potential issues with dangling pointers in the previous implementation. =================================================================== M source/blender/io/usd/CMakeLists.txt A source/blender/io/usd/import/usd_data_cache.cc A source/blender/io/usd/import/usd_data_cache.h M source/blender/io/usd/import/usd_importer_context.h M source/blender/io/usd/import/usd_prim_iterator.cc M source/blender/io/usd/import/usd_prim_iterator.h M source/blender/io/usd/import/usd_reader_camera.cc M source/blender/io/usd/import/usd_reader_camera.h M source/blender/io/usd/import/usd_reader_light.cc M source/blender/io/usd/import/usd_reader_light.h M source/blender/io/usd/import/usd_reader_mesh_base.cc M source/blender/io/usd/import/usd_reader_mesh_base.h M source/blender/io/usd/import/usd_reader_xform.cc M source/blender/io/usd/import/usd_reader_xform.h M source/blender/io/usd/import/usd_reader_xformable.h M source/blender/io/usd/intern/usd_capi.cc =================================================================== diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index dc22045476a..6d693401b6d 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -54,6 +54,7 @@ set(INC_SYS set(SRC + import/usd_data_cache.cc import/usd_import_util.cc import/usd_material_importer.cc import/usd_prim_iterator.cc @@ -75,6 +76,7 @@ set(SRC intern/usd_writer_transform.cc usd.h + import/usd_data_cache.h import/usd_importer_context.h import/usd_import_util.h import/usd_material_importer.h diff --git a/source/blender/io/usd/import/usd_reader_xform.h b/source/blender/io/usd/import/usd_data_cache.cc similarity index 52% copy from source/blender/io/usd/import/usd_reader_xform.h copy to source/blender/io/usd/import/usd_data_cache.cc index 4be0f2d1273..55558aba517 100644 --- a/source/blender/io/usd/import/usd_reader_xform.h +++ b/source/blender/io/usd/import/usd_data_cache.cc @@ -16,31 +16,42 @@ * The Original Code is Copyright (C) 2020 Blender Foundation. * All rights reserved. */ -#pragma once -#include "usd_reader_xformable.h" +#include "usd_data_cache.h" -#include <pxr/usd/usdGeom/xform.h> +#include <iostream> namespace blender::io::usd { -/* Wraps the UsdGeomXform schema. Creates a Blender Empty object. */ - -class USDXformReader : public USDXformableReader { - - pxr::UsdGeomXform xform_; - - public: - USDXformReader(const pxr::UsdPrim &prim, const USDImporterContext &context); - - bool valid() const override; - - bool can_merge_with_parent() const override - { - return false; +USDDataCache::USDDataCache() +{ +} + +USDDataCache::~USDDataCache() +{ + /* TODO(makowalski): decrement use count and/or delete the cached data? */ +} + +bool USDDataCache::add_prototype_mesh(const pxr::SdfPath path, Mesh *mesh) +{ + /* TODO(makowalsk): should we increment mesh use count? */ + return prototype_meshes_.insert(std::make_pair(path, mesh)).second; +} + +void USDDataCache::clear_protype_mesh(const pxr::SdfPath &path) +{ + /* TODO(makowalsk): should we decrement mesh use count or delete mesh? */ + prototype_meshes_.erase(path); +} + +Mesh *USDDataCache::get_prototype_mesh(const pxr::SdfPath &path) const +{ + std::map<pxr::SdfPath, Mesh *>::const_iterator it = prototype_meshes_.find(path); + if (it != prototype_meshes_.end()) { + return it->second; } - void create_object(Main *bmain, double time) override; -}; + return nullptr; +} } // namespace blender::io::usd diff --git a/source/blender/io/usd/import/usd_reader_xform.h b/source/blender/io/usd/import/usd_data_cache.h similarity index 55% copy from source/blender/io/usd/import/usd_reader_xform.h copy to source/blender/io/usd/import/usd_data_cache.h index 4be0f2d1273..6f3767387f6 100644 --- a/source/blender/io/usd/import/usd_reader_xform.h +++ b/source/blender/io/usd/import/usd_data_cache.h @@ -18,29 +18,43 @@ */ #pragma once -#include "usd_reader_xformable.h" +#include <map> -#include <pxr/usd/usdGeom/xform.h> +#include <pxr/usd/sdf/path.h> -namespace blender::io::usd { +struct Mesh; -/* Wraps the UsdGeomXform schema. Creates a Blender Empty object. */ +namespace blender::io::usd { -class USDXformReader : public USDXformableReader { +/* Caches data imported from USD, typically shared data for instanced primitives. */ - pxr::UsdGeomXform xform_; +class USDDataCache { + protected: + /* Shared meshes for instancing. */ + std::map<pxr::SdfPath, Mesh *> prototype_meshes_; public: - USDXformReader(const pxr::UsdPrim &prim, const USDImporterContext &context); + USDDataCache(); - bool valid() const override; + ~USDDataCache(); + + const std::map<pxr::SdfPath, Mesh *> &prototype_meshes() const + { + return prototype_meshes_; + } - bool can_merge_with_parent() const override + void clear_prototype_meshes() { - return false; + /* TODO(makowalsk): should we decrement mesh use counts or delete meshes? */ + prototype_meshes_.clear(); } - void create_object(Main *bmain, double time) override; + bool add_prototype_mesh(const pxr::SdfPath path, Mesh *mesh); + + void clear_protype_mesh(const pxr::SdfPath &path); + + Mesh *get_prototype_mesh(const pxr::SdfPath &path) const; + }; } // namespace blender::io::usd diff --git a/source/blender/io/usd/import/usd_importer_context.h b/source/blender/io/usd/import/usd_importer_context.h index 0970fd9e789..49750a55dfc 100644 --- a/source/blender/io/usd/import/usd_importer_context.h +++ b/source/blender/io/usd/import/usd_importer_context.h @@ -31,7 +31,6 @@ typedef std::map<pxr::SdfPath, USDXformableReader *> ObjectReaderMap; struct USDImporterContext { const pxr::TfToken stage_up_axis; const USDImportParams import_params; - ObjectReaderMap *proto_readers; }; } // namespace blender::io::usd diff --git a/source/blender/io/usd/import/usd_prim_iterator.cc b/source/blender/io/usd/import/usd_prim_iterator.cc index 7f6f311e90a..18d4bc11d46 100644 --- a/source/blender/io/usd/import/usd_prim_iterator.cc +++ b/source/blender/io/usd/import/usd_prim_iterator.cc @@ -20,6 +20,7 @@ #include "usd_prim_iterator.h" #include "usd.h" +#include "usd_data_cache.h" #include "usd_importer_context.h" #include "usd_reader_camera.h" #include "usd_reader_light.h" @@ -41,23 +42,24 @@ namespace blender::io::usd { -USDPrimIterator::USDPrimIterator(pxr::UsdStageRefPtr stage) : stage_(stage) +USDPrimIterator::USDPrimIterator(pxr::UsdStageRefPtr stage, + const USDImporterContext &context, + Main *bmain) + : stage_(stage), context_(context), bmain_(bmain) { } -void USDPrimIterator::create_object_readers(const USDImporterContext &context, - std::vector<USDXformableReader *> &r_readers) const +void USDPrimIterator::create_object_readers(std::vector<USDXformableReader *> &r_readers) const { if (!stage_) { return; } std::vector<USDXformableReader *> child_readers; - create_object_readers(stage_->GetPseudoRoot(), context, r_readers, child_readers); + create_object_readers(stage_->GetPseudoRoot(), context_, r_readers, child_readers); } void USDPrimIterator::create_prototype_object_readers( - const USDImporterContext &context, std::map<pxr::SdfPath, USDXformableReader *> &r_proto_readers) const { if (!stage_) { @@ -70,7 +72,7 @@ void USDPrimIterator::create_prototype_object_readers( std::vector<USDXformableReader *> proto_readers; std::vector<USDXformableReader *> child_readers; - create_object_readers(proto_prim, context, proto_readers, child_readers); + create_object_readers(proto_prim, context_, proto_readers, child_readers); for (USDXformableReader *reader : proto_readers) { if (reader) { @@ -168,6 +170,45 @@ void USDPrimIterator::create_object_readers(const pxr::UsdPrim &prim, } } +void USDPrimIterator::cache_prototype_data(USDDataCache &r_cache) const +{ + if (!stage_) { + return; + } + + std::vector<pxr::UsdPrim> protos = stage_->GetMasters(); + + for (const pxr::UsdPrim &proto_prim : protos) { + std::vector<USDXformableReader *> proto_readers; + std::vector<USDXformableReader *> child_readers; + + create_object_readers(proto_prim, context_, proto_readers, child_readers); + + for (USDXformableReader *reader : proto_readers) { + if (reader) { + pxr::UsdPrim reader_prim = reader->prim(); + if (reader_prim) { + + if (USDMeshReaderBase *mesh_reader = dynamic_cast<USDMeshReaderBase *>(reader)) { + Mesh *proto_mesh = mesh_reader->create_mesh(bmain_, 0.0); + if (proto_mesh) { + /* TODO(makowalski): Do we want to decrement the mesh's use count to 0? + * Might have a small memory leak otherwise. Also, check if mesh is + * already in cache before adding? */ + r_cache.add_prototype_mesh(reader_prim.GetPath(), proto_mesh); + } + } + } + } + } + + /* Clean up the readers. */ + for (USDXformableReader *reader : proto_readers) { + delete reader; + } + } +} + void USDPrimIterator::debug_traverse_stage(const pxr::UsdStageRefPtr &usd_stage) { if (!usd_stage) { diff --git a/source/blender/io/usd/import/usd_prim_iterator.h b/source/blender/io/usd/import/usd_prim_iterator.h index 672dbb098c6..1605d919051 100644 --- a/source/blender/io/usd/import/usd_prim_iterator.h +++ b/source/blender/io/usd/import/usd_prim_iterator.h @@ -18,30 +18,36 @@ */ #pragma once -#include "pxr/usd/usd/common.h" +#include "usd_importer_context.h" + +#include <pxr/usd/usd/common.h> #include <map> #include <vector> +struct Main; + namespace blender::io::usd { -struct USDImporterContext; +class USDDataCache; class USDXformableReader; class USDPrimIterator { protected: pxr::UsdStageRefPtr stage_; + USDImporterContext context_; + Main *bmain_; public: - USDPrimIterator(pxr::UsdStageRefPtr stage); + USDPrimIterator(pxr::UsdStageRefPtr stage, const USDImporterContext &context, Main *bmain); - void create_object_readers(const USDImporterContext &context, - std::vector<USDXformableReader *> &r_readers) const; + void create_object_readers(std::vector<USDXformableReader *> &r_readers) const; void create_prototype_object_readers( - const USDImporterContext &context, std::map<pxr::SdfPath, USDXformableReader *> &r_proto_readers) const; + void cache_prototype_data(USDDataCache &r_cache) const; + void debug_traverse_stage() const; static USDXformableReader *get_object_reader(const pxr::UsdPrim &prim, diff --git a/source/blender/io/usd/import/usd_reader_camera.cc b/source/blender/io/usd/import/usd_reader_camera.cc index 6ad2b55dcb0..418d6a4ee77 100644 --- a/source/blender/io/usd/import/usd_reader_camera.cc +++ b/source/blender/io/usd/import/usd_reader_camera.cc @@ -43,7 +43,7 @@ bool USDCameraReader::valid() const return static_cast<bool>(camera_); } -void USDCameraReader::create_object(Main *bmain, double time) +void USDCameraReader::create_object(Main *bmain, double time, USDDataCache *data_cache) { if (!this->valid() @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs