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 file.setCopyMaxBytes(0);
93 file.open(delay_load);
94 vdb_grids = *(file.readAllGridMetadata());
95 file_cache.meta_data = *file.getMetadata();
97 catch (
const openvdb::IoError &
e) {
98 file_cache.error_message =
e.what();
101 file_cache.error_message =
"Unknown error reading VDB file";
103 if (!file_cache.error_message.empty()) {
107 for (openvdb::GridBase::Ptr &vdb_grid : vdb_grids) {
111 GridCache grid_cache;
112 grid_cache.meta_data_grid = vdb_grid;
113 file_cache.grids.append(std::move(grid_cache));
119static FileCache &get_file_cache(
const StringRef file_path)
121 GlobalCache &global_cache = get_global_cache();
124 return global_cache.file_map.lookup_or_add_cb_as(file_path,
125 [&]() {
return create_file_cache(file_path); });
131class GridReadKey :
public GenericKey {
133 std::string file_path;
134 std::string grid_name;
139 return get_default_hash(this->file_path, this->grid_name, this->simplify_level);
144 bool equal_to(
const GenericKey &other)
const override
146 if (
const auto *other_typed =
dynamic_cast<const GridReadKey *
>(&other)) {
147 return *
this == *other_typed;
152 std::unique_ptr<GenericKey> to_storable()
const override
154 return std::make_unique<GridReadKey>(*
this);
158class GridReadValue :
public memory_cache::CachedValue {
160 mutable std::atomic<int64_t> bytes_ = 0;
163 ImplicitSharingPtr<> tree_sharing_info;
164 openvdb::GridBase::Ptr grid;
170 this->bytes_ = grid->baseTree().memUsage();
180static openvdb::GridBase::Ptr load_single_grid_from_disk(
const StringRef file_path,
181 const StringRef grid_name)
185 const bool delay_load =
false;
187 openvdb::io::File
file(file_path);
188 file.setCopyMaxBytes(0);
189 file.open(delay_load);
190 return file.readGrid(grid_name);
197static LazyLoadedGrid load_single_grid_from_disk_cached(
const StringRef file_path,
198 const StringRef grid_name,
199 const int simplify_level)
202 key.file_path = file_path;
203 key.grid_name = grid_name;
204 key.simplify_level = simplify_level;
206 std::shared_ptr<const GridReadValue> value = memory_cache::get<GridReadValue>(key, [&key]() {
207 openvdb::GridBase::Ptr grid;
208 if (key.simplify_level == 0) {
209 grid = load_single_grid_from_disk(key.file_path, key.grid_name);
213 const GVolumeGrid main_grid = get_grid_from_file(key.file_path, key.grid_name, 0);
214 const VolumeGridType grid_type = main_grid->grid_type();
215 const float resolution_factor = 1.0f / (1 << key.simplify_level);
216 VolumeTreeAccessToken tree_token;
217 grid = BKE_volume_grid_create_with_changed_resolution(
218 grid_type, main_grid->grid(tree_token), resolution_factor);
220 auto value = std::make_unique<GridReadValue>();
221 value->grid = std::move(grid);
222 value->tree_sharing_info = OpenvdbTreeSharingInfo::make(value->grid->baseTreePtr());
230 openvdb::GridBase::Ptr grid = value->grid->copyGrid();
231 grid->setTransform(grid->transform().copy());
232 return {grid, value->tree_sharing_info};
239static GVolumeGrid get_cached_grid(
const StringRef file_path,
240 GridCache &grid_cache,
241 const int simplify_level)
243 if (GVolumeGrid *grid = grid_cache.grid_by_simplify_level.lookup_ptr(simplify_level)) {
247 auto load_grid_fn = [file_path = std::string(file_path),
248 grid_name = std::string(grid_cache.meta_data_grid->getName()),
249 simplify_level]() -> LazyLoadedGrid {
250 return load_single_grid_from_disk_cached(file_path, grid_name, simplify_level);
254 openvdb::GridBase::Ptr meta_data_and_transform_grid;
255 if (simplify_level == 0) {
258 meta_data_and_transform_grid = grid_cache.meta_data_grid->copyGrid();
260 VolumeGridData *grid_data = MEM_new<VolumeGridData>(
261 __func__, load_grid_fn, meta_data_and_transform_grid);
262 GVolumeGrid grid{grid_data};
263 grid_cache.grid_by_simplify_level.add(simplify_level, grid);
267GVolumeGrid get_grid_from_file(
const StringRef file_path,
268 const StringRef grid_name,
269 const int simplify_level)
271 GlobalCache &global_cache = get_global_cache();
272 std::lock_guard
lock{global_cache.mutex};
273 FileCache &file_cache = get_file_cache(file_path);
274 if (GridCache *grid_cache = file_cache.grid_cache_by_name(grid_name)) {
275 return get_cached_grid(file_path, *grid_cache, simplify_level);
280GridsFromFile get_all_grids_from_file(
const StringRef file_path,
const int simplify_level)
283 GlobalCache &global_cache = get_global_cache();
284 std::lock_guard
lock{global_cache.mutex};
285 FileCache &file_cache = get_file_cache(file_path);
287 if (!file_cache.error_message.empty()) {
288 result.error_message = file_cache.error_message;
291 result.file_meta_data = std::make_shared<openvdb::MetaMap>(file_cache.meta_data);
292 for (GridCache &grid_cache : file_cache.grids) {
293 result.grids.append(get_cached_grid(file_path, grid_cache, simplify_level));
300 GlobalCache &global_cache = get_global_cache();
301 std::lock_guard
lock{global_cache.mutex};
302 for (FileCache &file_cache : global_cache.file_map.values()) {
303 for (GridCache &grid_cache : file_cache.grids) {
304 grid_cache.grid_by_simplify_level.remove_if(
305 [&](
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
void count_memory(const VolumeGridData &grid, MemoryCounter &memory)
uint64_t get_default_hash(const T &v)
unsigned __int64 uint64_t