Skip to content
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

Implement Deref(Mut) on BufferVec/UniformVec #3532

Closed
wants to merge 15 commits into from

Conversation

james7132
Copy link
Member

This PR fixes #3531, and is required by #3504 to improve rendering performance and readability.

Objective

  • Expose more of the Vec API for more efficiently handling larger mutations to the underlying Vec.
  • Clean up some parts of the implementation.
  • Document the public API of the type.

Solution

  • Implemented Deref and DerefMut on BufferVec, targeting the underlying Vec
  • Privated the reserve function and renamed to reserve_buffer since it only really needs to run before queuing a write to the buffer.
  • Removed all of the pass-through BufferVec functions (is_empty, len, clear, etc), which are now exposed via Deref(Mut).
  • Renamed capacity to buffer_capacity to avoid clashing with the Deref'ed capacity from Vec.
  • Removed the item_size field from the type as it is run-time constant for the type.
  • Documented the new publicly available API for the type.

@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Jan 2, 2022
@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen C-Usability A targeted quality-of-life change that makes Bevy easier to use C-Code-Quality A section of code that is hard to understand or change and removed S-Needs-Triage This issue needs to be labelled labels Jan 4, 2022
@james7132
Copy link
Member Author

Added UniformVec to this as well. (Couldn't find a good way to handle DynamicUniformVec).

@james7132 james7132 changed the title Implement Dereff(Mut) on BufferVec. Implement Dereff(Mut) on BufferVec/UniformVec Jan 8, 2022
@superdump
Copy link
Contributor

superdump commented Mar 2, 2022

I’ll do a full review in a bit but capacity can also be removed in my opinion. In reserve we can just use size > self.scratch.len() and otherwise capacity is just self.values.len().

@james7132 james7132 changed the title Implement Dereff(Mut) on BufferVec/UniformVec Implement Deref(Mut) on BufferVec/UniformVec Mar 2, 2022
Copy link
Contributor

@superdump superdump left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a few suggestions for what I think are improvements.

I see what you mean about implementing Deref and DerefMut on DynamicUniformVec. It looks to me like it could be done, but the user needs to know they need to wrap their T in DynamicUniform. I would argue that we should just do that for consistency and deref through to the UniformVec's internal Vec<DynamicUniform<T>>. What do you think?

crates/bevy_render/src/render_resource/buffer_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/buffer_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/buffer_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/uniform_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/uniform_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/uniform_vec.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/render_resource/uniform_vec.rs Outdated Show resolved Hide resolved
superdump added a commit to superdump/bevy that referenced this pull request Mar 2, 2022
@james7132
Copy link
Member Author

I see what you mean about implementing Deref and DerefMut on DynamicUniformVec. It looks to me like it could be done, but the user needs to know they need to wrap their T in DynamicUniform. I would argue that we should just do that for consistency and deref through to the UniformVec's internal Vec<DynamicUniform<T>>. What do you think?

I went ahead and did it, though I'm not a fan of exposing the need for users to wrap it themselves, seems like a regression in API design. However, it's probably for the best in terms of consistency here.

@james7132 james7132 requested a review from superdump March 2, 2022 20:55
@superdump
Copy link
Contributor

Also note the failing docs check.

@james7132 james7132 requested a review from superdump March 3, 2022 23:38
Copy link
Contributor

@superdump superdump left a 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!

@james7132 james7132 added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Mar 6, 2022
@superdump
Copy link
Contributor

@james7132 could you update this on top of main ready for tomorrow’s round of reviews by Cart?

@alice-i-cecile
Copy link
Member

bors try

bors bot added a commit that referenced this pull request Mar 14, 2022
@bors
Copy link
Contributor

bors bot commented Mar 14, 2022

try

Build failed:

@superdump
Copy link
Contributor

@cart on #4079 for storage buffers you didn’t want to use deref and derefmut, and instead have accessors so I added .values() and .values_mut(). What do you want to do with this PR/with *UniformVec and BufferVec? They are specifically Vec-like but I think the goal is to expose the internal Vec of values to allow use of all Vec APIs for optimisation purposes. That could be achieved by either deref impls or accessors.

@cart
Copy link
Member

cart commented Mar 24, 2022

My biggest reservation about this is that it is basically saying "vec is our public interface, forever". It is committing to never syncing any internal state between the backing Vec and other fields on UniformVec. For example, maybe in the future we decide we want to preserve data across frames and track what needs to be updated internally. That should probably be a new abstraction, but the point is, exposing the vec internals eliminates all forms of internal state tracking. Likewise, it means we can't choose to abstract out things like the self.values.alloc().init(value) to force callers to use the optimized call (see #3590).

@superdump
Copy link
Contributor

My biggest reservation about this is that it is basically saying "vec is our public interface, forever". It is committing to never syncing any internal state between the backing Vec and other fields on UniformVec. For example, maybe in the future we decide we want to preserve data across frames and track what needs to be updated internally. That should probably be a new abstraction, but the point is, exposing the vec internals eliminates all forms of internal state tracking. Likewise, it means we can't choose to abstract out things like the self.values.alloc().init(value) to force callers to use the optimized call (see #3590).

Should we close this then?

@cart
Copy link
Member

cart commented Apr 4, 2022

Barring further discussion on the matter (I'm open to having my mind changed), then yeah I think we should close this.

@james7132 james7132 deleted the buffer-vec-api branch June 22, 2022 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Expose more of the Vec API on BufferVec
5 participants