USD: Add common Blender attribute to USD primvar utilities #121145

Merged
Jesse Yurkovich merged 17 commits from deadpin/blender:usd-commonattributes into main 2024-05-15 05:44:42 +02:00

This factors out the current set of attribute-to-primvar functions
inside the USD mesh reader/writer so we can use them elsewhere. Namely
they will also be used for exporting Curves attributes like UVs etc.

Outside of this PR I've verified these common functions should be
directly useful for upcoming PointCloud support and for our Curves.

This factors out the current set of attribute-to-primvar functions inside the USD mesh reader/writer so we can use them elsewhere. Namely they will also be used for exporting Curves attributes like UVs etc. Outside of this PR I've verified these common functions should be directly useful for upcoming PointCloud support and for our Curves.
Jesse Yurkovich added 2 commits 2024-04-26 20:48:22 +02:00
Jesse Yurkovich requested review from Michael Kowalski 2024-04-26 20:53:32 +02:00
Jesse Yurkovich requested review from Hans Goudey 2024-04-26 21:07:32 +02:00
Jesse Yurkovich reviewed 2024-04-26 21:12:25 +02:00
@ -0,0 +177,4 @@
attribute.typed<math::Quaternion>(), timecode, primvar, value_writer);
break;
default:
BLI_assert_unreachable();
Author
Member

Note: Generally this function works in concert with convert_blender_type_to_usd so we shouldn't see this even though e.g. a FLOAT4X4 type exists today.

Note: Generally this function works in concert with `convert_blender_type_to_usd` so we shouldn't see this even though e.g. a FLOAT4X4 type exists today.
Hans Goudey reviewed 2024-04-26 23:18:55 +02:00
Hans Goudey left a comment
Member

The recent support for USD Shape colors factored out attribute "reading" into a common "mesh" attribute file. Should those move into this common "attribute" file instead

Yeah, it seems valuable to have similar utilities for reading attributes, to avoid duplication between meshes, point clouds, and curves.

Am I following the right patterns in transferring the attributes most efficiently? See copy_blender_buffer_to_primvar

That's a complex topic I think, but I think it's good enough. I left a comment there anyway.

We could move the implementation of the helper methods to a usd_attribute_utils.cc file. But it would require extra ceremony to duplicate the template signatures in the header. Should we do it?

The benefit would be reducing compile time? Not sure it's worth it if the templates are only used twice. But no strong opinion, and more information may help make that decision.

There's unfortunate convert_value overloads for bool, int, and float that I haven't figured out how to template away. Minor but annoying.

I think they are avoidable, left a comment inline.

>The recent support for USD Shape colors factored out attribute "reading" into a common "mesh" attribute file. Should those move into this common "attribute" file instead Yeah, it seems valuable to have similar utilities for reading attributes, to avoid duplication between meshes, point clouds, and curves. >Am I following the right patterns in transferring the attributes most efficiently? See copy_blender_buffer_to_primvar That's a complex topic I think, but I think it's good enough. I left a comment there anyway. >We could move the implementation of the helper methods to a usd_attribute_utils.cc file. But it would require extra ceremony to duplicate the template signatures in the header. Should we do it? The benefit would be reducing compile time? Not sure it's worth it if the templates are only used twice. But no strong opinion, and more information may help make that decision. >There's unfortunate convert_value overloads for bool, int, and float that I haven't figured out how to template away. Minor but annoying. I think they are avoidable, left a comment inline.
@ -0,0 +42,4 @@
/* Conversion utilities to convert a Blender type to an USD type. */
template<typename BlenderT, typename USDT> inline USDT convert_value(const BlenderT value);
template<> inline bool convert_value(const bool value)
Member

I think you could avoid these redundant convert_value functions by using if constexpr in copy_blender_buffer_to_primvar

I think you could avoid these redundant `convert_value` functions by using `if constexpr` in `copy_blender_buffer_to_primvar`
deadpin marked this conversation as resolved
@ -0,0 +115,4 @@
if (const std::optional<BlenderT> value = buffer.get_if_single()) {
usd_data.assign(buffer.size(), detail::convert_value<BlenderT, USDT>(*value));
}
else if (buffer.is_span() && (is_same || is_compatible)) {
Member

const VArraySpan<T> src(buffer); would make this simpler (no need for the "not span" check), and probably won't be a bottleneck unless we get very fancy with out attribute storage, at which point we'll want to change this anyway.

`const VArraySpan<T> src(buffer);` would make this simpler (no need for the "not span" check), and probably won't be a bottleneck unless we get very fancy with out attribute storage, at which point we'll want to change this anyway.
Author
Member

I'm a bit unsure what you mean for this one. How would you structure these conditionals instead?

I'm a bit unsure what you mean for this one. How would you structure these conditionals instead?
Member

Like this I think:

  if (const std::optional<BlenderT> value = buffer.get_if_single()) {
    usd_data.assign(buffer.size(), detail::convert_value<BlenderT, USDT>(*value));
  }
  else {
    const VArraySpan<BlenderT> data(buffer);
    if constexpr (is_same || is_compatible) {
      usd_data.assign(data.cast<USDT>().begin(), data.cast<USDT>().end());
    }
    else {
      for (const int i : buffer.index_range()) {
        usd_data[i] = detail::convert_value<BlenderT, USDT>(data[i]);
      }
    }
  }

I guess the last for loop could be written with std::transform too. Not sure about that though.

Like this I think: ```cpp if (const std::optional<BlenderT> value = buffer.get_if_single()) { usd_data.assign(buffer.size(), detail::convert_value<BlenderT, USDT>(*value)); } else { const VArraySpan<BlenderT> data(buffer); if constexpr (is_same || is_compatible) { usd_data.assign(data.cast<USDT>().begin(), data.cast<USDT>().end()); } else { for (const int i : buffer.index_range()) { usd_data[i] = detail::convert_value<BlenderT, USDT>(data[i]); } } } ``` I guess the last for loop could be written with `std::transform` too. Not sure about that though.
deadpin marked this conversation as resolved
@ -0,0 +118,4 @@
else if (buffer.is_span() && (is_same || is_compatible)) {
Span<USDT> data = buffer.get_internal_span().cast<USDT>();
usd_data.assign(data.begin(), data.end());
Member

This seems fine, with so much copying going on we're probably more memory bound anyway, so multithreading might not help so much.

This seems fine, with so much copying going on we're probably more memory bound anyway, so multithreading might not help so much.
deadpin marked this conversation as resolved
@ -30,3 +36,3 @@
namespace blender::io::usd {
#pragma optimize("", off)
Member

Temporary?

Temporary?
Author
Member

Yes, was completely temporary for local debugging and removed now.

Yes, was completely temporary for local debugging and removed now.
deadpin marked this conversation as resolved
@ -357,0 +449,4 @@
}
}
else {
write_generic_data(curves, attribute_id, meta_data, usd_curves);
Member

Use this-> to access class methods

Use `this->` to access class methods
deadpin marked this conversation as resolved
Jesse Yurkovich added 2 commits 2024-04-29 03:40:15 +02:00
Author
Member

Thanks for the look!

We could move the implementation of the helper methods to a usd_attribute_utils.cc file. But it would require extra ceremony to duplicate the template signatures in the header. Should we do it?

The benefit would be reducing compile time? Not sure it's worth it if the templates are only used twice. But no strong opinion, and more information may help make that decision.

Yes, there would probably be 4(?) uses of the file. Mesh, Curves, Point Clouds, and the Shape reader (if the common reader stuff is merged in here too)

There's unfortunate convert_value overloads for bool, int, and float that I haven't figured out how to template away. Minor but annoying.

I think they are avoidable, left a comment inline.

I think I found another, simpler solution while trying this out.

Thanks for the look! > >We could move the implementation of the helper methods to a usd_attribute_utils.cc file. But it would require extra ceremony to duplicate the template signatures in the header. Should we do it? > > The benefit would be reducing compile time? Not sure it's worth it if the templates are only used twice. But no strong opinion, and more information may help make that decision. Yes, there would probably be 4(?) uses of the file. Mesh, Curves, Point Clouds, and the Shape reader (if the common reader stuff is merged in here too) > >There's unfortunate convert_value overloads for bool, int, and float that I haven't figured out how to template away. Minor but annoying. > > I think they are avoidable, left a comment inline. I think I found another, simpler solution while trying this out.

@deadpin I will review this PR in the next couple of days. My apologies for the delay.

@deadpin I will review this PR in the next couple of days. My apologies for the delay.
Jesse Yurkovich added 3 commits 2024-05-02 20:08:27 +02:00
Author
Member

The most recent update to the PR now brings in the code for our Readers and commonizes it.
I have not tried this for Curves/PointClouds yet to see how well the API works in another example, but it works for the Meshes and has test coverage as of yesterday for it.

Along the way it lost logging to Reports, which I feel was always a bit weird since it can be so verbose. It would also be odd now that this is low-level common code shared among the object types. I do think that some code paths could warrent a CLOG output though, which would be fine, but that means we should probably move the templates into a .cc file somehow so we can use CLOG there...

The API set looks like:

Reading Writing
copy_primvar_to_blender_attribute
copy_primvar_to_blender_buffer

convert_usd_type_to_blender
copy_blender_attribute_to_primvar
copy_blender_buffer_to_primvar

convert_blender_type_to_usd

The attribute functions contain the big switch statement which sets up the appropriate typed calls to the "buffer" functions.

The buffer functions do the actual copying, as efficiently as possible. They'll effectively memcpy for types that are layout compatible between Blender and USD i.e. float vs. float, or float3 vs. GfVec3 etc.

The type functions switch between Blender and USD type names as appropriate.

These names are a little verbose and I'm not married to them. Anything with symmetry would work. Perhaps we could append attr to the outer namspace and use something like:

Reading - attr::copy_from_primvar / attr::copy_from_usd_to_blender
Writing - attr::copy_to_primvar / attr::copy_to_usd_from_blender
The most recent update to the PR now brings in the code for our Readers and commonizes it. I have not tried this for Curves/PointClouds yet to see how well the API works in another example, but it works for the Meshes and has test coverage as of yesterday for it. Along the way it lost logging to Reports, which I feel was always a bit weird since it can be so verbose. It would also be odd now that this is low-level common code shared among the object types. I do think that some code paths could warrent a CLOG output though, which would be fine, but that means we should probably move the templates into a .cc file somehow so we can use CLOG there... The API set looks like: | Reading | Writing | | ---- | ---- | | `copy_primvar_to_blender_attribute`<br>`copy_primvar_to_blender_buffer`<br><br>`convert_usd_type_to_blender`<br> | `copy_blender_attribute_to_primvar`<br>`copy_blender_buffer_to_primvar`<br><br>`convert_blender_type_to_usd` | The `attribute` functions contain the big switch statement which sets up the appropriate typed calls to the "buffer" functions. The `buffer` functions do the actual copying, as efficiently as possible. They'll effectively memcpy for types that are layout compatible between Blender and USD i.e. float vs. float, or float3 vs. GfVec3 etc. The `type` functions switch between Blender and USD type names as appropriate. These names are a little verbose and I'm not married to them. Anything with symmetry would work. Perhaps we could append `attr` to the outer namspace and use something like: ``` Reading - attr::copy_from_primvar / attr::copy_from_usd_to_blender Writing - attr::copy_to_primvar / attr::copy_to_usd_from_blender ```
Hans Goudey reviewed 2024-05-02 20:49:01 +02:00
@ -0,0 +246,4 @@
template<typename USDT, typename BlenderT>
void copy_primvar_to_blender_buffer(const pxr::UsdGeomPrimvar &primvar,
const pxr::UsdTimeCode timecode,
const blender::OffsetIndices<int> face_indices,
Member

blender:: unnecessary here I think? Also I'd go with just faces instead of face_indices which makes me think of an array of actual indices into the mesh faces arrays

`blender::` unnecessary here I think? Also I'd go with just `faces` instead of `face_indices` which makes me think of an array of actual indices into the mesh faces arrays
deadpin marked this conversation as resolved
@ -0,0 +291,4 @@
if (usd_data.size() == attribute.size()) {
if constexpr (is_same || is_compatible) {
const Span<USDT> src(usd_data.data(), usd_data.size());
attribute.copy_from(src.cast<BlenderT>());
Member

For creating Blender attributes in this is_same || is_compatible case, there's one potential optimization that might be worth thinking about at this point, creating attributes with implicitly shared data.

With implicit sharing, the custom data layer data pointer could just point to the VtArray if the VtArray could be owned by something like MEMFreeImplicitSharing.

To allow that optimization in the future it might be necessary to potentially delay creating the attribute until we know whether the buffer can be reused. Or not, maybe that gives you an idea.

For creating Blender attributes in this `is_same || is_compatible` case, there's one potential optimization that might be worth thinking about at this point, creating attributes with implicitly shared data. With implicit sharing, the custom data layer `data` pointer could just point to the `VtArray` if the `VtArray` could be owned by something like `MEMFreeImplicitSharing`. To allow that optimization in the future it might be necessary to potentially delay creating the attribute until we know whether the buffer can be reused. Or not, maybe that gives you an idea.
Michael Kowalski approved these changes 2024-05-04 04:19:46 +02:00
Michael Kowalski left a comment
Member

The code looks good and works well in my tests.

I don't feel strongly about whether to move functions to a usd_attribute_utils.cc file. I would be inclined to leave the current implementation as-is and move the code to a .cc file later if needed, but I wouldn't object if you want to move it now, either.

The code looks good and works well in my tests. I don't feel strongly about whether to move functions to a `usd_attribute_utils.cc` file. I would be inclined to leave the current implementation as-is and move the code to a .cc file later if needed, but I wouldn't object if you want to move it now, either.
Jesse Yurkovich added 7 commits 2024-05-13 18:05:57 +02:00
Jesse Yurkovich changed title from WIP: USD: Add common Blender attribute to USD primvar utilities to USD: Add common Blender attribute to USD primvar utilities 2024-05-13 18:08:57 +02:00
Author
Member

Alright, this PR should be ready to go now in case folks here want to take a final look. Main changes since last time are the removal of the Curve* items which will come in separately since it's net-new functionality and addressing feedback/cleanup.

I'm still open to naming/namespace related changes if the raw function names are problematic in any way.

Alright, this PR should be ready to go now in case folks here want to take a final look. Main changes since last time are the removal of the Curve* items which will come in separately since it's net-new functionality and addressing feedback/cleanup. I'm still open to naming/namespace related changes if the raw function names are problematic in any way.

The latest changes look good to me. I also preformed some basic testing and the code seems to work as expected. Thank you for the updates!

The latest changes look good to me. I also preformed some basic testing and the code seems to work as expected. Thank you for the updates!
Hans Goudey reviewed 2024-05-14 17:32:28 +02:00
Hans Goudey left a comment
Member

Looking at this again I noticed all of the important entry points aren't templated. And the inline functions are quite large. So I think it would make sense to put the implementations in .cc file. Other than that it looks great.

Looking at this again I noticed all of the important entry points aren't templated. And the inline functions are quite large. So I think it would make sense to put the implementations in `.cc` file. Other than that it looks great.
Jesse Yurkovich added 1 commit 2024-05-14 19:15:48 +02:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
a37abfd0e3
Feedback - Move non-templates to impl file
Author
Member

Moved the non-templates to an implementation file. Let's see if the build bot agrees with this all now.

@blender-bot build

Moved the non-templates to an implementation file. Let's see if the build bot agrees with this all now. @blender-bot build
Jesse Yurkovich added 1 commit 2024-05-14 20:31:54 +02:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
44c6749142
Gcc/clang compile fixes
Author
Member

@blender-bot build

@blender-bot build
Jesse Yurkovich added 1 commit 2024-05-14 22:59:53 +02:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
806b4c55b9
constexpr std::optional not support on mac clang?
Author
Member

@blender-bot build

@blender-bot build
Jesse Yurkovich merged commit 3b31d73c62 into main 2024-05-15 05:44:42 +02:00
Jesse Yurkovich deleted branch usd-commonattributes 2024-05-15 05:44:44 +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
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#121145
No description provided.