Geometry nodes impacting performance even when GN modifier fully disabled #88332

Closed
opened 2021-05-16 21:23:24 +02:00 by Nathan Vasil · 19 comments

System Information
Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: GeForce GTX 1070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 456.71

Blender Version
Broken: version: 2.93.0 Beta, branch: master, commit date: 2021-05-14 16:16, hash: d4a36c7ad5

Short description of error

Even when disabled, geometry nodes are being fully evaluated, leading to performance problems.

Exact steps for others to reproduce the error

GNdisabled.blend

Attached file has a heavily subdivided cube with a geometry node modifier that references the camera, and a camera that is locked to the 3D viewport. The GN modifier is disabled. Move the view/camera and notice the lag. Delete the modifier, and the lag disappears.

This can be improved by applying the subdivision (the GN modifier is triggering the subdivision modifier to reevaluate every frame), but not eliminated-- the GN modifier isn't just triggering update of earlier modifiers, but is being evaluated every frame even when fully disabled.

Note that performance is okay when the entire object (or its collection) is disabled in viewports.

**System Information** Operating system: Windows-10-10.0.18362-SP0 64 Bits Graphics card: GeForce GTX 1070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 456.71 **Blender Version** Broken: version: 2.93.0 Beta, branch: master, commit date: 2021-05-14 16:16, hash: `d4a36c7ad5` **Short description of error** Even when disabled, geometry nodes are being fully evaluated, leading to performance problems. **Exact steps for others to reproduce the error** [GNdisabled.blend](https://archive.blender.org/developer/F10113330/GNdisabled.blend) Attached file has a heavily subdivided cube with a geometry node modifier that references the camera, and a camera that is locked to the 3D viewport. The GN modifier is disabled. Move the view/camera and notice the lag. Delete the modifier, and the lag disappears. This can be improved by applying the subdivision (the GN modifier is triggering the subdivision modifier to reevaluate every frame), but not eliminated-- the GN modifier isn't just triggering update of earlier modifiers, but is being evaluated every frame even when fully disabled. Note that performance is okay when the entire object (or its collection) is disabled in viewports.
Author

Added subscriber: @vasiln

Added subscriber: @vasiln
Member

Added subscriber: @lichtwerk

Added subscriber: @lichtwerk
Member

This looks like #73199 (Editing an object that is referenced in a disabled modifier (of another object) forces the other modifiers on the same stack to update) and has been discussed for other modifiers in said report.

I assume it is safe to merge these reports, since underlying roots seem to be the same.

This looks like #73199 (Editing an object that is referenced in a disabled modifier (of another object) forces the other modifiers on the same stack to update) and has been discussed for other modifiers in said report. I assume it is safe to merge these reports, since underlying roots seem to be the same.
Member

Closed as duplicate of #73199

Closed as duplicate of #73199
Author

@lichtwerk No, that's incidental to the main issue here. Performance is impacted with only a disabled geometry nodes modifier, no other modifiers. From original report: "This can be improved by applying the subdivision (the GN modifier is triggering the subdivision modifier to reevaluate every frame), but not eliminated."

Edit: I made a file to demo this, but it's really too big to upload because of the vertex count needed to clearly see the lag. You can pump up the subdiv iterations to 9 and then apply the modifier in the file given to see it in action. Just revisited to make sure it wasn't an issue with undo levels or anything, so saved, quit, reloaded-- still an issue.

@lichtwerk No, that's incidental to the main issue here. Performance is impacted with only a disabled geometry nodes modifier, no other modifiers. From original report: "This can be improved by applying the subdivision (the GN modifier is triggering the subdivision modifier to reevaluate every frame), but **not eliminated**." Edit: I made a file to demo this, but it's really too big to upload because of the vertex count needed to clearly see the lag. You can pump up the subdiv iterations to 9 and then apply the modifier in the file given to see it in action. Just revisited to make sure it wasn't an issue with undo levels or anything, so saved, quit, reloaded-- still an issue.
Member

Changed status from 'Duplicate' to: 'Needs Triage'

Changed status from 'Duplicate' to: 'Needs Triage'
Member

Added subscriber: @lone_noel

Added subscriber: @lone_noel
Member

Changed status from 'Needs Triage' to: 'Needs Developer To Reproduce'

Changed status from 'Needs Triage' to: 'Needs Developer To Reproduce'
Member

I can confirm the issue is present in 2.93 as well as in 3.2 and was able to simplify the file a lot (Note that you'll have to apply the subdivision modifier yourself, because I wanted to keep the file size small. The huge number of vertices is needed to create noticeable lag when moving the empty.)
#88332.png
#88332.blend


The undesired behavior is that the shown node tree seems to be reevaluated when moving the Empty despite

  1. the modifier being completely disabled and
  2. the Object Info node not actually being part of the evaluated tree.

I also tried to investigate a bit, but I'm really not familiar with this area so I might be completely off base:

Point 1. seems to me like it is similar to what is described by Bastien in #73199#876117 just that in this case it's not triggered by another modifier but by the Object Info node?

Regarding Point 2. I see that in process_nodes_for_depsgraph we're iterating over the whole node tree checking for things like object sockets to build the depsgraph relation.
I've noticed that we're not checking, whether the node the socket belongs to is actually part of the connected node tree.
Not sure if that's something that can be done? But I saw that c9b578eac8 added an exception for the object's own transform, when the Object Info nodes are only in "Original" mode, so I was wondering if there was a way to exclude dependencies from nodes that aren't actually part of the relevant node tree.

Another thing I noticed is, that the lag is still happening even after deleting the Object Info node and persists until the geometry nodes modifier is removed. Not sure if there's a missing update to the dependencies?

Setting to Needs Information from Developers as I don't know if there is something that can be done about any of this.

I can confirm the issue is present in 2.93 as well as in 3.2 and was able to simplify the file a lot (Note that you'll have to apply the subdivision modifier yourself, because I wanted to keep the file size small. The huge number of vertices is needed to create noticeable lag when moving the empty.) ![#88332.png](https://archive.blender.org/developer/F12862563/T88332.png) [#88332.blend](https://archive.blender.org/developer/F12862590/T88332.blend) --- The undesired behavior is that the shown node tree seems to be reevaluated when moving the Empty despite 1. the modifier being completely disabled and 2. the Object Info node not actually being part of the evaluated tree. --- I also tried to investigate a bit, but I'm really not familiar with this area so I might be completely off base: Point 1. seems to me like it is similar to what is described by Bastien in #73199#876117 just that in this case it's not triggered by another modifier but by the Object Info node? Regarding Point 2. I see that in `process_nodes_for_depsgraph` we're iterating over the whole node tree checking for things like object sockets to build the depsgraph relation. I've noticed that we're not checking, whether the node the socket belongs to is actually part of the connected node tree. Not sure if that's something that can be done? But I saw that c9b578eac8 added an exception for the object's own transform, when the Object Info nodes are only in "Original" mode, so I was wondering if there was a way to exclude dependencies from nodes that aren't actually part of the relevant node tree. Another thing I noticed is, that the lag is still happening *even after deleting the Object Info node* and persists until the geometry nodes modifier is removed. Not sure if there's a missing update to the dependencies? Setting to *Needs Information from Developers* as I don't know if there is something that can be done about any of this.
Member

Added subscriber: @HooglyBoogly

Added subscriber: @HooglyBoogly
Member

Here are a few thoughts about this:

  1. We don't have a cheap way of detecting whether the node is connected to an output currently. I'm not sure how we would implement that, but possibly by creating some cached flags in node_tree_update.cc. Generally I don't like adding runtime information to DNA structs though, so I'm not totally sure.
  • With things like switch nodes, we don't even have any way to detect whether a node will actually be used without evaluating the tree. So this sort of static "is node used" detection only gets you so far. Maybe that's expected, it's just something to note.
  1. Removing the object info node probably doesn't update depsgraph relations (The changes to rna_nodetree.c in c9b578eac8). I'm not sure if there's a cost to updating relations. On a large scene I expect it could quite slow?
Here are a few thoughts about this: 1. We don't have a cheap way of detecting whether the node is connected to an output currently. I'm not sure how we would implement that, but possibly by creating some cached flags in `node_tree_update.cc`. Generally I don't like adding runtime information to DNA structs though, so I'm not totally sure. - With things like switch nodes, we don't even have *any* way to detect whether a node will actually be used without evaluating the tree. So this sort of static "is node used" detection only gets you so far. Maybe that's expected, it's just something to note. 2. Removing the object info node probably doesn't update depsgraph relations (The changes to `rna_nodetree.c` in c9b578eac8). I'm not sure if there's a cost to updating relations. On a large scene I expect it could quite slow?
Author

It seems to me that the fact that it remains dependent on the camera with disconnected noodles is a separate issue from the fact that it evaluates even when disabled.

Updating dependencies on noodle changes would be desirable, but it's certainly understandable that it remains dependent; erring on the side of dependency is currently pretty typical Blender behavior, and experienced users won't have a hard time figuring out that GN dependencies don't care about noodles.

Failing to update dependencies on deletion of nodes (rather than disconnection of noodles) is less understandable-- but again, probably best considered a different issue. Absent any explicit operation for users to force a recalculation of dependencies, users will be forced to get creative, to figure out what operations will trigger a full dependency update as a side effect. (Similar situations occur with physics cache. If the philosophy is, "Blender is smart enough about this that people don't have to worry about it, so we don't need tools for users to handle it manually," then Blender needs to actually be smart enough.)

Recalculation of dependencies on unanimatable, discrete user input is routine (every time the user designates a target for a constraint or modifier, for example.) In my experience, even in large, complex scenes it is unnoticeable. It is far faster to recalculate dependencies one time, immediately following user input, than it is to evaluate more objects than you need to, over and over again. In both simple and complex scenes, the time spent evaluating objects dwarfs any time spent calculating dependencies.

I apologize if I'm speaking out of place; I'm not really sure if these comments are welcome or if you'd rather simple users kept their noses out of it.

It seems to me that the fact that it remains dependent on the camera with disconnected noodles is a separate issue from the fact that it evaluates even when disabled. Updating dependencies on noodle changes would be desirable, but it's certainly understandable that it remains dependent; erring on the side of dependency is currently pretty typical Blender behavior, and experienced users won't have a hard time figuring out that GN dependencies don't care about noodles. Failing to update dependencies on deletion of nodes (rather than disconnection of noodles) is less understandable-- but again, probably best considered a different issue. Absent any explicit operation for users to force a recalculation of dependencies, users will be forced to get creative, to figure out what operations *will* trigger a full dependency update as a side effect. (Similar situations occur with physics cache. If the philosophy is, "Blender is smart enough about this that people don't have to worry about it, so we don't need tools for users to handle it manually," then Blender needs to actually be smart enough.) Recalculation of dependencies on unanimatable, discrete user input is routine (every time the user designates a target for a constraint or modifier, for example.) In my experience, even in large, complex scenes it is unnoticeable. It is far faster to recalculate dependencies one time, immediately following user input, than it is to evaluate more objects than you need to, over and over again. In both simple and complex scenes, the time spent evaluating objects dwarfs any time spent calculating dependencies. I apologize if I'm speaking out of place; I'm not really sure if these comments are welcome or if you'd rather simple users kept their noses out of it.
Member

Great points, thanks for the detailed thoughts!

I'm not aware of a design for this sort of thing. I guess the trade-off is "always keep the dependencies current" vs. "don't update dependencies too much". Your anecdotal evidence points towards the former, but like I mentioned above, getting the information to know whether to do a dependency update or not isn't trivial in lots of cases.

One specific thing I'd like to know: Is a modifier adding its dependencies when it's disabled considered a bug? We could pretty easily make the "show_viewport" property update relations, and then only call updateDepsgraph if the modifier isn't disabled.

Great points, thanks for the detailed thoughts! I'm not aware of a design for this sort of thing. I guess the trade-off is "always keep the dependencies current" vs. "don't update dependencies too much". Your anecdotal evidence points towards the former, but like I mentioned above, getting the information to know whether to do a dependency update or not isn't trivial in lots of cases. One specific thing I'd like to know: Is a modifier adding its dependencies when it's disabled considered a bug? We could pretty easily make the "show_viewport" property update relations, and then only call `updateDepsgraph` if the modifier isn't disabled.
Author

In #88332#1308410, @HooglyBoogly wrote:
One specific thing I'd like to know: Is a modifier adding its dependencies when it's disabled considered a bug? We could pretty easily make the "show_viewport" property update relations, and then only call updateDepsgraph if the modifier isn't disabled.

It is considered a bug, but it's also the current way that things work; that's what #73199, referenced above, is. I think it's arguable about bug/new feature categorization for that particular issue, but that report has been seen by a lot of developers and is still around. Even if it were to be considered a feature, it would be a high priority feature.

> In #88332#1308410, @HooglyBoogly wrote: > One specific thing I'd like to know: Is a modifier adding its dependencies when it's disabled considered a bug? We could pretty easily make the "show_viewport" property update relations, and then only call `updateDepsgraph` if the modifier isn't disabled. It is considered a bug, but it's also the current way that things work; that's what #73199, referenced above, is. I think it's arguable about bug/new feature categorization for that particular issue, but that report has been seen by a lot of developers and is still around. Even if it were to be considered a feature, it would be a high priority feature.
Member

Okay, I think I'll merge this into #73199, since they're basically the same issue. The thing about nodes that are muted or not used is another thing-- but reading Sergey's comments in that report and patch, I don't think that's likely to be addressed soon honestly.

Okay, I think I'll merge this into #73199, since they're basically the same issue. The thing about nodes that are muted or not used is another thing-- but reading Sergey's comments in that report and patch, I don't think that's likely to be addressed soon honestly.
Member

Closed as duplicate of #73199

Closed as duplicate of #73199
Author

I don't think that this is the same issue. There are two things that are happening here:

  1. The object is being reevaluated based on a change of something it's dependent upon. In this example, whenever we move the camera, we're reevaluating our GN object. Regardless of whether the modifier is enabled or disabled. This is the same #73199.

  2. As part of its reevaluation, the object is evaluating its GN modifier, regardless of whether that modifier is enabled or disabled. This is not the same as #73199.

In #73199, disabling both modifiers in the example file means lagless editing. We're still re-evaluating all of our objects, but we're not performing the disabled booleans. In that example file, we still have the dependencies with disabled modifiers, and we are reevaluating the object, but we're not evaluating disabled booleans. It is only the single remaining boolean that is responsible for the lag. The issue there is that the dependencies mean that the second, enabled boolean is still evaluated, even though the object is no longer dependent on the cube being edited. When we disable both booleans, speed is fast, not because we've changed any of our dependencies, but because we're no longer doing anything expensive-- evaluating the unmodified cubes + sphere is cheap.

That's why I said above that I consider recalculation of dependencies to be a separate issue from #88332. Recalculation of dependencies is nice. Certain aspects of it are being dealt with in #73199. But regardless of dependencies, disabled modifiers should not be evaluated, and here, they're being evaluated.

However, it's entirely possible that I'm misunderstanding what's happening here, or that I'm misunderstanding what I'm reading in #73199.

I don't think that this is the same issue. There are two things that are happening here: 1) The object is being reevaluated based on a change of something it's dependent upon. In this example, whenever we move the camera, we're reevaluating our GN object. Regardless of whether the modifier is enabled or disabled. This is the same #73199. 2) As part of its reevaluation, the object is evaluating its GN modifier, regardless of whether that modifier is enabled or disabled. This is not the same as #73199. In #73199, disabling both modifiers in the example file means lagless editing. We're still re-evaluating all of our objects, but we're not performing the disabled booleans. In that example file, we still have the dependencies with disabled modifiers, and we are reevaluating the object, but we're not evaluating disabled booleans. It is only the single remaining boolean that is responsible for the lag. The issue there is that the dependencies mean that the second, enabled boolean is still evaluated, even though the object is no longer dependent on the cube being edited. When we disable both booleans, speed is fast, not because we've changed any of our dependencies, but because we're no longer doing anything expensive-- evaluating the unmodified cubes + sphere is cheap. That's why I said above that I consider recalculation of dependencies to be a separate issue from #88332. Recalculation of dependencies is nice. Certain aspects of it are being dealt with in #73199. But regardless of dependencies, disabled modifiers should not be evaluated, and here, they're being evaluated. However, it's entirely possible that I'm misunderstanding what's happening here, or that I'm misunderstanding what I'm reading in #73199.
Author

Actually, I'm wrong. I was mistaken and didn't test this through properly. It is appropriate to merge this, or, considering the intent of the original report and the conversation, to delete it. I'll leave the above comment as a record of my shame....

  1. above is not happening. It is not evaluating the disabled geometry nodes. I tested this by making the GN do something really really slow (like subdivision surface *16). Any slowdown is simply from the density of the mesh.
Actually, I'm wrong. I was mistaken and didn't test this through properly. It is appropriate to merge this, or, considering the intent of the original report and the conversation, to delete it. I'll leave the above comment as a record of my shame.... 2) above is not happening. It is not evaluating the disabled geometry nodes. I tested this by making the GN do something really really slow (like subdivision surface *16). Any slowdown is simply from the density of the mesh.

This issue was referenced by 734c6a4405

This issue was referenced by 734c6a4405f21078270e71a4c2f0e98e74173ad7
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
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
EEVEE & Viewport
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
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
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
EEVEE & Viewport
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
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
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
5 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#88332
No description provided.