mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 22:18:33 +00:00
Documenting UniformBuffer
, DynamicUniformBuffer
, StorageBuffer
and DynamicStorageBuffer
. (#5223)
# Objective Documents the `UniformBuffer`, `DynamicUniformBuffer`, `StorageBuffer` and `DynamicStorageBuffer` render resources. ## Solution I looked through Discord discussion on these structures, and found [a comment](https://discord.com/channels/691052431525675048/953222550568173580/956596218857918464) to be particularly helpful, in the general discussion around encase. Other resources I have used are documented here: https://discord.com/channels/691052431525675048/968333504838524958/991195474029715520 Co-authored-by: Brian Merchant <bhmerchant@gmail.com>
This commit is contained in:
parent
db86023069
commit
433306b978
3 changed files with 107 additions and 12 deletions
|
@ -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>,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::doc_markdown)]
|
||||
|
||||
use super::Buffer;
|
||||
use crate::renderer::{RenderDevice, RenderQueue};
|
||||
use encase::{
|
||||
|
@ -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>>,
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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>>,
|
||||
|
|
|
@ -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>>,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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>>,
|
||||
|
@ -118,6 +162,7 @@ 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;
|
||||
|
@ -125,6 +170,11 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
|
|||
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();
|
||||
|
|
Loading…
Add table
Reference in a new issue