Confusing DepsgraphUpdate fields #59090

Closed
opened 2018-12-09 22:28:34 +01:00 by Paul Melis · 12 comments

System Information
Operating system: Arch Linux
Graphics card: GTX 970

Blender Version
Broken:
blender-2.80-e79bb957fc3-linux-glibc224-x86_64

The description of DepsgraphUpdate (at https://docs.blender.org/api/blender2.8/bpy.types.DepsgraphUpdate.html#bpy.types.DepsgraphUpdate) reads

is_dirty_geometry
Object geometry is not updated

is_dirty_transform
Object transformation is not updated

It seems contradictory when something called is_xxx_dirty being True actually means "not updated". However, I tested a bit what values are actually returned in a custom renderengine script, relevant excerpt:

class CustomRenderEngine(bpy.types.RenderEngine):

    ...

    def view_update(self, context):
        """Update on data changes for viewport render"" 
        depsgraph = context.depsgraph
        print('%d object instances' % len(depsgraph.object_instances))
        print('%d updates:' % len(depsgraph.updates))
        for update in depsgraph.updates:
            print(('ID %s, geom %s, xform %s' % (update.id, update.is_dirty_geometry, update.is_dirty_transform)))

I see the following behaviour for the is_dirty_geometry and is_dirty_transform fields:

  • Changing the object selection:
    • Scene instance: both fields True
  • Entering edit mode on a selected mesh:
    • Object instance: geom false, xform true
    • Mesh instance: geom false, xform false
  • Moving vertex in the mesh:
    • Object instance: geom false, xform true
    • Mesh instance: geom false, xform false
  • Moving camera in the scene:
    • Camera instance: geom true, xform false

So it appears the fields really have the negated meaning, i.e. they are False when something was updated. Together with their name this leads to really confusing usage and behaviour. Wouldn't it be better to change their values to actually match their name? I.e. set them to True when something was updated.

**System Information** Operating system: Arch Linux Graphics card: GTX 970 **Blender Version** Broken: blender-2.80-e79bb957fc3-linux-glibc224-x86_64 The description of DepsgraphUpdate (at https://docs.blender.org/api/blender2.8/bpy.types.DepsgraphUpdate.html#bpy.types.DepsgraphUpdate) reads ``` is_dirty_geometry Object geometry is not updated is_dirty_transform Object transformation is not updated ``` It seems contradictory when something called `is_xxx_dirty` being True actually means "not updated". However, I tested a bit what values are actually returned in a custom renderengine script, relevant excerpt: ``` class CustomRenderEngine(bpy.types.RenderEngine): ... def view_update(self, context): """Update on data changes for viewport render"" depsgraph = context.depsgraph print('%d object instances' % len(depsgraph.object_instances)) print('%d updates:' % len(depsgraph.updates)) for update in depsgraph.updates: print(('ID %s, geom %s, xform %s' % (update.id, update.is_dirty_geometry, update.is_dirty_transform))) ``` I see the following behaviour for the `is_dirty_geometry` and `is_dirty_transform` fields: - Changing the object selection: - Scene instance: both fields True - Entering edit mode on a selected mesh: - Object instance: geom false, xform true - Mesh instance: geom false, xform false - Moving vertex in the mesh: - Object instance: geom false, xform true - Mesh instance: geom false, xform false - Moving camera in the scene: - Camera instance: geom true, xform false So it appears the fields really have the negated meaning, i.e. they are False when something was updated. Together with their name this leads to really confusing usage and behaviour. Wouldn't it be better to change their values to actually match their name? I.e. set them to True when something was updated.
Author

Added subscriber: @PaulMelis

Added subscriber: @PaulMelis
Author

Hmm, more weird behaviour:

  • Deleting all objects in the scene:
    • Scene instance: geom false, xform false
    • Collection instance: geom true, xform true

Why is the collection flagged differently from the scene? I would expect both to have similar values (the scene because the object selection changed, the collection because it was emptied). Plus changing the object selection (shown above) is flagged as 2x True, but deleting objects as 2x False?

  • Adding a cube mesh:
    • Scene instance: geom false, xform false
    • Object (cube) instance: geom false, xform false
    • Mesh (cube) instance: geom false, xform false
    • Collection instance: geom true, xform true

Similar values as in deleting all objects, with collection values seemingly inconsistent with the others.

But perhaps there are specific values being passed depending on the instance reported and the operation done that isn't documented?

Hmm, more weird behaviour: - Deleting all objects in the scene: - Scene instance: geom false, xform false - Collection instance: geom true, xform true Why is the collection flagged differently from the scene? I would expect both to have similar values (the scene because the object selection changed, the collection because it was emptied). Plus changing the object selection (shown above) is flagged as 2x True, but deleting objects as 2x False? - Adding a cube mesh: - Scene instance: geom false, xform false - Object (cube) instance: geom false, xform false - Mesh (cube) instance: geom false, xform false - Collection instance: geom true, xform true Similar values as in deleting all objects, with collection values seemingly inconsistent with the others. But perhaps there are specific values being passed depending on the instance reported and the operation done that isn't documented?

Added subscriber: @brhumphe

Added subscriber: @brhumphe

It seems contradictory when something called is_xxx_dirty being True actually means "not updated".

This is the conventional terminology in computing. Read "is dirty" as meaning "needs cleanup" or in this case, "needs updated".

I'm speculating here, but my guess is that some operations immediately trigger an update to the dependency graph. If the is_xxx_dirty flag is False after an operation, the operation probably triggered an update to happen before you read the value.

> It seems contradictory when something called is_xxx_dirty being True actually means "not updated". This is the conventional terminology in computing. Read "is dirty" as meaning "needs cleanup" or in this case, "needs updated". I'm speculating here, but my guess is that some operations immediately trigger an update to the dependency graph. If the `is_xxx_dirty` flag is `False` after an operation, the operation probably triggered an update to happen before you read the value.
Author

This is the conventional terminology in computing. Read "is dirty" as meaning "needs cleanup" or in this case, "needs updated".

Yes, I'm familiar with the convention, that's why the current description doesn't make any sense. And the description is also ambiguous, as "Object geometry is not updated" can be interpreted as not being updated (yet) on the receiving end (i.e. render engine) or not updated on the sending side (Blender depgraph). The latter would be really confusing, so I would expect it to actually mean "object geometry was updated on the depsgraph side". So that the receiver (render engine) knows it needs to update its own data for that object when a dirty flag is set to True.

I'm speculating here, but my guess is that some operations immediately trigger an update to the dependency graph. If the is_xxx_dirty flag is False after an operation, the operation probably triggered an update to happen before you read the value.

But the depsgraph is fully managed by Blender and the render engine can only derive its data from it (and not influence it). So when or how the updates are being done is of no interest to the render engine script, the only thing that matters is being able to unambiguously determine which objects were updated. Which is what the dirty flags are hopefully meant for, as they otherwise provide very little useful information for a render engine script.

> This is the conventional terminology in computing. Read "is dirty" as meaning "needs cleanup" or in this case, "needs updated". Yes, I'm familiar with the convention, that's why the current description doesn't make any sense. And the description is also ambiguous, as "Object geometry is not updated" can be interpreted as not being updated (yet) on the receiving end (i.e. render engine) or not updated on the sending side (Blender depgraph). The latter would be really confusing, so I would expect it to actually mean "object geometry was updated on the depsgraph side". So that the receiver (render engine) knows it needs to update its own data for that object when a dirty flag is set to True. > I'm speculating here, but my guess is that some operations immediately trigger an update to the dependency graph. If the is_xxx_dirty flag is False after an operation, the operation probably triggered an update to happen before you read the value. But the depsgraph is fully managed by Blender and the render engine can only derive its data from it (and not influence it). So when or how the updates are being done is of no interest to the render engine script, the only thing that matters is being able to unambiguously determine which objects were updated. Which is what the dirty flags are hopefully meant for, as they otherwise provide very little useful information for a render engine script.

Added subscribers: @ideasman42, @brecht

Added subscribers: @ideasman42, @brecht
Campbell Barton was assigned by Brecht Van Lommel 2018-12-10 00:26:32 +01:00

@ideasman42, please revert blender/blender@45fdf41be8 and blender/blender@6d38d82437.

We use the name is_dirty to refer to something having unsaved changes, and these flags are not about that. Further it's not clear to me how "is dirty" describes "not updated".

@ideasman42, please revert blender/blender@45fdf41be8 and blender/blender@6d38d82437. We use the name `is_dirty` to refer to something having unsaved changes, and these flags are not about that. Further it's not clear to me how "is dirty" describes "not updated".

@brecht as far as I can see dirty applies here: internally ID_RECALC_TRANSFORM / ID_RECALC_GEOMETRY means this data needs to be recalculated, and that the current state isn't ensured to be up to date.

We use naming for data/cache not being updated quite a lot elsewhere, unrelated to saving files, eg: BOUNDBOX_DIRTY, GPU_UBO_FLAG_DIRTY, BKE_MESH_BATCH_DIRTY_ALL, DM_DIRTY_NORMALS, BM_SPACEARR_DIRTY, mesh->runtime.cd_dirty_vert.

If we used C flag naming we'd rename dirty to recalculate without negating it.

Is there a semantic difference in this case?

@brecht as far as I can see dirty applies here: internally `ID_RECALC_TRANSFORM` / `ID_RECALC_GEOMETRY` means this data needs to be recalculated, and that the current state isn't ensured to be up to date. We use naming for data/cache not being updated quite a lot elsewhere, unrelated to saving files, eg: `BOUNDBOX_DIRTY`, `GPU_UBO_FLAG_DIRTY`, `BKE_MESH_BATCH_DIRTY_ALL`, `DM_DIRTY_NORMALS`, `BM_SPACEARR_DIRTY`, `mesh->runtime.cd_dirty_vert`. If we used C flag naming we'd rename `dirty` to `recalculate` without negating it. Is there a semantic difference in this case?
Author

Just chiming in here as the OP: renaming is_dirty_xxx to recalculate_xxx without negating the value would seem to just as confusing to me (e.g. moving a camera would trigger with recalculate_geom set to True). But maybe I'm misunderstanding what exactly the flags are supposed to signal to downstream users of depsgraph updates (e.g. a render engine script). I originally expected the flags to indicate for which objects the local (downstream) copy of the scene needs to be updated to match the current depsgraph. But it seems that that is a secondary usage, as the flags actually specify which parts of the depsgraph itself need updating. Which is surprising, because what if the downstream script does not handle the updated depsgraph part and therefore doesn't take any action on them to update?

Just chiming in here as the OP: renaming `is_dirty_xxx` to `recalculate_xxx` without negating the value would seem to just as confusing to me (e.g. moving a camera would trigger with `recalculate_geom` set to True). But maybe I'm misunderstanding what exactly the flags are supposed to signal to downstream users of depsgraph updates (e.g. a render engine script). I originally expected the flags to indicate for which objects the local (downstream) copy of the scene needs to be updated to match the current depsgraph. But it seems that that is a secondary usage, as the flags actually specify which parts of the depsgraph itself need updating. Which is surprising, because what if the downstream script does not handle the updated depsgraph part and therefore doesn't take any action on them to update?

@ideasman42, there is a semantic difference. In those cases "dirty" means data is out of date and needs to be refreshed (or saved) in some way. With this API we are merely informing the script that some data has changed, if the script then needs to refresh something in response to that is another matter. In depsgraph_update_post and RenderEngine.view_update the data has already been refreshed on the Blender side, so is also not dirty anymore.

@ideasman42, there is a semantic difference. In those cases "dirty" means data is out of date and needs to be refreshed (or saved) in some way. With this API we are merely informing the script that some data has changed, if the script then needs to refresh something in response to that is another matter. In `depsgraph_update_post` and `RenderEngine.view_update` the data has already been refreshed on the Blender side, so is also not dirty anymore.

Changed status from 'Open' to: 'Resolved'

Changed status from 'Open' to: 'Resolved'

Makes sense then, added note comments in RNA and renamed back (use 'is_' prefix since this is a read-only boolean. blender/blender@5b6cb2de9a)

Makes sense then, added note comments in RNA and renamed back (use 'is_' prefix since this is a read-only boolean. blender/blender@5b6cb2de9a)
Sign in to join this conversation.
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender-addons#59090
No description provided.