14# include <openvdb/openvdb.h>
16namespace blender::bke::volume_grid::file_cache {
26 openvdb::GridBase::Ptr meta_data_grid;
30 Map<int, GVolumeGrid> grid_by_simplify_level;
40 std::string error_message;
44 openvdb::MetaMap meta_data;
48 Vector<GridCache> grids;
50 GridCache *grid_cache_by_name(
const StringRef
name)
52 for (GridCache &grid_cache : this->grids) {
53 if (grid_cache.meta_data_grid->getName() ==
name) {
66 Map<std::string, FileCache> file_map;
72static GlobalCache &get_global_cache()
74 static GlobalCache global_cache;
82static FileCache create_file_cache(
const StringRef file_path)
86 openvdb::io::File file(file_path);
87 openvdb::GridPtrVec vdb_grids;
91 const bool delay_load =
false;
92# ifdef OPENVDB_USE_DELAYED_LOADING
93 file.setCopyMaxBytes(0);
95 file.open(delay_load);
96 vdb_grids = *(file.readAllGridMetadata());
97 file_cache.meta_data = *file.getMetadata();
99 catch (
const openvdb::IoError &
e) {
100 file_cache.error_message =
e.what();
103 file_cache.error_message =
"Unknown error reading VDB file";
105 if (!file_cache.error_message.empty()) {
109 for (openvdb::GridBase::Ptr &vdb_grid : vdb_grids) {
113 GridCache grid_cache;
114 grid_cache.meta_data_grid = vdb_grid;
115 file_cache.grids.append(std::move(grid_cache));
121static FileCache &get_file_cache(
const StringRef file_path)
123 GlobalCache &global_cache = get_global_cache();
126 return global_cache.file_map.lookup_or_add_cb_as(file_path,
127 [&]() {
return create_file_cache(file_path); });
133class GridReadKey :
public GenericKey {
135 std::string file_path;
136 std::string grid_name;
141 return get_default_hash(this->file_path, this->grid_name, this->simplify_level);
146 bool equal_to(
const GenericKey &other)
const override
148 if (
const auto *other_typed =
dynamic_cast<const GridReadKey *
>(&other)) {
149 return *
this == *other_typed;
154 std::unique_ptr<GenericKey> to_storable()
const override
156 return std::make_unique<GridReadKey>(*
this);
160class GridReadValue :
public memory_cache::CachedValue {
162 mutable std::atomic<int64_t> bytes_ = 0;
165 ImplicitSharingPtr<> tree_sharing_info;
166 openvdb::GridBase::Ptr grid;
172 this->bytes_ = grid->baseTree().memUsage();
182static openvdb::GridBase::Ptr load_single_grid_from_disk(
const StringRef file_path,
183 const StringRef grid_name)
187 const bool delay_load =
false;
189 openvdb::io::File file(file_path);
190# ifdef OPENVDB_USE_DELAYED_LOADING
191 file.setCopyMaxBytes(0);
193 file.open(delay_load);
194 return file.readGrid(grid_name);
201static LazyLoadedGrid load_single_grid_from_disk_cached(
const StringRef file_path,
202 const StringRef grid_name,
203 const int simplify_level)
206 key.file_path = file_path;
207 key.grid_name = grid_name;
208 key.simplify_level = simplify_level;
210 std::shared_ptr<const GridReadValue> value = memory_cache::get<GridReadValue>(key, [&key]() {
211 openvdb::GridBase::Ptr grid;
212 if (key.simplify_level == 0) {
213 grid = load_single_grid_from_disk(key.file_path, key.grid_name);
217 const GVolumeGrid main_grid = get_grid_from_file(key.file_path, key.grid_name, 0);
219 const float resolution_factor = 1.0f / (1 << key.simplify_level);
220 VolumeTreeAccessToken tree_token;
221 grid = BKE_volume_grid_create_with_changed_resolution(
222 grid_type, main_grid->grid(tree_token), resolution_factor);
224 auto value = std::make_unique<GridReadValue>();
225 value->grid = std::move(grid);
226 value->tree_sharing_info = OpenvdbTreeSharingInfo::make(value->grid->baseTreePtr());
234 openvdb::GridBase::Ptr grid = value->grid->copyGrid();
235 grid->setTransform(grid->transform().copy());
236 return {grid, value->tree_sharing_info};
243static GVolumeGrid get_cached_grid(
const StringRef file_path,
244 GridCache &grid_cache,
245 const int simplify_level)
247 if (GVolumeGrid *grid = grid_cache.grid_by_simplify_level.lookup_ptr(simplify_level)) {
251 auto load_grid_fn = [file_path = std::string(file_path),
252 grid_name = std::string(grid_cache.meta_data_grid->getName()),
253 simplify_level]() -> LazyLoadedGrid {
254 return load_single_grid_from_disk_cached(file_path, grid_name, simplify_level);
258 openvdb::GridBase::Ptr meta_data_and_transform_grid;
259 if (simplify_level == 0) {
262 meta_data_and_transform_grid = grid_cache.meta_data_grid->copyGrid();
264 VolumeGridData *grid_data = MEM_new<VolumeGridData>(
265 __func__, load_grid_fn, meta_data_and_transform_grid);
266 GVolumeGrid grid{grid_data};
267 grid_cache.grid_by_simplify_level.add(simplify_level, grid);
271GVolumeGrid get_grid_from_file(
const StringRef file_path,
272 const StringRef grid_name,
273 const int simplify_level)
275 GlobalCache &global_cache = get_global_cache();
276 std::lock_guard
lock{global_cache.mutex};
277 FileCache &file_cache = get_file_cache(file_path);
278 if (GridCache *grid_cache = file_cache.grid_cache_by_name(grid_name)) {
279 return get_cached_grid(file_path, *grid_cache, simplify_level);
284GridsFromFile get_all_grids_from_file(
const StringRef file_path,
const int simplify_level)
287 GlobalCache &global_cache = get_global_cache();
288 std::lock_guard
lock{global_cache.mutex};
289 FileCache &file_cache = get_file_cache(file_path);
291 if (!file_cache.error_message.empty()) {
292 result.error_message = file_cache.error_message;
295 result.file_meta_data = std::make_shared<openvdb::MetaMap>(file_cache.meta_data);
296 for (GridCache &grid_cache : file_cache.grids) {
297 result.grids.append(get_cached_grid(file_path, grid_cache, simplify_level));
304 GlobalCache &global_cache = get_global_cache();
305 std::lock_guard
lock{global_cache.mutex};
306 for (FileCache &file_cache : global_cache.file_map.values()) {
307 for (GridCache &grid_cache : file_cache.grids) {
308 grid_cache.grid_by_simplify_level.remove_if(
309 [&](
const auto &item) {
return item.value->is_mutable(); });
#define BLI_STRUCT_EQUALITY_OPERATORS_3(Type, m1, m2, m3)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
unsigned long long int uint64_t
void count_memory(const VolumeGridData &grid, MemoryCounter &memory)
uint64_t get_default_hash(const T &v, const Args &...args)