Geometry Nodes: deduplicate code to deal with dynamic socket amounts #113114

Merged
Jacques Lucke merged 56 commits from JacquesLucke/blender:simplify-item-array-handling into main 2023-10-04 11:03:01 +02:00
Member

The goal of this refactor is to reduce the amount of boilerplate code that is necessary to have a dynamic number of sockets on nodes. This is achieved by making the code more reusable. Currently, only the simulation and repeat zone nodes make use of this. However, even with just those two, the amount of code is reduced already. The benefit of this refactor will become even more significant as more nodes support a dynamic number of sockets. For example, the bake node and for-each zone will also benefit from this.

We could probably make some of the utility functions non-templates using type erasure. This could reduce the compilation overhead when the number of nodes with item arrays increases. The main reason for why everything is templated now is that it made this refactor easier. Without this patch, all the code was essentially "manually templated". So the implementations look still similar to before now, just that concrete types are replaced with template parameters.

No user-visible changes are expected.

The goal of this refactor is to reduce the amount of boilerplate code that is necessary to have a dynamic number of sockets on nodes. This is achieved by making the code more reusable. Currently, only the simulation and repeat zone nodes make use of this. However, even with just those two, the amount of code is reduced already. The benefit of this refactor will become even more significant as more nodes support a dynamic number of sockets. For example, the bake node and for-each zone will also benefit from this. We could probably make some of the utility functions non-templates using type erasure. This could reduce the compilation overhead when the number of nodes with item arrays increases. The main reason for why everything is templated now is that it made this refactor easier. Without this patch, all the code was essentially "manually templated". So the implementations look still similar to before now, just that concrete types are replaced with template parameters. No user-visible changes are expected.
Jacques Lucke added 29 commits 2023-10-01 14:47:39 +02:00
Jacques Lucke added 1 commit 2023-10-01 14:48:18 +02:00
Jacques Lucke added 7 commits 2023-10-01 15:51:53 +02:00
Jacques Lucke added 3 commits 2023-10-01 16:26:19 +02:00
Jacques Lucke requested review from Lukas Tönne 2023-10-01 16:54:18 +02:00
Jacques Lucke requested review from Hans Goudey 2023-10-01 16:54:19 +02:00
Jacques Lucke changed title from WIP: Geometry Nodes: deduplicate item arrays code to WIP: Geometry Nodes: deduplicate code to deal with dynamic socket amounts 2023-10-01 16:54:43 +02:00
Jacques Lucke changed title from WIP: Geometry Nodes: deduplicate code to deal with dynamic socket amounts to Geometry Nodes: deduplicate code to deal with dynamic socket amounts 2023-10-01 22:51:59 +02:00
Jacques Lucke added 1 commit 2023-10-01 22:57:56 +02:00
Jacques Lucke added 1 commit 2023-10-01 23:28:04 +02:00
Jacques Lucke added 1 commit 2023-10-01 23:45:23 +02:00
buildbot/vexp-code-patch-coordinator Build done. Details
1bddd378cf
remove more rna redundancy
Author
Member

@blender-bot build

@blender-bot build
Jacques Lucke added 2 commits 2023-10-02 12:20:12 +02:00
Jacques Lucke added 5 commits 2023-10-02 13:10:17 +02:00
Hans Goudey reviewed 2023-10-02 13:47:45 +02:00
Hans Goudey left a comment
Member

I guess my main comment is that it seems weird to have a "item array" abstraction that's specific to nodes. That confuses the design a bit IMO, since that concept is related to everything DNA/RNA, not just nodes. But then there are node-specific things mixed in right now.

It does seem like there's value in all of these abstractions/utilities, but maybe they could be organized a bit differently:

  1. DNA C Array wrapper thing (maybe this isn't the long term design, but it makes things easier now)
  2. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices
  3. Node utilities that use that code for the repeat and simulation zones

I guess my other larger comment is that it seems worth considering using the CPPType system to avoid the need for templates in lots of these cases.

I guess my main comment is that it seems weird to have a "item array" abstraction that's specific to nodes. That confuses the design a bit IMO, since that concept is related to everything DNA/RNA, not just nodes. But then there are node-specific things mixed in right now. It does seem like there's value in all of these abstractions/utilities, but maybe they could be organized a bit differently: 1. DNA C Array wrapper thing (maybe this isn't the long term design, but it makes things easier now) 2. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices 3. Node utilities that use that code for the repeat and simulation zones I guess my other larger comment is that it seems worth considering using the `CPPType` system to avoid the need for templates in lots of these cases.
Author
Member

I guess my main comment is that it seems weird to have a "item array" abstraction that's specific to nodes. That confuses the design a bit IMO, since that concept is related to everything DNA/RNA, not just nodes. But then there are node-specific things mixed in right now.

I agree. I think we should eventually split the abstraction up more in the future, but I don't think we can't really do that without testing that in a smaller scope first to figure out what works well and what doesn't. For now the abstraction solves the problem that we have. If our problem changes we can change the abstraction with it.

I guess my other larger comment is that it seems worth considering using the CPPType system to avoid the need for templates in lots of these cases.

Not sure if you read my patch description, but I mention that. The thing is that right now the patch is mostly just deduplicating code that exists which was essentially templated (manually instantiated) already. I could look into removing templates from some functions and using something like CPPType separately. One thing that holds me back with using CPPType or other C++ wrappers is that we currently treat our DNA structs in ways that aren't super compatible with C++ objects. E.g. we relocate them with memcpy a lot, but that's not really a concept that C++ has out of the box. Instead it uses move-semantics which we don't have for DNA structs and likely don't want to implement.

  1. DNA C Array wrapper thing (maybe this isn't the long term design, but it makes things easier now)
  2. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices
  3. Node utilities that use that code for the repeat and simulation zones

I did try a fair amount of different refactors already, including the DNA C array wrapper. What I have in this patch is by far the cleanest cleanup I could come up with so far. I think it also makes testing the other things you mention much easier to try.

> I guess my main comment is that it seems weird to have a "item array" abstraction that's specific to nodes. That confuses the design a bit IMO, since that concept is related to everything DNA/RNA, not just nodes. But then there are node-specific things mixed in right now. I agree. I think we should eventually split the abstraction up more in the future, but I don't think we can't really do that without testing that in a smaller scope first to figure out what works well and what doesn't. For now the abstraction solves the problem that we have. If our problem changes we can change the abstraction with it. > I guess my other larger comment is that it seems worth considering using the `CPPType` system to avoid the need for templates in lots of these cases. Not sure if you read my patch description, but I mention that. The thing is that right now the patch is mostly just deduplicating code that exists which was essentially templated (manually instantiated) already. I could look into removing templates from some functions and using something like `CPPType` separately. One thing that holds me back with using `CPPType` or other C++ wrappers is that we currently treat our DNA structs in ways that aren't super compatible with C++ objects. E.g. we relocate them with memcpy a lot, but that's not really a concept that C++ has out of the box. Instead it uses move-semantics which we don't have for DNA structs and likely don't want to implement. > 1. DNA C Array wrapper thing (maybe this isn't the long term design, but it makes things easier now) > 2. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices > 3. Node utilities that use that code for the repeat and simulation zones I did try a fair amount of different refactors already, including the DNA C array wrapper. What I have in this patch is by far the cleanest cleanup I could come up with so far. I think it also makes testing the other things you mention much easier to try.
Author
Member

@blender-bot build

@blender-bot build
Author
Member

I think even with the other refactors you mention it seems like a good idea to have a central place where all the behavior of a specific node items array is defined (e.g. for simulation zones). That doesn't mean that all code that deals with the item arrays has to be templated on the same struct going forward. Code that deals with a subset of the behavior of item arrays could also be made to just depend on that subset in the future.

Doing that doesn't seem too hard but I think it would be premature abstraction before we don't have more code that could make use of the abtraction. For the nodes that I'll work on soonish (for-each, bake), the abstraction in this patch seems like exactly what I need.

I think even with the other refactors you mention it seems like a good idea to have a central place where all the behavior of a specific node items array is defined (e.g. for simulation zones). That doesn't mean that all code that deals with the item arrays has to be templated on the same struct going forward. Code that deals with a subset of the behavior of item arrays could also be made to just depend on that subset in the future. Doing that doesn't seem too hard but I think it would be premature abstraction before we don't have more code that could make use of the abtraction. For the nodes that I'll work on soonish (for-each, bake), the abstraction in this patch seems like exactly what I need.
Member

I agree. I think we should eventually split the abstraction up more in the future, but I don't think we can't really do that without testing that in a smaller scope first to figure out what works well and what doesn't. For now the abstraction solves the problem that we have. If our problem changes we can change the abstraction with it.

I hear your point, but even if it's just temporary, it's hard for me to get behind a class like nodes::item_arrays::ItemArrayRef. It's just confusing, because there's nothing specific to nodes in part of it, but then there is. It's just confusing organization. And as for the process of improving things, I agree it's nice to test things at a smaller scale, but that doesn't mean it has to be specific to nodes by design at the beginning. As an alternative, I would suggest discussing this a bit with other people interested in RNA/C++ (Sergey/Brecht/Campbell?) and agree to test this as an initial solution. Otherwise the risk is that we use this, it solves some local problem, and it just starts spreading without any proper discussion.

As a side-point, the name "Item Array" isn't super great. I wonder if something like "CArrayRef" of "TrivialArrayRef" is clearer. Every array is an "item array", so the word "item" doesn't really help, except maybe when the concept of "node interface item" gets involved, but even there the word "item" hardly pulls its weight.

One thing that holds me back with using CPPType or other C++ wrappers is that we currently treat our DNA structs in ways that aren't super compatible with C++ objects. E.g. we relocate them with memcpy a lot, but that's not really a concept that C++ has out of the box. Instead it uses move-semantics which we don't have for DNA structs and likely don't want to implement.

This is one case where CPPType could help. It gives us the opportunity to add this C-like dumb shallow copy into C++ code, and add some assets and checks to make it a bit safer.

> I agree. I think we should eventually split the abstraction up more in the future, but I don't think we can't really do that without testing that in a smaller scope first to figure out what works well and what doesn't. For now the abstraction solves the problem that we have. If our problem changes we can change the abstraction with it. I hear your point, but even if it's just temporary, it's hard for me to get behind a class like `nodes::item_arrays::ItemArrayRef`. It's just confusing, because there's nothing specific to nodes in part of it, but then there is. It's just confusing organization. And as for the process of improving things, I agree it's nice to test things at a smaller scale, but that doesn't mean it has to be specific to nodes _by design_ at the beginning. As an alternative, I would suggest discussing this a bit with other people interested in RNA/C++ (Sergey/Brecht/Campbell?) and agree to test this as an initial solution. Otherwise the risk is that we use this, it solves some local problem, and it just starts spreading without any proper discussion. As a side-point, the name "Item Array" isn't super great. I wonder if something like "CArrayRef" of "TrivialArrayRef" is clearer. Every array is an "item array", so the word "item" doesn't really help, except maybe when the concept of "node interface item" gets involved, but even there the word "item" hardly pulls its weight. > One thing that holds me back with using CPPType or other C++ wrappers is that we currently treat our DNA structs in ways that aren't super compatible with C++ objects. E.g. we relocate them with memcpy a lot, but that's not really a concept that C++ has out of the box. Instead it uses move-semantics which we don't have for DNA structs and likely don't want to implement. This is one case where `CPPType` could help. It gives us the opportunity to add this C-like dumb shallow copy into C++ code, and add some assets and checks to make it a bit safer.
Author
Member

I guess, I'm mostly concerned that opening up the larger discussion will stall this patch for an unknown amount of time without acknowledging that what we have in this patch is significantly more maintainable and extensible than what we have in main now (let me know if you don't agree with that part). It doesn't feel like for the larger picture with DNA/RNA it makes a significant difference whether this patch is in main or not.

Right now, I'm undetermined whether I should make this patch less general and more specific to nodes by renaming a few things (e.g. ItemArrayRef to SocketItemsRef), or whether I should try to add more general abstractions. What do you think is the most productive way going forward to be able to implement the features we want to implement? I definitely don't want to add all the boilerplate another three times for the bake/foreach-input/foreach-output nodes.

  1. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices

Note that this stuff is also not fully general, because different arrays have different update callbacks and need to maintain different invariants (like unique names, socket identifiers, supported socket types, ...). So most arrays will likely still need some special code of RNA.

I wonder if something like "CArrayRef" of "TrivialArrayRef" is clearer.

The problem with those names is that CArray could mean many different things, but usually it's used to refer to something like int[10]. TrivialArrayRef is also difficult because while the underlying type may be trivial, the "real" type is neither trivially copyable nor destructible.

Every array is an "item array", so the word "item" doesn't really help

I use the term "item", because we use the names SimulationItem and RepeatItem. So maybe if I rename everything to "socket items" instead of "item array", things become clearer and less general for now.

I would suggest discussing this a bit with other people interested in RNA/C++ (Sergey/Brecht/Campbell?) and agree to test this as an initial solution.

I can surely discuss this with them but it still feels like something independent of this patch, since here I'm mostly concerned about code deduplication for dynamic number of sockets and not so much how to change DNA/RNA to integrate better with C++. Conflating the two topics doesn't seem useful. Maybe it's my fault that these topics are conflated now due to how I formulated the patch description.

This is one case where CPPType could help. It gives us the opportunity to add this C-like dumb shallow copy into C++ code, and add some assets and checks to make it a bit safer.

Not quite sure what kinds of asserts you mean here. Maybe you can give an example?

I guess, I'm mostly concerned that opening up the larger discussion will stall this patch for an unknown amount of time without acknowledging that what we have in this patch is significantly more maintainable and extensible than what we have in `main` now (let me know if you don't agree with that part). It doesn't feel like for the larger picture with DNA/RNA it makes a significant difference whether this patch is in `main` or not. Right now, I'm undetermined whether I should make this patch less general and more specific to nodes by renaming a few things (e.g. `ItemArrayRef` to `SocketItemsRef`), or whether I should try to add more general abstractions. What do you think is the most productive way going forward to be able to implement the features we want to implement? I definitely don't want to add all the boilerplate another three times for the bake/foreach-input/foreach-output nodes. > 2. RNA utilities for resizing/adding/clearing while maintaining unique names and active indices Note that this stuff is also not fully general, because different arrays have different update callbacks and need to maintain different invariants (like unique names, socket identifiers, supported socket types, ...). So most arrays will likely still need some special code of RNA. > I wonder if something like "CArrayRef" of "TrivialArrayRef" is clearer. The problem with those names is that `CArray` could mean many different things, but usually it's used to refer to something like `int[10]`. `TrivialArrayRef` is also difficult because while the underlying type may be trivial, the "real" type is neither trivially copyable nor destructible. > Every array is an "item array", so the word "item" doesn't really help I use the term "item", because we use the names `SimulationItem` and `RepeatItem`. So maybe if I rename everything to "socket items" instead of "item array", things become clearer and less general for now. > I would suggest discussing this a bit with other people interested in RNA/C++ (Sergey/Brecht/Campbell?) and agree to test this as an initial solution. I can surely discuss this with them but it still feels like something independent of this patch, since here I'm mostly concerned about code deduplication for dynamic number of sockets and not so much how to change DNA/RNA to integrate better with C++. Conflating the two topics doesn't seem useful. Maybe it's my fault that these topics are conflated now due to how I formulated the patch description. > This is one case where CPPType could help. It gives us the opportunity to add this C-like dumb shallow copy into C++ code, and add some assets and checks to make it a bit safer. Not quite sure what kinds of asserts you mean here. Maybe you can give an example?
Member

Right now, I'm undetermined whether I should make this patch less general and more specific to nodes by renaming a few things (e.g. ItemArrayRef to SocketItemsRef),

Thanks for summing it up constructively like that. I think making things more clearly node-specific would help (while still organizing the internal code so that it's "generalize-able" later if we want to.

I guess I was coming at this with the perspective of it being a continuation of the discussion from the devtalk thread. Considering it as a local thing changes that, but indeed, more specific naming would really help.

Not quite sure what kinds of asserts you mean here. Maybe you can give an example?

I meant something stupidly simple like:

void CPPType::shallow_copy(const void *src, void *dst)
{
  BLI_assert(this->is_trivial());
  ...
}
>Right now, I'm undetermined whether I should make this patch less general and more specific to nodes by renaming a few things (e.g. `ItemArrayRef` to `SocketItemsRef`), Thanks for summing it up constructively like that. I think making things more clearly node-specific would help (while still organizing the internal code so that it's "generalize-able" later if we want to. I guess I was coming at this with the perspective of it being a continuation of the discussion from the devtalk thread. Considering it as a local thing changes that, but indeed, more specific naming would really help. >Not quite sure what kinds of asserts you mean here. Maybe you can give an example? I meant something stupidly simple like: ``` void CPPType::shallow_copy(const void *src, void *dst) { BLI_assert(this->is_trivial()); ... } ```
Jacques Lucke added 4 commits 2023-10-03 12:10:43 +02:00
Hans Goudey approved these changes 2023-10-03 23:36:55 +02:00
Hans Goudey left a comment
Member

Very nice now!

Very nice now!
@ -8916,0 +8810,4 @@
SNPRINTF(name, "rna_Node_ItemArray_new_with_socket_and_name<%s>", accessor_name);
func = RNA_def_function(srna, "new", allocator.copy_string(name).c_str());
RNA_def_function_ui_description(func, "Add a item at the end");
Member

a item -> an item

`a item` -> `an item`
JacquesLucke marked this conversation as resolved
@ -0,0 +211,4 @@
}
/**
* Check if the links connects to the `extend_socket`. If yes, create a new item for the linked
Member

the links connects -> the link connects

`the links connects` -> `the link connects`
JacquesLucke marked this conversation as resolved
@ -0,0 +11,4 @@
namespace blender::nodes {
StructRNA *SimulationItemsAccessor::item_srna = &RNA_SimulationStateItem;
int SimulationItemsAccessor::node_type = GEO_NODE_SIMULATION_OUTPUT;
Member

I guess this one is to avoid including BKE_node.hh in NOD_zone_socket_items.hh? Seems reasonable, maybe worth a comment though?

I guess this one is to avoid including `BKE_node.hh` in `NOD_zone_socket_items.hh`? Seems reasonable, maybe worth a comment though?
JacquesLucke marked this conversation as resolved
Author
Member

@blender-bot build

@blender-bot build
Jacques Lucke added 2 commits 2023-10-04 10:55:01 +02:00
Jacques Lucke merged commit 012289b1e7 into main 2023-10-04 11:03:01 +02:00
Jacques Lucke deleted branch simplify-item-array-handling 2023-10-04 11:03:03 +02:00
Sign in to join this conversation.
No reviewers
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
2 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#113114
No description provided.