From a22ecede49c7db7ac5ad354358d0f5fc7aa7e754 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Sun, 5 May 2024 18:16:11 -0400 Subject: [PATCH] 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 --- crates/bevy_render/src/render_resource/buffer_vec.rs | 12 ++++++------ .../src/render_resource/storage_buffer.rs | 2 +- .../src/render_resource/uniform_buffer.rs | 4 ++-- crates/bevy_render/src/view/mod.rs | 1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 15874e4743b76..4db7bacd3e01a 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -43,7 +43,7 @@ pub struct RawBufferVec { item_size: usize, buffer_usage: BufferUsages, label: Option, - label_changed: bool, + changed: bool, } impl RawBufferVec { @@ -55,7 +55,7 @@ impl RawBufferVec { item_size: std::mem::size_of::(), buffer_usage, label: None, - label_changed: false, + changed: false, } } @@ -93,7 +93,7 @@ impl RawBufferVec { let label = label.map(str::to_string); if label != self.label { - self.label_changed = true; + self.changed = true; } self.label = label; @@ -115,16 +115,16 @@ impl RawBufferVec { /// the `RawBufferVec` was created, the buffer on the [`RenderDevice`] /// is marked as [`BufferUsages::COPY_DST`](BufferUsages). 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; - let size = self.item_size * capacity; self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor { label: self.label.as_deref(), size: size as BufferAddress, usage: BufferUsages::COPY_DST | self.buffer_usage, mapped_at_creation: false, })); - self.label_changed = false; + self.changed = false; } } diff --git a/crates/bevy_render/src/render_resource/storage_buffer.rs b/crates/bevy_render/src/render_resource/storage_buffer.rs index 1212b02ba742a..1b244f90327ac 100644 --- a/crates/bevy_render/src/render_resource/storage_buffer.rs +++ b/crates/bevy_render/src/render_resource/storage_buffer.rs @@ -250,7 +250,7 @@ impl DynamicStorageBuffer { let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0); 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 { label: self.label.as_deref(), usage: self.buffer_usage, diff --git a/crates/bevy_render/src/render_resource/uniform_buffer.rs b/crates/bevy_render/src/render_resource/uniform_buffer.rs index f71cdc1cebb22..de4d84c94a06e 100644 --- a/crates/bevy_render/src/render_resource/uniform_buffer.rs +++ b/crates/bevy_render/src/render_resource/uniform_buffer.rs @@ -295,7 +295,7 @@ impl DynamicUniformBuffer { .checked_mul(max_count as u64) .unwrap(); - if capacity < size || self.changed { + if capacity < size || (self.changed && size > 0) { let buffer = device.create_buffer(&BufferDescriptor { label: self.label.as_deref(), usage: self.buffer_usage, @@ -336,7 +336,7 @@ impl DynamicUniformBuffer { let capacity = self.buffer.as_deref().map(wgpu::Buffer::size).unwrap_or(0); 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 { label: self.label.as_deref(), usage: self.buffer_usage, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index d211ef71b7b66..2c7e4c9e0459d 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -429,6 +429,7 @@ pub struct ViewUniforms { impl FromWorld for ViewUniforms { fn from_world(world: &mut World) -> Self { let mut uniforms = DynamicUniformBuffer::default(); + uniforms.set_label(Some("view_uniforms_buffer")); let render_device = world.resource::(); if render_device.limits().max_storage_buffers_per_shader_stage > 0 {