mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Only create changed buffer if it already exists (#13242)
# Objective - `DynamicUniformBuffer` tries to create a buffer as soon as the changed flag is set to true. This doesn't work correctly when the buffer wasn't already created. This currently creates a crash because it's trying to create a buffer of size 0 if the flag is set but there's no buffer yet. ## Solution - Don't create a changed buffer until there's data that needs to be written to a buffer. ## Testing - run `cargo run --example scene_viewer` and see that it doesn't crash anymore Fixes #13235
This commit is contained in:
parent
088960f597
commit
a22ecede49
4 changed files with 10 additions and 9 deletions
|
@ -43,7 +43,7 @@ pub struct RawBufferVec<T: NoUninit> {
|
||||||
item_size: usize,
|
item_size: usize,
|
||||||
buffer_usage: BufferUsages,
|
buffer_usage: BufferUsages,
|
||||||
label: Option<String>,
|
label: Option<String>,
|
||||||
label_changed: bool,
|
changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NoUninit> RawBufferVec<T> {
|
impl<T: NoUninit> RawBufferVec<T> {
|
||||||
|
@ -55,7 +55,7 @@ impl<T: NoUninit> RawBufferVec<T> {
|
||||||
item_size: std::mem::size_of::<T>(),
|
item_size: std::mem::size_of::<T>(),
|
||||||
buffer_usage,
|
buffer_usage,
|
||||||
label: None,
|
label: None,
|
||||||
label_changed: false,
|
changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ impl<T: NoUninit> RawBufferVec<T> {
|
||||||
let label = label.map(str::to_string);
|
let label = label.map(str::to_string);
|
||||||
|
|
||||||
if label != self.label {
|
if label != self.label {
|
||||||
self.label_changed = true;
|
self.changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.label = label;
|
self.label = label;
|
||||||
|
@ -115,16 +115,16 @@ impl<T: NoUninit> RawBufferVec<T> {
|
||||||
/// the `RawBufferVec` was created, the buffer on the [`RenderDevice`]
|
/// the `RawBufferVec` was created, the buffer on the [`RenderDevice`]
|
||||||
/// is marked as [`BufferUsages::COPY_DST`](BufferUsages).
|
/// is marked as [`BufferUsages::COPY_DST`](BufferUsages).
|
||||||
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
||||||
if capacity > self.capacity || self.label_changed {
|
let size = self.item_size * capacity;
|
||||||
|
if capacity > self.capacity || (self.changed && size > 0) {
|
||||||
self.capacity = capacity;
|
self.capacity = capacity;
|
||||||
let size = self.item_size * capacity;
|
|
||||||
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: self.label.as_deref(),
|
label: self.label.as_deref(),
|
||||||
size: size as BufferAddress,
|
size: size as 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;
|
self.changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@ impl<T: ShaderType + WriteInto> DynamicStorageBuffer<T> {
|
||||||
let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0);
|
let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0);
|
||||||
let size = self.scratch.as_ref().len() as u64;
|
let size = self.scratch.as_ref().len() as u64;
|
||||||
|
|
||||||
if capacity < size || self.changed {
|
if capacity < size || (self.changed && size > 0) {
|
||||||
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
label: self.label.as_deref(),
|
label: self.label.as_deref(),
|
||||||
usage: self.buffer_usage,
|
usage: self.buffer_usage,
|
||||||
|
|
|
@ -295,7 +295,7 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
|
||||||
.checked_mul(max_count as u64)
|
.checked_mul(max_count as u64)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if capacity < size || self.changed {
|
if capacity < size || (self.changed && size > 0) {
|
||||||
let buffer = device.create_buffer(&BufferDescriptor {
|
let buffer = device.create_buffer(&BufferDescriptor {
|
||||||
label: self.label.as_deref(),
|
label: self.label.as_deref(),
|
||||||
usage: self.buffer_usage,
|
usage: self.buffer_usage,
|
||||||
|
@ -336,7 +336,7 @@ impl<T: ShaderType + WriteInto> DynamicUniformBuffer<T> {
|
||||||
let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0);
|
let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0);
|
||||||
let size = self.scratch.as_ref().len() as u64;
|
let size = self.scratch.as_ref().len() as u64;
|
||||||
|
|
||||||
if capacity < size || self.changed {
|
if capacity < size || (self.changed && size > 0) {
|
||||||
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
label: self.label.as_deref(),
|
label: self.label.as_deref(),
|
||||||
usage: self.buffer_usage,
|
usage: self.buffer_usage,
|
||||||
|
|
|
@ -429,6 +429,7 @@ pub struct ViewUniforms {
|
||||||
impl FromWorld for ViewUniforms {
|
impl FromWorld for ViewUniforms {
|
||||||
fn from_world(world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
let mut uniforms = DynamicUniformBuffer::default();
|
let mut uniforms = DynamicUniformBuffer::default();
|
||||||
|
uniforms.set_label(Some("view_uniforms_buffer"));
|
||||||
|
|
||||||
let render_device = world.resource::<RenderDevice>();
|
let render_device = world.resource::<RenderDevice>();
|
||||||
if render_device.limits().max_storage_buffers_per_shader_stage > 0 {
|
if render_device.limits().max_storage_buffers_per_shader_stage > 0 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue