add a debug label to storage buffers (#5341)

# Objective

- Expose the wgpu debug label on storage buffer types.

## Solution

🐄

- Add an optional cow static string and pass that to the label field of create_buffer_with_data
- This pattern is already used by Bevy for debug tags on bind group and layout descriptors.

---

Example Usage:

A buffer is given a label using the label function. Alternatively a buffer may be labeled when it is created if the default() convention is not used.
![ray_buf](https://user-images.githubusercontent.com/106117615/179366494-f037bd8c-4d65-4b37-8135-01ac0c5c8ee0.png)

Here is the buffer appearing with the correct name in RenderDoc. Previously the buffer would have an anonymous name such as "Buffer223":
![buffer_named](https://user-images.githubusercontent.com/106117615/179366552-faeb6c27-5373-4e4e-a0e2-c04446f95a4b.png)



Co-authored-by: rebelroad-reinhart <reinhart@rebelroad.gg>
This commit is contained in:
Brandon Reinhart 2022-07-28 20:37:49 +00:00
parent 4e2600b788
commit 2d2ea337dd
3 changed files with 115 additions and 17 deletions

View file

@ -33,6 +33,8 @@ pub struct BufferVec<T: Pod> {
capacity: usize,
item_size: usize,
buffer_usage: BufferUsages,
label: Option<String>,
label_changed: bool,
}
impl<T: Pod> BufferVec<T> {
@ -43,6 +45,8 @@ impl<T: Pod> BufferVec<T> {
capacity: 0,
item_size: std::mem::size_of::<T>(),
buffer_usage,
label: None,
label_changed: false,
}
}
@ -72,6 +76,20 @@ impl<T: Pod> BufferVec<T> {
index
}
pub fn set_label(&mut self, label: Option<&str>) {
let label = label.map(str::to_string);
if label != self.label {
self.label_changed = true;
}
self.label = label;
}
pub fn get_label(&self) -> Option<&str> {
self.label.as_deref()
}
/// Creates a [`Buffer`](crate::render_resource::Buffer) on the [`RenderDevice`](crate::renderer::RenderDevice) with size
/// at least `std::mem::size_of::<T>() * capacity`, unless a such a buffer already exists.
///
@ -84,15 +102,16 @@ impl<T: Pod> BufferVec<T> {
/// the `BufferVec` was created, the buffer on the [`RenderDevice`](crate::renderer::RenderDevice)
/// is marked as [`BufferUsages::COPY_DST`](crate::render_resource::BufferUsages).
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
if capacity > self.capacity {
if capacity > self.capacity || self.label_changed {
self.capacity = capacity;
let size = self.item_size * capacity;
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
label: None,
label: self.label.as_deref(),
size: size as wgpu::BufferAddress,
usage: BufferUsages::COPY_DST | self.buffer_usage,
mapped_at_creation: false,
}));
self.label_changed = false;
}
}

View file

@ -32,6 +32,8 @@ pub struct StorageBuffer<T: ShaderType> {
scratch: StorageBufferWrapper<Vec<u8>>,
buffer: Option<Buffer>,
capacity: usize,
label: Option<String>,
label_changed: bool,
}
impl<T: ShaderType> From<T> for StorageBuffer<T> {
@ -41,6 +43,8 @@ impl<T: ShaderType> From<T> for StorageBuffer<T> {
scratch: StorageBufferWrapper::new(Vec::new()),
buffer: None,
capacity: 0,
label: None,
label_changed: false,
}
}
}
@ -52,6 +56,8 @@ impl<T: ShaderType + Default> Default for StorageBuffer<T> {
scratch: StorageBufferWrapper::new(Vec::new()),
buffer: None,
capacity: 0,
label: None,
label_changed: false,
}
}
}
@ -81,6 +87,20 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
&mut self.value
}
pub fn set_label(&mut self, label: Option<&str>) {
let label = label.map(str::to_string);
if label != self.label {
self.label_changed = true;
}
self.label = label;
}
pub fn get_label(&self) -> Option<&str> {
self.label.as_deref()
}
/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
///
@ -91,13 +111,14 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
let size = self.scratch.as_ref().len();
if self.capacity < size {
if self.capacity < size || self.label_changed {
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
label: None,
label: self.label.as_deref(),
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
contents: self.scratch.as_ref(),
}));
self.capacity = size;
self.label_changed = false;
} else if let Some(buffer) = &self.buffer {
queue.write_buffer(buffer, 0, self.scratch.as_ref());
}
@ -130,6 +151,8 @@ pub struct DynamicStorageBuffer<T: ShaderType> {
scratch: DynamicStorageBufferWrapper<Vec<u8>>,
buffer: Option<Buffer>,
capacity: usize,
label: Option<String>,
label_changed: bool,
}
impl<T: ShaderType> Default for DynamicStorageBuffer<T> {
@ -139,6 +162,8 @@ impl<T: ShaderType> Default for DynamicStorageBuffer<T> {
scratch: DynamicStorageBufferWrapper::new(Vec::new()),
buffer: None,
capacity: 0,
label: None,
label_changed: false,
}
}
}
@ -175,17 +200,32 @@ impl<T: ShaderType + WriteInto> DynamicStorageBuffer<T> {
offset
}
pub fn set_label(&mut self, label: Option<&str>) {
let label = label.map(str::to_string);
if label != self.label {
self.label_changed = true;
}
self.label = label;
}
pub fn get_label(&self) -> Option<&str> {
self.label.as_deref()
}
#[inline]
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
let size = self.scratch.as_ref().len();
if self.capacity < size {
if self.capacity < size || self.label_changed {
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
label: None,
label: self.label.as_deref(),
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
contents: self.scratch.as_ref(),
}));
self.capacity = size;
self.label_changed = false;
} else if let Some(buffer) = &self.buffer {
queue.write_buffer(buffer, 0, self.scratch.as_ref());
}

View file

@ -31,6 +31,8 @@ pub struct UniformBuffer<T: ShaderType> {
value: T,
scratch: UniformBufferWrapper<Vec<u8>>,
buffer: Option<Buffer>,
label: Option<String>,
label_changed: bool,
}
impl<T: ShaderType> From<T> for UniformBuffer<T> {
@ -39,6 +41,8 @@ impl<T: ShaderType> From<T> for UniformBuffer<T> {
value,
scratch: UniformBufferWrapper::new(Vec::new()),
buffer: None,
label: None,
label_changed: false,
}
}
}
@ -49,6 +53,8 @@ impl<T: ShaderType + Default> Default for UniformBuffer<T> {
value: T::default(),
scratch: UniformBufferWrapper::new(Vec::new()),
buffer: None,
label: None,
label_changed: false,
}
}
}
@ -79,6 +85,20 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
&mut self.value
}
pub fn set_label(&mut self, label: Option<&str>) {
let label = label.map(str::to_string);
if label != self.label {
self.label_changed = true;
}
self.label = label;
}
pub fn get_label(&self) -> Option<&str> {
self.label.as_deref()
}
/// 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.
///
@ -87,15 +107,15 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
self.scratch.write(&self.value).unwrap();
match &self.buffer {
Some(buffer) => queue.write_buffer(buffer, 0, self.scratch.as_ref()),
None => {
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
label: None,
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
contents: self.scratch.as_ref(),
}));
}
if self.label_changed || self.buffer.is_none() {
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
label: self.label.as_deref(),
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
contents: self.scratch.as_ref(),
}));
self.label_changed = false;
} else if let Some(buffer) = &self.buffer {
queue.write_buffer(buffer, 0, self.scratch.as_ref());
}
}
}
@ -124,6 +144,8 @@ pub struct DynamicUniformBuffer<T: ShaderType> {
scratch: DynamicUniformBufferWrapper<Vec<u8>>,
buffer: Option<Buffer>,
capacity: usize,
label: Option<String>,
label_changed: bool,
}
impl<T: ShaderType> Default for DynamicUniformBuffer<T> {
@ -133,6 +155,8 @@ impl<T: ShaderType> Default for DynamicUniformBuffer<T> {
scratch: DynamicUniformBufferWrapper::new(Vec::new()),
buffer: None,
capacity: 0,
label: None,
label_changed: false,
}
}
}
@ -170,6 +194,20 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
offset
}
pub fn set_label(&mut self, label: Option<&str>) {
let label = label.map(str::to_string);
if label != self.label {
self.label_changed = true;
}
self.label = label;
}
pub fn get_label(&self) -> Option<&str> {
self.label.as_deref()
}
/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
///
@ -179,13 +217,14 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
let size = self.scratch.as_ref().len();
if self.capacity < size {
if self.capacity < size || self.label_changed {
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
label: None,
label: self.label.as_deref(),
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
contents: self.scratch.as_ref(),
}));
self.capacity = size;
self.label_changed = false;
} else if let Some(buffer) = &self.buffer {
queue.write_buffer(buffer, 0, self.scratch.as_ref());
}