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.  Here is the buffer appearing with the correct name in RenderDoc. Previously the buffer would have an anonymous name such as "Buffer223":  Co-authored-by: rebelroad-reinhart <reinhart@rebelroad.gg>
This commit is contained in:
parent
4e2600b788
commit
2d2ea337dd
@ -33,6 +33,8 @@ pub struct BufferVec<T: Pod> {
|
|||||||
capacity: usize,
|
capacity: usize,
|
||||||
item_size: usize,
|
item_size: usize,
|
||||||
buffer_usage: BufferUsages,
|
buffer_usage: BufferUsages,
|
||||||
|
label: Option<String>,
|
||||||
|
label_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Pod> BufferVec<T> {
|
impl<T: Pod> BufferVec<T> {
|
||||||
@ -43,6 +45,8 @@ impl<T: Pod> BufferVec<T> {
|
|||||||
capacity: 0,
|
capacity: 0,
|
||||||
item_size: std::mem::size_of::<T>(),
|
item_size: std::mem::size_of::<T>(),
|
||||||
buffer_usage,
|
buffer_usage,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +76,20 @@ impl<T: Pod> BufferVec<T> {
|
|||||||
index
|
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
|
/// 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.
|
/// 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)
|
/// the `BufferVec` was created, the buffer on the [`RenderDevice`](crate::renderer::RenderDevice)
|
||||||
/// is marked as [`BufferUsages::COPY_DST`](crate::render_resource::BufferUsages).
|
/// is marked as [`BufferUsages::COPY_DST`](crate::render_resource::BufferUsages).
|
||||||
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
||||||
if capacity > self.capacity {
|
if capacity > self.capacity || self.label_changed {
|
||||||
self.capacity = capacity;
|
self.capacity = capacity;
|
||||||
let size = self.item_size * capacity;
|
let size = self.item_size * capacity;
|
||||||
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: self.label.as_deref(),
|
||||||
size: size as wgpu::BufferAddress,
|
size: size as wgpu::BufferAddress,
|
||||||
usage: BufferUsages::COPY_DST | self.buffer_usage,
|
usage: BufferUsages::COPY_DST | self.buffer_usage,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
}));
|
}));
|
||||||
|
self.label_changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ pub struct StorageBuffer<T: ShaderType> {
|
|||||||
scratch: StorageBufferWrapper<Vec<u8>>,
|
scratch: StorageBufferWrapper<Vec<u8>>,
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
|
label: Option<String>,
|
||||||
|
label_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ShaderType> From<T> for StorageBuffer<T> {
|
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()),
|
scratch: StorageBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,6 +56,8 @@ impl<T: ShaderType + Default> Default for StorageBuffer<T> {
|
|||||||
scratch: StorageBufferWrapper::new(Vec::new()),
|
scratch: StorageBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,6 +87,20 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
|
|||||||
&mut self.value
|
&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)
|
/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
|
||||||
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
|
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
|
||||||
///
|
///
|
||||||
@ -91,13 +111,14 @@ impl<T: ShaderType + WriteInto> StorageBuffer<T> {
|
|||||||
|
|
||||||
let size = self.scratch.as_ref().len();
|
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 {
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
label: None,
|
label: self.label.as_deref(),
|
||||||
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
|
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
|
||||||
contents: self.scratch.as_ref(),
|
contents: self.scratch.as_ref(),
|
||||||
}));
|
}));
|
||||||
self.capacity = size;
|
self.capacity = size;
|
||||||
|
self.label_changed = false;
|
||||||
} else if let Some(buffer) = &self.buffer {
|
} else if let Some(buffer) = &self.buffer {
|
||||||
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
||||||
}
|
}
|
||||||
@ -130,6 +151,8 @@ pub struct DynamicStorageBuffer<T: ShaderType> {
|
|||||||
scratch: DynamicStorageBufferWrapper<Vec<u8>>,
|
scratch: DynamicStorageBufferWrapper<Vec<u8>>,
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
|
label: Option<String>,
|
||||||
|
label_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ShaderType> Default for DynamicStorageBuffer<T> {
|
impl<T: ShaderType> Default for DynamicStorageBuffer<T> {
|
||||||
@ -139,6 +162,8 @@ impl<T: ShaderType> Default for DynamicStorageBuffer<T> {
|
|||||||
scratch: DynamicStorageBufferWrapper::new(Vec::new()),
|
scratch: DynamicStorageBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,17 +200,32 @@ impl<T: ShaderType + WriteInto> DynamicStorageBuffer<T> {
|
|||||||
offset
|
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]
|
#[inline]
|
||||||
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
|
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
|
||||||
let size = self.scratch.as_ref().len();
|
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 {
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
label: None,
|
label: self.label.as_deref(),
|
||||||
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
|
usage: BufferUsages::COPY_DST | BufferUsages::STORAGE,
|
||||||
contents: self.scratch.as_ref(),
|
contents: self.scratch.as_ref(),
|
||||||
}));
|
}));
|
||||||
self.capacity = size;
|
self.capacity = size;
|
||||||
|
self.label_changed = false;
|
||||||
} else if let Some(buffer) = &self.buffer {
|
} else if let Some(buffer) = &self.buffer {
|
||||||
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ pub struct UniformBuffer<T: ShaderType> {
|
|||||||
value: T,
|
value: T,
|
||||||
scratch: UniformBufferWrapper<Vec<u8>>,
|
scratch: UniformBufferWrapper<Vec<u8>>,
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
|
label: Option<String>,
|
||||||
|
label_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ShaderType> From<T> for UniformBuffer<T> {
|
impl<T: ShaderType> From<T> for UniformBuffer<T> {
|
||||||
@ -39,6 +41,8 @@ impl<T: ShaderType> From<T> for UniformBuffer<T> {
|
|||||||
value,
|
value,
|
||||||
scratch: UniformBufferWrapper::new(Vec::new()),
|
scratch: UniformBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,6 +53,8 @@ impl<T: ShaderType + Default> Default for UniformBuffer<T> {
|
|||||||
value: T::default(),
|
value: T::default(),
|
||||||
scratch: UniformBufferWrapper::new(Vec::new()),
|
scratch: UniformBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,6 +85,20 @@ impl<T: ShaderType + WriteInto> UniformBuffer<T> {
|
|||||||
&mut self.value
|
&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)
|
/// 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.
|
/// 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) {
|
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
|
||||||
self.scratch.write(&self.value).unwrap();
|
self.scratch.write(&self.value).unwrap();
|
||||||
|
|
||||||
match &self.buffer {
|
if self.label_changed || self.buffer.is_none() {
|
||||||
Some(buffer) => queue.write_buffer(buffer, 0, self.scratch.as_ref()),
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
None => {
|
label: self.label.as_deref(),
|
||||||
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
|
||||||
label: None,
|
contents: self.scratch.as_ref(),
|
||||||
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>>,
|
scratch: DynamicUniformBufferWrapper<Vec<u8>>,
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
|
label: Option<String>,
|
||||||
|
label_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ShaderType> Default for DynamicUniformBuffer<T> {
|
impl<T: ShaderType> Default for DynamicUniformBuffer<T> {
|
||||||
@ -133,6 +155,8 @@ impl<T: ShaderType> Default for DynamicUniformBuffer<T> {
|
|||||||
scratch: DynamicUniformBufferWrapper::new(Vec::new()),
|
scratch: DynamicUniformBufferWrapper::new(Vec::new()),
|
||||||
buffer: None,
|
buffer: None,
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
|
label: None,
|
||||||
|
label_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,6 +194,20 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
|
|||||||
offset
|
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)
|
/// Queues writing of data from system RAM to VRAM using the [`RenderDevice`](crate::renderer::RenderDevice)
|
||||||
/// and the provided [`RenderQueue`](crate::renderer::RenderQueue).
|
/// 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) {
|
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
|
||||||
let size = self.scratch.as_ref().len();
|
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 {
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
label: None,
|
label: self.label.as_deref(),
|
||||||
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
|
usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
|
||||||
contents: self.scratch.as_ref(),
|
contents: self.scratch.as_ref(),
|
||||||
}));
|
}));
|
||||||
self.capacity = size;
|
self.capacity = size;
|
||||||
|
self.label_changed = false;
|
||||||
} else if let Some(buffer) = &self.buffer {
|
} else if let Some(buffer) = &self.buffer {
|
||||||
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
queue.write_buffer(buffer, 0, self.scratch.as_ref());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user