Commit Graph

45 Commits

Author SHA1 Message Date
eedcf1876a Functions: introduce multi-function namespace
This moves all multi-function related code in the `functions` module
into a new `multi_function` namespace. This is similar to how there
is a `lazy_function` namespace.

The main benefit of this is that many types names that were prefixed
with `MF` (for "multi function") can be simplified.

There is also a common shorthand for the `multi_function` namespace: `mf`.
This is also similar to lazy-functions where the shortened namespace
is called `lf`.
2023-01-07 17:32:28 +01:00
b3146200a8 Functions: refactor multi-function builder API
* New `build_mf` namespace for the multi-function builders.
* The type name of the created multi-functions is now "private",
  i.e. the caller has to use `auto`. This has the benefit that the
  implementation can change more freely without affecting
  the caller.
* `CustomMF` does not use `std::function` internally anymore.
  This reduces some overhead during code generation and at
  run-time.
* `CustomMF` now supports single-mutable parameters.
2023-01-07 16:19:59 +01:00
30753f7692 Functions: add method to iterate over all inputs of a field
This is part of D16858. Iterating over all field inputs allows us to extract
all anonymous attributes used by a field relatively easily which is necessary
for D16858.

This could potentially be used for better field tooltips for nested fields,
but that needs further investigation.
2023-01-03 12:37:18 +01:00
2155bdd500 Cleanup: Remove "done" variable from node runtime
The runtime storage is meant for more persistent things. These local
states for an algorithm are much better handled by an array now.
2022-12-02 14:14:14 -06:00
14d0b57be7 Cleanup: Use array_utils to copy evaluated field array 2022-11-22 12:49:51 -06:00
97746129d5 Cleanup: replace UNUSED macro with commented args in C++ code
This is the conventional way of dealing with unused arguments in C++,
since it works on all compilers.

Regex find and replace: `UNUSED\((\w+)\)` -> `/*$1*/`
2022-10-03 17:38:16 -05:00
c6e70e7bac Cleanup: follow C++ type cast style guide in some files
https://wiki.blender.org/wiki/Style_Guide/C_Cpp#C.2B.2B_Type_Cast

This was discussed in https://devtalk.blender.org/t/rfc-style-guide-for-type-casts-in-c-code/25907.
2022-09-25 17:39:45 +02:00
95f05a6a4b Cleanup: spelling in comments 2022-09-16 18:14:33 +10:00
2c53970bbf Cleanup: use doxy sections, remove outdated comment 2022-09-15 15:27:21 +10:00
3e5a4d1412 Geometry Nodes: Optimize selection for virtual array input
This makes calculation of selected indices slightly faster when the
input is a virtual array (the direct output of various nodes like
Face Area, etc). The utility can be helpful for other areas that
need to find selected indices besides field evaluation.

With the face area node used as a selection with 4 million faces,
the speedup is 3.51 ms to 3.39 ms, just a slight speedup.

Differential Revision: https://developer.blender.org/D15127
2022-06-23 11:51:33 -05:00
c4e11122c5 Geometry Nodes: Use fields for delete geometry inversion
The separate geometry and delete geometry nodes often invert the
selection so that deleting elements from a geometry can be implemented
as copying the opposite selection of elements. This should make the two
nodes faster in some cases, since the generic versions of selection
creation functions (i.e. from d3a1e9cbb9) are used instead
of the single threaded code that was used for this node.

The change also makes the deletion/separation code easier to
understand because it doesn't have to pass around the inversion.
2022-06-05 16:46:20 +02:00
b9799dfb8a Geometry Nodes: better support for byte color attributes
Since {rBeae36be372a6b16ee3e76eff0485a47da4f3c230} the distinction
between float and byte colors is more explicit in the ui. So far, geometry
nodes couldn't really deal with byte colors in general. This patch fixes that.
There is still only one color socket, which contains float colors. Conversion
to and from byte colors is done when read from or writing to attributes.

* Support writing to byte color attributes in Store Named Attribute node.
* Support converting to/from byte color in attribute conversion operator.
* Support propagating byte color attributes.
* Add all the implicit conversions from byte colors to the other types.
* Display byte colors as integers in spreadsheet.

Differential Revision: https://developer.blender.org/D14705
2022-04-21 16:11:26 +02:00
2aff04917f Functions: parallelize materializing arrays after field evaluation
This improves performance e.g. when creating an integer attribute
based on an index field. For 4 million vertices, I measured a speedup
from 3.5 ms to 1.2 ms.
2022-04-07 09:48:07 +02:00
7bd614d431 Cleanup: use value initialization instead of copying default value
Value-initialization has the potential to be more efficient.
Also, the code becomes simpler.
2022-03-29 09:29:09 +02:00
d3a1e9cbb9 Geometry Nodes: Multi-thread creation of selection from field
When boolean fields are evaluated and used as selections, we create
a vector of indices. This process is currently single-threaded, but
226f0c4fef added a more optimized multi-threaded version
of this process. It's simple to use this in the field evaluator.

I tested this with the set position node and a random
value node set to boolean mode on a Ryzen 2700x:
|              | Before  |  After  | Improvement |
| 10% Selected | 40.5 ms | 29.0 ms | 1.4x        |
| 90% Selected | 115 ms  | 45.3 ms | 2.5x        |

In the future there could be a specialized version for non-span
virtual array selections that uses `materialize` to lower virtual
call overhead.

Differential Revision: https://developer.blender.org/D14436
2022-03-24 18:48:38 -05:00
7393cc1db7 Cleanup: Remove repeated word in comments 2022-02-23 18:24:37 +11:00
c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00
b4563ab2df Cleanup: avoid generating some functions in all translation units
Every translation unit that included the modified headers generated
some extra code, even though it was not used. This adds unnecessary
compile time overhead and is annoying when investigating the
generated assembly.
2022-02-04 17:18:56 +01:00
675d3cdd69 Cleanup: Clang tidy 2022-01-03 13:52:55 -06:00
8be217ada5 Geometry Nodes: add field node type for constants
It is common to have fields that contain a constant value. Before this
commit, such constants were represented by operation nodes which
don't have inputs. Having a special node type for constants makes
working with them a bit cheaper.

It also allows skipping some unnecessary processing when evaluating
fields, because constant fields can be detected more easily.

This commit also generalizes the concept of field node types a bit.
2022-01-02 14:27:16 +01:00
8e2c9f2dd3 Geometry Nodes: simplify using selection when evaluating fields
We often had to use two `FieldEvaluator` instances to first evaluate
the selection and then the remaining fields. Now both can be done
with a single `FieldEvaluator`. This results in less boilerplate code in
many cases.

Performance is not affected by this change. In a separate patch we
could improve performance by reusing evaluated sub-fields that are
used by the selection and the other fields.

Differential Revision: https://developer.blender.org/D13571
2021-12-14 15:40:27 +01:00
8ba6302696 Geometry Nodes: fix combining field inputs
This was an oversight in rB7b88a4a3ba7eb9b839afa6c42d070812a3af7997.
2021-12-13 13:51:42 +01:00
1686979747 Geometry Nodes: move up destruct instructions in procedure
This implements an optimization pass for multi-function procedures.
It optimizes memory reuse by moving destruct instructions up.
For more details see the in-code comment.

In very large fields with many short lived intermediate values, this change
can improve performance 3-4x. Furthermore, in such cases, peak memory
consumption is reduced significantly (e.g. 100x lower peak memory usage).

Differential Revision: https://developer.blender.org/D13548
2021-12-13 13:28:33 +01:00
7b88a4a3ba Geometry Nodes: remove accidental exponential time algorithm
Calling `foreach_field_input` on a highly nested field (we do that
often) has an exponential running time in the number of nodes.
That is because the same node may be visited many times.
This made Blender freeze on some setups that should work just fine.
Now every field keeps track of its inputs all the time. That replaces
the exponential algorithm with constant time access.
2021-12-11 11:26:55 +01:00
7f4878ac7f Cleanup: move public doc-strings into headers for 'functions'
Ref T92709
2021-12-09 21:17:16 +11:00
2d4c7fa896 Geometry Nodes: reduce code duplication with new GeometyrFieldInput
Most of our field inputs are currently specific to geometry. This patch introduces
a new `GeometryFieldInput` that reduces the overhead of adding new geometry
field input.

Differential Revision: https://developer.blender.org/D13489
2021-12-06 19:13:24 +01:00
658fd8df0b Geometry Nodes: refactor multi-threading in field evaluation
Previously, there was a fixed grain size for all multi-functions. That was
not sufficient because some functions could benefit a lot from smaller
grain sizes.

This refactors adds a new `MultiFunction::call_auto` method which has the
same effect as just calling `MultiFunction::call` but additionally figures
out how to execute the specific multi-function efficiently. It determines
a good grain size and decides whether the mask indices should be shifted
or not.

Most multi-function evaluations benefit from this, but medium sized work
loads (1000 - 50000 elements) benefit from it the most. Especially when
expensive multi-functions (e.g. noise) is involved. This is because for
smaller work loads, threading is rarely used and for larger work loads
threading worked fine before already.

With this patch, multi-functions can specify execution hints, that allow
the caller to execute it most efficiently. These execution hints still
have to be added to more functions.

Some performance measurements of a field evaluation involving noise and
math nodes, ordered by the number of elements being evaluated:
```
1,000,000: 133 ms   -> 120 ms
  100,000:  30 ms   ->  18 ms
   10,000:  20 ms   ->   2.7 ms
    1,000:   4 ms   ->   0.5 ms
      100:   0.5 ms ->   0.4 ms
```
2021-11-26 11:06:16 +01:00
47276b8470 Geometry Nodes: reduce overhead when processing single values
Currently the geometry nodes evaluator always stores a field for every
type that supports it, even if it is just a single value. This results in a lot
of overhead when there are many sockets that just contain a single
value, which is often the case.

This introduces a new `ValueOrField<T>` type that is used by the geometry
nodes evaluator. Now a field will only be created when it is actually
necessary. See D13307 for more details. In extrem cases this can speed
up the evaluation 2-3x (those cases are probably never hit in practice
though, but it's good to get rid of unnecessary overhead nevertheless).

Differential Revision: https://developer.blender.org/D13307
2021-11-23 14:49:26 +01:00
6ee2abde82 Functions: use static names for multi-functions
Previously, the function names were stored in `std::string` and were often
created dynamically (especially when the function just output a constant).
This resulted in a lot of overhead.

Now the function name is just a `const char *` that should be statically
allocated. This is good enough for the majority of cases. If a multi-function
needs a more dynamic name, it can override the `MultiFunction::debug_name`
method.

In my test file with >400,000 simple math nodes, the execution time improves from
3s to 1s.
2021-11-21 12:48:07 +01:00
d4c868da9f Geometry Nodes: refactor virtual array system
Goals of this refactor:
* Simplify creating virtual arrays.
* Simplify passing virtual arrays around.
* Simplify converting between typed and generic virtual arrays.
* Reduce memory allocations.

As a quick reminder, a virtual arrays is a data structure that behaves like an
array (i.e. it can be accessed using an index). However, it may not actually
be stored as array internally. The two most important implementations
of virtual arrays are those that correspond to an actual plain array and those
that have the same value for every index. However, many more
implementations exist for various reasons (interfacing with legacy attributes,
unified iterator over all points in multiple splines, ...).

With this refactor the core types (`VArray`, `GVArray`, `VMutableArray` and
`GVMutableArray`) can be used like "normal values". They typically live
on the stack. Before, they were usually inside a `std::unique_ptr`. This makes
passing them around much easier. Creation of new virtual arrays is also
much simpler now due to some constructors. Memory allocations are
reduced by making use of small object optimization inside the core types.

Previously, `VArray` was a class with virtual methods that had to be overridden
to change the behavior of a the virtual array. Now,`VArray` has a fixed size
and has no virtual methods. Instead it contains a `VArrayImpl` that is
similar to the old `VArray`. `VArrayImpl` should rarely ever be used directly,
unless a new virtual array implementation is added.

To support the small object optimization for many `VArrayImpl` classes,
a new `blender::Any` type is added. It is similar to `std::any` with two
additional features. It has an adjustable inline buffer size and alignment.
The inline buffer size of `std::any` can't be relied on and is usually too
small for our use case here. Furthermore, `blender::Any` can store
additional user-defined type information without increasing the
stack size.

Differential Revision: https://developer.blender.org/D12986
2021-11-16 10:16:30 +01:00
fd477e738d Geometry Nodes: remove reference to anonymous attributes in tooltips
This changes socket inspection for fields according to T91881.

Differential Revision: https://developer.blender.org/D13006
2021-10-26 15:32:01 +02:00
cc388651eb Fix T92327: use default value when field is passed into data socket
Previously, the computed value passed into the data socket could depend
on the actual field a bit. However, given that the link is marked as invalid
in the ui, the user should not depend on this behavior.
Using a default value is consistent with other cases when there are
invalid links.
2021-10-24 17:53:19 +02:00
40c3b8836b Geometry Nodes: Make Random ID a builtin attribute, remove sockets
In order to address feedback that the "Stable ID" was not easy enough
to use, remove the "Stable ID" output from the distribution node and
the input from the instance on points node. Instead, the nodes write
or read a builtin named attribute called `id`. In the future we may
add more attributes like `edge_id` and `face_id`.

The downside is that more behavior is invisible, which is les
expected now that most attributes are passed around with node links.
This behavior will have to be explained in the manual.

The random value node's "ID" input that had an implicit index input
is converted to a special implicit input that uses the `id` attribute
if possible, but otherwise defaults to the index. There is no way to
tell in the UI which it uses, except by knowing that rule and checking
in the spreadsheet for the id attribute.

Because it isn't always possible to create stable randomness, this
attribute does not always exist, and it will be possible to remove it
when we have the attribute remove node back, to improve performance.

Differential Revision: https://developer.blender.org/D12903
2021-10-20 10:54:54 -05:00
a3457704fb Geometry Nodes: De-duplicate index input nodes during evaluation
We do this in other nodes to reduce overhead of using the same node more
than once. I don't think it will make a difference with index nodes
currently, but at least it's consistent.
2021-10-18 20:13:37 -05:00
eb0d216dc1 Geometry Nodes: decouple multi-function lifetimes from modifier
Previously, some multi-functions were allocated in a resource scope.
This was fine as long as the multi-functions were only needed during
the current evaluation of the node tree. However, now cases arise
that require the multi-functions to be alive after the modifier is finished.
For example, we want to evaluate fields created with geometry nodes
outside of geometry nodes.

To make this work, `std::shared_ptr` has to be used in a few more places.
Realistically, this shouldn't have a noticable impact on performance.
If this does become a bottleneck in the future, we can think about ways
to make this work without using `shared_ptr` for multi-functions that
are only used once.
2021-10-18 11:46:21 +02:00
1cd8a438bb Cleanup: simplify field evaluation 2021-09-26 23:28:14 +02:00
88a2b054da Fix T91732: crash in Set Position node on empty mesh 2021-09-26 23:28:14 +02:00
90b410fe74 Fix: field evaluation crash when the domain size is zero 2021-09-24 16:42:20 +02:00
95ec6e4dd3 Geometry Nodes: make index field more reusable
Some inputs will be the index field implicitly, so we want this
class to be available outside of `node_geo_input_index.cc`.
2021-09-24 16:03:07 +02:00
bd1c4a781f Geometry Nodes: fix evaluating field to span 2021-09-22 18:45:11 +02:00
e6ca054590 Geometry Nodes: multi threaded field evaluation
This adds a new `ParallelMultiFunction` which wraps another multi-function
and evaluates it with multiple threads. The speeds up field evaluation
quite a bit (the effect is most noticeable when the number of evaluations
and the field is large).

There are still other single-threaded performance bottlenecks in field
evaluation that will need to be solved separately. Most notably here
is the process of copying the computed data into the position attribute
in the Set Position node.

Differential Revision: https://developer.blender.org/D12457
2021-09-15 11:02:39 +02:00
dee0b56b92 Cleanup: simplify resource scope methods
Previously, a debug name had to be passed to all methods
that added a resource to the `ResourceScope`. The idea was
that this would make it easier to find certain bugs. In reality
I never found this to be useful, and it was mostly annoying.
The thing is, something that is in a resource scope never leaks
(unless the resource scope is not destructed of course).

Removing the name parameter makes the structure easier to use.
2021-09-14 16:08:09 +02:00
fd60f6713a Functions: support optional outputs in multi-function
Sometimes not all outputs of a multi-function are required by the
caller. In those cases it would be a waste of compute resources
to calculate the unused values anyway. Now, the caller of a
multi-function can specify when a specific output is not used.
The called function can check if an output is unused and may
ignore it. Multi-functions can still computed unused outputs as
before if they don't want to check if a specific output is unused.

The multi-function procedure system has been updated to support
ignored outputs in call instructions. An ignored output just has no
variable assigned to it.

The field system has been updated to generate a multi-function
procedure where unused outputs are ignored.
2021-09-14 14:52:44 +02:00
4e78b89e48 Geometry Nodes: add field support for socket inspection
Since fields were committed to master, socket inspection did
not work correctly for all socket types anymore. Now the same
functionality as before is back. Furthermore, fields that depend
on some input will now show the inputs in the socket inspection.

I added support for evaluating constant fields more immediately.
This has the benefit that the same constant field is not evaluated
more than once. It also helps with making the field independent
of the multi-functions that it uses. We might still want to change
the ownership handling for the multi-functions of nodes a bit,
but that can be done separately.

Differential Revision: https://developer.blender.org/D12444
2021-09-11 13:05:20 +02:00
bf47fb40fd Geometry Nodes: fields and anonymous attributes
This implements the initial core framework for fields and anonymous
attributes (also see T91274).

The new functionality is hidden behind the "Geometry Nodes Fields"
feature flag. When enabled in the user preferences, the following
new nodes become available: `Position`, `Index`, `Normal`,
`Set Position` and `Attribute Capture`.

Socket inspection has not been updated to work with fields yet.

Besides these changes at the user level, this patch contains the
ground work for:
* building and evaluating fields at run-time (`FN_fields.hh`) and
* creating and accessing anonymous attributes on geometry
  (`BKE_anonymous_attribute.h`).

For evaluating fields we use a new so called multi-function procedure
(`FN_multi_function_procedure.hh`). It allows composing multi-functions
in arbitrary ways and supports efficient evaluation as is required by
fields. See `FN_multi_function_procedure.hh` for more details on how
this evaluation mechanism can be used.

A new `AttributeIDRef` has been added which allows handling named
and anonymous attributes in the same way in many places.

Hans and I worked on this patch together.

Differential Revision: https://developer.blender.org/D12414
2021-09-09 12:54:20 +02:00