Fix T94715: multiple volumes using the same .vdb causes freeze

Needs more TBB task isolation, as even freeing an OpenVDB grid uses
multithreading.
This commit is contained in:
Brecht Van Lommel 2022-01-17 20:36:59 +01:00 committed by Philipp Oeser
parent 9600f36cfc
commit 0039432cfc
Notes: blender-bot 2023-02-14 06:00:49 +01:00
Referenced by issue #94715, Multiple volumes using same data can cause crash/freeze
Referenced by issue #93479, 3.0 Potential candidates for corrective releases
1 changed files with 26 additions and 14 deletions

View File

@ -137,11 +137,19 @@ static struct VolumeFileCache {
}
std::lock_guard<std::mutex> lock(mutex);
return simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
const float resolution_factor = 1.0f / (1 << simplify_level);
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid);
return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor);
openvdb::GridBase::Ptr simple_grid;
/* Isolate creating grid since that's multithreaded and we are
* holding a mutex lock. */
blender::threading::isolate_task([&] {
simple_grid = simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
const float resolution_factor = 1.0f / (1 << simplify_level);
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid);
return BKE_volume_grid_create_with_changed_resolution(
grid_type, *grid, resolution_factor);
});
});
return simple_grid;
}
/* Unique key: filename + grid name. */
@ -246,16 +254,20 @@ static struct VolumeFileCache {
protected:
void update_for_remove_user(Entry &entry)
{
if (entry.num_metadata_users + entry.num_tree_users == 0) {
cache.erase(entry);
}
else if (entry.num_tree_users == 0) {
/* Note we replace the grid rather than clearing, so that if there is
* any other shared pointer to the grid it will keep the tree. */
entry.grid = entry.grid->copyGridWithNewTree();
entry.simplified_grids.clear();
entry.is_loaded = false;
}
/* Isolate file unloading since that's multithreaded and we are
* holding a mutex lock. */
blender::threading::isolate_task([&] {
if (entry.num_metadata_users + entry.num_tree_users == 0) {
cache.erase(entry);
}
else if (entry.num_tree_users == 0) {
/* Note we replace the grid rather than clearing, so that if there is
* any other shared pointer to the grid it will keep the tree. */
entry.grid = entry.grid->copyGridWithNewTree();
entry.simplified_grids.clear();
entry.is_loaded = false;
}
});
}
/* Cache contents */