Page MenuHome

Depsgraph: remove redundant mesh data duplication in edit-mode
ClosedPublic

Authored by Campbell Barton (campbellbarton) on May 21 2021, 10:23 AM.
Tokens
"Love" token, awarded by kursadk."Love" token, awarded by Tetone."Love" token, awarded by gilberto_rodrigues."Like" token, awarded by erickblender.

Details

Summary

This resolves a bottleneck where every update while transforming
copied the entire mesh data-block, which isn't needed as the edit-mesh
is the source of the data being edited.

Testing shows a significant overall speedup when transforming:

  • ~1.5x with a subdivided cube 1.5 million vertices.
  • ~3.0x with the spring mesh (edit-mode with modifiers disabled, duplicated 10x to drop performance).

Notes:

Alternatives:

Some alternative solutions I considered, although I'm not so experienced with the depsgraph, so it's possible I missed something.

  • Copy-on-write could define components for updating e.g. shared-pointers, runtime-data, id-data. This would allow copy-on-write updates to be left enabled, while avoiding expensive operations.
  • Recalculating geometry could never do copy-on-write, instead we could require the caller to pass:

    ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE. This might not be so bad as there aren't so many mesh editing operations in object mode, although it might still be error prone.
  • There could be a separate kind of ID_RECALC_GEOMETRY flag for edit-mode, instead of making the current flag check the id-state. From some tests though it seems like adding similar flags ends up requiring duplicate code-paths for something that's virtually the same, so it didn't seem worthwhile.

Further Work:

  • Armatures might be able to skip a full COW copy too.
  • DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY) on the object data still causes the mesh data to be copied while in edit-mode. Solutions to this should be investigated too.

Diff Detail

Repository
rB Blender
Branch
TEMP-DEPSGRAPH-SKIP-EDITMODE-COW (branched from master)
Build Status
Buildable 14682
Build 14682: arc lint + arc unit

Event Timeline

Campbell Barton (campbellbarton) created this revision.
  • Don't use this for armatures since that should be evaluated separately.
Campbell Barton (campbellbarton) retitled this revision from Remove redundant depsgraph mesh data duplication in edit-mode to Depsgraph: remove redundant mesh data duplication in edit-mode.May 21 2021, 10:39 AM
Campbell Barton (campbellbarton) edited the summary of this revision. (Show Details)
Campbell Barton (campbellbarton) edited the summary of this revision. (Show Details)
Campbell Barton (campbellbarton) edited the summary of this revision. (Show Details)
Sergey Sharybin (sergey) requested changes to this revision.EditedMay 21 2021, 10:56 AM

I do not think this is correct thing to do. There are users of the geometry data which needs datablock to be consistent: for example, animation system, possibly render engines. The geometry datablock is at very least to be ensured to be "expanded" and properties are to be synchronized into the depsgraph CoW datablock.

Edit: Please try to make the patch well-presented before assigning reviews. Not only this will ensure all the information is as clear as it possible when review starts, but also avoids spamming inboxes of the reviewers.

This revision now requires changes to proceed.May 21 2021, 10:56 AM

I think the current patch could be made to work.
New data blocks will always get expanded, tagging that requires the COW copies are updated could use ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE.

Nevertheless, I'm not pushing for this as the final solution.

I do not think this is correct thing to do. There are users of the geometry data which needs datablock to be consistent: for example, animation system, possibly render engines. The geometry datablock is at very least to be ensured to be "expanded" and properties are to be synchronized into the depsgraph CoW datablock.

In that case it might be simpler to have a tag for shared-runtime data e.g. ID_RECALC_GEOMETRY_RUNTIME or even ID_RECALC_RUNTIME, since only the depsgraph just needs to re-evaluate the current data taking changes into account that are already in shared pointers which the COW ID's are referencing.

May be better to discuss this in chat.

Edit: Please try to make the patch well-presented before assigning reviews. Not only this will ensure all the information is as clear as it possible when review starts, but also avoids spamming inboxes of the reviewers.

Will do.

Campbell Barton (campbellbarton) planned changes to this revision.EditedMay 21 2021, 1:52 PM

Based on discussion with Sergey and Sybren in #core-module.

This patch has a problem that properties being modified currently use ID_RECALC_GEOMETRY, this patch will prevent them from updating the copy-on-write data.


Solution proposed by Sergey is to make sure non-geometry mesh properties are handled with ID_RECALC_PARAMETERS.
& mesh always expanded at least once, then this patch should work.

This patch has a problem that properties being modified currently use ID_RECALC_GEOMETRY, this patch will prevent them from updating the copy-on-write data.

Does this mean that this patch requires D11377: Depsgraph: support flushing parameters without a full COW update to be applied first? Because that patch describes itself as "a follow up to [this patch]", so then it's a bit unclear which one "goes first". Or is the described problem simply not solved by either patch?

source/blender/depsgraph/intern/node/deg_node_component.h
171

This member function should be declared with override, so:

bool need_tag_cow_before_update() override \
173–174

Is there a specific reason why this is written as two separate if-statements, instead of simply &&-ing together the two conditions?

  • use 'override'
  • use single instead of nested if statements.
source/blender/depsgraph/intern/node/deg_node_component.h
171

Shouldn't this apply to the existing DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE below? Also BoneComponentNode 's init function.

This patch has a problem that properties being modified currently use ID_RECALC_GEOMETRY, this patch will prevent them from updating the copy-on-write data.

Does this mean that this patch requires D11377: Depsgraph: support flushing parameters without a full COW update to be applied first? Because that patch describes itself as "a follow up to [this patch]", so then it's a bit unclear which one "goes first". Or is the described problem simply not solved by either patch?

The intention is to apply D11377 before this patch (updated description).

Sergey was concerned that this patch could cause problems in cases RNA parameters used a ID_RECALC_GEOMETRY tag would not work.

As far as I can tell, this never happens at the moment, nevertheless the concern is valid.

I had an idea that might be worth considering.
Based on D11599, (which "solved" the problem by creating a GEOMETRY_NO_COW component), my idea is to create a component called GEOMETRY_SHARED and an ID_RECALC_GEOMETRY_SHARED flag.
The name "SHARED" indicates that only parameters shared on different evaluated ids have been modified.
And since they're shared, there's no need to COW.

The difference between the GEOMETRY component and the GEOMETRY_SHARED component is just that the former requires COW.

Did you test non-mesh objects in edit mode/

For the D11599, it does seem that there are few different directions being investigated. Not sure if they are mutually exclusive, or solve different aspects. Can you align the forces here?

D11599 was postponed in favor of this one.
They are not mutually exclusive.
That one will be edited according to the decision made here.
I will be satisfied whichever path is chosen.

Did you test non-mesh objects in edit mode/

Yes, although this patch doesn't impact other object types.

It would be good to check other object types, although duplicating most other kind of object data (armatures, curves ... etc), isn't as much of a bottleneck as it is for meshes.

For the D11599, it does seem that there are few different directions being investigated. Not sure if they are mutually exclusive, or solve different aspects. Can you align the forces here?

From checking this patch - it doesn't seem directly related to the change this makes.

Use 'virtual bool need_tag_cow_before_update() override' based on feedback to D11377.

Yes, although this patch doesn't impact other object types.

I don't see how this patch does not affect other object types: geometry is a generic component, and need_tag_cow_before_update doesn't do any checks either. What am I missing? Is the hypnotises that we never access object->data when in edit mode correct?
Surely, as you're saying, other object types work, which is great. I am trying to better understand what's going on.

P.S. To me the code seems fine, and does intuitive things. Just want to understand implications and be ready to possible consequences of the patch before it lands.

My mistake (I was jumping between this patch and D11377 which is only for meshes).

Yes, this has been tested with all other object types that support edit-mode (linked duplicates & multi-edit).

Changing Sybren to non-blocking, as he wouldn't review the patch is the near-future, and I do not see anything stopping for the patch.

This revision is now accepted and ready to land.Jun 24 2021, 9:18 AM