-
Notifications
You must be signed in to change notification settings - Fork 373
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
[re_renderer] Uniform buffer utility using CpuWriteGpuReadBelt
#1400
Merged
Wumpf
merged 10 commits into
main
from
andreas/re_renderer/fast-and-easy-uniform-buffer-creation
Feb 27, 2023
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
9ff93a3
utility function for uniform buffer from struct
Wumpf 8c344ee
method for batches of uniform buffers
Wumpf f238793
Uniform buffers are now compile time forced to be 256 bytes aligned
Wumpf 1c83a68
create_and_fill_uniform_buffer_batch for rectangles.rs
Wumpf 3d1127a
CpuWriteGpuReadBelt no longer takes mutable buffer pool
Wumpf 301d317
Renderers and frame_global_command_encoder are now behind locks
Wumpf 4776df2
use uniform_buffer_allocation_size on lines
Wumpf b0d9589
move uniform buffer fill method to its own module
Wumpf 89c80f4
fix create_and_fill_uniform_buffer_batch not actually doing batches c…
Wumpf a7d4ffc
Merge branch 'main' into andreas/re_renderer/fast-and-easy-uniform-bu…
teh-cmc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
crates/re_renderer/src/allocator/uniform_buffer_fill.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
pub use super::cpu_write_gpu_read_belt::{CpuWriteGpuReadBelt, CpuWriteGpuReadBuffer}; | ||
|
||
use crate::{wgpu_resources::BindGroupEntry, DebugLabel, RenderContext}; | ||
|
||
struct UniformBufferAlignmentCheck<T> { | ||
pub _marker: std::marker::PhantomData<T>, | ||
} | ||
impl<T> UniformBufferAlignmentCheck<T> { | ||
/// wgpu requires uniform buffers to be aligned to up to 256 bytes. | ||
/// | ||
/// This is a property of device limits, see [`WebGPU` specification](https://www.w3.org/TR/webgpu/#limits). | ||
/// Implementations are allowed to advertise a lower alignment requirement, however | ||
/// 256 bytes is fairly common even in modern hardware and is even hardcoded for DX12. | ||
/// | ||
/// Technically this is only relevant when sub-allocating a buffer, as the wgpu backend | ||
/// is internally forced to make sure that the start of any [`wgpu::Buffer`] with [`wgpu::BufferUsages::UNIFORM`] usage | ||
/// has this alignment. Practically, ensuring this alignment everywhere | ||
/// | ||
/// Alternatively to enforcing this alignment on the type we could: | ||
/// * only align on the gpu buffer | ||
/// -> causes more fine grained `copy_buffer_to_buffer` calls on the gpu encoder | ||
/// * only align on the [`CpuWriteGpuReadBuffer`] & gpu buffer | ||
/// -> causes more complicated offset computation on [`CpuWriteGpuReadBuffer`] as well as either | ||
/// holes at padding (-> undefined values & slow for write combined!) or complicated nulling of padding | ||
/// | ||
/// About the [`bytemuck::Pod`] requirement (dragged in by [`CpuWriteGpuReadBuffer`]): | ||
/// [`bytemuck::Pod`] forces us to be explicit about padding as it doesn't allow invisible padding bytes! | ||
/// We could drop this and thus make it easier to define uniform buffer types. | ||
/// But this leads to more unsafe code, harder to avoid holes in write combined memory access | ||
/// and potentially undefined values in the padding bytes on GPU. | ||
const CHECK: () = assert!( | ||
std::mem::align_of::<T>() >= 256, | ||
"Uniform buffers need to be aligned to 256 bytes. Use `#[repr(C, align(256))]`" | ||
); | ||
} | ||
/// Utility for fast & efficient creation of uniform buffers from a series of structs. | ||
/// | ||
/// For subsequent frames, this will automatically not allocate any resources (thanks to our buffer pooling mechanism). | ||
/// | ||
/// TODO(#1383): We could do this on a more complex stack allocator. | ||
pub fn create_and_fill_uniform_buffer_batch<T: bytemuck::Pod>( | ||
ctx: &RenderContext, | ||
label: DebugLabel, | ||
content: impl ExactSizeIterator<Item = T>, | ||
) -> Vec<BindGroupEntry> { | ||
#[allow(clippy::let_unit_value)] | ||
let _ = UniformBufferAlignmentCheck::<T>::CHECK; | ||
|
||
let num_buffers = content.len() as u64; | ||
let element_size = std::mem::size_of::<T>() as u64; | ||
|
||
assert!( | ||
element_size > 0, | ||
"Uniform buffer need to have a non-zero size" | ||
); | ||
|
||
let buffer = ctx.gpu_resources.buffers.alloc( | ||
&ctx.device, | ||
&crate::wgpu_resources::BufferDesc { | ||
label, | ||
size: num_buffers * element_size, | ||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, | ||
mapped_at_creation: false, | ||
}, | ||
); | ||
|
||
let mut staging_buffer = ctx.cpu_write_gpu_read_belt.lock().allocate::<T>( | ||
&ctx.device, | ||
&ctx.gpu_resources.buffers, | ||
num_buffers as _, | ||
); | ||
staging_buffer.extend(content); | ||
staging_buffer.copy_to_buffer( | ||
ctx.active_frame | ||
.frame_global_command_encoder | ||
.lock() | ||
.get_or_create(&ctx.device), | ||
&buffer, | ||
0, | ||
); | ||
|
||
(0..num_buffers) | ||
.into_iter() | ||
.map(|i| BindGroupEntry::Buffer { | ||
handle: buffer.handle, | ||
offset: i * element_size, | ||
size: Some(std::num::NonZeroU64::new(element_size).unwrap()), | ||
}) | ||
.collect() | ||
} | ||
|
||
/// See [`create_and_fill_uniform_buffer`]. | ||
pub fn create_and_fill_uniform_buffer<T: bytemuck::Pod>( | ||
ctx: &mut RenderContext, | ||
label: DebugLabel, | ||
content: T, | ||
) -> BindGroupEntry { | ||
create_and_fill_uniform_buffer_batch(ctx, label, std::iter::once(content)) | ||
.into_iter() | ||
.next() | ||
.unwrap() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I'd expect an
==
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.
Higher alignment is unlikely but absolutely allowed. If something is aligned to 512 we're okay with that as well (but I really hope nothing is!)