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

[Merged by Bors] - Documenting UniformBuffer, DynamicUniformBuffer, StorageBuffer and DynamicStorageBuffer. #5223

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
11727c5
Documenting `BufferVec`.
May 6, 2022
9ef6d24
Replace RenderDevice by GPU.
bzm3r Jun 21, 2022
5ffd580
State Pod as the direct requirement; and reflect reality of encase no…
bzm3r Jun 21, 2022
da1f666
Say "system RAM" instead of "host memory" and "VRAM" instead of "devi…
bzm3r Jun 21, 2022
e407b97
remove repetition of "data"
bzm3r Jun 21, 2022
c50f80c
run cargo fmt
bzm3r Jun 27, 2022
1dab056
Merge branch 'main' of github.com:bevyengine/bevy
bzm3r Jun 28, 2022
b974929
Add documentation for UniformBuffer and DynamicUniformBuffer.
bzm3r Jul 6, 2022
8a49be6
run cargo fmt
bzm3r Jul 6, 2022
919c444
Merge branch 'bevyengine:main' into main
bzm3r Jul 6, 2022
f77cd5a
Clarifications regarding dynamic vs. non-dynamic buffers. Also added…
bzm3r Jul 6, 2022
ecfeac0
Merge branch 'main' of github.com:bzm3r/bevy
bzm3r Jul 6, 2022
908bd6a
clarifying docs further.
bzm3r Jul 8, 2022
d275294
say 'dynamic storage buffer', instead of only storage buffer, in dyna…
bzm3r Jul 8, 2022
d34311f
addressing suggestions by @superdump (robswain)
bzm3r Jul 11, 2022
e77771e
Update crates/bevy_render/src/render_resource/uniform_buffer.rs
bzm3r Jul 20, 2022
8cb0f04
Update crates/bevy_render/src/render_resource/uniform_buffer.rs
bzm3r Jul 20, 2022
d4c1761
Update crates/bevy_render/src/render_resource/storage_buffer.rs
bzm3r Jul 20, 2022
a109dad
Update crates/bevy_render/src/render_resource/storage_buffer.rs
bzm3r Jul 20, 2022
d5bf796
Update crates/bevy_render/src/render_resource/storage_buffer.rs
bzm3r Jul 20, 2022
4ff1a55
Update crates/bevy_render/src/render_resource/uniform_buffer.rs
bzm3r Jul 20, 2022
fb5001a
strip down docs a bit, to avoid repetition, and provide a cohesive se…
bzm3r Jul 20, 2022
15f7033
allow doc_markdown clippy lint so that we can write WebGL2 without ba…
Jul 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions crates/bevy_render/src/render_resource/buffer_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,23 @@ use wgpu::BufferUsages;
/// for use by the GPU.
///
/// "Properly formatted" means that item data already meets the alignment and padding
/// requirements for how it will be used on the GPU.
/// requirements for how it will be used on the GPU. The item type must implement [`Pod`]
/// for its data representation to be directly copyable.
///
/// Index, vertex, and instance-rate vertex buffers have no alignment nor padding requirements and
/// so this helper type is a good choice for them. Uniform buffers must adhere to std140
/// alignment/padding requirements, and storage buffers to std430. There are helper types for such
/// buffers:
/// - Uniform buffers
/// - Plain: [`UniformBuffer`](crate::render_resource::UniformBuffer)
/// - Dynamic offsets: [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// - Storage buffers
/// - Plain: [`StorageBuffer`](crate::render_resource::StorageBuffer)
/// - Dynamic offsets: [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
///
/// The item type must implement [`Pod`] for its data representation to be directly copyable.
/// so this helper type is a good choice for them.
///
/// The contained data is stored in system RAM. Calling [`reserve`](crate::render_resource::BufferVec::reserve)
/// allocates VRAM from the [`RenderDevice`](crate::renderer::RenderDevice).
/// [`write_buffer`](crate::render_resource::BufferVec::write_buffer) queues copying of the data
/// from system RAM to VRAM.
///
/// Other options for storing GPU-accessible data are:
/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// * [`BufferVec`](crate::render_resource::BufferVec)
/// * [`Texture`](crate::render_resource::Texture)
pub struct BufferVec<T: Pod> {
values: Vec<T>,
buffer: Option<Buffer>,
Expand Down
47 changes: 47 additions & 0 deletions crates/bevy_render/src/render_resource/storage_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(clippy::doc_markdown)]

use super::Buffer;
use crate::renderer::{RenderDevice, RenderQueue};
use encase::{
Expand All @@ -6,6 +8,25 @@ use encase::{
};
use wgpu::{util::BufferInitDescriptor, BindingResource, BufferBinding, BufferUsages};

/// Stores data to be transferred to the GPU and made accessible to shaders as a storage buffer.
///
/// Storage buffers can be made available to shaders in some combination of read/write mode, and can store large amounts of data.
/// Note however that WebGL2 does not support storage buffers, so consider alternative options in this case.
///
/// Storage buffers can store runtime-sized arrays, but only if they are the last field in a structure.
///
/// The contained data is stored in system RAM. [`write_buffer`](crate::render_resource::StorageBuffer::write_buffer) queues
/// copying of the data from system RAM to VRAM. Storage buffers must conform to [std430 alignment/padding requirements], which
/// is automatically enforced by this structure.
///
/// Other options for storing GPU-accessible data are:
/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// * [`BufferVec`](crate::render_resource::BufferVec)
/// * [`Texture`](crate::render_resource::Texture)
///
/// [std430 alignment/padding requirements]: https://www.w3.org/TR/WGSL/#address-spaces-storage
pub struct StorageBuffer<T: ShaderType> {
value: T,
scratch: StorageBufferWrapper<Vec<u8>>,
Expand Down Expand Up @@ -60,6 +81,11 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
&mut self.value
}

/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
///
/// If there is no GPU-side buffer allocated to hold the data currently stored, or if a GPU-side buffer previously
/// allocated does not have enough capacity, a new GPU-side buffer is created.
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
self.scratch.write(&self.value).unwrap();

Expand All @@ -78,6 +104,27 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
}
}

/// Stores data to be transferred to the GPU and made accessible to shaders as a dynamic storage buffer.
///
/// Dynamic storage buffers can be made available to shaders in some combination of read/write mode, and can store large amounts
/// of data. Note however that WebGL2 does not support storage buffers, so consider alternative options in this case. Dynamic
/// storage buffers support multiple separate bindings at dynamic byte offsets and so have a
/// [`push`](crate::render_resource::DynamicStorageBuffer::push) method.
///
/// The contained data is stored in system RAM. [`write_buffer`](crate::render_resource::DynamicStorageBuffer::write_buffer)
/// queues copying of the data from system RAM to VRAM. The data within a storage buffer binding must conform to
/// [std430 alignment/padding requirements]. `DynamicStorageBuffer` takes care of serialising the inner type to conform to
/// these requirements. Each item [`push`](crate::render_resource::DynamicStorageBuffer::push)ed into this structure
/// will additionally be aligned to meet dynamic offset alignment requirements.
///
/// Other options for storing GPU-accessible data are:
/// * [`StorageBuffer`](crate::render_resource::StorageBuffer)
/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// * [`BufferVec`](crate::render_resource::BufferVec)
/// * [`Texture`](crate::render_resource::Texture)
///
/// [std430 alignment/padding requirements]: https://www.w3.org/TR/WGSL/#address-spaces-storage
pub struct DynamicStorageBuffer<T: ShaderType> {
values: Vec<T>,
scratch: DynamicStorageBufferWrapper<Vec<u8>>,
Expand Down
50 changes: 50 additions & 0 deletions crates/bevy_render/src/render_resource/uniform_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,25 @@ use encase::{
};
use wgpu::{util::BufferInitDescriptor, BindingResource, BufferBinding, BufferUsages};

/// Stores data to be transferred to the GPU and made accessible to shaders as a uniform buffer.
///
/// Uniform buffers are available to shaders on a read-only basis. Uniform buffers are commonly used to make available to shaders
/// parameters that are constant during shader execution, and are best used for data that is relatively small in size as they are
/// only guaranteed to support up to 16kB per binding.
///
/// The contained data is stored in system RAM. [`write_buffer`](crate::render_resource::UniformBuffer::write_buffer) queues
/// copying of the data from system RAM to VRAM. Data in uniform buffers must follow [std140 alignment/padding requirements],
/// which is automatically enforced by this structure. Per the WGPU spec, uniform buffers cannot store runtime-sized array
/// (vectors), or structures with fields that are vectors.
///
/// Other options for storing GPU-accessible data are:
/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// * [`StorageBuffer`](crate::render_resource::StorageBuffer)
/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
/// * [`BufferVec`](crate::render_resource::BufferVec)
/// * [`Texture`](crate::render_resource::Texture)
///
/// [std140 alignment/padding requirements]: https://www.w3.org/TR/WGSL/#address-spaces-uniform
pub struct UniformBuffer<T: ShaderType> {
value: T,
scratch: UniformBufferWrapper<Vec<u8>>,
Expand Down Expand Up @@ -47,6 +66,7 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
))
}

/// Set the data the buffer stores.
pub fn set(&mut self, value: T) {
self.value = value;
}
Expand All @@ -59,6 +79,11 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
&mut self.value
}

/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue), if a GPU-side backing buffer already exists.
///
/// If a GPU-side buffer does not already exist for this data, such a buffer is initialized with currently
/// available data.
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
self.scratch.write(&self.value).unwrap();

Expand All @@ -75,6 +100,25 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
}
}

/// Stores data to be transferred to the GPU and made accessible to shaders as a dynamic uniform buffer.
///
/// Dynamic uniform buffers are available to shaders on a read-only basis. Dynamic uniform buffers are commonly used to make
/// available to shaders runtime-sized arrays of parameters that are otherwise constant during shader execution, and are best
/// suited to data that is relatively small in size as they are only guaranteed to support up to 16kB per binding.
///
/// The contained data is stored in system RAM. [`write_buffer`](crate::render_resource::DynamicUniformBuffer::write_buffer) queues
/// copying of the data from system RAM to VRAM. Data in uniform buffers must follow [std140 alignment/padding requirements],
/// which is automatically enforced by this structure. Per the WGPU spec, uniform buffers cannot store runtime-sized array
/// (vectors), or structures with fields that are vectors.
///
/// Other options for storing GPU-accessible data are:
/// * [`StorageBuffer`](crate::render_resource::StorageBuffer)
/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
/// * [`Texture`](crate::render_resource::Texture)
///
/// [std140 alignment/padding requirements]: https://www.w3.org/TR/WGSL/#address-spaces-uniform
pub struct DynamicUniformBuffer<T: ShaderType> {
values: Vec<T>,
scratch: DynamicUniformBufferWrapper<Vec<u8>>,
Expand Down Expand Up @@ -118,13 +162,19 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
self.values.is_empty()
}

/// Push data into the `DynamicUniformBuffer`'s internal vector (residing on system RAM).
#[inline]
pub fn push(&mut self, value: T) -> u32 {
let offset = self.scratch.write(&value).unwrap() as u32;
self.values.push(value);
offset
}

/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
///
/// If there is no GPU-side buffer allocated to hold the data currently stored, or if a GPU-side buffer previously
/// allocated does not have enough capacity, a new GPU-side buffer is created.
#[inline]
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
let size = self.scratch.as_ref().len();
Expand Down