Volumes: refactor volume grid storage #116315
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#116315
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "JacquesLucke/blender:volume-grid-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This is preparation for #115270.
This refactors how volume grids are stored with the following new goals in mind:
VolumeGrid
data structure was tightly coupled with theVolume
data block.Volume
data blocks loaded grids from the same.vdb
files but this was not flexible enough.Volume
data block.openvdb
involvement:OpenVDB
: SinceWITH_OPENVDB
is optional, it's helpful to have parts of the API that still work in this case. This makes it possible to write high level code for volumes that does not require#ifdef WITH_OPENVDB
checks everywhere. This is inBKE_volume_grid_fwd.hh
.OpenVDB
: Code using this API requiresWITH_OPENVDB
checks. However, care is taken to not include the expensive parts ofOpenVDB
and to use forward declarations as much as possible. This is inBKE_volume_grid.hh
and usesopenvdb_fwd.hh
.OpenVDB
: This API requires more heavyOpenVDB
includes. Fortunately, it turned out to be not necessary for the common API. So this is only used for task specific APIs.At the core of the new API is the
VolumeGridData
type. It's a wrapper around anopenvdb::Grid
and adds some features on top like implicit sharing, lazy-loading and unloading. Then there areGVolumeGrid
andVolumeGrid
which are containers for a volume grid. Semantically, eachVolumeGrid
has its own independent grid, but this is cheap due to implicit sharing. At highest level we currently have theVolume
data-block which contains a list ofVolumeGrid
.The loading of
.vdb
files is abstracted away behind the volume file cache API. This API makes it easy to load and reuse entire files and individual grids from disk. It also supports caching simplify levels for grids on disk.An important new concept are the "tree access tokens". Whenever some code wants to work with an openvdb tree, it has to retrieve an access token from the corresponding
VolumeGridData
. This access token has to be kept alive for as long as the code works with the grid data. The same token is valid for read and write access. The purpose of these access tokens is to make it possible to detect when some code is currently working with the openvdb tree. This allows freeing it if it's possible to reload it later on (e.g. from disk). It's possible to free a tree that is referenced by multiple owners, but only no one is actively working with. In some sense, this is similar to the existingImageUser
concept.The most important files to read are
BKE_volume_grid.hh
andBKE_volume_grid_file_cache.hh
. Most other changes are updates to existing code to use the new API.void
instead of a generic MaskTree to indicate that string attributes are unsupported. 898cf929d4typed()
method. 3d5b151366@blender-bot build
@blender-bot build
Overall this seems like a nice API, and I really appreciate the documentation in the headers and the PR description.
The part I understand least now is why it's worth having implicit sharing at the
VolumeGridData
level when it's already implemented at the grid level withtree_sharing_info_
.VolumeGridData
seems very light in comparison-- not really a problem to copy. But maybe it is if we're passing it around as socket data.@ -0,0 +37,4 @@
*
* Features:
* - Implicit sharing of the #VolumeGridData: This makes it cheap to copy e.g. a #VolumeGrid<T>,
* because it just increases the number of users. On actual copy is only done, when the grid is
On actual copy is only done, when
->An actual copy is only done when
@ -0,0 +105,4 @@
* not. If this variable is the only owner of the `shared_ptr`, no one else has access to the
* tree.
*/
std::shared_ptr<AccessToken> tree_access_token_;
I guess a shared pointer is just a simple way of keeping a use count?
Correct. Will extend the comment.
@ -0,0 +23,4 @@
namespace blender::bke::volume_grid::file_cache {
/**
* Get the volume grid identified by the parameters from a cache. This does load the tree data in
This does load
->This does not load
?@ -0,0 +26,4 @@
* Get the volume grid identified by the parameters from a cache. This does load the tree data in
* grid because that is done on demand when it is accessed.
*/
GVolumeGrid get_grid_from_file(StringRef file_path, StringRef grid_name, int simplify_level = 0);
I guess it might be nice if this function could give an error message too, at least optionally?
EDIT: Looks like the error is stored in the grid data-- that's how it already is in
main
. Seems a bit odd but not a big deal.Yeah, one issue is that you can't really reliably know whether there is a load error in this function, because it doesn't actually load the grid.
@ -0,0 +34,4 @@
class GVolumeGrid;
/**
* Same as #GVolumeGrid but makes sure that the contained grid is of a specific type.
I'd say "means" or something instead of "makes sure" which implies some sort of action (like implicit conversion or something). Even if that happened, this wouldn't be the place to mention it IMO.
@ -29,3 +29,3 @@
bool BKE_volume_grid_dense_floats(const Volume *volume,
const VolumeGrid *volume_grid,
const blender::bke::VolumeGridData *volume_grid,
Missing forward declarations here
It's a good point. It's definitely light in comparison to the tree, but it's also "copied" more often. I see little reason not to use implicit sharing here. A more important reason may be that it is more natural to share the grid that's loaded from a file than it is to just share the tree. Also, I don't actually know if it's common to put lots of meta data into a grid or not. There are a fair amount of allocations involved when copying a grid, even if the tree is shared (it also wouldn't fit into
SocketValueVariant
).That said, almost everything is light compared to a tree haha
Okay, interesting. Sounds a bit like "since we have to allocate it anyway, and it does have some relatively non-trivial data in it, might as well make it implicitly shared". I can get behind that, since it seems like a nice goal for most allocated Blender data in general. OTOH, it would probably simplify understanding the design if it wasn't shared, but that's fine.
Maybe it would, not 100% sure. I'm especially not sure if this might become a problem with lazy-loading if we don't have this intermediate level.
That aside, I think the "since we have to allocate it anyway, and it does have some relatively non-trivial data in it, might as well make it implicitly shared" argument isn't too bad in itself either. At least as long as the API used to work with the data is safe and generally hides the sharing if possible, which I think is the case here. It's not really something one has to think about when implementing nodes for example: https://projects.blender.org/blender/blender/pulls/115270/files#diff-b343e08adb4ec2030715a70d36bd88ea641779d6
@blender-bot build