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:
- D11377: Depsgraph: support flushing parameters without a full COW update is meant to be applied first, while both patches can be applied independently, a design concern in this patch is addressed by D11377, although in practice this patch is functional on it's own.
- These changes where needed for this patch to function properly.
- Some tests in T88021: Edit-Mesh Performance Overview found this operation took about 40% of the overall time taken to update the mesh while transforming.
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.