Refresh shader node previews per updated nodes #110651

Open
opened 2023-07-31 14:16:23 +02:00 by Colin Marmond · 8 comments
Member

Overview

It would be very useful for the new preview system introduced in the shader editor #110353 to refresh only the previews of the node updated (modified or having a parent modified).

The main thing that is hard to define is the way the previews are invalidated and thus to know which preview needs to be re-rendered.


Proposed solution

Use some dirty state variables (node tagging)

The ideal solution would be to tag a node that has been modified. But this is not possible, because at the moment of removing the flag, we are not sure that all the previews of this node are rendered (actually they wont).
So we cannot use a single flag for that. I think it could be possible to use a dirty state is different places to compare the stored previews with the current tree to see if there are any nodes that needs to be re-rendered.
There is already I guess this king of implementation for in TimeStamp.h.
I think the following dirty states could be added:

in bNodeTreeRuntime in bNodeRuntime
• a dirty state for all nodes, being the sum of every node dirty state
• a dirty state for the node tree itself (referring to whole tree modifications)
• a dirty state for the node

The idea behind those dirty state is to avoid as much as possible the graph parses.
When a node is updated, its dirty state is incremented as well as its nodetree all-nodes dirty state (first one).
When checking if the previews need to be redrawn, we just have to check the nodetree all-nodes dirty state. If it differs from the cached state, then we have to parse the tree to determine the modified nodes.

If the whole nodetree is modified, then we just use the nodetree dirty state (second one) to determine whether a full re-render is needed or not.

Alternatives

Remove the outdated preview image

It would have the advantage of being really simple (design wise).
But the main problem is that we would have to kill the render(if happening) in order to remove the ImBuf from the RenderResult. It is not possible to kill a render in this situation because when the user will be dragging a slider, it will be extremely laggy.

Store (inside SpaceNode) a list of updated nodes

This is an interesting option, because it would have no implementation problems, but there would be too much complexity because of the various graph parses. This solution would also require a mutex for the list because this one would be accessed in two threads (main thread will add nodes to the list while the render thread will remove nodes once rendered).

## Overview It would be very useful for the new preview system introduced in the shader editor #110353 to refresh only the previews of the node updated (modified or having a parent modified). The main thing that is hard to define is the way the previews are invalidated and thus to know which preview needs to be re-rendered. --- ## Proposed solution ### Use some dirty state variables (node tagging) The ideal solution would be to tag a node that has been modified. But this is not possible, because at the moment of removing the flag, we are not sure that all the previews of this node are rendered (actually they wont). So we cannot use a single flag for that. I think it could be possible to use a dirty state is different places to compare the stored previews with the current tree to see if there are any nodes that needs to be re-rendered. There is already I guess this king of implementation for in `TimeStamp.h`. I think the following dirty states could be added: | in `bNodeTreeRuntime` | in `bNodeRuntime` | | - | - | | • a dirty state for all nodes, being the sum of every node dirty state <br> • a dirty state for the node tree itself (referring to whole tree modifications) | • a dirty state for the node | The idea behind those dirty state is to avoid as much as possible the graph parses. When a node is updated, its dirty state is incremented as well as its nodetree all-nodes dirty state (first one). When checking if the previews need to be redrawn, we just have to check the nodetree all-nodes dirty state. If it differs from the cached state, then we have to parse the tree to determine the modified nodes. If the whole nodetree is modified, then we just use the nodetree dirty state (second one) to determine whether a full re-render is needed or not. ## Alternatives ### Remove the outdated preview image It would have the advantage of being really simple (design wise). But the main problem is that we would have to kill the render(if happening) in order to remove the `ImBuf` from the `RenderResult`. It is not possible to kill a render in this situation because when the user will be dragging a slider, it will be extremely laggy. ### Store (inside SpaceNode) a list of updated nodes This is an interesting option, because it would have no implementation problems, but there would be too much complexity because of the various graph parses. This solution would also require a mutex for the list because this one would be accessed in two threads (main thread will add nodes to the list while the render thread will remove nodes once rendered).
Colin Marmond added the
Type
Design
label 2023-07-31 14:16:23 +02:00
Iliya Katushenock added this to the Nodes & Physics project 2023-07-31 14:18:27 +02:00
Iliya Katushenock added the
Module
Render & Cycles
label 2023-07-31 14:18:32 +02:00
Author
Member

@brecht @HooglyBoogly Could you take a look ?
After discussing, it wasn't clear what could be a good solution, so I gathered what I explored in order to discuss about it.

If none of the proposed solution seems good, I am very curious to know if you have something else to propose.

@brecht @HooglyBoogly Could you take a look ? After discussing, it wasn't clear what could be a good solution, so I gathered what I explored in order to discuss about it. If none of the proposed solution seems good, I am very curious to know if you have something else to propose.

To me the proposed solution seems good.

With the previews being re-rendered asynchronously and on demand, we have to assume there can be an arbitrary number of node graph edits between the change and actually updating the preview. Additionally the intent is to store the previews on the space/editor instead of the material/nodetree.

I think to decouple those cleanly some counter on nodes and node trees seems like the simplest solution. With alternative solutions the synchronization just seems much more complicated.

To me the proposed solution seems good. With the previews being re-rendered asynchronously and on demand, we have to assume there can be an arbitrary number of node graph edits between the change and actually updating the preview. Additionally the intent is to store the previews on the space/editor instead of the material/nodetree. I think to decouple those cleanly some counter on nodes and node trees seems like the simplest solution. With alternative solutions the synchronization just seems much more complicated.

It seems to be logical to first study the implementation of main updating node trees in their current form and build from there.

It seems to be logical to first study the implementation of main updating node trees in their current form and build from there.

We did look at that already.

We did look at that already.

Also, it would be good to point out things that are not so clear to those who are not related to shaders:
Who owns the preview. Material? In that case, updating the preview is part of the material evaluation?
If it's only a matter of owning the images in the process of computing new images, then couldn't it have been shared storage?
Logging geometry nodes looks like this:

  1. The modifier owns the log.
  2. The log owns all data about nodes eval time, attribute names, ... .
  3. Updating a modifier only overwrites it. Doesn't delete log until start to compute. So the log is always there.
    In this case, the deletion of images would only occur at the end of the material calculation, which would also include the calculation of previews?
Also, it would be good to point out things that are not so clear to those who are not related to shaders: Who owns the preview. Material? In that case, updating the preview is part of the material evaluation? If it's only a matter of owning the images in the process of computing new images, then couldn't it have been shared storage? Logging geometry nodes looks like this: 1. The modifier owns the log. 2. The log owns all data about nodes eval time, attribute names, ... . 3. Updating a modifier only overwrites it. Doesn't delete log until start to compute. So the log is always there. In this case, the deletion of images would only occur at the end of the material calculation, which would also include the calculation of previews?

The node editor owns the preview.

It can not work like geometry nodes, and it can not be done as part of depsgraph evaluation. It has to be a non-blocking job since it's too slow, and it has to be done on demand and only compute when the previews become or are visible to avoid doing unnecessary work.

The node editor owns the preview. It can not work like geometry nodes, and it can not be done as part of depsgraph evaluation. It has to be a non-blocking job since it's too slow, and it has to be done on demand and only compute when the previews become or are visible to avoid doing unnecessary work.

Still looks like a task for a dependency graph. Previews should not be very different from the subdivision, on editors with different settings and if there is a shared ownership.

Still looks like a task for a dependency graph. Previews should not be very different from the subdivision, on editors with different settings and if there is a shared ownership.

I think they are very different.

  • Rendering a preview itself involves constructing and evaluating a dependency graph, with a small preview scene.
  • Previews can be rendered for datablocks that are not used in the current scene, so not in the dependency graph.
  • We already use this mechanism for icon previews, material properties editor previews, no need to be inconsistent.
  • Making current depsgraph evaluation asynchronous would be a huge design change.
I think they are very different. * Rendering a preview itself involves constructing and evaluating a dependency graph, with a small preview scene. * Previews can be rendered for datablocks that are not used in the current scene, so not in the dependency graph. * We already use this mechanism for icon previews, material properties editor previews, no need to be inconsistent. * Making current depsgraph evaluation asynchronous would be a huge design change.
Sign in to join this conversation.
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
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
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
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 Assignees
3 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#110651
No description provided.