Commit Graph

21 Commits

Author SHA1 Message Date
2ffd08e952 Geometry Nodes: deterministic anonymous attribute lifetimes
Previously, the lifetimes of anonymous attributes were determined by
reference counts which were non-deterministic when multiple threads
are used. Now the lifetimes of anonymous attributes are handled
more explicitly and deterministically. This is a prerequisite for any kind
of caching, because caching the output of nodes that do things
non-deterministically and have "invisible inputs" (reference counts)
doesn't really work.

For more details for how deterministic lifetimes are achieved, see D16858.

No functional changes are expected. Small performance changes are expected
as well (within few percent, anything larger regressions should be reported as
bugs).

Differential Revision: https://developer.blender.org/D16858
2023-01-05 14:05:30 +01:00
Mattias Fredriksson
ce54f48556 BLI: Add generic utlity for gathering values with indices
Add new functions to `array_utils` namespace called `gather(..)`.
Versions of `GVArray::materialize_compressed_to_uninitialized(..)` with
threading have been reimplemented locally in multiple geometry node
contexts. The purpose of this patch is therefore to:
 * Assemble these implementations in a single file.
 * Provide a naming convention that is easier to recognize.

Differential Revision: https://developer.blender.org/D15786
2022-09-17 22:12:02 -05:00
d593497421 Cleanup: Use C++ methods to retrieve attribute accessors
Replace `mesh_attributes`, `mesh_attributes_for_write` and the point
cloud versions with methods on the `Mesh` and `PointCloud` types.
This makes them friendlier to use and improves readability.

Differential Revision: https://developer.blender.org/D15907
2022-09-07 21:41:39 -05:00
be038b844c Cleanup: Tweak naming for recently added mesh accessors
Use `verts` instead of `vertices` and `polys` instead of `polygons`
in the API added in 05952aa94d. This aligns better with
existing naming where the shorter names are much more common.
2022-09-07 00:06:31 -05:00
05952aa94d Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.

The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7, 410a6efb74). Removing use of
the pointers generally makes code more obvious and more reusable.

Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).

The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.

**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.

Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).

Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
Erik Abrahamsson
c8ae1fce60 Geometry Nodes: Shortest Paths nodes
This adds three new nodes:
* `Shortest Edge Paths`: Actually finds the shortest paths.
* `Edge Paths to Curves`: Converts the paths to separate curves.
  This may generate a quadratic amount of data, making it slow
  for large meshes.
* `Edge Paths to Selection`: Generates an edge selection that
  contains all edges that are part of a path. This can be used
  with the Separate Geometry node to only keep the edges that
  are part of a path. For large meshes, this approach can be
  much faster than the `Edge Paths to Curves` node, because
  less data is created.

Differential Revision: https://developer.blender.org/D15274
2022-07-27 15:38:44 +02:00
6a1ab4747b Geometry Nodes: Copy parameters when copying a curves data-block
Previously, things like materials, symmetry, and selection options
stored on `Curves` weren't copied to the result in nodes like the
subdivide and resample nodes. Now they are, which fixes some
unexpected behavior and allows visualization of the sculpt mode
selection.

In the realize instances and join nodes the behavior is the same as
for meshes, the parameters are taken from the first (top) input.

I also refactored some functions to return a `CurvesGeometry` by-value,
which makes it the responsibility of the node to copy the parameters.
That should make the algorithms more reusable in other situations.

Differential Revision: https://developer.blender.org/D15408
2022-07-19 10:16:30 -05:00
b876ce2a4a Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.

This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.

The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.

For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.

Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.

The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.

There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`

All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.

Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
ae94e36cfb Geometry Nodes: refactor array devirtualization
Goals:
* Better high level control over where devirtualization occurs. There is always
  a trade-off between performance and compile-time/binary-size.
* Simplify using array devirtualization.
* Better performance for cases where devirtualization wasn't used before.

Many geometry nodes accept fields as inputs. Internally, that means that the
execution functions have to accept so called "virtual arrays" as inputs. Those
 can be e.g. actual arrays, just single values, or lazily computed arrays.
Due to these different possible virtual arrays implementations, access to
individual elements is slower than it would be if everything was just a normal
array (access does through a virtual function call). For more complex execution
functions, this overhead does not matter, but for small functions (like a simple
addition) it very much does. The virtual function call also prevents the compiler
from doing some optimizations (e.g. loop unrolling and inserting simd instructions).

The solution is to "devirtualize" the virtual arrays for small functions where the
overhead is measurable. Essentially, the function is generated many times with
different array types as input. Then there is a run-time dispatch that calls the
best implementation. We have been doing devirtualization in e.g. math nodes
for a long time already. This patch just generalizes the concept and makes it
easier to control. It also makes it easier to investigate the different trade-offs
when it comes to devirtualization.

Nodes that we've optimized using devirtualization before didn't get a speedup.
However, a couple of nodes are using devirtualization now, that didn't before.
Those got a 2-4x speedup in common cases.
* Map Range
* Random Value
* Switch
* Combine XYZ

Differential Revision: https://developer.blender.org/D14628
2022-04-26 17:12:34 +02:00
f431be224f Curves: Cache the number of curves of each type
Remembering the number of curves of every type makes it fast to know
whether processing specific to a single curve type has to be done.
This information was accessed in quite a few places, so this should be
an overall reduction in overhead for the new curves type.

The cache is computed eagerly, in other words every time after changing
the curve types. In order to reduce verbosity I added helper functions
for some common ways to set the types.

Differential Revision: https://developer.blender.org/D14732
2022-04-25 13:40:07 -05:00
8551e89068 Curves: Name mutable data retrieval functions explicitly
Add "for_write" on function names that retrieve mutable data arrays.
Though this makes function names longer, it's likely worth it because
it allows more easily using the const functions in a non-const context,
and reduces cases of mistakenly retrieving with edit access.

In the long term, this situation might change more if we implement
attributes storage that is accessible directly on `CurvesGeometry`
without duplicating the attribute API on geometry components,
which is currently the rough plan.

Differential Revision: https://developer.blender.org/D14562
2022-04-06 16:30:27 -05:00
3e16f3b3ef BLI: move generic data structures to blenlib
This is a follow up to rB2252bc6a5527cd7360d1ccfe7a2d1bc640a8dfa6.
2022-03-19 08:26:29 +01:00
0835996cc9 Cleanup: Rename "spline" variables to "curve"
Ref T95355
2022-03-17 17:08:36 -05:00
901a03725e Curves: Port mesh to curve node to new data-block
The main improvement is a code simplification, because attributes don't
have to be transferred separately for each curve, and all attributes can
be handled generically. Performance improves significantly when the
output contains many curves. Basic testing with a 2 million curve output
shows an approximate 10x performance improvement.
2022-03-07 19:06:40 -06: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
1931387799 Fix: Curve trim node test failure
Caused by 60c59d7d61. The position wasn't copied into the correct
place on each spline. Somehow I didn't catch that in the tests I ran.
2021-12-22 18:38:30 -06:00
60c59d7d61 Cleanup: Remove spline add_point method, refactor mesh to curve node
It's better to calculate the size of a spline before creating it, and this
should simplify refactoring to a data structure that stores all point
attribute contiguously (see T94193). The mesh to curve conversion is
simplified slightly now, it creates the curve output after gathering all
of the result vertex indices. This should be more efficient too, since
it only grows an index vector for each spline, not a whole spline.
2021-12-22 17:39:35 -06:00
3647a1e621 Cleanup: move public doc-strings into headers for 'geometry'
Ref T92709
2021-12-09 20:23:10 +11: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
990b912fd7 Cleanup: Add check whether to remove an anonymous atttribute
Add a higher level check that can be used instead of checking whether
the attribute ID is anonymous and checking whether it has any strong
references.
2021-10-20 09:57:54 -05:00
17b8da7196 Geometry Nodes: Field version of mesh to curve node
This commit adds a fields version of the mesh to curve node, with a
field for the input selection. In order to reduce code duplication,
it adds the mesh to curve conversion to the new geometry module
and calls that implementation from both places.

More details on the geometry module can be found here: T86869

Differential Revision: https://developer.blender.org/D12579
2021-10-14 12:06:48 -05:00