-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BufferAttribute: Add support for multiple update ranges #27103
Conversation
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
src/core/BufferAttribute.js
Outdated
@@ -360,7 +380,8 @@ class BufferAttribute { | |||
|
|||
if ( this.name !== '' ) data.name = this.name; | |||
if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; | |||
if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange; | |||
if ( this._updateRange.offset !== 0 || this._updateRange.count !== - 1 ) data.updateRange = this._updateRange; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed if we're aiming for backwards compatibility for 10 releases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's keep this until updateRange
is completely removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't think of a use case when this is needed in the json though...
Maybe we can skip adding this.updateRanges
this time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Update rangers are resetted after the render has processed the frame so it's not a typical data that you serialize for a scene graph structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great - I removed toJSON and BufferGeometryLoader support for both the old updateRange and updateRanges
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
@mrdoob Are you okay with changing the API like proposed in this PR? This new feature will be useful for BatchedMesh
since it enables more efficient updates without rearranging buffer data (which would be too expensive anyway, see #27080 (comment)).
It's also useful for large dynamic geometries even without BatchedMesh. For example this another case where I was updating geometry in a ring-buffer style fashion but was unable to upload all the changes in one frame when reaching the end of the array: https://twitter.com/garrettkjohnson/status/1642890723531055104 |
Do you want to add support in the WebGPURenderer WebGL fallback? examples/jsm/renderers/webgl/utils/WebGPUAttributeUtils.js |
I'll add support in another PR since updateRange wasn't used, yet, and keep this PR focused on migrating existing usage. |
Incidentally is there a typical size of update where the overhead of a number of small updates exceeds any gains from reduction of bytes copied? |
Not that I am aware of. Concrete numbers will also vary from device to device. I think projects need to find out by their own whether multiple update ranges makes sense for their use case or not. |
cc @mrdoob is this API okay to merge? Before only one update range is allowed attr.updateRange.offset = 100;
attr.updateRange.count = 100; After multiple update ranges are allowed attr.addUpdateRange( 100, 100 );
attr.addUpdateRange( 300, 100 );
attr.updateRanges.length // 2 |
src/core/BufferAttribute.js
Outdated
addUpdateRange( offset, count ) { | ||
|
||
this.updateRanges.push( { offset, count } ); | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we name it start
instead of offset
this time?
addUpdateRange( start, count ) {
this.updateRanges.push( { start, count } );
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
I've added a couple of comments, but the new API looks good to me 👍 |
Made the changes - merging! |
@@ -42,6 +43,13 @@ class BufferAttribute { | |||
|
|||
} | |||
|
|||
get updateRange() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gkjohnson Please add a // @deprecated, r159
comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to make a PR. This one is merged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that since this only defines a getter, setting updateRange
is in fact broken in r159.
This broke our project and we were able to work around it easily, but I think it would be nice if the release notes for r159 were updated to mention the sudden breaking change for setting the value. As of right now, they only mention a new feature without mentioning any breaking changes:
Add support for multiple update ranges. #27103, #27148, #27149 (@gkjohnson)
https://github.com/mrdoob/three.js/releases/tag/r159
(Or you could introduce a setter with a deprecation message.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking changes are separately listed in the migration guide along with the migration tasks: https://github.com/mrdoob/three.js/wiki/Migration-Guide#r158--r159
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha! Unfortunately, that updateRange
does not appear on this page when I search for it. I had to spend a few minutes trying to figure out why setting updateRange
wasn't working, because nothing in the release notes actually mentioned the removal of the setter. While I understand the appeal of a condensed migration reference, it feels like the release notes themselves are sort of pretending that certain changes don't exist — when in fact those are the most impactful changes for existing codebases.
Would it be reasonable to inline a copy of the migration changes into the release notes, or to include the breaking changes directly as bullets in the list of changes? I think this would make the release notes a lot more intuitive, since other projects include breaking changes in the release notes themselves.
@@ -28,6 +29,13 @@ class InterleavedBuffer { | |||
|
|||
} | |||
|
|||
get updateRange() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
|
||
} | ||
|
||
// deprecated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Related issue: #27080, #27078
Description
Adds support for updating multiple ranges in an attribute buffer. It's the users responsibility to make sure there are no overlapping or duplicate ranges uploaded.
BufferAttribute.updateRange
.BufferAttribute.updateRanges
and associated clear and add functions.I will update other docs once this is merged.