Refactor: ANIM_setting_get_rna_values to return a Vector #113931

Merged
Christoph Lendenfeld merged 5 commits from ChrisLend/blender:refactor_get_rna_values into main 2023-10-24 09:01:48 +02:00

No functional changes.

Changing old C code to C++ by returning a Vector.
This reduces the argument count for that function and simplifies the code.


Questions for the reviewer:

  • when returning a Vector by value the memory will not be copied if I am not mistaken. That's the l_value/r_value feature in C++. Right?
  • I am using std::copy instead of memcpy. It compiles, the internet says that's the way. But I still feel unsure about the implications.
No functional changes. Changing old C code to C++ by returning a `Vector`. This reduces the argument count for that function and simplifies the code. ---- Questions for the reviewer: * when returning a Vector by value the memory will not be copied if I am not mistaken. That's the l_value/r_value feature in C++. Right? * I am using `std::copy` instead of `memcpy`. It compiles, the internet says that's the way. But I still feel unsure about the implications.
Christoph Lendenfeld added the
Module
Animation & Rigging
label 2023-10-19 12:50:33 +02:00
Christoph Lendenfeld added 1 commit 2023-10-19 12:50:44 +02:00
Christoph Lendenfeld added 1 commit 2023-10-19 13:41:42 +02:00
Member

when returning a Vector by value the memory will not be copied if I am not mistaken. That's the l_value/r_value feature in C++. Right?

That's right. In most cases where a function returns a vector that it just creates there is no extra copy or move. The new vector will be created directly in the stack space of the calling function. Also see https://en.cppreference.com/w/cpp/language/copy_elision

I am using std::copy instead of memcpy. It compiles, the internet says that's the way. But I still feel unsure about the implications.

For trivial types, like float, there is no functional difference between using memcpy or std::copy. For non-trivial types, std::copy will call assignment operators appropriately. Sometimes using std::copy_n may be easier.

> when returning a Vector by value the memory will not be copied if I am not mistaken. That's the l_value/r_value feature in C++. Right? That's right. In most cases where a function returns a vector that it just creates there is no extra copy or move. The new vector will be created directly in the stack space of the calling function. Also see https://en.cppreference.com/w/cpp/language/copy_elision > I am using std::copy instead of memcpy. It compiles, the internet says that's the way. But I still feel unsure about the implications. For [trivial types](https://en.cppreference.com/w/cpp/named_req/TrivialType), like `float`, there is no functional difference between using `memcpy` or `std::copy`. For non-trivial types, `std::copy` will call assignment operators appropriately. Sometimes using `std::copy_n` may be easier.
Sybren A. Stüvel requested changes 2023-10-19 14:30:30 +02:00
Sybren A. Stüvel left a comment
Member

Such an improvement! Thanks!

I've left some inline notes, should be fairly straight forward to address.

Such an improvement! Thanks! I've left some inline notes, should be fairly straight forward to address.
@ -235,3 +233,1 @@
copy_v3_v3(buffer, ob->object_to_world[3]);
*r_count = 3;
return buffer;
for (int i = 0; i < 3; i++) {

I think it might be nice to keep the abstractions the way they were, at least here. That would mean having some copy_vector_v3(blender::Vector<float> dest, const float src[3]) function that basically performs this loop.

I think it might be nice to keep the abstractions the way they were, at least here. That would mean having some `copy_vector_v3(blender::Vector<float> dest, const float src[3])` function that basically performs this loop.
Member

How about vector.extend({ob->object_to_world[3], 3});

How about `vector.extend({ob->object_to_world[3], 3});`
Author
Member

used vector.extend since I am not sure where I would put such a function

used `vector.extend` since I am not sure where I would put such a function
@ -273,3 +276,1 @@
*r_count = 4;
return buffer;
for (int i = 0; i < 4; i++) {

Same as above, concerning abstraction level. IMO it would be perfectly fine to have a mat4_to_quat_vector() function that basically performs the same operation as you have here.

Same as above, concerning abstraction level. IMO it would be perfectly fine to have a `mat4_to_quat_vector()` function that basically performs the same operation as you have here.
dr.sybren marked this conversation as resolved
@ -263,3 +263,2 @@
struct PropertyRNA *prop,
float *values,
int count,
const blender::MutableSpan<float> &values,

AFAIK Span and MutableSpan are reference types anyway, and don't need to be passed as reference themselves. But @HooglyBoogly can say more about that.

AFAIK `Span` and `MutableSpan` are reference types anyway, and don't need to be passed as reference themselves. But @HooglyBoogly can say more about that.
Member

Yes, it's better to pass them by value, otherwise inside the function it's like a pointer to a pointer.

They are 16 bytes, so they are small enough as well.

Yes, it's better to pass them by value, otherwise inside the function it's like a pointer to a pointer. They are 16 bytes, so they are small enough as well.
Author
Member

thanks for that, fixed

thanks for that, fixed
@ -594,1 +584,3 @@
RNA_property_float_get_array(ptr, prop, values);
}
case PROP_FLOAT: {
float *tmp_float = static_cast<float *>(

Since the values don't need to be cast to float here, it might just work here to create a length-size Vector<float> and pass the address of the first element to RNA_property_float_get_array()?

Since the values don't need to be cast to `float` here, it might just work here to create a `length`-size `Vector<float>` and pass the address of the first element to `RNA_property_float_get_array()`?
Author
Member

yep that seems to work

yep that seems to work
@ -615,3 +611,3 @@
break;
default:
*values = 0.0f;
break;

This is a change in behaviour. Instead of returning one zero value, it returns no value. Not sure if this is an important distinction, but given that this PR is labeled "refactor", it's better to avoid functional changes.

This is a change in behaviour. Instead of returning one zero value, it returns no value. Not sure if this is an important distinction, but given that this PR is labeled "refactor", it's better to avoid functional changes.
Author
Member

good point. Also changed it for the property array case

good point. Also changed it for the property array case
Christoph Lendenfeld added 1 commit 2023-10-19 15:08:52 +02:00
Christoph Lendenfeld requested review from Sybren A. Stüvel 2023-10-19 15:15:06 +02:00
Author
Member

thanks all for the feedback
@dr.sybren as mentioned in the comment, I went for vector.extend since I don't know where to put functions like copy_vector_v3
can still do them if you point me to where they would live

thanks all for the feedback @dr.sybren as mentioned in the comment, I went for `vector.extend` since I don't know where to put functions like `copy_vector_v3` can still do them if you point me to where they would live
Iliya Katushenock reviewed 2023-10-19 17:13:02 +02:00
@ -16,3 +18,2 @@
bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop);
float *visualkey_get_values(
PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count);
Vector<float> visualkey_get_values(PointerRNA *ptr, PropertyRNA *prop);

You can add forward declaration for vector in header to do not include big header.

You can add forward declaration for vector in header to do not include big header.
Author
Member

is there an example for that? All the header files I could find just include BLI_vector.hh
I tried the forward declaration but couldn't get it to work

is there an example for that? All the header files I could find just include `BLI_vector.hh` I tried the forward declaration but couldn't get it to work
namespace blender {
template<typename T, int64_t InlineBufferCapacity, typename Allocator> class Vector;
}   // namespace blender

Something like ^ should works. If that is not so trivial, then it's not that important.

```Cpp namespace blender { template<typename T, int64_t InlineBufferCapacity, typename Allocator> class Vector; } // namespace blender ``` Something like ^ should works. If that is not so trivial, then it's not that important.
Author
Member

still doesn't work. Complains about
cannot overload functions distinguished by return type alone

still doesn't work. Complains about `cannot overload functions distinguished by return type alone`
mod_moder marked this conversation as resolved
@ -3783,3 +3783,3 @@
NlaEvalChannelSnapshot *blended_necs = nlaeval_snapshot_ensure_channel(&blended_snapshot, nec);
memcpy(blended_necs->values, values, sizeof(float) * count);
std::copy(values.begin(), values.end(), blended_necs->values);

You can also use BLI_array_utils.hh to use parallel version of this function (in case is large spans).

You can also use `BLI_array_utils.hh` to use parallel version of this function (in case is large spans).
Author
Member

the element count is at most 4. I don't think parallel makes a difference here
but i'll keep it in mind. There will be things in animation that need to be run in parallel

the element count is at most 4. I don't think parallel makes a difference here but i'll keep it in mind. There will be things in animation that need to be run in parallel
dr.sybren marked this conversation as resolved
@ -594,1 +584,3 @@
RNA_property_float_get_array(ptr, prop, values);
}
case PROP_FLOAT: {
values = blender::Vector<float>(length);

values.reinitialize(length);

`values.reinitialize(length);`
Author
Member

thanks, done that

thanks, done that
Christoph Lendenfeld added 1 commit 2023-10-19 17:52:50 +02:00

@dr.sybren as mentioned in the comment, I went for vector.extend since I don't know where to put functions like copy_vector_v3
can still do them if you point me to where they would live

I think those could go into the same files as their array-based counterparts. That would require a little discussion with the code module, though. What could work also is something like this:

values.resize(3);
mat4_to_size(values.data(), tmat);

I think this is both more readable and more efficient. And if this works, it prevents us from having to create a copy of every single array-based function to a vector-based alternative.

> @dr.sybren as mentioned in the comment, I went for `vector.extend` since I don't know where to put functions like `copy_vector_v3` > can still do them if you point me to where they would live I think those could go into the same files as their array-based counterparts. That would require a little discussion with the code module, though. What could work also is something like this: ```cpp values.resize(3); mat4_to_size(values.data(), tmat); ``` I think this is both more readable and more efficient. And if this works, it prevents us from having to create a copy of every single array-based function to a vector-based alternative.
Christoph Lendenfeld added 1 commit 2023-10-20 14:12:10 +02:00
Author
Member

@dr.sybren that's even better, changed to that
except for this line
mat4_to_axis_angle(&values[1], &values[0], tmat);
but that also works

@dr.sybren that's even better, changed to that except for this line `mat4_to_axis_angle(&values[1], &values[0], tmat);` but that also works

Please don't chenge size of vector manually. Or use values.resize(values.size() + 3); In other case this will be a stateful variable and everyone going to make sure is any append / reinitialize / clear will not break your manual copying.
If implicit span initializing ({data, size}) not clear for you, is there already extend(data, size) method overload.

Please don't chenge size of vector manually. Or use `values.resize(values.size() + 3);` In other case this will be a stateful variable and everyone going to make sure is any `append` / `reinitialize` / `clear` will not break your manual copying. If implicit span initializing (`{data, size}`) not clear for you, is there already `extend(data, size)` method overload.
Author
Member

@mod_moder does it matter in this case? the function doing the resizing is creating the vector. so no one else could have used it yet

@mod_moder does it matter in this case? the function doing the resizing is creating the vector. so no one else could have used it yet
Sybren A. Stüvel approved these changes 2023-10-23 10:32:16 +02:00
Sybren A. Stüvel left a comment
Member

👍

:+1:
Christoph Lendenfeld merged commit 265858525e into main 2023-10-24 09:01:48 +02:00
Christoph Lendenfeld deleted branch refactor_get_rna_values 2023-10-24 09:01:50 +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
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#113931
No description provided.